From 707f75f7ba5b77eecd1d56931c408292fe4268da Mon Sep 17 00:00:00 2001 From: Joshua Hale Date: Wed, 30 Jan 2019 11:36:48 +0000 Subject: [PATCH 0001/2538] doc: remove - from command arguments --- java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java b/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java index 1529c1fd203f..ab831d158732 100644 --- a/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java +++ b/java/ql/src/Security/CWE/CWE-078/ExecUnescaped.java @@ -4,7 +4,7 @@ public static void main(String[] args) { { String latlonCoords = args[1]; Runtime rt = Runtime.getRuntime(); - Process exec = rt.exec("cmd.exe /C latlon2utm.exe -" + latlonCoords); + Process exec = rt.exec("cmd.exe /C latlon2utm.exe " + latlonCoords); } // GOOD: use an array of arguments instead of executing a string From 5e409a3eaacba728662360401598a424ab11835a Mon Sep 17 00:00:00 2001 From: Luke Cartey Date: Thu, 16 May 2019 12:33:02 +0100 Subject: [PATCH 0002/2538] Python: Change invalid @kind. --- python/ql/src/Filters/NotGenerated.ql | 2 +- python/ql/src/Filters/NotTest.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/python/ql/src/Filters/NotGenerated.ql b/python/ql/src/Filters/NotGenerated.ql index 121fc3c7a458..f06861e43d6d 100644 --- a/python/ql/src/Filters/NotGenerated.ql +++ b/python/ql/src/Filters/NotGenerated.ql @@ -1,7 +1,7 @@ /** * @name Filter: non-generated files * @description Only keep results that aren't (or don't appear to be) generated. - * @kind file-classifier + * @kind problem * @id py/not-generated-file-filter */ import external.DefectFilter diff --git a/python/ql/src/Filters/NotTest.ql b/python/ql/src/Filters/NotTest.ql index 4d6b0ec51622..3cfb1a423fd6 100644 --- a/python/ql/src/Filters/NotTest.ql +++ b/python/ql/src/Filters/NotTest.ql @@ -1,7 +1,7 @@ /** * @name Filter: non-test files * @description Only keep results that aren't in tests - * @kind file-classifier + * @kind problem * @id py/not-test-file-filter */ import external.DefectFilter From 562bffe71047d90de8f9ab05182d3b4258a9dd2a Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 12 Sep 2019 10:17:01 +0200 Subject: [PATCH 0003/2538] C++: Simplify `toString` of ImplicitParameterNode This string looked out of place compared to `ExplicitParameterNode`, whose string is simply the name of the parameter and therefore indistinguishable from an access to the parameter without looking at the location also. This has not been a problem so far, and if we want to distinguish more clearly between initial values and accesses at some point, we should do it for `ExplicitParameterNode` and `UninitializedNode` too. --- .../cpp/dataflow/internal/DataFlowUtil.qll | 2 +- .../dataflow/fields/flow.expected | 18 +++++++++--------- .../dataflow/taint-tests/localTaint.expected | 16 ++++++++-------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll index abbb5190d463..cc9687296f7b 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowUtil.qll @@ -179,7 +179,7 @@ class ImplicitParameterNode extends ParameterNode, TInstanceParameterNode { override Type getType() { result = f.getDeclaringType() } - override string toString() { result = "`this` parameter in " + f.getName() } + override string toString() { result = "this" } override Location getLocation() { result = f.getLocation() } diff --git a/cpp/ql/test/library-tests/dataflow/fields/flow.expected b/cpp/ql/test/library-tests/dataflow/fields/flow.expected index 1119b705bbf5..d9bc55253f90 100644 --- a/cpp/ql/test/library-tests/dataflow/fields/flow.expected +++ b/cpp/ql/test/library-tests/dataflow/fields/flow.expected @@ -78,15 +78,15 @@ edges | B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 | | C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] | | C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] | -| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | `this` parameter in func [s1] | -| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | `this` parameter in func [s3] | +| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] | +| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | this [s3] | | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:18:12:18:18 | call to C [s1] | | C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | | C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] | | C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | this [post update] [s3] | | C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... | -| C.cpp:27:8:27:11 | `this` parameter in func [s1] | C.cpp:29:10:29:11 | this [s1] | -| C.cpp:27:8:27:11 | `this` parameter in func [s3] | C.cpp:31:10:31:11 | this [s3] | +| C.cpp:27:8:27:11 | this [s1] | C.cpp:29:10:29:11 | this [s1] | +| C.cpp:27:8:27:11 | this [s3] | C.cpp:31:10:31:11 | this [s3] | | C.cpp:29:10:29:11 | this [s1] | C.cpp:29:10:29:11 | s1 | | C.cpp:31:10:31:11 | this [s3] | C.cpp:31:10:31:11 | s3 | | D.cpp:21:30:21:31 | b2 [box, elem] | D.cpp:22:10:22:11 | b2 [box, elem] | @@ -117,8 +117,8 @@ edges | D.cpp:58:5:58:12 | this [post update] [boxfield, box, ... (3)] | D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | | D.cpp:58:5:58:27 | ... = ... | D.cpp:58:15:58:17 | box [post update] [elem] | | D.cpp:58:15:58:17 | box [post update] [elem] | D.cpp:58:5:58:12 | boxfield [post update] [box, elem] | -| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | -| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | +| D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | +| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | | D.cpp:64:10:64:17 | boxfield [box, elem] | D.cpp:64:20:64:22 | box [elem] | | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | D.cpp:64:10:64:17 | boxfield [box, elem] | | D.cpp:64:20:64:22 | box [elem] | D.cpp:64:25:64:28 | elem | @@ -313,8 +313,8 @@ nodes | C.cpp:24:5:24:8 | this [post update] [s3] | semmle.label | this [post update] [s3] | | C.cpp:24:5:24:25 | ... = ... | semmle.label | ... = ... | | C.cpp:24:16:24:25 | new | semmle.label | new | -| C.cpp:27:8:27:11 | `this` parameter in func [s1] | semmle.label | `this` parameter in func [s1] | -| C.cpp:27:8:27:11 | `this` parameter in func [s3] | semmle.label | `this` parameter in func [s3] | +| C.cpp:27:8:27:11 | this [s1] | semmle.label | this [s1] | +| C.cpp:27:8:27:11 | this [s3] | semmle.label | this [s3] | | C.cpp:29:10:29:11 | s1 | semmle.label | s1 | | C.cpp:29:10:29:11 | this [s1] | semmle.label | this [s1] | | C.cpp:31:10:31:11 | s3 | semmle.label | s3 | @@ -349,7 +349,7 @@ nodes | D.cpp:58:5:58:27 | ... = ... | semmle.label | ... = ... | | D.cpp:58:15:58:17 | box [post update] [elem] | semmle.label | box [post update] [elem] | | D.cpp:59:5:59:7 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] | -| D.cpp:63:8:63:10 | `this` parameter in f5b [boxfield, box, ... (3)] | semmle.label | `this` parameter in f5b [boxfield, box, ... (3)] | +| D.cpp:63:8:63:10 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] | | D.cpp:64:10:64:17 | boxfield [box, elem] | semmle.label | boxfield [box, elem] | | D.cpp:64:10:64:17 | this [boxfield, box, ... (3)] | semmle.label | this [boxfield, box, ... (3)] | | D.cpp:64:20:64:22 | box [elem] | semmle.label | box [elem] | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected index 4895cf711126..efad80dd9f97 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/localTaint.expected @@ -40,7 +40,7 @@ | taint.cpp:37:12:37:20 | call to increment | taint.cpp:43:7:43:13 | global9 | | | taint.cpp:38:13:38:16 | call to zero | taint.cpp:38:2:38:26 | ... = ... | | | taint.cpp:38:13:38:16 | call to zero | taint.cpp:44:7:44:14 | global10 | | -| taint.cpp:71:2:71:8 | `this` parameter in MyClass | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | | +| taint.cpp:71:2:71:8 | this | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | | | taint.cpp:71:14:71:17 | 0 | taint.cpp:71:14:71:17 | constructor init of field a | TAINT | | taint.cpp:71:14:71:17 | constructor init of field a [post-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | | | taint.cpp:71:14:71:17 | constructor init of field a [pre-this] | taint.cpp:71:20:71:30 | constructor init of field b [pre-this] | | @@ -51,7 +51,7 @@ | taint.cpp:72:3:72:3 | this [post update] | taint.cpp:73:3:73:3 | this | | | taint.cpp:72:7:72:12 | call to source | taint.cpp:72:3:72:14 | ... = ... | | | taint.cpp:73:7:73:7 | 0 | taint.cpp:73:3:73:7 | ... = ... | | -| taint.cpp:76:7:76:14 | `this` parameter in myMethod | taint.cpp:77:3:77:3 | this | | +| taint.cpp:76:7:76:14 | this | taint.cpp:77:3:77:3 | this | | | taint.cpp:77:7:77:12 | call to source | taint.cpp:77:3:77:14 | ... = ... | | | taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:86:2:86:4 | mc1 | | | taint.cpp:84:10:84:12 | call to MyClass | taint.cpp:88:7:88:9 | mc1 | | @@ -188,36 +188,36 @@ | taint.cpp:226:9:226:10 | 0 | taint.cpp:261:7:261:7 | w | | | taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field t | TAINT | | taint.cpp:228:11:228:11 | Unknown literal | taint.cpp:228:11:228:11 | constructor init of field u | TAINT | -| taint.cpp:228:11:228:11 | `this` parameter in (constructor) | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | | | taint.cpp:228:11:228:11 | constructor init of field t [post-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | | | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | taint.cpp:228:11:228:11 | constructor init of field u [pre-this] | | +| taint.cpp:228:11:228:11 | this | taint.cpp:228:11:228:11 | constructor init of field t [pre-this] | | | taint.cpp:228:11:232:2 | [...](...){...} | taint.cpp:233:7:233:7 | a | | | taint.cpp:228:11:232:2 | {...} | taint.cpp:228:11:232:2 | [...](...){...} | | -| taint.cpp:228:17:228:17 | `this` parameter in operator() | taint.cpp:229:3:229:6 | this | | +| taint.cpp:228:17:228:17 | this | taint.cpp:229:3:229:6 | this | | | taint.cpp:229:3:229:6 | this | taint.cpp:230:3:230:6 | this | | | taint.cpp:230:3:230:6 | this | taint.cpp:231:3:231:11 | this | | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field t | TAINT | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field u | TAINT | | taint.cpp:235:11:235:11 | Unknown literal | taint.cpp:235:11:235:11 | constructor init of field v | TAINT | -| taint.cpp:235:11:235:11 | `this` parameter in (constructor) | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | | | taint.cpp:235:11:235:11 | constructor init of field t [post-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | | | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | | | taint.cpp:235:11:235:11 | constructor init of field u [post-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | | | taint.cpp:235:11:235:11 | constructor init of field u [pre-this] | taint.cpp:235:11:235:11 | constructor init of field v [pre-this] | | +| taint.cpp:235:11:235:11 | this | taint.cpp:235:11:235:11 | constructor init of field t [pre-this] | | | taint.cpp:235:11:239:2 | [...](...){...} | taint.cpp:240:2:240:2 | b | | | taint.cpp:235:11:239:2 | {...} | taint.cpp:235:11:239:2 | [...](...){...} | | -| taint.cpp:235:15:235:15 | `this` parameter in operator() | taint.cpp:236:3:236:6 | this | | +| taint.cpp:235:15:235:15 | this | taint.cpp:236:3:236:6 | this | | | taint.cpp:236:3:236:6 | this | taint.cpp:237:3:237:6 | this | | | taint.cpp:237:3:237:6 | this | taint.cpp:238:3:238:14 | this | | | taint.cpp:238:7:238:12 | call to source | taint.cpp:238:3:238:14 | ... = ... | | | taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field t | TAINT | | taint.cpp:243:11:243:11 | Unknown literal | taint.cpp:243:11:243:11 | constructor init of field u | TAINT | -| taint.cpp:243:11:243:11 | `this` parameter in (constructor) | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | | | taint.cpp:243:11:243:11 | constructor init of field t [post-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | | | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | taint.cpp:243:11:243:11 | constructor init of field u [pre-this] | | +| taint.cpp:243:11:243:11 | this | taint.cpp:243:11:243:11 | constructor init of field t [pre-this] | | | taint.cpp:243:11:246:2 | [...](...){...} | taint.cpp:247:2:247:2 | c | | | taint.cpp:243:11:246:2 | {...} | taint.cpp:243:11:246:2 | [...](...){...} | | -| taint.cpp:243:15:243:15 | `this` parameter in operator() | taint.cpp:244:3:244:6 | this | | +| taint.cpp:243:15:243:15 | this | taint.cpp:244:3:244:6 | this | | | taint.cpp:244:3:244:6 | this | taint.cpp:245:3:245:6 | this | | | taint.cpp:249:11:252:2 | [...](...){...} | taint.cpp:253:2:253:2 | d | | | taint.cpp:249:18:249:18 | a | taint.cpp:250:8:250:8 | a | | From 7cfbe88e7bdd7140054a70d45dcd428f4cb3b20e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 12 Sep 2019 10:20:39 +0200 Subject: [PATCH 0004/2538] C++: IR DataFlow::Node.toString consistency The `toString` for IR data-flow nodes are now similar to AST data-flow nodes. This should make it easier to use the IR as a drop-in replacement in the future. There are still differences because the IR data flow library takes conversions into account. I did not attempt to align the new nodes we use for field flow. That can come later, when we add field flow to IR data flow. --- .../cpp/ir/dataflow/internal/DataFlowUtil.qll | 18 +++- .../dataflow/dataflow-tests/test_ir.expected | 88 +++++++++---------- .../dataflow/taint-tests/test_ir.expected | 24 ++--- 3 files changed, 74 insertions(+), 56 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index 0476ea3c30ab..b5415f2bc656 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -84,7 +84,11 @@ class Node extends TIRDataFlowNode { this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } - string toString() { result = instr.toString() } + string toString() { + // This predicate is overridden in subclasses. This default implementation + // does not use `Instruction.toString` because that's expensive to compute. + result = this.asInstruction().getOpcode().toString() + } } /** @@ -106,6 +110,8 @@ class ExprNode extends Node { * expression may be a `Conversion`. */ Expr getConvertedExpr() { result = this.asConvertedExpr() } + + override string toString() { result = this.asConvertedExpr().toString() } } /** @@ -122,6 +128,14 @@ class ParameterNode extends Node { predicate isParameterOf(Function f, int i) { f.getParameter(i) = instr.getParameter() } Parameter getParameter() { result = instr.getParameter() } + + override string toString() { result = instr.getParameter().toString() } +} + +private class ThisParameterNode extends Node { + override InitializeThisInstruction instr; + + override string toString() { result = "this" } } /** @@ -132,6 +146,8 @@ class UninitializedNode extends Node { override UninitializedInstruction instr; LocalVariable getLocalVariable() { result = instr.getLocalVariable() } + + override string toString() { result = this.getLocalVariable().toString() } } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 83ba546480f9..8ec0cf4f397b 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -1,44 +1,44 @@ -| acrossLinkTargets.cpp:12:8:12:8 | Convert: (int)... | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source | -| acrossLinkTargets.cpp:12:8:12:8 | Load: x | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source | -| clang.cpp:18:8:18:19 | Convert: (const int *)... | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 | -| clang.cpp:18:8:18:19 | Load: sourceArray1 | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 | -| clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source | -| clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source | -| clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | -| test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | -| test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | -| test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source | -| test.cpp:15:8:15:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source | -| test.cpp:26:8:26:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | -| test.cpp:30:8:30:8 | Load: t | test.cpp:35:10:35:15 | Call: call to source | -| test.cpp:31:8:31:8 | Load: c | test.cpp:36:13:36:18 | Call: call to source | -| test.cpp:58:10:58:10 | Load: t | test.cpp:50:14:50:19 | Call: call to source | -| test.cpp:71:8:71:9 | Load: x4 | test.cpp:66:30:66:36 | InitializeParameter: source1 | -| test.cpp:76:8:76:9 | Load: u1 | test.cpp:75:7:75:8 | Uninitialized: definition of u1 | -| test.cpp:84:8:84:18 | Load: ... ? ... : ... | test.cpp:83:7:83:8 | Uninitialized: definition of u2 | -| test.cpp:86:8:86:9 | Load: i1 | test.cpp:83:7:83:8 | Uninitialized: definition of u2 | -| test.cpp:90:8:90:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 | -| test.cpp:92:8:92:14 | Load: source1 | test.cpp:89:28:89:34 | InitializeParameter: source1 | -| test.cpp:110:10:110:12 | Load: (reference dereference) | test.cpp:109:9:109:14 | Call: call to source | -| test.cpp:140:8:140:8 | Load: y | test.cpp:138:27:138:32 | Call: call to source | -| test.cpp:144:8:144:8 | Load: s | test.cpp:151:33:151:38 | Call: call to source | -| test.cpp:152:8:152:8 | Load: y | test.cpp:151:33:151:38 | Call: call to source | -| test.cpp:157:8:157:8 | Load: x | test.cpp:164:34:164:39 | Call: call to source | -| test.cpp:165:8:165:8 | Load: y | test.cpp:164:34:164:39 | Call: call to source | -| test.cpp:178:8:178:8 | Load: y | test.cpp:171:11:171:16 | Call: call to source | -| test.cpp:260:12:260:12 | Load: x | test.cpp:245:14:245:19 | Call: call to source | -| test.cpp:266:12:266:12 | Load: x | test.cpp:265:22:265:27 | Call: call to source | -| test.cpp:289:14:289:14 | Load: x | test.cpp:305:17:305:22 | Call: call to source | -| test.cpp:318:7:318:7 | Load: x | test.cpp:314:4:314:9 | Call: call to source | -| test.cpp:450:9:450:22 | CopyValue: (statement expression) | test.cpp:449:26:449:32 | InitializeParameter: source1 | -| test.cpp:461:8:461:12 | Load: local | test.cpp:449:26:449:32 | InitializeParameter: source1 | -| true_upon_entry.cpp:13:8:13:8 | Load: x | true_upon_entry.cpp:9:11:9:16 | Call: call to source | -| true_upon_entry.cpp:21:8:21:8 | Load: x | true_upon_entry.cpp:17:11:17:16 | Call: call to source | -| true_upon_entry.cpp:29:8:29:8 | Load: x | true_upon_entry.cpp:27:9:27:14 | Call: call to source | -| true_upon_entry.cpp:39:8:39:8 | Load: x | true_upon_entry.cpp:33:11:33:16 | Call: call to source | -| true_upon_entry.cpp:49:8:49:8 | Load: x | true_upon_entry.cpp:43:11:43:16 | Call: call to source | -| true_upon_entry.cpp:57:8:57:8 | Load: x | true_upon_entry.cpp:54:11:54:16 | Call: call to source | -| true_upon_entry.cpp:66:8:66:8 | Load: x | true_upon_entry.cpp:62:11:62:16 | Call: call to source | -| true_upon_entry.cpp:78:8:78:8 | Load: x | true_upon_entry.cpp:70:11:70:16 | Call: call to source | -| true_upon_entry.cpp:86:8:86:8 | Load: x | true_upon_entry.cpp:83:11:83:16 | Call: call to source | -| true_upon_entry.cpp:105:8:105:8 | Load: x | true_upon_entry.cpp:98:11:98:16 | Call: call to source | +| acrossLinkTargets.cpp:12:8:12:8 | (int)... | acrossLinkTargets.cpp:19:27:19:32 | call to source | +| acrossLinkTargets.cpp:12:8:12:8 | x | acrossLinkTargets.cpp:19:27:19:32 | call to source | +| clang.cpp:18:8:18:19 | (const int *)... | clang.cpp:12:9:12:20 | sourceArray1 | +| clang.cpp:18:8:18:19 | sourceArray1 | clang.cpp:12:9:12:20 | sourceArray1 | +| clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source | +| clang.cpp:41:18:41:19 | m2 | clang.cpp:39:42:39:47 | call to source | +| clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source | +| test.cpp:7:8:7:9 | t1 | test.cpp:6:12:6:17 | call to source | +| test.cpp:9:8:9:9 | t1 | test.cpp:6:12:6:17 | call to source | +| test.cpp:10:8:10:9 | t2 | test.cpp:6:12:6:17 | call to source | +| test.cpp:15:8:15:9 | t2 | test.cpp:6:12:6:17 | call to source | +| test.cpp:26:8:26:9 | t1 | test.cpp:6:12:6:17 | call to source | +| test.cpp:30:8:30:8 | t | test.cpp:35:10:35:15 | call to source | +| test.cpp:31:8:31:8 | c | test.cpp:36:13:36:18 | call to source | +| test.cpp:58:10:58:10 | t | test.cpp:50:14:50:19 | call to source | +| test.cpp:71:8:71:9 | x4 | test.cpp:66:30:66:36 | source1 | +| test.cpp:76:8:76:9 | u1 | test.cpp:75:7:75:8 | u1 | +| test.cpp:84:8:84:18 | ... ? ... : ... | test.cpp:83:7:83:8 | u2 | +| test.cpp:86:8:86:9 | i1 | test.cpp:83:7:83:8 | u2 | +| test.cpp:90:8:90:14 | source1 | test.cpp:89:28:89:34 | source1 | +| test.cpp:92:8:92:14 | source1 | test.cpp:89:28:89:34 | source1 | +| test.cpp:110:10:110:12 | (reference dereference) | test.cpp:109:9:109:14 | call to source | +| test.cpp:140:8:140:8 | y | test.cpp:138:27:138:32 | call to source | +| test.cpp:144:8:144:8 | s | test.cpp:151:33:151:38 | call to source | +| test.cpp:152:8:152:8 | y | test.cpp:151:33:151:38 | call to source | +| test.cpp:157:8:157:8 | x | test.cpp:164:34:164:39 | call to source | +| test.cpp:165:8:165:8 | y | test.cpp:164:34:164:39 | call to source | +| test.cpp:178:8:178:8 | y | test.cpp:171:11:171:16 | call to source | +| test.cpp:260:12:260:12 | x | test.cpp:245:14:245:19 | call to source | +| test.cpp:266:12:266:12 | x | test.cpp:265:22:265:27 | call to source | +| test.cpp:289:14:289:14 | x | test.cpp:305:17:305:22 | call to source | +| test.cpp:318:7:318:7 | x | test.cpp:314:4:314:9 | call to source | +| test.cpp:450:9:450:22 | (statement expression) | test.cpp:449:26:449:32 | source1 | +| test.cpp:461:8:461:12 | local | test.cpp:449:26:449:32 | source1 | +| true_upon_entry.cpp:13:8:13:8 | x | true_upon_entry.cpp:9:11:9:16 | call to source | +| true_upon_entry.cpp:21:8:21:8 | x | true_upon_entry.cpp:17:11:17:16 | call to source | +| true_upon_entry.cpp:29:8:29:8 | x | true_upon_entry.cpp:27:9:27:14 | call to source | +| true_upon_entry.cpp:39:8:39:8 | x | true_upon_entry.cpp:33:11:33:16 | call to source | +| true_upon_entry.cpp:49:8:49:8 | x | true_upon_entry.cpp:43:11:43:16 | call to source | +| true_upon_entry.cpp:57:8:57:8 | x | true_upon_entry.cpp:54:11:54:16 | call to source | +| true_upon_entry.cpp:66:8:66:8 | x | true_upon_entry.cpp:62:11:62:16 | call to source | +| true_upon_entry.cpp:78:8:78:8 | x | true_upon_entry.cpp:70:11:70:16 | call to source | +| true_upon_entry.cpp:86:8:86:8 | x | true_upon_entry.cpp:83:11:83:16 | call to source | +| true_upon_entry.cpp:105:8:105:8 | x | true_upon_entry.cpp:98:11:98:16 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected index b08cc19d0dfa..de2c7642e44b 100644 --- a/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/taint-tests/test_ir.expected @@ -1,11 +1,13 @@ -| taint.cpp:8:8:8:13 | Load: clean1 | taint.cpp:4:27:4:33 | InitializeParameter: source1 | -| taint.cpp:16:8:16:14 | Load: source1 | taint.cpp:12:22:12:27 | Call: call to source | -| taint.cpp:17:8:17:16 | Add: ++ ... | taint.cpp:12:22:12:27 | Call: call to source | -| taint.cpp:109:7:109:13 | Load: access to array | taint.cpp:105:12:105:17 | Call: call to source | -| taint.cpp:129:7:129:9 | Load: * ... | taint.cpp:120:11:120:16 | Call: call to source | -| taint.cpp:130:7:130:9 | Load: * ... | taint.cpp:127:8:127:13 | Call: call to source | -| taint.cpp:134:7:134:9 | Load: * ... | taint.cpp:120:11:120:16 | Call: call to source | -| taint.cpp:151:7:151:12 | Call: call to select | taint.cpp:151:20:151:25 | Call: call to source | -| taint.cpp:167:8:167:13 | Call: call to source | taint.cpp:167:8:167:13 | Call: call to source | -| taint.cpp:168:8:168:14 | Load: tainted | taint.cpp:164:19:164:24 | Call: call to source | -| taint.cpp:210:7:210:7 | Load: x | taint.cpp:207:6:207:11 | Call: call to source | +| taint.cpp:8:8:8:13 | clean1 | taint.cpp:4:27:4:33 | source1 | +| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | ... = ... | +| taint.cpp:16:8:16:14 | source1 | taint.cpp:12:22:12:27 | call to source | +| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | ... = ... | +| taint.cpp:17:8:17:16 | ++ ... | taint.cpp:12:22:12:27 | call to source | +| taint.cpp:109:7:109:13 | access to array | taint.cpp:105:12:105:17 | call to source | +| taint.cpp:129:7:129:9 | * ... | taint.cpp:120:11:120:16 | call to source | +| taint.cpp:130:7:130:9 | * ... | taint.cpp:127:8:127:13 | call to source | +| taint.cpp:134:7:134:9 | * ... | taint.cpp:120:11:120:16 | call to source | +| taint.cpp:151:7:151:12 | call to select | taint.cpp:151:20:151:25 | call to source | +| taint.cpp:167:8:167:13 | call to source | taint.cpp:167:8:167:13 | call to source | +| taint.cpp:168:8:168:14 | tainted | taint.cpp:164:19:164:24 | call to source | +| taint.cpp:210:7:210:7 | x | taint.cpp:207:6:207:11 | call to source | From 06b391ef9ba35fdcee626e40a42d229884243f52 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 20 Sep 2019 11:14:16 +0100 Subject: [PATCH 0005/2538] docs: fix links --- docs/language/learn-ql/java/introduce-libraries-java.rst | 2 +- docs/language/learn-ql/javascript/introduce-libraries-ts.rst | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index 4757085cfe11..32863b099e0b 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -369,7 +369,7 @@ Conversely, ``Callable.getAReference`` returns a ``Call`` that refers to it. So where not exists(c.getAReference()) select c -➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see `Navigating the call graph `__. +➤ `See this in the query console `__. The LGTM.com demo projects all appear to have many methods that are not called directly, but this is unlikely to be the whole story. To explore this area further, see :doc:`Navigating the call graph `. For more information about callables and calls, see the :doc:`call graph tutorial `. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst index a31bf9ffad62..539d81fb0162 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-ts.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-ts.rst @@ -134,7 +134,7 @@ The QL class `ClassOrInterface `__. -Also see the documentation for classes in the `Introduction to the QL libraries for JavaScript `__. +Also see the documentation for classes in the `Introduction to the QL libraries for JavaScript `__. To select the type references to a class or an interface, use ``getTypeName()``. @@ -443,6 +443,6 @@ A `LocalNamespaceName `. +- Learn about the QL standard libraries used to write queries for JavaScript in :doc:`Introducing the JavaScript libraries `. - Find out more about QL in the `QL language handbook `__ and `QL language specification `__. - Learn more about the query console in `Using the query console `__. \ No newline at end of file From cd5f3b84a8a9b62100ef4f697fa9740b911083ab Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 23 Sep 2019 14:51:59 +0200 Subject: [PATCH 0006/2538] C++: Make sure there's a Instruction for each Expr This change ensures that all `Expr`s (except parentheses) have a `TranslatedExpr` with a `getResult` that's one of its own instructions, not an instruction from one of its operands. This means that when we translate back and forth between `Expr` and `Instruction`, like in `DataFlow::exprNode`, we will not conflate `e` with `&e` or `... = e`. --- .../raw/internal/InstructionTag.qll | 1 + .../raw/internal/TranslatedElement.qll | 10 + .../raw/internal/TranslatedExpr.qll | 94 +- .../ir/escape/points_to.expected | 58 + .../test/library-tests/ir/ir/raw_ir.expected | 3213 +++++++++-------- .../ir/ssa/aliased_ssa_ir.expected | 141 +- .../ir/ssa/unaliased_ssa_ir.expected | 131 +- 7 files changed, 2075 insertions(+), 1573 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index ddac5692cdfb..c18ff8279921 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -44,6 +44,7 @@ newtype TInstructionTag = ConditionValueResultLoadTag() or BoolConversionConstantTag() or BoolConversionCompareTag() or + ResultCopyTag() or LoadTag() or // Implicit load due to lvalue-to-rvalue conversion CatchTag() or ThrowTag() or diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 23d3036ca15c..b9a6d4c737d6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -8,6 +8,7 @@ private import InstructionTag private import TranslatedCondition private import TranslatedFunction private import TranslatedStmt +private import TranslatedExpr private import IRConstruction /** @@ -235,6 +236,15 @@ newtype TTranslatedElement = expr.hasLValueToRValueConversion() and not ignoreLoad(expr) } or + TTranslatedResultCopy(Expr expr) { + not ignoreExpr(expr) and + exprNeedsCopyIfNotLoaded(expr) and + // Doesn't have a TTranslatedLoad + not ( + expr.hasLValueToRValueConversion() and + not ignoreLoad(expr) + ) + } or // An expression most naturally translated as control flow. TTranslatedNativeCondition(Expr expr) { not ignoreExpr(expr) and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index fa8eeb36adb7..e9e7cf59cb09 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -85,11 +85,14 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { final override predicate producesExprResult() { // If there's no load, then this is the only TranslatedExpr for this // expression. - not expr.hasLValueToRValueConversion() - or - // If we're supposed to ignore the load on this expression, then this - // is the only TranslatedExpr. - ignoreLoad(expr) + not hasLoad() and + // If there's a result copy, then this expression's result is the copy. + not exprNeedsCopyIfNotLoaded(expr) + } + + private predicate hasLoad() { + expr.hasLValueToRValueConversion() and + not ignoreLoad(expr) } /** @@ -106,7 +109,7 @@ abstract class TranslatedCoreExpr extends TranslatedExpr { or // If this TranslatedExpr doesn't produce the result, then it must represent // a glvalue that is then loaded by a TranslatedLoad. - not producesExprResult() + hasLoad() then result = true else result = false } @@ -302,6 +305,51 @@ class TranslatedLoad extends TranslatedExpr, TTranslatedLoad { private TranslatedCoreExpr getOperand() { result.getExpr() = expr } } +/** + * IR translation of an implicit lvalue-to-rvalue conversion on the result of + * an expression. + */ +class TranslatedResultCopy extends TranslatedExpr, TTranslatedResultCopy { + TranslatedResultCopy() { this = TTranslatedResultCopy(expr) } + + override string toString() { result = "Result of " + expr.toString() } + + override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() } + + override TranslatedElement getChild(int id) { id = 0 and result = getOperand() } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + tag = ResultCopyTag() and + opcode instanceof Opcode::CopyValue and + resultType = getOperand().getResultType() and + isGLValue = getOperand().isResultGLValue() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + tag = ResultCopyTag() and + result = getParent().getChildSuccessor(this) and + kind instanceof GotoEdge + } + + override Instruction getChildSuccessor(TranslatedElement child) { + child = getOperand() and result = getInstruction(ResultCopyTag()) + } + + override Instruction getResult() { result = getInstruction(ResultCopyTag()) } + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = ResultCopyTag() and + operandTag instanceof UnaryOperandTag and + result = getOperand().getResult() + } + + final override predicate producesExprResult() { any() } + + private TranslatedCoreExpr getOperand() { result.getExpr() = expr } +} + class TranslatedCommaExpr extends TranslatedNonConstantExpr { override CommaExpr expr; @@ -2485,3 +2533,37 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { final override Opcode getOpcode() { result instanceof Opcode::Error } } + +/** + * Holds if the translation of `expr` will not directly generate any + * `Instruction` for use as result. For such instructions we can synthesize a + * `CopyValue` instruction to ensure that there is a 1-to-1 mapping between + * expressions and result-bearing instructions. + */ +// This should ideally be a dispatch predicate on TranslatedNonConstantExpr, +// but it doesn't look monotonic to QL. +predicate exprNeedsCopyIfNotLoaded(Expr expr) { + expr instanceof AssignExpr + or + expr instanceof AssignOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PrefixCrementOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PointerDereferenceExpr + or + expr instanceof AddressOfExpr + or + expr instanceof BuiltInOperationBuiltInAddressOf + // No case for ParenthesisExpr to avoid getting too many instructions + or + expr instanceof ReferenceDereferenceExpr + or + expr instanceof ReferenceToExpr + or + expr instanceof CommaExpr + or + expr instanceof ConditionDeclExpr + // TODO: simplify TranslatedStmtExpr too +} diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index f40460f4d91b..e6fefda7bb55 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,47 +1,105 @@ +| escape.cpp:108:5:108:11 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:109:5:109:13 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:110:5:110:19 | CopyValue | no_result+0:0 | no_result+0:0 | +| escape.cpp:111:5:111:21 | CopyValue | no_result+0:0 | no_result+0:0 | +| escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:114:5:114:8 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:115:5:115:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:116:5:116:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | +| escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:117:5:117:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | +| escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:9:124:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:124:21:124:24 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 | +| escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:134:11:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:12 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 | +| escape.cpp:137:5:137:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | +| escape.cpp:138:5:138:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | +| escape.cpp:142:5:142:21 | CopyValue | no_Point+4:0 | no_Point+4:0 | | escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:5:144:25 | CopyValue | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | +| escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:5:146:25 | CopyValue | no_Point+8:0 | no_Point+8:0 | +| escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | +| escape.cpp:149:5:149:20 | CopyValue | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | +| escape.cpp:151:5:151:21 | CopyValue | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | +| escape.cpp:155:17:155:30 | CopyValue | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | | escape.cpp:155:17:155:30 | Store | no_ssa_addrOf+0:0 | no_ssa_addrOf+0:0 | +| escape.cpp:158:17:158:28 | CopyValue | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | | escape.cpp:158:17:158:28 | Store | no_ssa_refTo+0:0 | no_ssa_refTo+0:0 | | escape.cpp:161:19:161:42 | Convert | no_ssa_refToArrayElement+0:0 | no_ssa_refToArrayElement+0:0 | +| escape.cpp:161:19:161:45 | CopyValue | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | PointerAdd[4] | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | | escape.cpp:161:19:161:45 | Store | no_ssa_refToArrayElement+20:0 | no_ssa_refToArrayElement+20:0 | +| escape.cpp:164:24:164:40 | CopyValue | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | | escape.cpp:164:24:164:40 | Store | no_ssa_refToArray+0:0 | no_ssa_refToArray+0:0 | +| escape.cpp:167:19:167:28 | CopyValue | passByPtr+0:0 | passByPtr+0:0 | +| escape.cpp:170:21:170:29 | CopyValue | passByRef+0:0 | passByRef+0:0 | +| escape.cpp:173:22:173:38 | CopyValue | no_ssa_passByPtr+0:0 | no_ssa_passByPtr+0:0 | +| escape.cpp:176:24:176:39 | CopyValue | no_ssa_passByRef+0:0 | no_ssa_passByRef+0:0 | +| escape.cpp:179:22:179:42 | CopyValue | no_ssa_passByPtr_ret+0:0 | no_ssa_passByPtr_ret+0:0 | +| escape.cpp:182:24:182:43 | CopyValue | no_ssa_passByRef_ret+0:0 | no_ssa_passByRef_ret+0:0 | +| escape.cpp:185:30:185:40 | CopyValue | passByPtr2+0:0 | passByPtr2+0:0 | +| escape.cpp:188:32:188:41 | CopyValue | passByRef2+0:0 | passByRef2+0:0 | | escape.cpp:191:30:191:42 | Call | none | passByPtr3+0:0 | +| escape.cpp:191:44:191:54 | CopyValue | passByPtr3+0:0 | passByPtr3+0:0 | | escape.cpp:194:32:194:46 | Call | none | passByRef3+0:0 | +| escape.cpp:194:32:194:59 | CopyValue | none | passByRef3+0:0 | +| escape.cpp:194:48:194:57 | CopyValue | passByRef3+0:0 | passByRef3+0:0 | +| escape.cpp:199:17:199:34 | CopyValue | no_ssa_passByPtr4+0:0 | no_ssa_passByPtr4+0:0 | +| escape.cpp:199:37:199:54 | CopyValue | no_ssa_passByPtr5+0:0 | no_ssa_passByPtr5+0:0 | | escape.cpp:202:5:202:19 | Call | none | passByRef6+0:0 | +| escape.cpp:202:5:202:32 | CopyValue | none | passByRef6+0:0 | +| escape.cpp:202:21:202:30 | CopyValue | passByRef6+0:0 | passByRef6+0:0 | | escape.cpp:205:5:205:19 | Call | none | no_ssa_passByRef7+0:0 | +| escape.cpp:205:5:205:39 | CopyValue | none | no_ssa_passByRef7+0:0 | +| escape.cpp:205:21:205:37 | CopyValue | no_ssa_passByRef7+0:0 | no_ssa_passByRef7+0:0 | | escape.cpp:209:14:209:25 | Call | none | no_ssa_c+0:0 | +| escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 | | escape.cpp:221:8:221:19 | Call | none | c3+0:0 | | escape.cpp:225:17:225:28 | Call | none | c4+0:0 | +| escape.cpp:247:2:247:27 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 | +| escape.cpp:249:9:249:34 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | +| escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 | diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 20f15e4f7723..788e4a726636 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -40,13 +40,14 @@ bad_asts.cpp: # 27| r0_5(glval) = VariableAddress[b] : # 27| r0_6(glval) = VariableAddress[a] : # 27| r0_7(Point &) = Load : &:r0_6, ~mu0_2 -# 27| r0_8(glval) = Convert : r0_7 -# 27| r0_9(Point) = Load : &:r0_8, ~mu0_2 -# 27| mu0_10(Point) = Store : &:r0_5, r0_9 -# 28| v0_11(void) = NoOp : -# 26| v0_12(void) = ReturnVoid : -# 26| v0_13(void) = UnmodeledUse : mu* -# 26| v0_14(void) = ExitFunction : +# 27| r0_8(glval) = CopyValue : r0_7 +# 27| r0_9(glval) = Convert : r0_8 +# 27| r0_10(Point) = Load : &:r0_9, ~mu0_2 +# 27| mu0_11(Point) = Store : &:r0_5, r0_10 +# 28| v0_12(void) = NoOp : +# 26| v0_13(void) = ReturnVoid : +# 26| v0_14(void) = UnmodeledUse : mu* +# 26| v0_15(void) = ExitFunction : # 30| void Bad::errorExpr() # 30| Block 0 @@ -63,10 +64,11 @@ bad_asts.cpp: #-----| r0_10(error) = Load : &:r0_9, ~mu0_2 # 33| r0_11(glval) = VariableAddress[x] : # 33| mu0_12(int) = Store : &:r0_11, r0_10 -# 34| v0_13(void) = NoOp : -# 30| v0_14(void) = ReturnVoid : -# 30| v0_15(void) = UnmodeledUse : mu* -# 30| v0_16(void) = ExitFunction : +# 33| r0_13(glval) = CopyValue : r0_11 +# 34| v0_14(void) = NoOp : +# 30| v0_15(void) = ReturnVoid : +# 30| v0_16(void) = UnmodeledUse : mu* +# 30| v0_17(void) = ExitFunction : clang.cpp: # 5| int* globalIntAddress() @@ -76,11 +78,12 @@ clang.cpp: # 5| mu0_2(unknown) = UnmodeledDefinition : # 6| r0_3(glval) = VariableAddress[#return] : # 6| r0_4(glval) = VariableAddress[globalInt] : -# 6| mu0_5(int *) = Store : &:r0_3, r0_4 -# 5| r0_6(glval) = VariableAddress[#return] : -# 5| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 5| v0_8(void) = UnmodeledUse : mu* -# 5| v0_9(void) = ExitFunction : +# 6| r0_5(int *) = CopyValue : r0_4 +# 6| mu0_6(int *) = Store : &:r0_3, r0_5 +# 5| r0_7(glval) = VariableAddress[#return] : +# 5| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 5| v0_9(void) = UnmodeledUse : mu* +# 5| v0_10(void) = ExitFunction : ir.cpp: # 1| void Constants() @@ -197,18 +200,20 @@ ir.cpp: # 46| r0_15(short) = Convert : r0_14 # 46| r0_16(glval) = VariableAddress[y] : # 46| mu0_17(short) = Store : &:r0_16, r0_15 -# 47| r0_18(glval) = VariableAddress[x] : -# 47| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 47| r0_20(glval) = VariableAddress[y] : -# 47| r0_21(short) = Load : &:r0_20, ~mu0_2 -# 47| r0_22(int) = Convert : r0_21 -# 47| r0_23(int) = Mul : r0_19, r0_22 -# 47| r0_24(glval) = VariableAddress[x] : -# 47| mu0_25(int) = Store : &:r0_24, r0_23 -# 48| v0_26(void) = NoOp : -# 43| v0_27(void) = ReturnVoid : -# 43| v0_28(void) = UnmodeledUse : mu* -# 43| v0_29(void) = ExitFunction : +# 46| r0_18(glval) = CopyValue : r0_16 +# 47| r0_19(glval) = VariableAddress[x] : +# 47| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 47| r0_21(glval) = VariableAddress[y] : +# 47| r0_22(short) = Load : &:r0_21, ~mu0_2 +# 47| r0_23(int) = Convert : r0_22 +# 47| r0_24(int) = Mul : r0_20, r0_23 +# 47| r0_25(glval) = VariableAddress[x] : +# 47| mu0_26(int) = Store : &:r0_25, r0_24 +# 47| r0_27(glval) = CopyValue : r0_25 +# 48| v0_28(void) = NoOp : +# 43| v0_29(void) = ReturnVoid : +# 43| v0_30(void) = UnmodeledUse : mu* +# 43| v0_31(void) = ExitFunction : # 50| void IntegerOps(int, int) # 50| Block 0 @@ -228,160 +233,185 @@ ir.cpp: # 53| r0_13(int) = Add : r0_10, r0_12 # 53| r0_14(glval) = VariableAddress[z] : # 53| mu0_15(int) = Store : &:r0_14, r0_13 -# 54| r0_16(glval) = VariableAddress[x] : -# 54| r0_17(int) = Load : &:r0_16, ~mu0_2 -# 54| r0_18(glval) = VariableAddress[y] : -# 54| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 54| r0_20(int) = Sub : r0_17, r0_19 -# 54| r0_21(glval) = VariableAddress[z] : -# 54| mu0_22(int) = Store : &:r0_21, r0_20 -# 55| r0_23(glval) = VariableAddress[x] : -# 55| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 55| r0_25(glval) = VariableAddress[y] : +# 53| r0_16(glval) = CopyValue : r0_14 +# 54| r0_17(glval) = VariableAddress[x] : +# 54| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 54| r0_19(glval) = VariableAddress[y] : +# 54| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 54| r0_21(int) = Sub : r0_18, r0_20 +# 54| r0_22(glval) = VariableAddress[z] : +# 54| mu0_23(int) = Store : &:r0_22, r0_21 +# 54| r0_24(glval) = CopyValue : r0_22 +# 55| r0_25(glval) = VariableAddress[x] : # 55| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 55| r0_27(int) = Mul : r0_24, r0_26 -# 55| r0_28(glval) = VariableAddress[z] : -# 55| mu0_29(int) = Store : &:r0_28, r0_27 -# 56| r0_30(glval) = VariableAddress[x] : -# 56| r0_31(int) = Load : &:r0_30, ~mu0_2 -# 56| r0_32(glval) = VariableAddress[y] : -# 56| r0_33(int) = Load : &:r0_32, ~mu0_2 -# 56| r0_34(int) = Div : r0_31, r0_33 -# 56| r0_35(glval) = VariableAddress[z] : -# 56| mu0_36(int) = Store : &:r0_35, r0_34 -# 57| r0_37(glval) = VariableAddress[x] : -# 57| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 57| r0_39(glval) = VariableAddress[y] : -# 57| r0_40(int) = Load : &:r0_39, ~mu0_2 -# 57| r0_41(int) = Rem : r0_38, r0_40 -# 57| r0_42(glval) = VariableAddress[z] : -# 57| mu0_43(int) = Store : &:r0_42, r0_41 -# 59| r0_44(glval) = VariableAddress[x] : -# 59| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 59| r0_46(glval) = VariableAddress[y] : -# 59| r0_47(int) = Load : &:r0_46, ~mu0_2 -# 59| r0_48(int) = BitAnd : r0_45, r0_47 -# 59| r0_49(glval) = VariableAddress[z] : -# 59| mu0_50(int) = Store : &:r0_49, r0_48 -# 60| r0_51(glval) = VariableAddress[x] : -# 60| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 60| r0_53(glval) = VariableAddress[y] : -# 60| r0_54(int) = Load : &:r0_53, ~mu0_2 -# 60| r0_55(int) = BitOr : r0_52, r0_54 -# 60| r0_56(glval) = VariableAddress[z] : -# 60| mu0_57(int) = Store : &:r0_56, r0_55 -# 61| r0_58(glval) = VariableAddress[x] : -# 61| r0_59(int) = Load : &:r0_58, ~mu0_2 -# 61| r0_60(glval) = VariableAddress[y] : -# 61| r0_61(int) = Load : &:r0_60, ~mu0_2 -# 61| r0_62(int) = BitXor : r0_59, r0_61 -# 61| r0_63(glval) = VariableAddress[z] : -# 61| mu0_64(int) = Store : &:r0_63, r0_62 -# 63| r0_65(glval) = VariableAddress[x] : -# 63| r0_66(int) = Load : &:r0_65, ~mu0_2 -# 63| r0_67(glval) = VariableAddress[y] : -# 63| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 63| r0_69(int) = ShiftLeft : r0_66, r0_68 -# 63| r0_70(glval) = VariableAddress[z] : -# 63| mu0_71(int) = Store : &:r0_70, r0_69 -# 64| r0_72(glval) = VariableAddress[x] : -# 64| r0_73(int) = Load : &:r0_72, ~mu0_2 -# 64| r0_74(glval) = VariableAddress[y] : -# 64| r0_75(int) = Load : &:r0_74, ~mu0_2 -# 64| r0_76(int) = ShiftRight : r0_73, r0_75 -# 64| r0_77(glval) = VariableAddress[z] : -# 64| mu0_78(int) = Store : &:r0_77, r0_76 -# 66| r0_79(glval) = VariableAddress[x] : -# 66| r0_80(int) = Load : &:r0_79, ~mu0_2 -# 66| r0_81(glval) = VariableAddress[z] : -# 66| mu0_82(int) = Store : &:r0_81, r0_80 -# 68| r0_83(glval) = VariableAddress[x] : -# 68| r0_84(int) = Load : &:r0_83, ~mu0_2 -# 68| r0_85(glval) = VariableAddress[z] : -# 68| r0_86(int) = Load : &:r0_85, ~mu0_2 -# 68| r0_87(int) = Add : r0_86, r0_84 -# 68| mu0_88(int) = Store : &:r0_85, r0_87 -# 69| r0_89(glval) = VariableAddress[x] : -# 69| r0_90(int) = Load : &:r0_89, ~mu0_2 -# 69| r0_91(glval) = VariableAddress[z] : -# 69| r0_92(int) = Load : &:r0_91, ~mu0_2 -# 69| r0_93(int) = Sub : r0_92, r0_90 -# 69| mu0_94(int) = Store : &:r0_91, r0_93 -# 70| r0_95(glval) = VariableAddress[x] : -# 70| r0_96(int) = Load : &:r0_95, ~mu0_2 -# 70| r0_97(glval) = VariableAddress[z] : -# 70| r0_98(int) = Load : &:r0_97, ~mu0_2 -# 70| r0_99(int) = Mul : r0_98, r0_96 -# 70| mu0_100(int) = Store : &:r0_97, r0_99 -# 71| r0_101(glval) = VariableAddress[x] : -# 71| r0_102(int) = Load : &:r0_101, ~mu0_2 -# 71| r0_103(glval) = VariableAddress[z] : -# 71| r0_104(int) = Load : &:r0_103, ~mu0_2 -# 71| r0_105(int) = Div : r0_104, r0_102 -# 71| mu0_106(int) = Store : &:r0_103, r0_105 -# 72| r0_107(glval) = VariableAddress[x] : -# 72| r0_108(int) = Load : &:r0_107, ~mu0_2 -# 72| r0_109(glval) = VariableAddress[z] : -# 72| r0_110(int) = Load : &:r0_109, ~mu0_2 -# 72| r0_111(int) = Rem : r0_110, r0_108 -# 72| mu0_112(int) = Store : &:r0_109, r0_111 -# 74| r0_113(glval) = VariableAddress[x] : -# 74| r0_114(int) = Load : &:r0_113, ~mu0_2 -# 74| r0_115(glval) = VariableAddress[z] : -# 74| r0_116(int) = Load : &:r0_115, ~mu0_2 -# 74| r0_117(int) = BitAnd : r0_116, r0_114 -# 74| mu0_118(int) = Store : &:r0_115, r0_117 -# 75| r0_119(glval) = VariableAddress[x] : -# 75| r0_120(int) = Load : &:r0_119, ~mu0_2 -# 75| r0_121(glval) = VariableAddress[z] : -# 75| r0_122(int) = Load : &:r0_121, ~mu0_2 -# 75| r0_123(int) = BitOr : r0_122, r0_120 -# 75| mu0_124(int) = Store : &:r0_121, r0_123 -# 76| r0_125(glval) = VariableAddress[x] : -# 76| r0_126(int) = Load : &:r0_125, ~mu0_2 -# 76| r0_127(glval) = VariableAddress[z] : -# 76| r0_128(int) = Load : &:r0_127, ~mu0_2 -# 76| r0_129(int) = BitXor : r0_128, r0_126 -# 76| mu0_130(int) = Store : &:r0_127, r0_129 -# 78| r0_131(glval) = VariableAddress[x] : -# 78| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 78| r0_133(glval) = VariableAddress[z] : -# 78| r0_134(int) = Load : &:r0_133, ~mu0_2 -# 78| r0_135(int) = ShiftLeft : r0_134, r0_132 -# 78| mu0_136(int) = Store : &:r0_133, r0_135 -# 79| r0_137(glval) = VariableAddress[x] : -# 79| r0_138(int) = Load : &:r0_137, ~mu0_2 -# 79| r0_139(glval) = VariableAddress[z] : -# 79| r0_140(int) = Load : &:r0_139, ~mu0_2 -# 79| r0_141(int) = ShiftRight : r0_140, r0_138 -# 79| mu0_142(int) = Store : &:r0_139, r0_141 -# 81| r0_143(glval) = VariableAddress[x] : -# 81| r0_144(int) = Load : &:r0_143, ~mu0_2 -# 81| r0_145(int) = CopyValue : r0_144 -# 81| r0_146(glval) = VariableAddress[z] : -# 81| mu0_147(int) = Store : &:r0_146, r0_145 -# 82| r0_148(glval) = VariableAddress[x] : -# 82| r0_149(int) = Load : &:r0_148, ~mu0_2 -# 82| r0_150(int) = Negate : r0_149 -# 82| r0_151(glval) = VariableAddress[z] : -# 82| mu0_152(int) = Store : &:r0_151, r0_150 -# 83| r0_153(glval) = VariableAddress[x] : -# 83| r0_154(int) = Load : &:r0_153, ~mu0_2 -# 83| r0_155(int) = BitComplement : r0_154 -# 83| r0_156(glval) = VariableAddress[z] : -# 83| mu0_157(int) = Store : &:r0_156, r0_155 -# 84| r0_158(glval) = VariableAddress[x] : -# 84| r0_159(int) = Load : &:r0_158, ~mu0_2 -# 84| r0_160(int) = Constant[0] : -# 84| r0_161(bool) = CompareNE : r0_159, r0_160 -# 84| r0_162(bool) = LogicalNot : r0_161 -# 84| r0_163(int) = Convert : r0_162 -# 84| r0_164(glval) = VariableAddress[z] : -# 84| mu0_165(int) = Store : &:r0_164, r0_163 -# 85| v0_166(void) = NoOp : -# 50| v0_167(void) = ReturnVoid : -# 50| v0_168(void) = UnmodeledUse : mu* -# 50| v0_169(void) = ExitFunction : +# 55| r0_27(glval) = VariableAddress[y] : +# 55| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 55| r0_29(int) = Mul : r0_26, r0_28 +# 55| r0_30(glval) = VariableAddress[z] : +# 55| mu0_31(int) = Store : &:r0_30, r0_29 +# 55| r0_32(glval) = CopyValue : r0_30 +# 56| r0_33(glval) = VariableAddress[x] : +# 56| r0_34(int) = Load : &:r0_33, ~mu0_2 +# 56| r0_35(glval) = VariableAddress[y] : +# 56| r0_36(int) = Load : &:r0_35, ~mu0_2 +# 56| r0_37(int) = Div : r0_34, r0_36 +# 56| r0_38(glval) = VariableAddress[z] : +# 56| mu0_39(int) = Store : &:r0_38, r0_37 +# 56| r0_40(glval) = CopyValue : r0_38 +# 57| r0_41(glval) = VariableAddress[x] : +# 57| r0_42(int) = Load : &:r0_41, ~mu0_2 +# 57| r0_43(glval) = VariableAddress[y] : +# 57| r0_44(int) = Load : &:r0_43, ~mu0_2 +# 57| r0_45(int) = Rem : r0_42, r0_44 +# 57| r0_46(glval) = VariableAddress[z] : +# 57| mu0_47(int) = Store : &:r0_46, r0_45 +# 57| r0_48(glval) = CopyValue : r0_46 +# 59| r0_49(glval) = VariableAddress[x] : +# 59| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 59| r0_51(glval) = VariableAddress[y] : +# 59| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 59| r0_53(int) = BitAnd : r0_50, r0_52 +# 59| r0_54(glval) = VariableAddress[z] : +# 59| mu0_55(int) = Store : &:r0_54, r0_53 +# 59| r0_56(glval) = CopyValue : r0_54 +# 60| r0_57(glval) = VariableAddress[x] : +# 60| r0_58(int) = Load : &:r0_57, ~mu0_2 +# 60| r0_59(glval) = VariableAddress[y] : +# 60| r0_60(int) = Load : &:r0_59, ~mu0_2 +# 60| r0_61(int) = BitOr : r0_58, r0_60 +# 60| r0_62(glval) = VariableAddress[z] : +# 60| mu0_63(int) = Store : &:r0_62, r0_61 +# 60| r0_64(glval) = CopyValue : r0_62 +# 61| r0_65(glval) = VariableAddress[x] : +# 61| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 61| r0_67(glval) = VariableAddress[y] : +# 61| r0_68(int) = Load : &:r0_67, ~mu0_2 +# 61| r0_69(int) = BitXor : r0_66, r0_68 +# 61| r0_70(glval) = VariableAddress[z] : +# 61| mu0_71(int) = Store : &:r0_70, r0_69 +# 61| r0_72(glval) = CopyValue : r0_70 +# 63| r0_73(glval) = VariableAddress[x] : +# 63| r0_74(int) = Load : &:r0_73, ~mu0_2 +# 63| r0_75(glval) = VariableAddress[y] : +# 63| r0_76(int) = Load : &:r0_75, ~mu0_2 +# 63| r0_77(int) = ShiftLeft : r0_74, r0_76 +# 63| r0_78(glval) = VariableAddress[z] : +# 63| mu0_79(int) = Store : &:r0_78, r0_77 +# 63| r0_80(glval) = CopyValue : r0_78 +# 64| r0_81(glval) = VariableAddress[x] : +# 64| r0_82(int) = Load : &:r0_81, ~mu0_2 +# 64| r0_83(glval) = VariableAddress[y] : +# 64| r0_84(int) = Load : &:r0_83, ~mu0_2 +# 64| r0_85(int) = ShiftRight : r0_82, r0_84 +# 64| r0_86(glval) = VariableAddress[z] : +# 64| mu0_87(int) = Store : &:r0_86, r0_85 +# 64| r0_88(glval) = CopyValue : r0_86 +# 66| r0_89(glval) = VariableAddress[x] : +# 66| r0_90(int) = Load : &:r0_89, ~mu0_2 +# 66| r0_91(glval) = VariableAddress[z] : +# 66| mu0_92(int) = Store : &:r0_91, r0_90 +# 66| r0_93(glval) = CopyValue : r0_91 +# 68| r0_94(glval) = VariableAddress[x] : +# 68| r0_95(int) = Load : &:r0_94, ~mu0_2 +# 68| r0_96(glval) = VariableAddress[z] : +# 68| r0_97(int) = Load : &:r0_96, ~mu0_2 +# 68| r0_98(int) = Add : r0_97, r0_95 +# 68| mu0_99(int) = Store : &:r0_96, r0_98 +# 68| r0_100(glval) = CopyValue : r0_96 +# 69| r0_101(glval) = VariableAddress[x] : +# 69| r0_102(int) = Load : &:r0_101, ~mu0_2 +# 69| r0_103(glval) = VariableAddress[z] : +# 69| r0_104(int) = Load : &:r0_103, ~mu0_2 +# 69| r0_105(int) = Sub : r0_104, r0_102 +# 69| mu0_106(int) = Store : &:r0_103, r0_105 +# 69| r0_107(glval) = CopyValue : r0_103 +# 70| r0_108(glval) = VariableAddress[x] : +# 70| r0_109(int) = Load : &:r0_108, ~mu0_2 +# 70| r0_110(glval) = VariableAddress[z] : +# 70| r0_111(int) = Load : &:r0_110, ~mu0_2 +# 70| r0_112(int) = Mul : r0_111, r0_109 +# 70| mu0_113(int) = Store : &:r0_110, r0_112 +# 70| r0_114(glval) = CopyValue : r0_110 +# 71| r0_115(glval) = VariableAddress[x] : +# 71| r0_116(int) = Load : &:r0_115, ~mu0_2 +# 71| r0_117(glval) = VariableAddress[z] : +# 71| r0_118(int) = Load : &:r0_117, ~mu0_2 +# 71| r0_119(int) = Div : r0_118, r0_116 +# 71| mu0_120(int) = Store : &:r0_117, r0_119 +# 71| r0_121(glval) = CopyValue : r0_117 +# 72| r0_122(glval) = VariableAddress[x] : +# 72| r0_123(int) = Load : &:r0_122, ~mu0_2 +# 72| r0_124(glval) = VariableAddress[z] : +# 72| r0_125(int) = Load : &:r0_124, ~mu0_2 +# 72| r0_126(int) = Rem : r0_125, r0_123 +# 72| mu0_127(int) = Store : &:r0_124, r0_126 +# 72| r0_128(glval) = CopyValue : r0_124 +# 74| r0_129(glval) = VariableAddress[x] : +# 74| r0_130(int) = Load : &:r0_129, ~mu0_2 +# 74| r0_131(glval) = VariableAddress[z] : +# 74| r0_132(int) = Load : &:r0_131, ~mu0_2 +# 74| r0_133(int) = BitAnd : r0_132, r0_130 +# 74| mu0_134(int) = Store : &:r0_131, r0_133 +# 74| r0_135(glval) = CopyValue : r0_131 +# 75| r0_136(glval) = VariableAddress[x] : +# 75| r0_137(int) = Load : &:r0_136, ~mu0_2 +# 75| r0_138(glval) = VariableAddress[z] : +# 75| r0_139(int) = Load : &:r0_138, ~mu0_2 +# 75| r0_140(int) = BitOr : r0_139, r0_137 +# 75| mu0_141(int) = Store : &:r0_138, r0_140 +# 75| r0_142(glval) = CopyValue : r0_138 +# 76| r0_143(glval) = VariableAddress[x] : +# 76| r0_144(int) = Load : &:r0_143, ~mu0_2 +# 76| r0_145(glval) = VariableAddress[z] : +# 76| r0_146(int) = Load : &:r0_145, ~mu0_2 +# 76| r0_147(int) = BitXor : r0_146, r0_144 +# 76| mu0_148(int) = Store : &:r0_145, r0_147 +# 76| r0_149(glval) = CopyValue : r0_145 +# 78| r0_150(glval) = VariableAddress[x] : +# 78| r0_151(int) = Load : &:r0_150, ~mu0_2 +# 78| r0_152(glval) = VariableAddress[z] : +# 78| r0_153(int) = Load : &:r0_152, ~mu0_2 +# 78| r0_154(int) = ShiftLeft : r0_153, r0_151 +# 78| mu0_155(int) = Store : &:r0_152, r0_154 +# 78| r0_156(glval) = CopyValue : r0_152 +# 79| r0_157(glval) = VariableAddress[x] : +# 79| r0_158(int) = Load : &:r0_157, ~mu0_2 +# 79| r0_159(glval) = VariableAddress[z] : +# 79| r0_160(int) = Load : &:r0_159, ~mu0_2 +# 79| r0_161(int) = ShiftRight : r0_160, r0_158 +# 79| mu0_162(int) = Store : &:r0_159, r0_161 +# 79| r0_163(glval) = CopyValue : r0_159 +# 81| r0_164(glval) = VariableAddress[x] : +# 81| r0_165(int) = Load : &:r0_164, ~mu0_2 +# 81| r0_166(int) = CopyValue : r0_165 +# 81| r0_167(glval) = VariableAddress[z] : +# 81| mu0_168(int) = Store : &:r0_167, r0_166 +# 81| r0_169(glval) = CopyValue : r0_167 +# 82| r0_170(glval) = VariableAddress[x] : +# 82| r0_171(int) = Load : &:r0_170, ~mu0_2 +# 82| r0_172(int) = Negate : r0_171 +# 82| r0_173(glval) = VariableAddress[z] : +# 82| mu0_174(int) = Store : &:r0_173, r0_172 +# 82| r0_175(glval) = CopyValue : r0_173 +# 83| r0_176(glval) = VariableAddress[x] : +# 83| r0_177(int) = Load : &:r0_176, ~mu0_2 +# 83| r0_178(int) = BitComplement : r0_177 +# 83| r0_179(glval) = VariableAddress[z] : +# 83| mu0_180(int) = Store : &:r0_179, r0_178 +# 83| r0_181(glval) = CopyValue : r0_179 +# 84| r0_182(glval) = VariableAddress[x] : +# 84| r0_183(int) = Load : &:r0_182, ~mu0_2 +# 84| r0_184(int) = Constant[0] : +# 84| r0_185(bool) = CompareNE : r0_183, r0_184 +# 84| r0_186(bool) = LogicalNot : r0_185 +# 84| r0_187(int) = Convert : r0_186 +# 84| r0_188(glval) = VariableAddress[z] : +# 84| mu0_189(int) = Store : &:r0_188, r0_187 +# 84| r0_190(glval) = CopyValue : r0_188 +# 85| v0_191(void) = NoOp : +# 50| v0_192(void) = ReturnVoid : +# 50| v0_193(void) = UnmodeledUse : mu* +# 50| v0_194(void) = ExitFunction : # 87| void IntegerCompare(int, int) # 87| Block 0 @@ -401,45 +431,51 @@ ir.cpp: # 90| r0_13(bool) = CompareEQ : r0_10, r0_12 # 90| r0_14(glval) = VariableAddress[b] : # 90| mu0_15(bool) = Store : &:r0_14, r0_13 -# 91| r0_16(glval) = VariableAddress[x] : -# 91| r0_17(int) = Load : &:r0_16, ~mu0_2 -# 91| r0_18(glval) = VariableAddress[y] : -# 91| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 91| r0_20(bool) = CompareNE : r0_17, r0_19 -# 91| r0_21(glval) = VariableAddress[b] : -# 91| mu0_22(bool) = Store : &:r0_21, r0_20 -# 92| r0_23(glval) = VariableAddress[x] : -# 92| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 92| r0_25(glval) = VariableAddress[y] : +# 90| r0_16(glval) = CopyValue : r0_14 +# 91| r0_17(glval) = VariableAddress[x] : +# 91| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 91| r0_19(glval) = VariableAddress[y] : +# 91| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 91| r0_21(bool) = CompareNE : r0_18, r0_20 +# 91| r0_22(glval) = VariableAddress[b] : +# 91| mu0_23(bool) = Store : &:r0_22, r0_21 +# 91| r0_24(glval) = CopyValue : r0_22 +# 92| r0_25(glval) = VariableAddress[x] : # 92| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 92| r0_27(bool) = CompareLT : r0_24, r0_26 -# 92| r0_28(glval) = VariableAddress[b] : -# 92| mu0_29(bool) = Store : &:r0_28, r0_27 -# 93| r0_30(glval) = VariableAddress[x] : -# 93| r0_31(int) = Load : &:r0_30, ~mu0_2 -# 93| r0_32(glval) = VariableAddress[y] : -# 93| r0_33(int) = Load : &:r0_32, ~mu0_2 -# 93| r0_34(bool) = CompareGT : r0_31, r0_33 -# 93| r0_35(glval) = VariableAddress[b] : -# 93| mu0_36(bool) = Store : &:r0_35, r0_34 -# 94| r0_37(glval) = VariableAddress[x] : -# 94| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 94| r0_39(glval) = VariableAddress[y] : -# 94| r0_40(int) = Load : &:r0_39, ~mu0_2 -# 94| r0_41(bool) = CompareLE : r0_38, r0_40 -# 94| r0_42(glval) = VariableAddress[b] : -# 94| mu0_43(bool) = Store : &:r0_42, r0_41 -# 95| r0_44(glval) = VariableAddress[x] : -# 95| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 95| r0_46(glval) = VariableAddress[y] : -# 95| r0_47(int) = Load : &:r0_46, ~mu0_2 -# 95| r0_48(bool) = CompareGE : r0_45, r0_47 -# 95| r0_49(glval) = VariableAddress[b] : -# 95| mu0_50(bool) = Store : &:r0_49, r0_48 -# 96| v0_51(void) = NoOp : -# 87| v0_52(void) = ReturnVoid : -# 87| v0_53(void) = UnmodeledUse : mu* -# 87| v0_54(void) = ExitFunction : +# 92| r0_27(glval) = VariableAddress[y] : +# 92| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 92| r0_29(bool) = CompareLT : r0_26, r0_28 +# 92| r0_30(glval) = VariableAddress[b] : +# 92| mu0_31(bool) = Store : &:r0_30, r0_29 +# 92| r0_32(glval) = CopyValue : r0_30 +# 93| r0_33(glval) = VariableAddress[x] : +# 93| r0_34(int) = Load : &:r0_33, ~mu0_2 +# 93| r0_35(glval) = VariableAddress[y] : +# 93| r0_36(int) = Load : &:r0_35, ~mu0_2 +# 93| r0_37(bool) = CompareGT : r0_34, r0_36 +# 93| r0_38(glval) = VariableAddress[b] : +# 93| mu0_39(bool) = Store : &:r0_38, r0_37 +# 93| r0_40(glval) = CopyValue : r0_38 +# 94| r0_41(glval) = VariableAddress[x] : +# 94| r0_42(int) = Load : &:r0_41, ~mu0_2 +# 94| r0_43(glval) = VariableAddress[y] : +# 94| r0_44(int) = Load : &:r0_43, ~mu0_2 +# 94| r0_45(bool) = CompareLE : r0_42, r0_44 +# 94| r0_46(glval) = VariableAddress[b] : +# 94| mu0_47(bool) = Store : &:r0_46, r0_45 +# 94| r0_48(glval) = CopyValue : r0_46 +# 95| r0_49(glval) = VariableAddress[x] : +# 95| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 95| r0_51(glval) = VariableAddress[y] : +# 95| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 95| r0_53(bool) = CompareGE : r0_50, r0_52 +# 95| r0_54(glval) = VariableAddress[b] : +# 95| mu0_55(bool) = Store : &:r0_54, r0_53 +# 95| r0_56(glval) = CopyValue : r0_54 +# 96| v0_57(void) = NoOp : +# 87| v0_58(void) = ReturnVoid : +# 87| v0_59(void) = UnmodeledUse : mu* +# 87| v0_60(void) = ExitFunction : # 98| void IntegerCrement(int) # 98| Block 0 @@ -457,31 +493,35 @@ ir.cpp: # 101| mu0_11(int) = Store : &:r0_7, r0_10 # 101| r0_12(glval) = VariableAddress[y] : # 101| mu0_13(int) = Store : &:r0_12, r0_10 -# 102| r0_14(glval) = VariableAddress[x] : -# 102| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 102| r0_16(int) = Constant[1] : -# 102| r0_17(int) = Sub : r0_15, r0_16 -# 102| mu0_18(int) = Store : &:r0_14, r0_17 -# 102| r0_19(glval) = VariableAddress[y] : -# 102| mu0_20(int) = Store : &:r0_19, r0_17 -# 103| r0_21(glval) = VariableAddress[x] : -# 103| r0_22(int) = Load : &:r0_21, ~mu0_2 -# 103| r0_23(int) = Constant[1] : -# 103| r0_24(int) = Add : r0_22, r0_23 -# 103| mu0_25(int) = Store : &:r0_21, r0_24 -# 103| r0_26(glval) = VariableAddress[y] : -# 103| mu0_27(int) = Store : &:r0_26, r0_22 -# 104| r0_28(glval) = VariableAddress[x] : -# 104| r0_29(int) = Load : &:r0_28, ~mu0_2 -# 104| r0_30(int) = Constant[1] : -# 104| r0_31(int) = Sub : r0_29, r0_30 -# 104| mu0_32(int) = Store : &:r0_28, r0_31 -# 104| r0_33(glval) = VariableAddress[y] : -# 104| mu0_34(int) = Store : &:r0_33, r0_29 -# 105| v0_35(void) = NoOp : -# 98| v0_36(void) = ReturnVoid : -# 98| v0_37(void) = UnmodeledUse : mu* -# 98| v0_38(void) = ExitFunction : +# 101| r0_14(glval) = CopyValue : r0_12 +# 102| r0_15(glval) = VariableAddress[x] : +# 102| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 102| r0_17(int) = Constant[1] : +# 102| r0_18(int) = Sub : r0_16, r0_17 +# 102| mu0_19(int) = Store : &:r0_15, r0_18 +# 102| r0_20(glval) = VariableAddress[y] : +# 102| mu0_21(int) = Store : &:r0_20, r0_18 +# 102| r0_22(glval) = CopyValue : r0_20 +# 103| r0_23(glval) = VariableAddress[x] : +# 103| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 103| r0_25(int) = Constant[1] : +# 103| r0_26(int) = Add : r0_24, r0_25 +# 103| mu0_27(int) = Store : &:r0_23, r0_26 +# 103| r0_28(glval) = VariableAddress[y] : +# 103| mu0_29(int) = Store : &:r0_28, r0_24 +# 103| r0_30(glval) = CopyValue : r0_28 +# 104| r0_31(glval) = VariableAddress[x] : +# 104| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 104| r0_33(int) = Constant[1] : +# 104| r0_34(int) = Sub : r0_32, r0_33 +# 104| mu0_35(int) = Store : &:r0_31, r0_34 +# 104| r0_36(glval) = VariableAddress[y] : +# 104| mu0_37(int) = Store : &:r0_36, r0_32 +# 104| r0_38(glval) = CopyValue : r0_36 +# 105| v0_39(void) = NoOp : +# 98| v0_40(void) = ReturnVoid : +# 98| v0_41(void) = UnmodeledUse : mu* +# 98| v0_42(void) = ExitFunction : # 107| void IntegerCrement_LValue(int) # 107| Block 0 @@ -497,19 +537,25 @@ ir.cpp: # 110| r0_9(int) = Constant[1] : # 110| r0_10(int) = Add : r0_8, r0_9 # 110| mu0_11(int) = Store : &:r0_7, r0_10 -# 110| r0_12(glval) = VariableAddress[p] : -# 110| mu0_13(int *) = Store : &:r0_12, r0_7 -# 111| r0_14(glval) = VariableAddress[x] : -# 111| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 111| r0_16(int) = Constant[1] : -# 111| r0_17(int) = Sub : r0_15, r0_16 -# 111| mu0_18(int) = Store : &:r0_14, r0_17 -# 111| r0_19(glval) = VariableAddress[p] : -# 111| mu0_20(int *) = Store : &:r0_19, r0_14 -# 112| v0_21(void) = NoOp : -# 107| v0_22(void) = ReturnVoid : -# 107| v0_23(void) = UnmodeledUse : mu* -# 107| v0_24(void) = ExitFunction : +# 110| r0_12(glval) = CopyValue : r0_7 +# 110| r0_13(int *) = CopyValue : r0_12 +# 110| r0_14(glval) = VariableAddress[p] : +# 110| mu0_15(int *) = Store : &:r0_14, r0_13 +# 110| r0_16(glval) = CopyValue : r0_14 +# 111| r0_17(glval) = VariableAddress[x] : +# 111| r0_18(int) = Load : &:r0_17, ~mu0_2 +# 111| r0_19(int) = Constant[1] : +# 111| r0_20(int) = Sub : r0_18, r0_19 +# 111| mu0_21(int) = Store : &:r0_17, r0_20 +# 111| r0_22(glval) = CopyValue : r0_17 +# 111| r0_23(int *) = CopyValue : r0_22 +# 111| r0_24(glval) = VariableAddress[p] : +# 111| mu0_25(int *) = Store : &:r0_24, r0_23 +# 111| r0_26(glval) = CopyValue : r0_24 +# 112| v0_27(void) = NoOp : +# 107| v0_28(void) = ReturnVoid : +# 107| v0_29(void) = UnmodeledUse : mu* +# 107| v0_30(void) = ExitFunction : # 114| void FloatOps(double, double) # 114| Block 0 @@ -529,69 +575,80 @@ ir.cpp: # 117| r0_13(double) = Add : r0_10, r0_12 # 117| r0_14(glval) = VariableAddress[z] : # 117| mu0_15(double) = Store : &:r0_14, r0_13 -# 118| r0_16(glval) = VariableAddress[x] : -# 118| r0_17(double) = Load : &:r0_16, ~mu0_2 -# 118| r0_18(glval) = VariableAddress[y] : -# 118| r0_19(double) = Load : &:r0_18, ~mu0_2 -# 118| r0_20(double) = Sub : r0_17, r0_19 -# 118| r0_21(glval) = VariableAddress[z] : -# 118| mu0_22(double) = Store : &:r0_21, r0_20 -# 119| r0_23(glval) = VariableAddress[x] : -# 119| r0_24(double) = Load : &:r0_23, ~mu0_2 -# 119| r0_25(glval) = VariableAddress[y] : +# 117| r0_16(glval) = CopyValue : r0_14 +# 118| r0_17(glval) = VariableAddress[x] : +# 118| r0_18(double) = Load : &:r0_17, ~mu0_2 +# 118| r0_19(glval) = VariableAddress[y] : +# 118| r0_20(double) = Load : &:r0_19, ~mu0_2 +# 118| r0_21(double) = Sub : r0_18, r0_20 +# 118| r0_22(glval) = VariableAddress[z] : +# 118| mu0_23(double) = Store : &:r0_22, r0_21 +# 118| r0_24(glval) = CopyValue : r0_22 +# 119| r0_25(glval) = VariableAddress[x] : # 119| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 119| r0_27(double) = Mul : r0_24, r0_26 -# 119| r0_28(glval) = VariableAddress[z] : -# 119| mu0_29(double) = Store : &:r0_28, r0_27 -# 120| r0_30(glval) = VariableAddress[x] : -# 120| r0_31(double) = Load : &:r0_30, ~mu0_2 -# 120| r0_32(glval) = VariableAddress[y] : -# 120| r0_33(double) = Load : &:r0_32, ~mu0_2 -# 120| r0_34(double) = Div : r0_31, r0_33 -# 120| r0_35(glval) = VariableAddress[z] : -# 120| mu0_36(double) = Store : &:r0_35, r0_34 -# 122| r0_37(glval) = VariableAddress[x] : -# 122| r0_38(double) = Load : &:r0_37, ~mu0_2 -# 122| r0_39(glval) = VariableAddress[z] : -# 122| mu0_40(double) = Store : &:r0_39, r0_38 -# 124| r0_41(glval) = VariableAddress[x] : -# 124| r0_42(double) = Load : &:r0_41, ~mu0_2 -# 124| r0_43(glval) = VariableAddress[z] : -# 124| r0_44(double) = Load : &:r0_43, ~mu0_2 -# 124| r0_45(double) = Add : r0_44, r0_42 -# 124| mu0_46(double) = Store : &:r0_43, r0_45 -# 125| r0_47(glval) = VariableAddress[x] : -# 125| r0_48(double) = Load : &:r0_47, ~mu0_2 -# 125| r0_49(glval) = VariableAddress[z] : -# 125| r0_50(double) = Load : &:r0_49, ~mu0_2 -# 125| r0_51(double) = Sub : r0_50, r0_48 -# 125| mu0_52(double) = Store : &:r0_49, r0_51 -# 126| r0_53(glval) = VariableAddress[x] : -# 126| r0_54(double) = Load : &:r0_53, ~mu0_2 -# 126| r0_55(glval) = VariableAddress[z] : -# 126| r0_56(double) = Load : &:r0_55, ~mu0_2 -# 126| r0_57(double) = Mul : r0_56, r0_54 -# 126| mu0_58(double) = Store : &:r0_55, r0_57 -# 127| r0_59(glval) = VariableAddress[x] : -# 127| r0_60(double) = Load : &:r0_59, ~mu0_2 -# 127| r0_61(glval) = VariableAddress[z] : -# 127| r0_62(double) = Load : &:r0_61, ~mu0_2 -# 127| r0_63(double) = Div : r0_62, r0_60 -# 127| mu0_64(double) = Store : &:r0_61, r0_63 -# 129| r0_65(glval) = VariableAddress[x] : -# 129| r0_66(double) = Load : &:r0_65, ~mu0_2 -# 129| r0_67(double) = CopyValue : r0_66 -# 129| r0_68(glval) = VariableAddress[z] : -# 129| mu0_69(double) = Store : &:r0_68, r0_67 -# 130| r0_70(glval) = VariableAddress[x] : -# 130| r0_71(double) = Load : &:r0_70, ~mu0_2 -# 130| r0_72(double) = Negate : r0_71 -# 130| r0_73(glval) = VariableAddress[z] : -# 130| mu0_74(double) = Store : &:r0_73, r0_72 -# 131| v0_75(void) = NoOp : -# 114| v0_76(void) = ReturnVoid : -# 114| v0_77(void) = UnmodeledUse : mu* -# 114| v0_78(void) = ExitFunction : +# 119| r0_27(glval) = VariableAddress[y] : +# 119| r0_28(double) = Load : &:r0_27, ~mu0_2 +# 119| r0_29(double) = Mul : r0_26, r0_28 +# 119| r0_30(glval) = VariableAddress[z] : +# 119| mu0_31(double) = Store : &:r0_30, r0_29 +# 119| r0_32(glval) = CopyValue : r0_30 +# 120| r0_33(glval) = VariableAddress[x] : +# 120| r0_34(double) = Load : &:r0_33, ~mu0_2 +# 120| r0_35(glval) = VariableAddress[y] : +# 120| r0_36(double) = Load : &:r0_35, ~mu0_2 +# 120| r0_37(double) = Div : r0_34, r0_36 +# 120| r0_38(glval) = VariableAddress[z] : +# 120| mu0_39(double) = Store : &:r0_38, r0_37 +# 120| r0_40(glval) = CopyValue : r0_38 +# 122| r0_41(glval) = VariableAddress[x] : +# 122| r0_42(double) = Load : &:r0_41, ~mu0_2 +# 122| r0_43(glval) = VariableAddress[z] : +# 122| mu0_44(double) = Store : &:r0_43, r0_42 +# 122| r0_45(glval) = CopyValue : r0_43 +# 124| r0_46(glval) = VariableAddress[x] : +# 124| r0_47(double) = Load : &:r0_46, ~mu0_2 +# 124| r0_48(glval) = VariableAddress[z] : +# 124| r0_49(double) = Load : &:r0_48, ~mu0_2 +# 124| r0_50(double) = Add : r0_49, r0_47 +# 124| mu0_51(double) = Store : &:r0_48, r0_50 +# 124| r0_52(glval) = CopyValue : r0_48 +# 125| r0_53(glval) = VariableAddress[x] : +# 125| r0_54(double) = Load : &:r0_53, ~mu0_2 +# 125| r0_55(glval) = VariableAddress[z] : +# 125| r0_56(double) = Load : &:r0_55, ~mu0_2 +# 125| r0_57(double) = Sub : r0_56, r0_54 +# 125| mu0_58(double) = Store : &:r0_55, r0_57 +# 125| r0_59(glval) = CopyValue : r0_55 +# 126| r0_60(glval) = VariableAddress[x] : +# 126| r0_61(double) = Load : &:r0_60, ~mu0_2 +# 126| r0_62(glval) = VariableAddress[z] : +# 126| r0_63(double) = Load : &:r0_62, ~mu0_2 +# 126| r0_64(double) = Mul : r0_63, r0_61 +# 126| mu0_65(double) = Store : &:r0_62, r0_64 +# 126| r0_66(glval) = CopyValue : r0_62 +# 127| r0_67(glval) = VariableAddress[x] : +# 127| r0_68(double) = Load : &:r0_67, ~mu0_2 +# 127| r0_69(glval) = VariableAddress[z] : +# 127| r0_70(double) = Load : &:r0_69, ~mu0_2 +# 127| r0_71(double) = Div : r0_70, r0_68 +# 127| mu0_72(double) = Store : &:r0_69, r0_71 +# 127| r0_73(glval) = CopyValue : r0_69 +# 129| r0_74(glval) = VariableAddress[x] : +# 129| r0_75(double) = Load : &:r0_74, ~mu0_2 +# 129| r0_76(double) = CopyValue : r0_75 +# 129| r0_77(glval) = VariableAddress[z] : +# 129| mu0_78(double) = Store : &:r0_77, r0_76 +# 129| r0_79(glval) = CopyValue : r0_77 +# 130| r0_80(glval) = VariableAddress[x] : +# 130| r0_81(double) = Load : &:r0_80, ~mu0_2 +# 130| r0_82(double) = Negate : r0_81 +# 130| r0_83(glval) = VariableAddress[z] : +# 130| mu0_84(double) = Store : &:r0_83, r0_82 +# 130| r0_85(glval) = CopyValue : r0_83 +# 131| v0_86(void) = NoOp : +# 114| v0_87(void) = ReturnVoid : +# 114| v0_88(void) = UnmodeledUse : mu* +# 114| v0_89(void) = ExitFunction : # 133| void FloatCompare(double, double) # 133| Block 0 @@ -611,45 +668,51 @@ ir.cpp: # 136| r0_13(bool) = CompareEQ : r0_10, r0_12 # 136| r0_14(glval) = VariableAddress[b] : # 136| mu0_15(bool) = Store : &:r0_14, r0_13 -# 137| r0_16(glval) = VariableAddress[x] : -# 137| r0_17(double) = Load : &:r0_16, ~mu0_2 -# 137| r0_18(glval) = VariableAddress[y] : -# 137| r0_19(double) = Load : &:r0_18, ~mu0_2 -# 137| r0_20(bool) = CompareNE : r0_17, r0_19 -# 137| r0_21(glval) = VariableAddress[b] : -# 137| mu0_22(bool) = Store : &:r0_21, r0_20 -# 138| r0_23(glval) = VariableAddress[x] : -# 138| r0_24(double) = Load : &:r0_23, ~mu0_2 -# 138| r0_25(glval) = VariableAddress[y] : +# 136| r0_16(glval) = CopyValue : r0_14 +# 137| r0_17(glval) = VariableAddress[x] : +# 137| r0_18(double) = Load : &:r0_17, ~mu0_2 +# 137| r0_19(glval) = VariableAddress[y] : +# 137| r0_20(double) = Load : &:r0_19, ~mu0_2 +# 137| r0_21(bool) = CompareNE : r0_18, r0_20 +# 137| r0_22(glval) = VariableAddress[b] : +# 137| mu0_23(bool) = Store : &:r0_22, r0_21 +# 137| r0_24(glval) = CopyValue : r0_22 +# 138| r0_25(glval) = VariableAddress[x] : # 138| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 138| r0_27(bool) = CompareLT : r0_24, r0_26 -# 138| r0_28(glval) = VariableAddress[b] : -# 138| mu0_29(bool) = Store : &:r0_28, r0_27 -# 139| r0_30(glval) = VariableAddress[x] : -# 139| r0_31(double) = Load : &:r0_30, ~mu0_2 -# 139| r0_32(glval) = VariableAddress[y] : -# 139| r0_33(double) = Load : &:r0_32, ~mu0_2 -# 139| r0_34(bool) = CompareGT : r0_31, r0_33 -# 139| r0_35(glval) = VariableAddress[b] : -# 139| mu0_36(bool) = Store : &:r0_35, r0_34 -# 140| r0_37(glval) = VariableAddress[x] : -# 140| r0_38(double) = Load : &:r0_37, ~mu0_2 -# 140| r0_39(glval) = VariableAddress[y] : -# 140| r0_40(double) = Load : &:r0_39, ~mu0_2 -# 140| r0_41(bool) = CompareLE : r0_38, r0_40 -# 140| r0_42(glval) = VariableAddress[b] : -# 140| mu0_43(bool) = Store : &:r0_42, r0_41 -# 141| r0_44(glval) = VariableAddress[x] : -# 141| r0_45(double) = Load : &:r0_44, ~mu0_2 -# 141| r0_46(glval) = VariableAddress[y] : -# 141| r0_47(double) = Load : &:r0_46, ~mu0_2 -# 141| r0_48(bool) = CompareGE : r0_45, r0_47 -# 141| r0_49(glval) = VariableAddress[b] : -# 141| mu0_50(bool) = Store : &:r0_49, r0_48 -# 142| v0_51(void) = NoOp : -# 133| v0_52(void) = ReturnVoid : -# 133| v0_53(void) = UnmodeledUse : mu* -# 133| v0_54(void) = ExitFunction : +# 138| r0_27(glval) = VariableAddress[y] : +# 138| r0_28(double) = Load : &:r0_27, ~mu0_2 +# 138| r0_29(bool) = CompareLT : r0_26, r0_28 +# 138| r0_30(glval) = VariableAddress[b] : +# 138| mu0_31(bool) = Store : &:r0_30, r0_29 +# 138| r0_32(glval) = CopyValue : r0_30 +# 139| r0_33(glval) = VariableAddress[x] : +# 139| r0_34(double) = Load : &:r0_33, ~mu0_2 +# 139| r0_35(glval) = VariableAddress[y] : +# 139| r0_36(double) = Load : &:r0_35, ~mu0_2 +# 139| r0_37(bool) = CompareGT : r0_34, r0_36 +# 139| r0_38(glval) = VariableAddress[b] : +# 139| mu0_39(bool) = Store : &:r0_38, r0_37 +# 139| r0_40(glval) = CopyValue : r0_38 +# 140| r0_41(glval) = VariableAddress[x] : +# 140| r0_42(double) = Load : &:r0_41, ~mu0_2 +# 140| r0_43(glval) = VariableAddress[y] : +# 140| r0_44(double) = Load : &:r0_43, ~mu0_2 +# 140| r0_45(bool) = CompareLE : r0_42, r0_44 +# 140| r0_46(glval) = VariableAddress[b] : +# 140| mu0_47(bool) = Store : &:r0_46, r0_45 +# 140| r0_48(glval) = CopyValue : r0_46 +# 141| r0_49(glval) = VariableAddress[x] : +# 141| r0_50(double) = Load : &:r0_49, ~mu0_2 +# 141| r0_51(glval) = VariableAddress[y] : +# 141| r0_52(double) = Load : &:r0_51, ~mu0_2 +# 141| r0_53(bool) = CompareGE : r0_50, r0_52 +# 141| r0_54(glval) = VariableAddress[b] : +# 141| mu0_55(bool) = Store : &:r0_54, r0_53 +# 141| r0_56(glval) = CopyValue : r0_54 +# 142| v0_57(void) = NoOp : +# 133| v0_58(void) = ReturnVoid : +# 133| v0_59(void) = UnmodeledUse : mu* +# 133| v0_60(void) = ExitFunction : # 144| void FloatCrement(float) # 144| Block 0 @@ -667,31 +730,35 @@ ir.cpp: # 147| mu0_11(float) = Store : &:r0_7, r0_10 # 147| r0_12(glval) = VariableAddress[y] : # 147| mu0_13(float) = Store : &:r0_12, r0_10 -# 148| r0_14(glval) = VariableAddress[x] : -# 148| r0_15(float) = Load : &:r0_14, ~mu0_2 -# 148| r0_16(float) = Constant[1.0] : -# 148| r0_17(float) = Sub : r0_15, r0_16 -# 148| mu0_18(float) = Store : &:r0_14, r0_17 -# 148| r0_19(glval) = VariableAddress[y] : -# 148| mu0_20(float) = Store : &:r0_19, r0_17 -# 149| r0_21(glval) = VariableAddress[x] : -# 149| r0_22(float) = Load : &:r0_21, ~mu0_2 -# 149| r0_23(float) = Constant[1.0] : -# 149| r0_24(float) = Add : r0_22, r0_23 -# 149| mu0_25(float) = Store : &:r0_21, r0_24 -# 149| r0_26(glval) = VariableAddress[y] : -# 149| mu0_27(float) = Store : &:r0_26, r0_22 -# 150| r0_28(glval) = VariableAddress[x] : -# 150| r0_29(float) = Load : &:r0_28, ~mu0_2 -# 150| r0_30(float) = Constant[1.0] : -# 150| r0_31(float) = Sub : r0_29, r0_30 -# 150| mu0_32(float) = Store : &:r0_28, r0_31 -# 150| r0_33(glval) = VariableAddress[y] : -# 150| mu0_34(float) = Store : &:r0_33, r0_29 -# 151| v0_35(void) = NoOp : -# 144| v0_36(void) = ReturnVoid : -# 144| v0_37(void) = UnmodeledUse : mu* -# 144| v0_38(void) = ExitFunction : +# 147| r0_14(glval) = CopyValue : r0_12 +# 148| r0_15(glval) = VariableAddress[x] : +# 148| r0_16(float) = Load : &:r0_15, ~mu0_2 +# 148| r0_17(float) = Constant[1.0] : +# 148| r0_18(float) = Sub : r0_16, r0_17 +# 148| mu0_19(float) = Store : &:r0_15, r0_18 +# 148| r0_20(glval) = VariableAddress[y] : +# 148| mu0_21(float) = Store : &:r0_20, r0_18 +# 148| r0_22(glval) = CopyValue : r0_20 +# 149| r0_23(glval) = VariableAddress[x] : +# 149| r0_24(float) = Load : &:r0_23, ~mu0_2 +# 149| r0_25(float) = Constant[1.0] : +# 149| r0_26(float) = Add : r0_24, r0_25 +# 149| mu0_27(float) = Store : &:r0_23, r0_26 +# 149| r0_28(glval) = VariableAddress[y] : +# 149| mu0_29(float) = Store : &:r0_28, r0_24 +# 149| r0_30(glval) = CopyValue : r0_28 +# 150| r0_31(glval) = VariableAddress[x] : +# 150| r0_32(float) = Load : &:r0_31, ~mu0_2 +# 150| r0_33(float) = Constant[1.0] : +# 150| r0_34(float) = Sub : r0_32, r0_33 +# 150| mu0_35(float) = Store : &:r0_31, r0_34 +# 150| r0_36(glval) = VariableAddress[y] : +# 150| mu0_37(float) = Store : &:r0_36, r0_32 +# 150| r0_38(glval) = CopyValue : r0_36 +# 151| v0_39(void) = NoOp : +# 144| v0_40(void) = ReturnVoid : +# 144| v0_41(void) = UnmodeledUse : mu* +# 144| v0_42(void) = ExitFunction : # 153| void PointerOps(int*, int) # 153| Block 0 @@ -713,61 +780,70 @@ ir.cpp: # 157| r0_15(int *) = PointerAdd[4] : r0_12, r0_14 # 157| r0_16(glval) = VariableAddress[q] : # 157| mu0_17(int *) = Store : &:r0_16, r0_15 -# 158| r0_18(glval) = VariableAddress[i] : -# 158| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 158| r0_20(glval) = VariableAddress[p] : -# 158| r0_21(int *) = Load : &:r0_20, ~mu0_2 -# 158| r0_22(int *) = PointerAdd[4] : r0_21, r0_19 -# 158| r0_23(glval) = VariableAddress[q] : -# 158| mu0_24(int *) = Store : &:r0_23, r0_22 -# 159| r0_25(glval) = VariableAddress[p] : -# 159| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 159| r0_27(glval) = VariableAddress[i] : -# 159| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 159| r0_29(int *) = PointerSub[4] : r0_26, r0_28 -# 159| r0_30(glval) = VariableAddress[q] : -# 159| mu0_31(int *) = Store : &:r0_30, r0_29 -# 160| r0_32(glval) = VariableAddress[p] : -# 160| r0_33(int *) = Load : &:r0_32, ~mu0_2 -# 160| r0_34(glval) = VariableAddress[q] : -# 160| r0_35(int *) = Load : &:r0_34, ~mu0_2 -# 160| r0_36(long) = PointerDiff[4] : r0_33, r0_35 -# 160| r0_37(int) = Convert : r0_36 -# 160| r0_38(glval) = VariableAddress[i] : -# 160| mu0_39(int) = Store : &:r0_38, r0_37 -# 162| r0_40(glval) = VariableAddress[p] : -# 162| r0_41(int *) = Load : &:r0_40, ~mu0_2 -# 162| r0_42(glval) = VariableAddress[q] : -# 162| mu0_43(int *) = Store : &:r0_42, r0_41 -# 164| r0_44(glval) = VariableAddress[i] : -# 164| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 164| r0_46(glval) = VariableAddress[q] : -# 164| r0_47(int *) = Load : &:r0_46, ~mu0_2 -# 164| r0_48(int *) = PointerAdd[4] : r0_47, r0_45 -# 164| mu0_49(int *) = Store : &:r0_46, r0_48 -# 165| r0_50(glval) = VariableAddress[i] : -# 165| r0_51(int) = Load : &:r0_50, ~mu0_2 -# 165| r0_52(glval) = VariableAddress[q] : -# 165| r0_53(int *) = Load : &:r0_52, ~mu0_2 -# 165| r0_54(int *) = PointerSub[4] : r0_53, r0_51 -# 165| mu0_55(int *) = Store : &:r0_52, r0_54 -# 167| r0_56(glval) = VariableAddress[p] : -# 167| r0_57(int *) = Load : &:r0_56, ~mu0_2 -# 167| r0_58(int *) = Constant[0] : -# 167| r0_59(bool) = CompareNE : r0_57, r0_58 -# 167| r0_60(glval) = VariableAddress[b] : -# 167| mu0_61(bool) = Store : &:r0_60, r0_59 -# 168| r0_62(glval) = VariableAddress[p] : -# 168| r0_63(int *) = Load : &:r0_62, ~mu0_2 -# 168| r0_64(int *) = Constant[0] : -# 168| r0_65(bool) = CompareNE : r0_63, r0_64 -# 168| r0_66(bool) = LogicalNot : r0_65 -# 168| r0_67(glval) = VariableAddress[b] : -# 168| mu0_68(bool) = Store : &:r0_67, r0_66 -# 169| v0_69(void) = NoOp : -# 153| v0_70(void) = ReturnVoid : -# 153| v0_71(void) = UnmodeledUse : mu* -# 153| v0_72(void) = ExitFunction : +# 157| r0_18(glval) = CopyValue : r0_16 +# 158| r0_19(glval) = VariableAddress[i] : +# 158| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 158| r0_21(glval) = VariableAddress[p] : +# 158| r0_22(int *) = Load : &:r0_21, ~mu0_2 +# 158| r0_23(int *) = PointerAdd[4] : r0_22, r0_20 +# 158| r0_24(glval) = VariableAddress[q] : +# 158| mu0_25(int *) = Store : &:r0_24, r0_23 +# 158| r0_26(glval) = CopyValue : r0_24 +# 159| r0_27(glval) = VariableAddress[p] : +# 159| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 159| r0_29(glval) = VariableAddress[i] : +# 159| r0_30(int) = Load : &:r0_29, ~mu0_2 +# 159| r0_31(int *) = PointerSub[4] : r0_28, r0_30 +# 159| r0_32(glval) = VariableAddress[q] : +# 159| mu0_33(int *) = Store : &:r0_32, r0_31 +# 159| r0_34(glval) = CopyValue : r0_32 +# 160| r0_35(glval) = VariableAddress[p] : +# 160| r0_36(int *) = Load : &:r0_35, ~mu0_2 +# 160| r0_37(glval) = VariableAddress[q] : +# 160| r0_38(int *) = Load : &:r0_37, ~mu0_2 +# 160| r0_39(long) = PointerDiff[4] : r0_36, r0_38 +# 160| r0_40(int) = Convert : r0_39 +# 160| r0_41(glval) = VariableAddress[i] : +# 160| mu0_42(int) = Store : &:r0_41, r0_40 +# 160| r0_43(glval) = CopyValue : r0_41 +# 162| r0_44(glval) = VariableAddress[p] : +# 162| r0_45(int *) = Load : &:r0_44, ~mu0_2 +# 162| r0_46(glval) = VariableAddress[q] : +# 162| mu0_47(int *) = Store : &:r0_46, r0_45 +# 162| r0_48(glval) = CopyValue : r0_46 +# 164| r0_49(glval) = VariableAddress[i] : +# 164| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 164| r0_51(glval) = VariableAddress[q] : +# 164| r0_52(int *) = Load : &:r0_51, ~mu0_2 +# 164| r0_53(int *) = PointerAdd[4] : r0_52, r0_50 +# 164| mu0_54(int *) = Store : &:r0_51, r0_53 +# 164| r0_55(glval) = CopyValue : r0_51 +# 165| r0_56(glval) = VariableAddress[i] : +# 165| r0_57(int) = Load : &:r0_56, ~mu0_2 +# 165| r0_58(glval) = VariableAddress[q] : +# 165| r0_59(int *) = Load : &:r0_58, ~mu0_2 +# 165| r0_60(int *) = PointerSub[4] : r0_59, r0_57 +# 165| mu0_61(int *) = Store : &:r0_58, r0_60 +# 165| r0_62(glval) = CopyValue : r0_58 +# 167| r0_63(glval) = VariableAddress[p] : +# 167| r0_64(int *) = Load : &:r0_63, ~mu0_2 +# 167| r0_65(int *) = Constant[0] : +# 167| r0_66(bool) = CompareNE : r0_64, r0_65 +# 167| r0_67(glval) = VariableAddress[b] : +# 167| mu0_68(bool) = Store : &:r0_67, r0_66 +# 167| r0_69(glval) = CopyValue : r0_67 +# 168| r0_70(glval) = VariableAddress[p] : +# 168| r0_71(int *) = Load : &:r0_70, ~mu0_2 +# 168| r0_72(int *) = Constant[0] : +# 168| r0_73(bool) = CompareNE : r0_71, r0_72 +# 168| r0_74(bool) = LogicalNot : r0_73 +# 168| r0_75(glval) = VariableAddress[b] : +# 168| mu0_76(bool) = Store : &:r0_75, r0_74 +# 168| r0_77(glval) = CopyValue : r0_75 +# 169| v0_78(void) = NoOp : +# 153| v0_79(void) = ReturnVoid : +# 153| v0_80(void) = UnmodeledUse : mu* +# 153| v0_81(void) = ExitFunction : # 171| void ArrayAccess(int*, int) # 171| Block 0 @@ -788,68 +864,76 @@ ir.cpp: # 174| r0_14(int) = Load : &:r0_13, ~mu0_2 # 174| r0_15(glval) = VariableAddress[x] : # 174| mu0_16(int) = Store : &:r0_15, r0_14 -# 175| r0_17(glval) = VariableAddress[p] : -# 175| r0_18(int *) = Load : &:r0_17, ~mu0_2 -# 175| r0_19(glval) = VariableAddress[i] : -# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 175| r0_21(glval) = PointerAdd[4] : r0_18, r0_20 -# 175| r0_22(int) = Load : &:r0_21, ~mu0_2 -# 175| r0_23(glval) = VariableAddress[x] : -# 175| mu0_24(int) = Store : &:r0_23, r0_22 -# 177| r0_25(glval) = VariableAddress[x] : -# 177| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 177| r0_27(glval) = VariableAddress[p] : -# 177| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 177| r0_29(glval) = VariableAddress[i] : -# 177| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 177| r0_31(glval) = PointerAdd[4] : r0_28, r0_30 -# 177| mu0_32(int) = Store : &:r0_31, r0_26 -# 178| r0_33(glval) = VariableAddress[x] : -# 178| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 178| r0_35(glval) = VariableAddress[p] : -# 178| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 178| r0_37(glval) = VariableAddress[i] : -# 178| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 178| r0_39(glval) = PointerAdd[4] : r0_36, r0_38 -# 178| mu0_40(int) = Store : &:r0_39, r0_34 -# 180| r0_41(glval) = VariableAddress[a] : -# 180| mu0_42(int[10]) = Uninitialized[a] : &:r0_41 -# 181| r0_43(glval) = VariableAddress[a] : -# 181| r0_44(int *) = Convert : r0_43 -# 181| r0_45(glval) = VariableAddress[i] : -# 181| r0_46(int) = Load : &:r0_45, ~mu0_2 -# 181| r0_47(glval) = PointerAdd[4] : r0_44, r0_46 -# 181| r0_48(int) = Load : &:r0_47, ~mu0_2 -# 181| r0_49(glval) = VariableAddress[x] : -# 181| mu0_50(int) = Store : &:r0_49, r0_48 -# 182| r0_51(glval) = VariableAddress[a] : -# 182| r0_52(int *) = Convert : r0_51 -# 182| r0_53(glval) = VariableAddress[i] : -# 182| r0_54(int) = Load : &:r0_53, ~mu0_2 -# 182| r0_55(glval) = PointerAdd[4] : r0_52, r0_54 -# 182| r0_56(int) = Load : &:r0_55, ~mu0_2 -# 182| r0_57(glval) = VariableAddress[x] : -# 182| mu0_58(int) = Store : &:r0_57, r0_56 -# 183| r0_59(glval) = VariableAddress[x] : -# 183| r0_60(int) = Load : &:r0_59, ~mu0_2 -# 183| r0_61(glval) = VariableAddress[a] : -# 183| r0_62(int *) = Convert : r0_61 -# 183| r0_63(glval) = VariableAddress[i] : -# 183| r0_64(int) = Load : &:r0_63, ~mu0_2 -# 183| r0_65(glval) = PointerAdd[4] : r0_62, r0_64 -# 183| mu0_66(int) = Store : &:r0_65, r0_60 -# 184| r0_67(glval) = VariableAddress[x] : -# 184| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 184| r0_69(glval) = VariableAddress[a] : -# 184| r0_70(int *) = Convert : r0_69 -# 184| r0_71(glval) = VariableAddress[i] : -# 184| r0_72(int) = Load : &:r0_71, ~mu0_2 -# 184| r0_73(glval) = PointerAdd[4] : r0_70, r0_72 -# 184| mu0_74(int) = Store : &:r0_73, r0_68 -# 185| v0_75(void) = NoOp : -# 171| v0_76(void) = ReturnVoid : -# 171| v0_77(void) = UnmodeledUse : mu* -# 171| v0_78(void) = ExitFunction : +# 174| r0_17(glval) = CopyValue : r0_15 +# 175| r0_18(glval) = VariableAddress[p] : +# 175| r0_19(int *) = Load : &:r0_18, ~mu0_2 +# 175| r0_20(glval) = VariableAddress[i] : +# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 175| r0_22(glval) = PointerAdd[4] : r0_19, r0_21 +# 175| r0_23(int) = Load : &:r0_22, ~mu0_2 +# 175| r0_24(glval) = VariableAddress[x] : +# 175| mu0_25(int) = Store : &:r0_24, r0_23 +# 175| r0_26(glval) = CopyValue : r0_24 +# 177| r0_27(glval) = VariableAddress[x] : +# 177| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 177| r0_29(glval) = VariableAddress[p] : +# 177| r0_30(int *) = Load : &:r0_29, ~mu0_2 +# 177| r0_31(glval) = VariableAddress[i] : +# 177| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 177| r0_33(glval) = PointerAdd[4] : r0_30, r0_32 +# 177| mu0_34(int) = Store : &:r0_33, r0_28 +# 177| r0_35(glval) = CopyValue : r0_33 +# 178| r0_36(glval) = VariableAddress[x] : +# 178| r0_37(int) = Load : &:r0_36, ~mu0_2 +# 178| r0_38(glval) = VariableAddress[p] : +# 178| r0_39(int *) = Load : &:r0_38, ~mu0_2 +# 178| r0_40(glval) = VariableAddress[i] : +# 178| r0_41(int) = Load : &:r0_40, ~mu0_2 +# 178| r0_42(glval) = PointerAdd[4] : r0_39, r0_41 +# 178| mu0_43(int) = Store : &:r0_42, r0_37 +# 178| r0_44(glval) = CopyValue : r0_42 +# 180| r0_45(glval) = VariableAddress[a] : +# 180| mu0_46(int[10]) = Uninitialized[a] : &:r0_45 +# 181| r0_47(glval) = VariableAddress[a] : +# 181| r0_48(int *) = Convert : r0_47 +# 181| r0_49(glval) = VariableAddress[i] : +# 181| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 181| r0_51(glval) = PointerAdd[4] : r0_48, r0_50 +# 181| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 181| r0_53(glval) = VariableAddress[x] : +# 181| mu0_54(int) = Store : &:r0_53, r0_52 +# 181| r0_55(glval) = CopyValue : r0_53 +# 182| r0_56(glval) = VariableAddress[a] : +# 182| r0_57(int *) = Convert : r0_56 +# 182| r0_58(glval) = VariableAddress[i] : +# 182| r0_59(int) = Load : &:r0_58, ~mu0_2 +# 182| r0_60(glval) = PointerAdd[4] : r0_57, r0_59 +# 182| r0_61(int) = Load : &:r0_60, ~mu0_2 +# 182| r0_62(glval) = VariableAddress[x] : +# 182| mu0_63(int) = Store : &:r0_62, r0_61 +# 182| r0_64(glval) = CopyValue : r0_62 +# 183| r0_65(glval) = VariableAddress[x] : +# 183| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 183| r0_67(glval) = VariableAddress[a] : +# 183| r0_68(int *) = Convert : r0_67 +# 183| r0_69(glval) = VariableAddress[i] : +# 183| r0_70(int) = Load : &:r0_69, ~mu0_2 +# 183| r0_71(glval) = PointerAdd[4] : r0_68, r0_70 +# 183| mu0_72(int) = Store : &:r0_71, r0_66 +# 183| r0_73(glval) = CopyValue : r0_71 +# 184| r0_74(glval) = VariableAddress[x] : +# 184| r0_75(int) = Load : &:r0_74, ~mu0_2 +# 184| r0_76(glval) = VariableAddress[a] : +# 184| r0_77(int *) = Convert : r0_76 +# 184| r0_78(glval) = VariableAddress[i] : +# 184| r0_79(int) = Load : &:r0_78, ~mu0_2 +# 184| r0_80(glval) = PointerAdd[4] : r0_77, r0_79 +# 184| mu0_81(int) = Store : &:r0_80, r0_75 +# 184| r0_82(glval) = CopyValue : r0_80 +# 185| v0_83(void) = NoOp : +# 171| v0_84(void) = ReturnVoid : +# 171| v0_85(void) = UnmodeledUse : mu* +# 171| v0_86(void) = ExitFunction : # 187| void StringLiteral(int) # 187| Block 0 @@ -902,45 +986,51 @@ ir.cpp: # 196| r0_13(bool) = CompareEQ : r0_10, r0_12 # 196| r0_14(glval) = VariableAddress[b] : # 196| mu0_15(bool) = Store : &:r0_14, r0_13 -# 197| r0_16(glval) = VariableAddress[p] : -# 197| r0_17(int *) = Load : &:r0_16, ~mu0_2 -# 197| r0_18(glval) = VariableAddress[q] : -# 197| r0_19(int *) = Load : &:r0_18, ~mu0_2 -# 197| r0_20(bool) = CompareNE : r0_17, r0_19 -# 197| r0_21(glval) = VariableAddress[b] : -# 197| mu0_22(bool) = Store : &:r0_21, r0_20 -# 198| r0_23(glval) = VariableAddress[p] : -# 198| r0_24(int *) = Load : &:r0_23, ~mu0_2 -# 198| r0_25(glval) = VariableAddress[q] : +# 196| r0_16(glval) = CopyValue : r0_14 +# 197| r0_17(glval) = VariableAddress[p] : +# 197| r0_18(int *) = Load : &:r0_17, ~mu0_2 +# 197| r0_19(glval) = VariableAddress[q] : +# 197| r0_20(int *) = Load : &:r0_19, ~mu0_2 +# 197| r0_21(bool) = CompareNE : r0_18, r0_20 +# 197| r0_22(glval) = VariableAddress[b] : +# 197| mu0_23(bool) = Store : &:r0_22, r0_21 +# 197| r0_24(glval) = CopyValue : r0_22 +# 198| r0_25(glval) = VariableAddress[p] : # 198| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 198| r0_27(bool) = CompareLT : r0_24, r0_26 -# 198| r0_28(glval) = VariableAddress[b] : -# 198| mu0_29(bool) = Store : &:r0_28, r0_27 -# 199| r0_30(glval) = VariableAddress[p] : -# 199| r0_31(int *) = Load : &:r0_30, ~mu0_2 -# 199| r0_32(glval) = VariableAddress[q] : -# 199| r0_33(int *) = Load : &:r0_32, ~mu0_2 -# 199| r0_34(bool) = CompareGT : r0_31, r0_33 -# 199| r0_35(glval) = VariableAddress[b] : -# 199| mu0_36(bool) = Store : &:r0_35, r0_34 -# 200| r0_37(glval) = VariableAddress[p] : -# 200| r0_38(int *) = Load : &:r0_37, ~mu0_2 -# 200| r0_39(glval) = VariableAddress[q] : -# 200| r0_40(int *) = Load : &:r0_39, ~mu0_2 -# 200| r0_41(bool) = CompareLE : r0_38, r0_40 -# 200| r0_42(glval) = VariableAddress[b] : -# 200| mu0_43(bool) = Store : &:r0_42, r0_41 -# 201| r0_44(glval) = VariableAddress[p] : -# 201| r0_45(int *) = Load : &:r0_44, ~mu0_2 -# 201| r0_46(glval) = VariableAddress[q] : -# 201| r0_47(int *) = Load : &:r0_46, ~mu0_2 -# 201| r0_48(bool) = CompareGE : r0_45, r0_47 -# 201| r0_49(glval) = VariableAddress[b] : -# 201| mu0_50(bool) = Store : &:r0_49, r0_48 -# 202| v0_51(void) = NoOp : -# 193| v0_52(void) = ReturnVoid : -# 193| v0_53(void) = UnmodeledUse : mu* -# 193| v0_54(void) = ExitFunction : +# 198| r0_27(glval) = VariableAddress[q] : +# 198| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 198| r0_29(bool) = CompareLT : r0_26, r0_28 +# 198| r0_30(glval) = VariableAddress[b] : +# 198| mu0_31(bool) = Store : &:r0_30, r0_29 +# 198| r0_32(glval) = CopyValue : r0_30 +# 199| r0_33(glval) = VariableAddress[p] : +# 199| r0_34(int *) = Load : &:r0_33, ~mu0_2 +# 199| r0_35(glval) = VariableAddress[q] : +# 199| r0_36(int *) = Load : &:r0_35, ~mu0_2 +# 199| r0_37(bool) = CompareGT : r0_34, r0_36 +# 199| r0_38(glval) = VariableAddress[b] : +# 199| mu0_39(bool) = Store : &:r0_38, r0_37 +# 199| r0_40(glval) = CopyValue : r0_38 +# 200| r0_41(glval) = VariableAddress[p] : +# 200| r0_42(int *) = Load : &:r0_41, ~mu0_2 +# 200| r0_43(glval) = VariableAddress[q] : +# 200| r0_44(int *) = Load : &:r0_43, ~mu0_2 +# 200| r0_45(bool) = CompareLE : r0_42, r0_44 +# 200| r0_46(glval) = VariableAddress[b] : +# 200| mu0_47(bool) = Store : &:r0_46, r0_45 +# 200| r0_48(glval) = CopyValue : r0_46 +# 201| r0_49(glval) = VariableAddress[p] : +# 201| r0_50(int *) = Load : &:r0_49, ~mu0_2 +# 201| r0_51(glval) = VariableAddress[q] : +# 201| r0_52(int *) = Load : &:r0_51, ~mu0_2 +# 201| r0_53(bool) = CompareGE : r0_50, r0_52 +# 201| r0_54(glval) = VariableAddress[b] : +# 201| mu0_55(bool) = Store : &:r0_54, r0_53 +# 201| r0_56(glval) = CopyValue : r0_54 +# 202| v0_57(void) = NoOp : +# 193| v0_58(void) = ReturnVoid : +# 193| v0_59(void) = UnmodeledUse : mu* +# 193| v0_60(void) = ExitFunction : # 204| void PointerCrement(int*) # 204| Block 0 @@ -958,31 +1048,35 @@ ir.cpp: # 207| mu0_11(int *) = Store : &:r0_7, r0_10 # 207| r0_12(glval) = VariableAddress[q] : # 207| mu0_13(int *) = Store : &:r0_12, r0_10 -# 208| r0_14(glval) = VariableAddress[p] : -# 208| r0_15(int *) = Load : &:r0_14, ~mu0_2 -# 208| r0_16(int) = Constant[1] : -# 208| r0_17(int *) = PointerSub[4] : r0_15, r0_16 -# 208| mu0_18(int *) = Store : &:r0_14, r0_17 -# 208| r0_19(glval) = VariableAddress[q] : -# 208| mu0_20(int *) = Store : &:r0_19, r0_17 -# 209| r0_21(glval) = VariableAddress[p] : -# 209| r0_22(int *) = Load : &:r0_21, ~mu0_2 -# 209| r0_23(int) = Constant[1] : -# 209| r0_24(int *) = PointerAdd[4] : r0_22, r0_23 -# 209| mu0_25(int *) = Store : &:r0_21, r0_24 -# 209| r0_26(glval) = VariableAddress[q] : -# 209| mu0_27(int *) = Store : &:r0_26, r0_22 -# 210| r0_28(glval) = VariableAddress[p] : -# 210| r0_29(int *) = Load : &:r0_28, ~mu0_2 -# 210| r0_30(int) = Constant[1] : -# 210| r0_31(int *) = PointerSub[4] : r0_29, r0_30 -# 210| mu0_32(int *) = Store : &:r0_28, r0_31 -# 210| r0_33(glval) = VariableAddress[q] : -# 210| mu0_34(int *) = Store : &:r0_33, r0_29 -# 211| v0_35(void) = NoOp : -# 204| v0_36(void) = ReturnVoid : -# 204| v0_37(void) = UnmodeledUse : mu* -# 204| v0_38(void) = ExitFunction : +# 207| r0_14(glval) = CopyValue : r0_12 +# 208| r0_15(glval) = VariableAddress[p] : +# 208| r0_16(int *) = Load : &:r0_15, ~mu0_2 +# 208| r0_17(int) = Constant[1] : +# 208| r0_18(int *) = PointerSub[4] : r0_16, r0_17 +# 208| mu0_19(int *) = Store : &:r0_15, r0_18 +# 208| r0_20(glval) = VariableAddress[q] : +# 208| mu0_21(int *) = Store : &:r0_20, r0_18 +# 208| r0_22(glval) = CopyValue : r0_20 +# 209| r0_23(glval) = VariableAddress[p] : +# 209| r0_24(int *) = Load : &:r0_23, ~mu0_2 +# 209| r0_25(int) = Constant[1] : +# 209| r0_26(int *) = PointerAdd[4] : r0_24, r0_25 +# 209| mu0_27(int *) = Store : &:r0_23, r0_26 +# 209| r0_28(glval) = VariableAddress[q] : +# 209| mu0_29(int *) = Store : &:r0_28, r0_24 +# 209| r0_30(glval) = CopyValue : r0_28 +# 210| r0_31(glval) = VariableAddress[p] : +# 210| r0_32(int *) = Load : &:r0_31, ~mu0_2 +# 210| r0_33(int) = Constant[1] : +# 210| r0_34(int *) = PointerSub[4] : r0_32, r0_33 +# 210| mu0_35(int *) = Store : &:r0_31, r0_34 +# 210| r0_36(glval) = VariableAddress[q] : +# 210| mu0_37(int *) = Store : &:r0_36, r0_32 +# 210| r0_38(glval) = CopyValue : r0_36 +# 211| v0_39(void) = NoOp : +# 204| v0_40(void) = ReturnVoid : +# 204| v0_41(void) = UnmodeledUse : mu* +# 204| v0_42(void) = ExitFunction : # 213| void CompoundAssignment() # 213| Block 0 @@ -997,36 +1091,40 @@ ir.cpp: # 216| r0_8(int) = Load : &:r0_7, ~mu0_2 # 216| r0_9(int) = Add : r0_8, r0_6 # 216| mu0_10(int) = Store : &:r0_7, r0_9 -# 219| r0_11(glval) = VariableAddress[y] : -# 219| r0_12(short) = Constant[5] : -# 219| mu0_13(short) = Store : &:r0_11, r0_12 -# 220| r0_14(glval) = VariableAddress[x] : -# 220| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 220| r0_16(glval) = VariableAddress[y] : -# 220| r0_17(short) = Load : &:r0_16, ~mu0_2 -# 220| r0_18(int) = Convert : r0_17 -# 220| r0_19(int) = Add : r0_18, r0_15 -# 220| r0_20(short) = Convert : r0_19 -# 220| mu0_21(short) = Store : &:r0_16, r0_20 -# 223| r0_22(int) = Constant[1] : -# 223| r0_23(glval) = VariableAddress[y] : -# 223| r0_24(short) = Load : &:r0_23, ~mu0_2 -# 223| r0_25(short) = ShiftLeft : r0_24, r0_22 -# 223| mu0_26(short) = Store : &:r0_23, r0_25 -# 226| r0_27(glval) = VariableAddress[z] : -# 226| r0_28(long) = Constant[7] : -# 226| mu0_29(long) = Store : &:r0_27, r0_28 -# 227| r0_30(float) = Constant[2.0] : -# 227| r0_31(glval) = VariableAddress[z] : -# 227| r0_32(long) = Load : &:r0_31, ~mu0_2 -# 227| r0_33(float) = Convert : r0_32 -# 227| r0_34(float) = Add : r0_33, r0_30 -# 227| r0_35(long) = Convert : r0_34 -# 227| mu0_36(long) = Store : &:r0_31, r0_35 -# 228| v0_37(void) = NoOp : -# 213| v0_38(void) = ReturnVoid : -# 213| v0_39(void) = UnmodeledUse : mu* -# 213| v0_40(void) = ExitFunction : +# 216| r0_11(glval) = CopyValue : r0_7 +# 219| r0_12(glval) = VariableAddress[y] : +# 219| r0_13(short) = Constant[5] : +# 219| mu0_14(short) = Store : &:r0_12, r0_13 +# 220| r0_15(glval) = VariableAddress[x] : +# 220| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 220| r0_17(glval) = VariableAddress[y] : +# 220| r0_18(short) = Load : &:r0_17, ~mu0_2 +# 220| r0_19(int) = Convert : r0_18 +# 220| r0_20(int) = Add : r0_19, r0_16 +# 220| r0_21(short) = Convert : r0_20 +# 220| mu0_22(short) = Store : &:r0_17, r0_21 +# 220| r0_23(glval) = CopyValue : r0_17 +# 223| r0_24(int) = Constant[1] : +# 223| r0_25(glval) = VariableAddress[y] : +# 223| r0_26(short) = Load : &:r0_25, ~mu0_2 +# 223| r0_27(short) = ShiftLeft : r0_26, r0_24 +# 223| mu0_28(short) = Store : &:r0_25, r0_27 +# 223| r0_29(glval) = CopyValue : r0_25 +# 226| r0_30(glval) = VariableAddress[z] : +# 226| r0_31(long) = Constant[7] : +# 226| mu0_32(long) = Store : &:r0_30, r0_31 +# 227| r0_33(float) = Constant[2.0] : +# 227| r0_34(glval) = VariableAddress[z] : +# 227| r0_35(long) = Load : &:r0_34, ~mu0_2 +# 227| r0_36(float) = Convert : r0_35 +# 227| r0_37(float) = Add : r0_36, r0_33 +# 227| r0_38(long) = Convert : r0_37 +# 227| mu0_39(long) = Store : &:r0_34, r0_38 +# 227| r0_40(glval) = CopyValue : r0_34 +# 228| v0_41(void) = NoOp : +# 213| v0_42(void) = ReturnVoid : +# 213| v0_43(void) = UnmodeledUse : mu* +# 213| v0_44(void) = ExitFunction : # 230| void UninitializedVariables() # 230| Block 0 @@ -1094,6 +1192,7 @@ ir.cpp: # 244| r2_1(int) = Load : &:r2_0, ~mu0_2 # 244| r2_2(glval) = VariableAddress[x] : # 244| mu2_3(int) = Store : &:r2_2, r2_1 +# 244| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 247| Block 3 @@ -1109,12 +1208,14 @@ ir.cpp: # 248| r4_0(int) = Constant[2] : # 248| r4_1(glval) = VariableAddress[x] : # 248| mu4_2(int) = Store : &:r4_1, r4_0 +# 248| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 250| Block 5 # 250| r5_0(int) = Constant[7] : # 250| r5_1(glval) = VariableAddress[x] : # 250| mu5_2(int) = Store : &:r5_1, r5_0 +# 250| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 251| Block 6 @@ -1142,6 +1243,7 @@ ir.cpp: # 255| r1_2(int) = Load : &:r1_1, ~mu0_2 # 255| r1_3(int) = Sub : r1_2, r1_0 # 255| mu1_4(int) = Store : &:r1_1, r1_3 +# 255| r1_5(glval) = CopyValue : r1_1 #-----| Goto (back edge) -> Block 3 # 257| Block 2 @@ -1174,11 +1276,12 @@ ir.cpp: # 261| r1_2(int) = Load : &:r1_1, ~mu0_2 # 261| r1_3(int) = Sub : r1_2, r1_0 # 261| mu1_4(int) = Store : &:r1_1, r1_3 -# 262| r1_5(glval) = VariableAddress[n] : -# 262| r1_6(int) = Load : &:r1_5, ~mu0_2 -# 262| r1_7(int) = Constant[0] : -# 262| r1_8(bool) = CompareGT : r1_6, r1_7 -# 262| v1_9(void) = ConditionalBranch : r1_8 +# 261| r1_5(glval) = CopyValue : r1_1 +# 262| r1_6(glval) = VariableAddress[n] : +# 262| r1_7(int) = Load : &:r1_6, ~mu0_2 +# 262| r1_8(int) = Constant[0] : +# 262| r1_9(bool) = CompareGT : r1_7, r1_8 +# 262| v1_10(void) = ConditionalBranch : r1_9 #-----| False -> Block 2 #-----| True (back edge) -> Block 1 @@ -1276,6 +1379,7 @@ ir.cpp: # 287| r2_3(int) = Load : &:r2_2, ~mu0_2 # 287| r2_4(int) = Add : r2_3, r2_1 # 287| mu2_5(int) = Store : &:r2_2, r2_4 +# 287| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 292| void For_InitCondition() @@ -1329,6 +1433,7 @@ ir.cpp: # 299| r2_3(int) = Load : &:r2_2, ~mu0_2 # 299| r2_4(int) = Add : r2_3, r2_1 # 299| mu2_5(int) = Store : &:r2_2, r2_4 +# 299| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 304| void For_ConditionUpdate() @@ -1357,6 +1462,7 @@ ir.cpp: # 306| r2_3(int) = Load : &:r2_2, ~mu0_2 # 306| r2_4(int) = Add : r2_3, r2_1 # 306| mu2_5(int) = Store : &:r2_2, r2_4 +# 306| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 309| Block 3 @@ -1391,6 +1497,7 @@ ir.cpp: # 312| r2_3(int) = Load : &:r2_2, ~mu0_2 # 312| r2_4(int) = Add : r2_3, r2_1 # 312| mu2_5(int) = Store : &:r2_2, r2_4 +# 312| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 315| Block 3 @@ -1424,6 +1531,7 @@ ir.cpp: # 318| r2_2(int) = Load : &:r2_1, ~mu0_2 # 318| r2_3(int) = Add : r2_2, r2_0 # 318| mu2_4(int) = Store : &:r2_1, r2_3 +# 318| r2_5(glval) = CopyValue : r2_1 #-----| Goto (back edge) -> Block 1 # 319| Block 3 @@ -1485,6 +1593,7 @@ ir.cpp: # 326| r4_3(int) = Load : &:r4_2, ~mu0_2 # 326| r4_4(int) = Add : r4_3, r4_1 # 326| mu4_5(int) = Store : &:r4_2, r4_4 +# 326| r4_6(glval) = CopyValue : r4_2 #-----| Goto (back edge) -> Block 1 # 331| Block 5 @@ -1545,16 +1654,18 @@ ir.cpp: # 342| r0_5(int) = Constant[1] : # 342| r0_6(glval) = VariableAddress[p] : # 342| r0_7(int *) = Load : &:r0_6, ~mu0_2 -# 342| mu0_8(int) = Store : &:r0_7, r0_5 -# 343| r0_9(glval) = VariableAddress[#return] : -# 343| r0_10(glval) = VariableAddress[p] : -# 343| r0_11(int *) = Load : &:r0_10, ~mu0_2 -# 343| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 343| mu0_13(int) = Store : &:r0_9, r0_12 -# 341| r0_14(glval) = VariableAddress[#return] : -# 341| v0_15(void) = ReturnValue : &:r0_14, ~mu0_2 -# 341| v0_16(void) = UnmodeledUse : mu* -# 341| v0_17(void) = ExitFunction : +# 342| r0_8(glval) = CopyValue : r0_7 +# 342| mu0_9(int) = Store : &:r0_8, r0_5 +# 342| r0_10(glval) = CopyValue : r0_8 +# 343| r0_11(glval) = VariableAddress[#return] : +# 343| r0_12(glval) = VariableAddress[p] : +# 343| r0_13(int *) = Load : &:r0_12, ~mu0_2 +# 343| r0_14(int) = Load : &:r0_13, ~mu0_2 +# 343| mu0_15(int) = Store : &:r0_11, r0_14 +# 341| r0_16(glval) = VariableAddress[#return] : +# 341| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 341| v0_18(void) = UnmodeledUse : mu* +# 341| v0_19(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -1563,11 +1674,12 @@ ir.cpp: # 348| mu0_2(unknown) = UnmodeledDefinition : # 349| r0_3(glval) = VariableAddress[#return] : # 349| r0_4(glval) = VariableAddress[g] : -# 349| mu0_5(int *) = Store : &:r0_3, r0_4 -# 348| r0_6(glval) = VariableAddress[#return] : -# 348| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 348| v0_8(void) = UnmodeledUse : mu* -# 348| v0_9(void) = ExitFunction : +# 349| r0_5(int *) = CopyValue : r0_4 +# 349| mu0_6(int *) = Store : &:r0_3, r0_5 +# 348| r0_7(glval) = VariableAddress[#return] : +# 348| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 348| v0_9(void) = UnmodeledUse : mu* +# 348| v0_10(void) = ExitFunction : # 352| void Break(int) # 352| Block 0 @@ -1597,6 +1709,7 @@ ir.cpp: # 356| r3_2(int) = Load : &:r3_1, ~mu0_2 # 356| r3_3(int) = Sub : r3_2, r3_0 # 356| mu3_4(int) = Store : &:r3_1, r3_3 +# 356| r3_5(glval) = CopyValue : r3_1 #-----| Goto (back edge) -> Block 5 # 357| Block 4 @@ -1643,6 +1756,7 @@ ir.cpp: # 365| r3_2(int) = Load : &:r3_1, ~mu0_2 # 365| r3_3(int) = Sub : r3_2, r3_0 # 365| mu3_4(int) = Store : &:r3_1, r3_3 +# 365| r3_5(glval) = CopyValue : r3_1 #-----| Goto -> Block 4 # 361| Block 4 @@ -1717,11 +1831,12 @@ ir.cpp: # 381| r0_15(int) = Load : &:r0_14, ~mu0_2 # 381| r0_16(int) = Call : func:r0_11, 0:r0_13, 1:r0_15 # 381| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 381| mu0_18(int) = Store : &:r0_7, r0_16 -# 380| r0_19(glval) = VariableAddress[#return] : -# 380| v0_20(void) = ReturnValue : &:r0_19, ~mu0_2 -# 380| v0_21(void) = UnmodeledUse : mu* -# 380| v0_22(void) = ExitFunction : +# 381| r0_18(int) = CopyValue : r0_16 +# 381| mu0_19(int) = Store : &:r0_7, r0_18 +# 380| r0_20(glval) = VariableAddress[#return] : +# 380| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 +# 380| v0_22(void) = UnmodeledUse : mu* +# 380| v0_23(void) = ExitFunction : # 384| void Switch(int) # 384| Block 0 @@ -1746,6 +1861,7 @@ ir.cpp: # 387| r1_0(int) = Constant[1234] : # 387| r1_1(glval) = VariableAddress[y] : # 387| mu1_2(int) = Store : &:r1_1, r1_0 +# 387| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 389| Block 2 @@ -1753,7 +1869,8 @@ ir.cpp: # 390| r2_1(int) = Constant[-1] : # 390| r2_2(glval) = VariableAddress[y] : # 390| mu2_3(int) = Store : &:r2_2, r2_1 -# 391| v2_4(void) = NoOp : +# 390| r2_4(glval) = CopyValue : r2_2 +# 391| v2_5(void) = NoOp : #-----| Goto -> Block 9 # 393| Block 3 @@ -1765,7 +1882,8 @@ ir.cpp: # 395| r4_1(int) = Constant[1] : # 395| r4_2(glval) = VariableAddress[y] : # 395| mu4_3(int) = Store : &:r4_2, r4_1 -# 396| v4_4(void) = NoOp : +# 395| r4_4(glval) = CopyValue : r4_2 +# 396| v4_5(void) = NoOp : #-----| Goto -> Block 9 # 398| Block 5 @@ -1773,6 +1891,7 @@ ir.cpp: # 399| r5_1(int) = Constant[3] : # 399| r5_2(glval) = VariableAddress[y] : # 399| mu5_3(int) = Store : &:r5_2, r5_1 +# 399| r5_4(glval) = CopyValue : r5_2 #-----| Goto -> Block 6 # 400| Block 6 @@ -1780,7 +1899,8 @@ ir.cpp: # 401| r6_1(int) = Constant[4] : # 401| r6_2(glval) = VariableAddress[y] : # 401| mu6_3(int) = Store : &:r6_2, r6_1 -# 402| v6_4(void) = NoOp : +# 401| r6_4(glval) = CopyValue : r6_2 +# 402| v6_5(void) = NoOp : #-----| Goto -> Block 9 # 404| Block 7 @@ -1788,13 +1908,15 @@ ir.cpp: # 405| r7_1(int) = Constant[0] : # 405| r7_2(glval) = VariableAddress[y] : # 405| mu7_3(int) = Store : &:r7_2, r7_1 -# 406| v7_4(void) = NoOp : +# 405| r7_4(glval) = CopyValue : r7_2 +# 406| v7_5(void) = NoOp : #-----| Goto -> Block 9 # 408| Block 8 # 408| r8_0(int) = Constant[5678] : # 408| r8_1(glval) = VariableAddress[y] : # 408| mu8_2(int) = Store : &:r8_1, r8_0 +# 408| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 9 # 409| Block 9 @@ -1831,20 +1953,23 @@ ir.cpp: # 428| r0_6(glval) = VariableAddress[pt] : # 428| r0_7(glval) = FieldAddress[x] : r0_6 # 428| mu0_8(int) = Store : &:r0_7, r0_5 -# 429| r0_9(glval) = VariableAddress[pt] : -# 429| r0_10(glval) = FieldAddress[x] : r0_9 -# 429| r0_11(int) = Load : &:r0_10, ~mu0_2 -# 429| r0_12(glval) = VariableAddress[pt] : -# 429| r0_13(glval) = FieldAddress[y] : r0_12 -# 429| mu0_14(int) = Store : &:r0_13, r0_11 -# 430| r0_15(glval) = VariableAddress[p] : -# 430| r0_16(glval) = VariableAddress[pt] : -# 430| r0_17(glval) = FieldAddress[y] : r0_16 -# 430| mu0_18(int *) = Store : &:r0_15, r0_17 -# 431| v0_19(void) = NoOp : -# 426| v0_20(void) = ReturnVoid : -# 426| v0_21(void) = UnmodeledUse : mu* -# 426| v0_22(void) = ExitFunction : +# 428| r0_9(glval) = CopyValue : r0_7 +# 429| r0_10(glval) = VariableAddress[pt] : +# 429| r0_11(glval) = FieldAddress[x] : r0_10 +# 429| r0_12(int) = Load : &:r0_11, ~mu0_2 +# 429| r0_13(glval) = VariableAddress[pt] : +# 429| r0_14(glval) = FieldAddress[y] : r0_13 +# 429| mu0_15(int) = Store : &:r0_14, r0_12 +# 429| r0_16(glval) = CopyValue : r0_14 +# 430| r0_17(glval) = VariableAddress[p] : +# 430| r0_18(glval) = VariableAddress[pt] : +# 430| r0_19(glval) = FieldAddress[y] : r0_18 +# 430| r0_20(int *) = CopyValue : r0_19 +# 430| mu0_21(int *) = Store : &:r0_17, r0_20 +# 431| v0_22(void) = NoOp : +# 426| v0_23(void) = ReturnVoid : +# 426| v0_24(void) = UnmodeledUse : mu* +# 426| v0_25(void) = ExitFunction : # 433| void LogicalOr(bool, bool) # 433| Block 0 @@ -1874,6 +1999,7 @@ ir.cpp: # 436| r2_0(int) = Constant[7] : # 436| r2_1(glval) = VariableAddress[x] : # 436| mu2_2(int) = Store : &:r2_1, r2_0 +# 436| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 439| Block 3 @@ -1894,12 +2020,14 @@ ir.cpp: # 440| r5_0(int) = Constant[1] : # 440| r5_1(glval) = VariableAddress[x] : # 440| mu5_2(int) = Store : &:r5_1, r5_0 +# 440| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 443| Block 6 # 443| r6_0(int) = Constant[5] : # 443| r6_1(glval) = VariableAddress[x] : # 443| mu6_2(int) = Store : &:r6_1, r6_0 +# 443| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 445| Block 7 @@ -1936,6 +2064,7 @@ ir.cpp: # 450| r2_0(int) = Constant[7] : # 450| r2_1(glval) = VariableAddress[x] : # 450| mu2_2(int) = Store : &:r2_1, r2_0 +# 450| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 453| Block 3 @@ -1956,12 +2085,14 @@ ir.cpp: # 454| r5_0(int) = Constant[1] : # 454| r5_1(glval) = VariableAddress[x] : # 454| mu5_2(int) = Store : &:r5_1, r5_0 +# 454| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 457| Block 6 # 457| r6_0(int) = Constant[5] : # 457| r6_1(glval) = VariableAddress[x] : # 457| mu6_2(int) = Store : &:r6_1, r6_0 +# 457| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 459| Block 7 @@ -1991,6 +2122,7 @@ ir.cpp: # 464| r1_0(int) = Constant[1] : # 464| r1_1(glval) = VariableAddress[x] : # 464| mu1_2(int) = Store : &:r1_1, r1_0 +# 464| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 467| Block 2 @@ -2011,12 +2143,14 @@ ir.cpp: # 468| r4_0(int) = Constant[2] : # 468| r4_1(glval) = VariableAddress[x] : # 468| mu4_2(int) = Store : &:r4_1, r4_0 +# 468| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 471| Block 5 # 471| r5_0(int) = Constant[3] : # 471| r5_1(glval) = VariableAddress[x] : # 471| mu5_2(int) = Store : &:r5_1, r5_0 +# 471| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 473| Block 6 @@ -2060,9 +2194,10 @@ ir.cpp: # 478| r3_1(bool) = Load : &:r3_0, ~mu0_2 # 478| r3_2(glval) = VariableAddress[x] : # 478| mu3_3(bool) = Store : &:r3_2, r3_1 -# 479| r3_4(glval) = VariableAddress[a] : -# 479| r3_5(bool) = Load : &:r3_4, ~mu0_2 -# 479| v3_6(void) = ConditionalBranch : r3_5 +# 478| r3_4(glval) = CopyValue : r3_2 +# 479| r3_5(glval) = VariableAddress[a] : +# 479| r3_6(bool) = Load : &:r3_5, ~mu0_2 +# 479| v3_7(void) = ConditionalBranch : r3_6 #-----| False -> Block 9 #-----| True -> Block 8 @@ -2091,10 +2226,11 @@ ir.cpp: # 479| r7_2(bool) = LogicalNot : r7_1 # 479| r7_3(glval) = VariableAddress[x] : # 479| mu7_4(bool) = Store : &:r7_3, r7_2 -# 480| v7_5(void) = NoOp : -# 475| v7_6(void) = ReturnVoid : -# 475| v7_7(void) = UnmodeledUse : mu* -# 475| v7_8(void) = ExitFunction : +# 479| r7_5(glval) = CopyValue : r7_3 +# 480| v7_6(void) = NoOp : +# 475| v7_7(void) = ReturnVoid : +# 475| v7_8(void) = UnmodeledUse : mu* +# 475| v7_9(void) = ExitFunction : # 479| Block 8 # 479| r8_0(glval) = VariableAddress[#temp479:11] : @@ -2120,9 +2256,10 @@ ir.cpp: # 477| r11_1(bool) = Load : &:r11_0, ~mu0_2 # 477| r11_2(glval) = VariableAddress[x] : # 477| mu11_3(bool) = Store : &:r11_2, r11_1 -# 478| r11_4(glval) = VariableAddress[a] : -# 478| r11_5(bool) = Load : &:r11_4, ~mu0_2 -# 478| v11_6(void) = ConditionalBranch : r11_5 +# 477| r11_4(glval) = CopyValue : r11_2 +# 478| r11_5(glval) = VariableAddress[a] : +# 478| r11_6(bool) = Load : &:r11_5, ~mu0_2 +# 478| v11_7(void) = ConditionalBranch : r11_6 #-----| False -> Block 5 #-----| True -> Block 4 @@ -2195,10 +2332,11 @@ ir.cpp: # 489| r1_0(glval) = VariableAddress[#temp489:6] : # 489| r1_1(glval) = Load : &:r1_0, ~mu0_2 # 489| mu1_2(int) = Store : &:r1_1, r0_9 -# 490| v1_3(void) = NoOp : -# 486| v1_4(void) = ReturnVoid : -# 486| v1_5(void) = UnmodeledUse : mu* -# 486| v1_6(void) = ExitFunction : +# 489| r1_3(glval) = CopyValue : r1_1 +# 490| v1_4(void) = NoOp : +# 486| v1_5(void) = ReturnVoid : +# 486| v1_6(void) = UnmodeledUse : mu* +# 486| v1_7(void) = ExitFunction : # 489| Block 2 # 489| r2_0(glval) = VariableAddress[x] : @@ -2257,13 +2395,15 @@ ir.cpp: # 499| r0_9(int *) = Constant[0] : # 499| r0_10(glval) = VariableAddress[p] : # 499| mu0_11(int *) = Store : &:r0_10, r0_9 -# 500| r0_12(int *) = Constant[0] : -# 500| r0_13(glval) = VariableAddress[q] : -# 500| mu0_14(int *) = Store : &:r0_13, r0_12 -# 501| v0_15(void) = NoOp : -# 496| v0_16(void) = ReturnVoid : -# 496| v0_17(void) = UnmodeledUse : mu* -# 496| v0_18(void) = ExitFunction : +# 499| r0_12(glval) = CopyValue : r0_10 +# 500| r0_13(int *) = Constant[0] : +# 500| r0_14(glval) = VariableAddress[q] : +# 500| mu0_15(int *) = Store : &:r0_14, r0_13 +# 500| r0_16(glval) = CopyValue : r0_14 +# 501| v0_17(void) = NoOp : +# 496| v0_18(void) = ReturnVoid : +# 496| v0_19(void) = UnmodeledUse : mu* +# 496| v0_20(void) = ExitFunction : # 503| void InitList(int, float) # 503| Block 0 @@ -2491,7 +2631,8 @@ ir.cpp: # 540| r3_1(int) = Load : &:r3_0, ~mu0_2 # 540| r3_2(glval) = VariableAddress[y] : # 540| mu3_3(int) = Store : &:r3_2, r3_1 -# 541| v3_4(void) = NoOp : +# 540| r3_4(glval) = CopyValue : r3_2 +# 541| v3_5(void) = NoOp : #-----| Goto -> Block 1 # 543| int EarlyReturnValue(int, int) @@ -2687,18 +2828,27 @@ ir.cpp: # 591| r0_4(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : # 591| mu0_5(..(*)(..)) = Store : &:r0_3, r0_4 # 592| r0_6(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 592| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : -# 592| mu0_8(..(*)(..)) = Store : &:r0_7, r0_6 -# 593| r0_9(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : -# 593| r0_10(glval<..(*)(..)>) = VariableAddress[pfn] : -# 593| mu0_11(..(*)(..)) = Store : &:r0_10, r0_9 -# 594| r0_12(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 594| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : -# 594| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 -# 595| v0_15(void) = NoOp : -# 590| v0_16(void) = ReturnVoid : -# 590| v0_17(void) = UnmodeledUse : mu* -# 590| v0_18(void) = ExitFunction : +# 592| r0_7(..(*)(..)) = CopyValue : r0_6 +# 592| r0_8(glval<..(*)(..)>) = VariableAddress[pfn] : +# 592| mu0_9(..(*)(..)) = Store : &:r0_8, r0_7 +# 592| r0_10(glval<..(*)(..)>) = CopyValue : r0_8 +# 593| r0_11(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : +# 593| r0_12(..(*)(..)) = CopyValue : r0_11 +# 593| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : +# 593| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 +# 593| r0_15(glval<..(*)(..)>) = CopyValue : r0_13 +# 594| r0_16(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 594| r0_17(..(*)(..)) = CopyValue : r0_16 +# 594| r0_18(..(*)(..)) = CopyValue : r0_17 +# 594| r0_19(..(*)(..)) = CopyValue : r0_18 +# 594| r0_20(..(*)(..)) = CopyValue : r0_19 +# 594| r0_21(glval<..(*)(..)>) = VariableAddress[pfn] : +# 594| mu0_22(..(*)(..)) = Store : &:r0_21, r0_20 +# 594| r0_23(glval<..(*)(..)>) = CopyValue : r0_21 +# 595| v0_24(void) = NoOp : +# 590| v0_25(void) = ReturnVoid : +# 590| v0_26(void) = UnmodeledUse : mu* +# 590| v0_27(void) = ExitFunction : # 615| void DeclareObject() # 615| Block 0 @@ -2744,25 +2894,26 @@ ir.cpp: # 622| mu0_8(String) = InitializeParameter[s] : &:r0_7 # 623| r0_9(glval) = VariableAddress[r] : # 623| r0_10(String &) = Load : &:r0_9, ~mu0_2 -# 623| r0_11(glval) = Convert : r0_10 -# 623| r0_12(glval) = FunctionAddress[c_str] : -# 623| r0_13(char *) = Call : func:r0_12, this:r0_11 -# 623| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 624| r0_15(glval) = VariableAddress[p] : -# 624| r0_16(String *) = Load : &:r0_15, ~mu0_2 -# 624| r0_17(String *) = Convert : r0_16 -# 624| r0_18(glval) = FunctionAddress[c_str] : -# 624| r0_19(char *) = Call : func:r0_18, this:r0_17 -# 624| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 -# 625| r0_21(glval) = VariableAddress[s] : -# 625| r0_22(glval) = Convert : r0_21 -# 625| r0_23(glval) = FunctionAddress[c_str] : -# 625| r0_24(char *) = Call : func:r0_23, this:r0_22 -# 625| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 626| v0_26(void) = NoOp : -# 622| v0_27(void) = ReturnVoid : -# 622| v0_28(void) = UnmodeledUse : mu* -# 622| v0_29(void) = ExitFunction : +# 623| r0_11(glval) = CopyValue : r0_10 +# 623| r0_12(glval) = Convert : r0_11 +# 623| r0_13(glval) = FunctionAddress[c_str] : +# 623| r0_14(char *) = Call : func:r0_13, this:r0_12 +# 623| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +# 624| r0_16(glval) = VariableAddress[p] : +# 624| r0_17(String *) = Load : &:r0_16, ~mu0_2 +# 624| r0_18(String *) = Convert : r0_17 +# 624| r0_19(glval) = FunctionAddress[c_str] : +# 624| r0_20(char *) = Call : func:r0_19, this:r0_18 +# 624| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 +# 625| r0_22(glval) = VariableAddress[s] : +# 625| r0_23(glval) = Convert : r0_22 +# 625| r0_24(glval) = FunctionAddress[c_str] : +# 625| r0_25(char *) = Call : func:r0_24, this:r0_23 +# 625| mu0_26(unknown) = ^CallSideEffect : ~mu0_2 +# 626| v0_27(void) = NoOp : +# 622| v0_28(void) = ReturnVoid : +# 622| v0_29(void) = UnmodeledUse : mu* +# 622| v0_30(void) = ExitFunction : # 630| int C::StaticMemberFunction(int) # 630| Block 0 @@ -2824,35 +2975,43 @@ ir.cpp: # 643| r0_5(C *) = CopyValue : r0_3 # 643| r0_6(glval) = FieldAddress[m_a] : r0_5 # 643| mu0_7(int) = Store : &:r0_6, r0_4 -# 644| r0_8(int) = Constant[1] : -# 644| r0_9(C *) = CopyValue : r0_3 -# 644| r0_10(glval) = FieldAddress[m_a] : r0_9 -# 644| mu0_11(int) = Store : &:r0_10, r0_8 -# 645| r0_12(int) = Constant[2] : -#-----| r0_13(C *) = CopyValue : r0_3 -# 645| r0_14(glval) = FieldAddress[m_a] : r0_13 -# 645| mu0_15(int) = Store : &:r0_14, r0_12 -# 646| r0_16(glval) = VariableAddress[x] : -# 646| mu0_17(int) = Uninitialized[x] : &:r0_16 -# 647| r0_18(C *) = CopyValue : r0_3 -# 647| r0_19(glval) = FieldAddress[m_a] : r0_18 -# 647| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 647| r0_21(glval) = VariableAddress[x] : -# 647| mu0_22(int) = Store : &:r0_21, r0_20 -# 648| r0_23(C *) = CopyValue : r0_3 -# 648| r0_24(glval) = FieldAddress[m_a] : r0_23 -# 648| r0_25(int) = Load : &:r0_24, ~mu0_2 -# 648| r0_26(glval) = VariableAddress[x] : -# 648| mu0_27(int) = Store : &:r0_26, r0_25 -#-----| r0_28(C *) = CopyValue : r0_3 -# 649| r0_29(glval) = FieldAddress[m_a] : r0_28 -# 649| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 649| r0_31(glval) = VariableAddress[x] : -# 649| mu0_32(int) = Store : &:r0_31, r0_30 -# 650| v0_33(void) = NoOp : -# 642| v0_34(void) = ReturnVoid : -# 642| v0_35(void) = UnmodeledUse : mu* -# 642| v0_36(void) = ExitFunction : +# 643| r0_8(glval) = CopyValue : r0_6 +# 644| r0_9(int) = Constant[1] : +# 644| r0_10(C *) = CopyValue : r0_3 +# 644| r0_11(glval) = CopyValue : r0_10 +# 644| r0_12(glval) = FieldAddress[m_a] : r0_11 +# 644| mu0_13(int) = Store : &:r0_12, r0_9 +# 644| r0_14(glval) = CopyValue : r0_12 +# 645| r0_15(int) = Constant[2] : +#-----| r0_16(C *) = CopyValue : r0_3 +# 645| r0_17(glval) = FieldAddress[m_a] : r0_16 +# 645| mu0_18(int) = Store : &:r0_17, r0_15 +# 645| r0_19(glval) = CopyValue : r0_17 +# 646| r0_20(glval) = VariableAddress[x] : +# 646| mu0_21(int) = Uninitialized[x] : &:r0_20 +# 647| r0_22(C *) = CopyValue : r0_3 +# 647| r0_23(glval) = FieldAddress[m_a] : r0_22 +# 647| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 647| r0_25(glval) = VariableAddress[x] : +# 647| mu0_26(int) = Store : &:r0_25, r0_24 +# 647| r0_27(glval) = CopyValue : r0_25 +# 648| r0_28(C *) = CopyValue : r0_3 +# 648| r0_29(glval) = CopyValue : r0_28 +# 648| r0_30(glval) = FieldAddress[m_a] : r0_29 +# 648| r0_31(int) = Load : &:r0_30, ~mu0_2 +# 648| r0_32(glval) = VariableAddress[x] : +# 648| mu0_33(int) = Store : &:r0_32, r0_31 +# 648| r0_34(glval) = CopyValue : r0_32 +#-----| r0_35(C *) = CopyValue : r0_3 +# 649| r0_36(glval) = FieldAddress[m_a] : r0_35 +# 649| r0_37(int) = Load : &:r0_36, ~mu0_2 +# 649| r0_38(glval) = VariableAddress[x] : +# 649| mu0_39(int) = Store : &:r0_38, r0_37 +# 649| r0_40(glval) = CopyValue : r0_38 +# 650| v0_41(void) = NoOp : +# 642| v0_42(void) = ReturnVoid : +# 642| v0_43(void) = UnmodeledUse : mu* +# 642| v0_44(void) = ExitFunction : # 652| void C::MethodCalls() # 652| Block 0 @@ -2866,19 +3025,20 @@ ir.cpp: # 653| r0_7(int) = Call : func:r0_5, this:r0_4, 0:r0_6 # 653| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 # 654| r0_9(C *) = CopyValue : r0_3 -# 654| r0_10(glval) = FunctionAddress[InstanceMemberFunction] : -# 654| r0_11(int) = Constant[1] : -# 654| r0_12(int) = Call : func:r0_10, this:r0_9, 0:r0_11 -# 654| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(C *) = CopyValue : r0_3 -# 655| r0_15(glval) = FunctionAddress[InstanceMemberFunction] : -# 655| r0_16(int) = Constant[2] : -# 655| r0_17(int) = Call : func:r0_15, this:r0_14, 0:r0_16 -# 655| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 -# 656| v0_19(void) = NoOp : -# 652| v0_20(void) = ReturnVoid : -# 652| v0_21(void) = UnmodeledUse : mu* -# 652| v0_22(void) = ExitFunction : +# 654| r0_10(glval) = CopyValue : r0_9 +# 654| r0_11(glval) = FunctionAddress[InstanceMemberFunction] : +# 654| r0_12(int) = Constant[1] : +# 654| r0_13(int) = Call : func:r0_11, this:r0_10, 0:r0_12 +# 654| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_15(C *) = CopyValue : r0_3 +# 655| r0_16(glval) = FunctionAddress[InstanceMemberFunction] : +# 655| r0_17(int) = Constant[2] : +# 655| r0_18(int) = Call : func:r0_16, this:r0_15, 0:r0_17 +# 655| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 656| v0_20(void) = NoOp : +# 652| v0_21(void) = ReturnVoid : +# 652| v0_22(void) = UnmodeledUse : mu* +# 652| v0_23(void) = ExitFunction : # 658| void C::C() # 658| Block 0 @@ -2934,11 +3094,12 @@ ir.cpp: # 679| mu0_2(unknown) = UnmodeledDefinition : # 680| r0_3(glval) = VariableAddress[#return] : # 680| r0_4(glval) = VariableAddress[g] : -# 680| mu0_5(int &) = Store : &:r0_3, r0_4 -# 679| r0_6(glval) = VariableAddress[#return] : -# 679| v0_7(void) = ReturnValue : &:r0_6, ~mu0_2 -# 679| v0_8(void) = UnmodeledUse : mu* -# 679| v0_9(void) = ExitFunction : +# 680| r0_5(int &) = CopyValue : r0_4 +# 680| mu0_6(int &) = Store : &:r0_3, r0_5 +# 679| r0_7(glval) = VariableAddress[#return] : +# 679| v0_8(void) = ReturnValue : &:r0_7, ~mu0_2 +# 679| v0_9(void) = UnmodeledUse : mu* +# 679| v0_10(void) = ExitFunction : # 685| void InitReference(int) # 685| Block 0 @@ -2949,44 +3110,51 @@ ir.cpp: # 685| mu0_4(int) = InitializeParameter[x] : &:r0_3 # 686| r0_5(glval) = VariableAddress[r] : # 686| r0_6(glval) = VariableAddress[x] : -# 686| mu0_7(int &) = Store : &:r0_5, r0_6 -# 687| r0_8(glval) = VariableAddress[r2] : -# 687| r0_9(glval) = VariableAddress[r] : -# 687| r0_10(int &) = Load : &:r0_9, ~mu0_2 -# 687| mu0_11(int &) = Store : &:r0_8, r0_10 -# 688| r0_12(glval) = VariableAddress[r3] : -# 688| r0_13(glval) = FunctionAddress[ReturnReference] : -# 688| r0_14(String &) = Call : func:r0_13 -# 688| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 688| r0_16(glval) = Convert : r0_14 -# 688| mu0_17(String &) = Store : &:r0_12, r0_16 -# 689| v0_18(void) = NoOp : -# 685| v0_19(void) = ReturnVoid : -# 685| v0_20(void) = UnmodeledUse : mu* -# 685| v0_21(void) = ExitFunction : +# 686| r0_7(int &) = CopyValue : r0_6 +# 686| mu0_8(int &) = Store : &:r0_5, r0_7 +# 687| r0_9(glval) = VariableAddress[r2] : +# 687| r0_10(glval) = VariableAddress[r] : +# 687| r0_11(int &) = Load : &:r0_10, ~mu0_2 +# 687| r0_12(glval) = CopyValue : r0_11 +# 687| r0_13(int &) = CopyValue : r0_12 +# 687| mu0_14(int &) = Store : &:r0_9, r0_13 +# 688| r0_15(glval) = VariableAddress[r3] : +# 688| r0_16(glval) = FunctionAddress[ReturnReference] : +# 688| r0_17(String &) = Call : func:r0_16 +# 688| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 688| r0_19(glval) = CopyValue : r0_17 +# 688| r0_20(glval) = Convert : r0_19 +# 688| r0_21(String &) = CopyValue : r0_20 +# 688| mu0_22(String &) = Store : &:r0_15, r0_21 +# 689| v0_23(void) = NoOp : +# 685| v0_24(void) = ReturnVoid : +# 685| v0_25(void) = UnmodeledUse : mu* +# 685| v0_26(void) = ExitFunction : # 691| void ArrayReferences() # 691| Block 0 -# 691| v0_0(void) = EnterFunction : -# 691| mu0_1(unknown) = AliasedDefinition : -# 691| mu0_2(unknown) = UnmodeledDefinition : -# 692| r0_3(glval) = VariableAddress[a] : -# 692| mu0_4(int[10]) = Uninitialized[a] : &:r0_3 -# 693| r0_5(glval) = VariableAddress[ra] : -# 693| r0_6(glval) = VariableAddress[a] : -# 693| mu0_7(int(&)[10]) = Store : &:r0_5, r0_6 -# 694| r0_8(glval) = VariableAddress[x] : -# 694| r0_9(glval) = VariableAddress[ra] : -# 694| r0_10(int(&)[10]) = Load : &:r0_9, ~mu0_2 -# 694| r0_11(int *) = Convert : r0_10 -# 694| r0_12(int) = Constant[5] : -# 694| r0_13(glval) = PointerAdd[4] : r0_11, r0_12 -# 694| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 694| mu0_15(int) = Store : &:r0_8, r0_14 -# 695| v0_16(void) = NoOp : -# 691| v0_17(void) = ReturnVoid : -# 691| v0_18(void) = UnmodeledUse : mu* -# 691| v0_19(void) = ExitFunction : +# 691| v0_0(void) = EnterFunction : +# 691| mu0_1(unknown) = AliasedDefinition : +# 691| mu0_2(unknown) = UnmodeledDefinition : +# 692| r0_3(glval) = VariableAddress[a] : +# 692| mu0_4(int[10]) = Uninitialized[a] : &:r0_3 +# 693| r0_5(glval) = VariableAddress[ra] : +# 693| r0_6(glval) = VariableAddress[a] : +# 693| r0_7(int(&)[10]) = CopyValue : r0_6 +# 693| mu0_8(int(&)[10]) = Store : &:r0_5, r0_7 +# 694| r0_9(glval) = VariableAddress[x] : +# 694| r0_10(glval) = VariableAddress[ra] : +# 694| r0_11(int(&)[10]) = Load : &:r0_10, ~mu0_2 +# 694| r0_12(glval) = CopyValue : r0_11 +# 694| r0_13(int *) = Convert : r0_12 +# 694| r0_14(int) = Constant[5] : +# 694| r0_15(glval) = PointerAdd[4] : r0_13, r0_14 +# 694| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 694| mu0_17(int) = Store : &:r0_9, r0_16 +# 695| v0_18(void) = NoOp : +# 691| v0_19(void) = ReturnVoid : +# 691| v0_20(void) = UnmodeledUse : mu* +# 691| v0_21(void) = ExitFunction : # 697| void FunctionReferences() # 697| Block 0 @@ -2995,20 +3163,23 @@ ir.cpp: # 697| mu0_2(unknown) = UnmodeledDefinition : # 698| r0_3(glval<..(&)(..)>) = VariableAddress[rfn] : # 698| r0_4(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : -# 698| mu0_5(..(&)(..)) = Store : &:r0_3, r0_4 -# 699| r0_6(glval<..(*)(..)>) = VariableAddress[pfn] : -# 699| r0_7(glval<..(&)(..)>) = VariableAddress[rfn] : -# 699| r0_8(..(&)(..)) = Load : &:r0_7, ~mu0_2 -# 699| mu0_9(..(*)(..)) = Store : &:r0_6, r0_8 -# 700| r0_10(glval<..(&)(..)>) = VariableAddress[rfn] : -# 700| r0_11(..(&)(..)) = Load : &:r0_10, ~mu0_2 -# 700| r0_12(int) = Constant[5] : -# 700| r0_13(int) = Call : func:r0_11, 0:r0_12 -# 700| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 701| v0_15(void) = NoOp : -# 697| v0_16(void) = ReturnVoid : -# 697| v0_17(void) = UnmodeledUse : mu* -# 697| v0_18(void) = ExitFunction : +# 698| r0_5(..(&)(..)) = CopyValue : r0_4 +# 698| mu0_6(..(&)(..)) = Store : &:r0_3, r0_5 +# 699| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : +# 699| r0_8(glval<..(&)(..)>) = VariableAddress[rfn] : +# 699| r0_9(..(&)(..)) = Load : &:r0_8, ~mu0_2 +# 699| r0_10(..(*)(..)) = CopyValue : r0_9 +# 699| mu0_11(..(*)(..)) = Store : &:r0_7, r0_10 +# 700| r0_12(glval<..(&)(..)>) = VariableAddress[rfn] : +# 700| r0_13(..(&)(..)) = Load : &:r0_12, ~mu0_2 +# 700| r0_14(..(*)(..)) = CopyValue : r0_13 +# 700| r0_15(int) = Constant[5] : +# 700| r0_16(int) = Call : func:r0_14, 0:r0_15 +# 700| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 701| v0_18(void) = NoOp : +# 697| v0_19(void) = ReturnVoid : +# 697| v0_20(void) = UnmodeledUse : mu* +# 697| v0_21(void) = ExitFunction : # 704| int min(int, int) # 704| Block 0 @@ -3166,6 +3337,7 @@ ir.cpp: # 731| r6_4(int) = Load : &:r6_3, ~mu0_2 # 731| r6_5(glval) = VariableAddress[x] : # 731| mu6_6(int) = Store : &:r6_5, r6_4 +# 731| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 731| Block 7 @@ -3182,6 +3354,7 @@ ir.cpp: # 733| r8_0(int) = Constant[7] : # 733| r8_1(glval) = VariableAddress[x] : # 733| mu8_2(int) = Store : &:r8_1, r8_0 +# 733| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 14 # 735| Block 9 @@ -3232,19 +3405,25 @@ ir.cpp: #-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 #-----| r0_6(Base *) = CopyValue : r0_3 #-----| r0_7(glval) = FieldAddress[base_s] : r0_6 -# 745| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Base &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(glval) = FieldAddress[base_s] : r0_10 -# 745| r0_12(String &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 745| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(glval) = VariableAddress[#return] : -#-----| r0_15(Base *) = CopyValue : r0_3 -#-----| mu0_16(Base &) = Store : &:r0_14, r0_15 -# 745| r0_17(glval) = VariableAddress[#return] : -# 745| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 -# 745| v0_19(void) = UnmodeledUse : mu* -# 745| v0_20(void) = ExitFunction : +#-----| r0_8(String *) = CopyValue : r0_7 +# 745| r0_9(glval) = FunctionAddress[operator=] : +#-----| r0_10(glval) = VariableAddress[p#0] : +#-----| r0_11(Base &) = Load : &:r0_10, ~mu0_2 +#-----| r0_12(glval) = CopyValue : r0_11 +#-----| r0_13(glval) = FieldAddress[base_s] : r0_12 +#-----| r0_14(String &) = CopyValue : r0_13 +# 745| r0_15(String &) = Call : func:r0_9, this:r0_8, 0:r0_14 +# 745| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_17(glval) = CopyValue : r0_15 +#-----| r0_18(glval) = VariableAddress[#return] : +#-----| r0_19(Base *) = CopyValue : r0_3 +#-----| r0_20(glval) = CopyValue : r0_19 +#-----| r0_21(Base &) = CopyValue : r0_20 +#-----| mu0_22(Base &) = Store : &:r0_18, r0_21 +# 745| r0_23(glval) = VariableAddress[#return] : +# 745| v0_24(void) = ReturnValue : &:r0_23, ~mu0_2 +# 745| v0_25(void) = UnmodeledUse : mu* +# 745| v0_26(void) = ExitFunction : # 745| void Base::Base(Base const&) # 745| Block 0 @@ -3306,24 +3485,35 @@ ir.cpp: # 754| r0_8(glval) = FunctionAddress[operator=] : #-----| r0_9(glval) = VariableAddress[p#0] : #-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Base *) = ConvertToBase[Middle : Base] : r0_10 -# 754| r0_12(Base &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 754| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(Middle *) = CopyValue : r0_3 -#-----| r0_15(glval) = FieldAddress[middle_s] : r0_14 -# 754| r0_16(glval) = FunctionAddress[operator=] : -#-----| r0_17(glval) = VariableAddress[p#0] : -#-----| r0_18(Middle &) = Load : &:r0_17, ~mu0_2 -#-----| r0_19(glval) = FieldAddress[middle_s] : r0_18 -# 754| r0_20(String &) = Call : func:r0_16, this:r0_15, 0:r0_19 -# 754| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_22(glval) = VariableAddress[#return] : -#-----| r0_23(Middle *) = CopyValue : r0_3 -#-----| mu0_24(Middle &) = Store : &:r0_22, r0_23 -# 754| r0_25(glval) = VariableAddress[#return] : -# 754| v0_26(void) = ReturnValue : &:r0_25, ~mu0_2 -# 754| v0_27(void) = UnmodeledUse : mu* -# 754| v0_28(void) = ExitFunction : +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Middle *) = CopyValue : r0_11 +#-----| r0_13(Base *) = ConvertToBase[Middle : Base] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Base &) = CopyValue : r0_14 +# 754| r0_16(Base &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 754| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_18(glval) = CopyValue : r0_16 +#-----| r0_19(Middle *) = CopyValue : r0_3 +#-----| r0_20(glval) = FieldAddress[middle_s] : r0_19 +#-----| r0_21(String *) = CopyValue : r0_20 +# 754| r0_22(glval) = FunctionAddress[operator=] : +#-----| r0_23(glval) = VariableAddress[p#0] : +#-----| r0_24(Middle &) = Load : &:r0_23, ~mu0_2 +#-----| r0_25(glval) = CopyValue : r0_24 +#-----| r0_26(glval) = FieldAddress[middle_s] : r0_25 +#-----| r0_27(String &) = CopyValue : r0_26 +# 754| r0_28(String &) = Call : func:r0_22, this:r0_21, 0:r0_27 +# 754| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_30(glval) = CopyValue : r0_28 +#-----| r0_31(glval) = VariableAddress[#return] : +#-----| r0_32(Middle *) = CopyValue : r0_3 +#-----| r0_33(glval) = CopyValue : r0_32 +#-----| r0_34(Middle &) = CopyValue : r0_33 +#-----| mu0_35(Middle &) = Store : &:r0_31, r0_34 +# 754| r0_36(glval) = VariableAddress[#return] : +# 754| v0_37(void) = ReturnValue : &:r0_36, ~mu0_2 +# 754| v0_38(void) = UnmodeledUse : mu* +# 754| v0_39(void) = ExitFunction : # 757| void Middle::Middle() # 757| Block 0 @@ -3376,24 +3566,35 @@ ir.cpp: # 763| r0_8(glval) = FunctionAddress[operator=] : #-----| r0_9(glval) = VariableAddress[p#0] : #-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Middle *) = ConvertToBase[Derived : Middle] : r0_10 -# 763| r0_12(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 763| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_14(Derived *) = CopyValue : r0_3 -#-----| r0_15(glval) = FieldAddress[derived_s] : r0_14 -# 763| r0_16(glval) = FunctionAddress[operator=] : -#-----| r0_17(glval) = VariableAddress[p#0] : -#-----| r0_18(Derived &) = Load : &:r0_17, ~mu0_2 -#-----| r0_19(glval) = FieldAddress[derived_s] : r0_18 -# 763| r0_20(String &) = Call : func:r0_16, this:r0_15, 0:r0_19 -# 763| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_22(glval) = VariableAddress[#return] : -#-----| r0_23(Derived *) = CopyValue : r0_3 -#-----| mu0_24(Derived &) = Store : &:r0_22, r0_23 -# 763| r0_25(glval) = VariableAddress[#return] : -# 763| v0_26(void) = ReturnValue : &:r0_25, ~mu0_2 -# 763| v0_27(void) = UnmodeledUse : mu* -# 763| v0_28(void) = ExitFunction : +#-----| r0_11(glval) = CopyValue : r0_10 +#-----| r0_12(Derived *) = CopyValue : r0_11 +#-----| r0_13(Middle *) = ConvertToBase[Derived : Middle] : r0_12 +#-----| r0_14(glval) = CopyValue : r0_13 +#-----| r0_15(Middle &) = CopyValue : r0_14 +# 763| r0_16(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_15 +# 763| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_18(glval) = CopyValue : r0_16 +#-----| r0_19(Derived *) = CopyValue : r0_3 +#-----| r0_20(glval) = FieldAddress[derived_s] : r0_19 +#-----| r0_21(String *) = CopyValue : r0_20 +# 763| r0_22(glval) = FunctionAddress[operator=] : +#-----| r0_23(glval) = VariableAddress[p#0] : +#-----| r0_24(Derived &) = Load : &:r0_23, ~mu0_2 +#-----| r0_25(glval) = CopyValue : r0_24 +#-----| r0_26(glval) = FieldAddress[derived_s] : r0_25 +#-----| r0_27(String &) = CopyValue : r0_26 +# 763| r0_28(String &) = Call : func:r0_22, this:r0_21, 0:r0_27 +# 763| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_30(glval) = CopyValue : r0_28 +#-----| r0_31(glval) = VariableAddress[#return] : +#-----| r0_32(Derived *) = CopyValue : r0_3 +#-----| r0_33(glval) = CopyValue : r0_32 +#-----| r0_34(Derived &) = CopyValue : r0_33 +#-----| mu0_35(Derived &) = Store : &:r0_31, r0_34 +# 763| r0_36(glval) = VariableAddress[#return] : +# 763| v0_37(void) = ReturnValue : &:r0_36, ~mu0_2 +# 763| v0_38(void) = UnmodeledUse : mu* +# 763| v0_39(void) = ExitFunction : # 766| void Derived::Derived() # 766| Block 0 @@ -3582,193 +3783,236 @@ ir.cpp: # 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 # 804| r0_15(glval) = VariableAddress[pb] : # 804| r0_16(glval) = VariableAddress[b] : -# 804| mu0_17(Base *) = Store : &:r0_15, r0_16 -# 805| r0_18(glval) = VariableAddress[pm] : -# 805| r0_19(glval) = VariableAddress[m] : -# 805| mu0_20(Middle *) = Store : &:r0_18, r0_19 -# 806| r0_21(glval) = VariableAddress[pd] : -# 806| r0_22(glval) = VariableAddress[d] : -# 806| mu0_23(Derived *) = Store : &:r0_21, r0_22 -# 808| r0_24(glval) = VariableAddress[b] : -# 808| r0_25(glval) = FunctionAddress[operator=] : -# 808| r0_26(glval) = VariableAddress[m] : -# 808| r0_27(glval) = ConvertToBase[Middle : Base] : r0_26 -# 808| r0_28(Base &) = Call : func:r0_25, this:r0_24, 0:r0_27 -# 808| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 -# 809| r0_30(glval) = VariableAddress[b] : -# 809| r0_31(glval) = FunctionAddress[operator=] : -# 809| r0_32(glval) = FunctionAddress[Base] : -# 809| r0_33(glval) = VariableAddress[m] : -# 809| r0_34(glval) = ConvertToBase[Middle : Base] : r0_33 -# 809| v0_35(void) = Call : func:r0_32, 0:r0_34 -# 809| mu0_36(unknown) = ^CallSideEffect : ~mu0_2 -# 809| r0_37(glval) = Convert : v0_35 -# 809| r0_38(Base &) = Call : func:r0_31, this:r0_30, 0:r0_37 -# 809| mu0_39(unknown) = ^CallSideEffect : ~mu0_2 -# 810| r0_40(glval) = VariableAddress[b] : -# 810| r0_41(glval) = FunctionAddress[operator=] : -# 810| r0_42(glval) = FunctionAddress[Base] : -# 810| r0_43(glval) = VariableAddress[m] : -# 810| r0_44(glval) = ConvertToBase[Middle : Base] : r0_43 -# 810| v0_45(void) = Call : func:r0_42, 0:r0_44 -# 810| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 -# 810| r0_47(glval) = Convert : v0_45 -# 810| r0_48(Base &) = Call : func:r0_41, this:r0_40, 0:r0_47 -# 810| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 -# 811| r0_50(glval) = VariableAddress[pm] : -# 811| r0_51(Middle *) = Load : &:r0_50, ~mu0_2 -# 811| r0_52(Base *) = ConvertToBase[Middle : Base] : r0_51 -# 811| r0_53(glval) = VariableAddress[pb] : -# 811| mu0_54(Base *) = Store : &:r0_53, r0_52 -# 812| r0_55(glval) = VariableAddress[pm] : -# 812| r0_56(Middle *) = Load : &:r0_55, ~mu0_2 -# 812| r0_57(Base *) = ConvertToBase[Middle : Base] : r0_56 -# 812| r0_58(glval) = VariableAddress[pb] : -# 812| mu0_59(Base *) = Store : &:r0_58, r0_57 -# 813| r0_60(glval) = VariableAddress[pm] : -# 813| r0_61(Middle *) = Load : &:r0_60, ~mu0_2 -# 813| r0_62(Base *) = ConvertToBase[Middle : Base] : r0_61 -# 813| r0_63(glval) = VariableAddress[pb] : -# 813| mu0_64(Base *) = Store : &:r0_63, r0_62 -# 814| r0_65(glval) = VariableAddress[pm] : -# 814| r0_66(Middle *) = Load : &:r0_65, ~mu0_2 -# 814| r0_67(Base *) = Convert : r0_66 -# 814| r0_68(glval) = VariableAddress[pb] : -# 814| mu0_69(Base *) = Store : &:r0_68, r0_67 -# 816| r0_70(glval) = VariableAddress[m] : -# 816| r0_71(glval) = FunctionAddress[operator=] : -# 816| r0_72(glval) = VariableAddress[b] : -# 816| r0_73(glval) = ConvertToDerived[Middle : Base] : r0_72 -# 816| r0_74(glval) = Convert : r0_73 -# 816| r0_75(Middle &) = Call : func:r0_71, this:r0_70, 0:r0_74 -# 816| mu0_76(unknown) = ^CallSideEffect : ~mu0_2 -# 817| r0_77(glval) = VariableAddress[m] : -# 817| r0_78(glval) = FunctionAddress[operator=] : -# 817| r0_79(glval) = VariableAddress[b] : -# 817| r0_80(glval) = ConvertToDerived[Middle : Base] : r0_79 -# 817| r0_81(glval) = Convert : r0_80 -# 817| r0_82(Middle &) = Call : func:r0_78, this:r0_77, 0:r0_81 -# 817| mu0_83(unknown) = ^CallSideEffect : ~mu0_2 -# 818| r0_84(glval) = VariableAddress[pb] : -# 818| r0_85(Base *) = Load : &:r0_84, ~mu0_2 -# 818| r0_86(Middle *) = ConvertToDerived[Middle : Base] : r0_85 -# 818| r0_87(glval) = VariableAddress[pm] : -# 818| mu0_88(Middle *) = Store : &:r0_87, r0_86 -# 819| r0_89(glval) = VariableAddress[pb] : -# 819| r0_90(Base *) = Load : &:r0_89, ~mu0_2 -# 819| r0_91(Middle *) = ConvertToDerived[Middle : Base] : r0_90 -# 819| r0_92(glval) = VariableAddress[pm] : -# 819| mu0_93(Middle *) = Store : &:r0_92, r0_91 -# 820| r0_94(glval) = VariableAddress[pb] : -# 820| r0_95(Base *) = Load : &:r0_94, ~mu0_2 -# 820| r0_96(Middle *) = Convert : r0_95 -# 820| r0_97(glval) = VariableAddress[pm] : -# 820| mu0_98(Middle *) = Store : &:r0_97, r0_96 -# 822| r0_99(glval) = VariableAddress[b] : -# 822| r0_100(glval) = FunctionAddress[operator=] : -# 822| r0_101(glval) = VariableAddress[d] : -# 822| r0_102(glval) = ConvertToBase[Derived : Middle] : r0_101 -# 822| r0_103(glval) = ConvertToBase[Middle : Base] : r0_102 -# 822| r0_104(Base &) = Call : func:r0_100, this:r0_99, 0:r0_103 -# 822| mu0_105(unknown) = ^CallSideEffect : ~mu0_2 -# 823| r0_106(glval) = VariableAddress[b] : -# 823| r0_107(glval) = FunctionAddress[operator=] : -# 823| r0_108(glval) = FunctionAddress[Base] : -# 823| r0_109(glval) = VariableAddress[d] : -# 823| r0_110(glval) = ConvertToBase[Derived : Middle] : r0_109 -# 823| r0_111(glval) = ConvertToBase[Middle : Base] : r0_110 -# 823| v0_112(void) = Call : func:r0_108, 0:r0_111 -# 823| mu0_113(unknown) = ^CallSideEffect : ~mu0_2 -# 823| r0_114(glval) = Convert : v0_112 -# 823| r0_115(Base &) = Call : func:r0_107, this:r0_106, 0:r0_114 -# 823| mu0_116(unknown) = ^CallSideEffect : ~mu0_2 -# 824| r0_117(glval) = VariableAddress[b] : -# 824| r0_118(glval) = FunctionAddress[operator=] : -# 824| r0_119(glval) = FunctionAddress[Base] : -# 824| r0_120(glval) = VariableAddress[d] : -# 824| r0_121(glval) = ConvertToBase[Derived : Middle] : r0_120 -# 824| r0_122(glval) = ConvertToBase[Middle : Base] : r0_121 -# 824| v0_123(void) = Call : func:r0_119, 0:r0_122 -# 824| mu0_124(unknown) = ^CallSideEffect : ~mu0_2 -# 824| r0_125(glval) = Convert : v0_123 -# 824| r0_126(Base &) = Call : func:r0_118, this:r0_117, 0:r0_125 -# 824| mu0_127(unknown) = ^CallSideEffect : ~mu0_2 -# 825| r0_128(glval) = VariableAddress[pd] : -# 825| r0_129(Derived *) = Load : &:r0_128, ~mu0_2 -# 825| r0_130(Middle *) = ConvertToBase[Derived : Middle] : r0_129 -# 825| r0_131(Base *) = ConvertToBase[Middle : Base] : r0_130 -# 825| r0_132(glval) = VariableAddress[pb] : -# 825| mu0_133(Base *) = Store : &:r0_132, r0_131 -# 826| r0_134(glval) = VariableAddress[pd] : -# 826| r0_135(Derived *) = Load : &:r0_134, ~mu0_2 -# 826| r0_136(Middle *) = ConvertToBase[Derived : Middle] : r0_135 -# 826| r0_137(Base *) = ConvertToBase[Middle : Base] : r0_136 -# 826| r0_138(glval) = VariableAddress[pb] : -# 826| mu0_139(Base *) = Store : &:r0_138, r0_137 -# 827| r0_140(glval) = VariableAddress[pd] : -# 827| r0_141(Derived *) = Load : &:r0_140, ~mu0_2 -# 827| r0_142(Middle *) = ConvertToBase[Derived : Middle] : r0_141 -# 827| r0_143(Base *) = ConvertToBase[Middle : Base] : r0_142 -# 827| r0_144(glval) = VariableAddress[pb] : -# 827| mu0_145(Base *) = Store : &:r0_144, r0_143 -# 828| r0_146(glval) = VariableAddress[pd] : -# 828| r0_147(Derived *) = Load : &:r0_146, ~mu0_2 -# 828| r0_148(Base *) = Convert : r0_147 -# 828| r0_149(glval) = VariableAddress[pb] : -# 828| mu0_150(Base *) = Store : &:r0_149, r0_148 -# 830| r0_151(glval) = VariableAddress[d] : -# 830| r0_152(glval) = FunctionAddress[operator=] : -# 830| r0_153(glval) = VariableAddress[b] : -# 830| r0_154(glval) = ConvertToDerived[Middle : Base] : r0_153 -# 830| r0_155(glval) = ConvertToDerived[Derived : Middle] : r0_154 -# 830| r0_156(glval) = Convert : r0_155 -# 830| r0_157(Derived &) = Call : func:r0_152, this:r0_151, 0:r0_156 -# 830| mu0_158(unknown) = ^CallSideEffect : ~mu0_2 -# 831| r0_159(glval) = VariableAddress[d] : -# 831| r0_160(glval) = FunctionAddress[operator=] : -# 831| r0_161(glval) = VariableAddress[b] : -# 831| r0_162(glval) = ConvertToDerived[Middle : Base] : r0_161 -# 831| r0_163(glval) = ConvertToDerived[Derived : Middle] : r0_162 -# 831| r0_164(glval) = Convert : r0_163 -# 831| r0_165(Derived &) = Call : func:r0_160, this:r0_159, 0:r0_164 -# 831| mu0_166(unknown) = ^CallSideEffect : ~mu0_2 -# 832| r0_167(glval) = VariableAddress[pb] : -# 832| r0_168(Base *) = Load : &:r0_167, ~mu0_2 -# 832| r0_169(Middle *) = ConvertToDerived[Middle : Base] : r0_168 -# 832| r0_170(Derived *) = ConvertToDerived[Derived : Middle] : r0_169 -# 832| r0_171(glval) = VariableAddress[pd] : -# 832| mu0_172(Derived *) = Store : &:r0_171, r0_170 -# 833| r0_173(glval) = VariableAddress[pb] : -# 833| r0_174(Base *) = Load : &:r0_173, ~mu0_2 -# 833| r0_175(Middle *) = ConvertToDerived[Middle : Base] : r0_174 -# 833| r0_176(Derived *) = ConvertToDerived[Derived : Middle] : r0_175 -# 833| r0_177(glval) = VariableAddress[pd] : -# 833| mu0_178(Derived *) = Store : &:r0_177, r0_176 -# 834| r0_179(glval) = VariableAddress[pb] : -# 834| r0_180(Base *) = Load : &:r0_179, ~mu0_2 -# 834| r0_181(Derived *) = Convert : r0_180 -# 834| r0_182(glval) = VariableAddress[pd] : -# 834| mu0_183(Derived *) = Store : &:r0_182, r0_181 -# 836| r0_184(glval) = VariableAddress[pmv] : -# 836| r0_185(MiddleVB1 *) = Constant[0] : -# 836| mu0_186(MiddleVB1 *) = Store : &:r0_184, r0_185 -# 837| r0_187(glval) = VariableAddress[pdv] : -# 837| r0_188(DerivedVB *) = Constant[0] : -# 837| mu0_189(DerivedVB *) = Store : &:r0_187, r0_188 -# 838| r0_190(glval) = VariableAddress[pmv] : -# 838| r0_191(MiddleVB1 *) = Load : &:r0_190, ~mu0_2 -# 838| r0_192(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_191 -# 838| r0_193(glval) = VariableAddress[pb] : -# 838| mu0_194(Base *) = Store : &:r0_193, r0_192 -# 839| r0_195(glval) = VariableAddress[pdv] : -# 839| r0_196(DerivedVB *) = Load : &:r0_195, ~mu0_2 -# 839| r0_197(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_196 -# 839| r0_198(glval) = VariableAddress[pb] : -# 839| mu0_199(Base *) = Store : &:r0_198, r0_197 -# 840| v0_200(void) = NoOp : -# 799| v0_201(void) = ReturnVoid : -# 799| v0_202(void) = UnmodeledUse : mu* -# 799| v0_203(void) = ExitFunction : +# 804| r0_17(Base *) = CopyValue : r0_16 +# 804| mu0_18(Base *) = Store : &:r0_15, r0_17 +# 805| r0_19(glval) = VariableAddress[pm] : +# 805| r0_20(glval) = VariableAddress[m] : +# 805| r0_21(Middle *) = CopyValue : r0_20 +# 805| mu0_22(Middle *) = Store : &:r0_19, r0_21 +# 806| r0_23(glval) = VariableAddress[pd] : +# 806| r0_24(glval) = VariableAddress[d] : +# 806| r0_25(Derived *) = CopyValue : r0_24 +# 806| mu0_26(Derived *) = Store : &:r0_23, r0_25 +# 808| r0_27(glval) = VariableAddress[b] : +# 808| r0_28(glval) = FunctionAddress[operator=] : +# 808| r0_29(glval) = VariableAddress[m] : +# 808| r0_30(glval) = ConvertToBase[Middle : Base] : r0_29 +# 808| r0_31(Base &) = CopyValue : r0_30 +# 808| r0_32(Base &) = Call : func:r0_28, this:r0_27, 0:r0_31 +# 808| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 808| r0_34(glval) = CopyValue : r0_32 +# 809| r0_35(glval) = VariableAddress[b] : +# 809| r0_36(glval) = FunctionAddress[operator=] : +# 809| r0_37(glval) = FunctionAddress[Base] : +# 809| r0_38(glval) = VariableAddress[m] : +# 809| r0_39(glval) = ConvertToBase[Middle : Base] : r0_38 +# 809| r0_40(Base &) = CopyValue : r0_39 +# 809| v0_41(void) = Call : func:r0_37, 0:r0_40 +# 809| mu0_42(unknown) = ^CallSideEffect : ~mu0_2 +# 809| r0_43(glval) = Convert : v0_41 +# 809| r0_44(Base &) = CopyValue : r0_43 +# 809| r0_45(Base &) = Call : func:r0_36, this:r0_35, 0:r0_44 +# 809| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 +# 809| r0_47(glval) = CopyValue : r0_45 +# 810| r0_48(glval) = VariableAddress[b] : +# 810| r0_49(glval) = FunctionAddress[operator=] : +# 810| r0_50(glval) = FunctionAddress[Base] : +# 810| r0_51(glval) = VariableAddress[m] : +# 810| r0_52(glval) = ConvertToBase[Middle : Base] : r0_51 +# 810| r0_53(Base &) = CopyValue : r0_52 +# 810| v0_54(void) = Call : func:r0_50, 0:r0_53 +# 810| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 +# 810| r0_56(glval) = Convert : v0_54 +# 810| r0_57(Base &) = CopyValue : r0_56 +# 810| r0_58(Base &) = Call : func:r0_49, this:r0_48, 0:r0_57 +# 810| mu0_59(unknown) = ^CallSideEffect : ~mu0_2 +# 810| r0_60(glval) = CopyValue : r0_58 +# 811| r0_61(glval) = VariableAddress[pm] : +# 811| r0_62(Middle *) = Load : &:r0_61, ~mu0_2 +# 811| r0_63(Base *) = ConvertToBase[Middle : Base] : r0_62 +# 811| r0_64(glval) = VariableAddress[pb] : +# 811| mu0_65(Base *) = Store : &:r0_64, r0_63 +# 811| r0_66(glval) = CopyValue : r0_64 +# 812| r0_67(glval) = VariableAddress[pm] : +# 812| r0_68(Middle *) = Load : &:r0_67, ~mu0_2 +# 812| r0_69(Base *) = ConvertToBase[Middle : Base] : r0_68 +# 812| r0_70(glval) = VariableAddress[pb] : +# 812| mu0_71(Base *) = Store : &:r0_70, r0_69 +# 812| r0_72(glval) = CopyValue : r0_70 +# 813| r0_73(glval) = VariableAddress[pm] : +# 813| r0_74(Middle *) = Load : &:r0_73, ~mu0_2 +# 813| r0_75(Base *) = ConvertToBase[Middle : Base] : r0_74 +# 813| r0_76(glval) = VariableAddress[pb] : +# 813| mu0_77(Base *) = Store : &:r0_76, r0_75 +# 813| r0_78(glval) = CopyValue : r0_76 +# 814| r0_79(glval) = VariableAddress[pm] : +# 814| r0_80(Middle *) = Load : &:r0_79, ~mu0_2 +# 814| r0_81(Base *) = Convert : r0_80 +# 814| r0_82(glval) = VariableAddress[pb] : +# 814| mu0_83(Base *) = Store : &:r0_82, r0_81 +# 814| r0_84(glval) = CopyValue : r0_82 +# 816| r0_85(glval) = VariableAddress[m] : +# 816| r0_86(glval) = FunctionAddress[operator=] : +# 816| r0_87(glval) = VariableAddress[b] : +# 816| r0_88(glval) = ConvertToDerived[Middle : Base] : r0_87 +# 816| r0_89(glval) = Convert : r0_88 +# 816| r0_90(Middle &) = CopyValue : r0_89 +# 816| r0_91(Middle &) = Call : func:r0_86, this:r0_85, 0:r0_90 +# 816| mu0_92(unknown) = ^CallSideEffect : ~mu0_2 +# 816| r0_93(glval) = CopyValue : r0_91 +# 817| r0_94(glval) = VariableAddress[m] : +# 817| r0_95(glval) = FunctionAddress[operator=] : +# 817| r0_96(glval) = VariableAddress[b] : +# 817| r0_97(glval) = ConvertToDerived[Middle : Base] : r0_96 +# 817| r0_98(glval) = Convert : r0_97 +# 817| r0_99(Middle &) = CopyValue : r0_98 +# 817| r0_100(Middle &) = Call : func:r0_95, this:r0_94, 0:r0_99 +# 817| mu0_101(unknown) = ^CallSideEffect : ~mu0_2 +# 817| r0_102(glval) = CopyValue : r0_100 +# 818| r0_103(glval) = VariableAddress[pb] : +# 818| r0_104(Base *) = Load : &:r0_103, ~mu0_2 +# 818| r0_105(Middle *) = ConvertToDerived[Middle : Base] : r0_104 +# 818| r0_106(glval) = VariableAddress[pm] : +# 818| mu0_107(Middle *) = Store : &:r0_106, r0_105 +# 818| r0_108(glval) = CopyValue : r0_106 +# 819| r0_109(glval) = VariableAddress[pb] : +# 819| r0_110(Base *) = Load : &:r0_109, ~mu0_2 +# 819| r0_111(Middle *) = ConvertToDerived[Middle : Base] : r0_110 +# 819| r0_112(glval) = VariableAddress[pm] : +# 819| mu0_113(Middle *) = Store : &:r0_112, r0_111 +# 819| r0_114(glval) = CopyValue : r0_112 +# 820| r0_115(glval) = VariableAddress[pb] : +# 820| r0_116(Base *) = Load : &:r0_115, ~mu0_2 +# 820| r0_117(Middle *) = Convert : r0_116 +# 820| r0_118(glval) = VariableAddress[pm] : +# 820| mu0_119(Middle *) = Store : &:r0_118, r0_117 +# 820| r0_120(glval) = CopyValue : r0_118 +# 822| r0_121(glval) = VariableAddress[b] : +# 822| r0_122(glval) = FunctionAddress[operator=] : +# 822| r0_123(glval) = VariableAddress[d] : +# 822| r0_124(glval) = ConvertToBase[Derived : Middle] : r0_123 +# 822| r0_125(glval) = ConvertToBase[Middle : Base] : r0_124 +# 822| r0_126(Base &) = CopyValue : r0_125 +# 822| r0_127(Base &) = Call : func:r0_122, this:r0_121, 0:r0_126 +# 822| mu0_128(unknown) = ^CallSideEffect : ~mu0_2 +# 822| r0_129(glval) = CopyValue : r0_127 +# 823| r0_130(glval) = VariableAddress[b] : +# 823| r0_131(glval) = FunctionAddress[operator=] : +# 823| r0_132(glval) = FunctionAddress[Base] : +# 823| r0_133(glval) = VariableAddress[d] : +# 823| r0_134(glval) = ConvertToBase[Derived : Middle] : r0_133 +# 823| r0_135(glval) = ConvertToBase[Middle : Base] : r0_134 +# 823| r0_136(Base &) = CopyValue : r0_135 +# 823| v0_137(void) = Call : func:r0_132, 0:r0_136 +# 823| mu0_138(unknown) = ^CallSideEffect : ~mu0_2 +# 823| r0_139(glval) = Convert : v0_137 +# 823| r0_140(Base &) = CopyValue : r0_139 +# 823| r0_141(Base &) = Call : func:r0_131, this:r0_130, 0:r0_140 +# 823| mu0_142(unknown) = ^CallSideEffect : ~mu0_2 +# 823| r0_143(glval) = CopyValue : r0_141 +# 824| r0_144(glval) = VariableAddress[b] : +# 824| r0_145(glval) = FunctionAddress[operator=] : +# 824| r0_146(glval) = FunctionAddress[Base] : +# 824| r0_147(glval) = VariableAddress[d] : +# 824| r0_148(glval) = ConvertToBase[Derived : Middle] : r0_147 +# 824| r0_149(glval) = ConvertToBase[Middle : Base] : r0_148 +# 824| r0_150(Base &) = CopyValue : r0_149 +# 824| v0_151(void) = Call : func:r0_146, 0:r0_150 +# 824| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 +# 824| r0_153(glval) = Convert : v0_151 +# 824| r0_154(Base &) = CopyValue : r0_153 +# 824| r0_155(Base &) = Call : func:r0_145, this:r0_144, 0:r0_154 +# 824| mu0_156(unknown) = ^CallSideEffect : ~mu0_2 +# 824| r0_157(glval) = CopyValue : r0_155 +# 825| r0_158(glval) = VariableAddress[pd] : +# 825| r0_159(Derived *) = Load : &:r0_158, ~mu0_2 +# 825| r0_160(Middle *) = ConvertToBase[Derived : Middle] : r0_159 +# 825| r0_161(Base *) = ConvertToBase[Middle : Base] : r0_160 +# 825| r0_162(glval) = VariableAddress[pb] : +# 825| mu0_163(Base *) = Store : &:r0_162, r0_161 +# 825| r0_164(glval) = CopyValue : r0_162 +# 826| r0_165(glval) = VariableAddress[pd] : +# 826| r0_166(Derived *) = Load : &:r0_165, ~mu0_2 +# 826| r0_167(Middle *) = ConvertToBase[Derived : Middle] : r0_166 +# 826| r0_168(Base *) = ConvertToBase[Middle : Base] : r0_167 +# 826| r0_169(glval) = VariableAddress[pb] : +# 826| mu0_170(Base *) = Store : &:r0_169, r0_168 +# 826| r0_171(glval) = CopyValue : r0_169 +# 827| r0_172(glval) = VariableAddress[pd] : +# 827| r0_173(Derived *) = Load : &:r0_172, ~mu0_2 +# 827| r0_174(Middle *) = ConvertToBase[Derived : Middle] : r0_173 +# 827| r0_175(Base *) = ConvertToBase[Middle : Base] : r0_174 +# 827| r0_176(glval) = VariableAddress[pb] : +# 827| mu0_177(Base *) = Store : &:r0_176, r0_175 +# 827| r0_178(glval) = CopyValue : r0_176 +# 828| r0_179(glval) = VariableAddress[pd] : +# 828| r0_180(Derived *) = Load : &:r0_179, ~mu0_2 +# 828| r0_181(Base *) = Convert : r0_180 +# 828| r0_182(glval) = VariableAddress[pb] : +# 828| mu0_183(Base *) = Store : &:r0_182, r0_181 +# 828| r0_184(glval) = CopyValue : r0_182 +# 830| r0_185(glval) = VariableAddress[d] : +# 830| r0_186(glval) = FunctionAddress[operator=] : +# 830| r0_187(glval) = VariableAddress[b] : +# 830| r0_188(glval) = ConvertToDerived[Middle : Base] : r0_187 +# 830| r0_189(glval) = ConvertToDerived[Derived : Middle] : r0_188 +# 830| r0_190(glval) = Convert : r0_189 +# 830| r0_191(Derived &) = CopyValue : r0_190 +# 830| r0_192(Derived &) = Call : func:r0_186, this:r0_185, 0:r0_191 +# 830| mu0_193(unknown) = ^CallSideEffect : ~mu0_2 +# 830| r0_194(glval) = CopyValue : r0_192 +# 831| r0_195(glval) = VariableAddress[d] : +# 831| r0_196(glval) = FunctionAddress[operator=] : +# 831| r0_197(glval) = VariableAddress[b] : +# 831| r0_198(glval) = ConvertToDerived[Middle : Base] : r0_197 +# 831| r0_199(glval) = ConvertToDerived[Derived : Middle] : r0_198 +# 831| r0_200(glval) = Convert : r0_199 +# 831| r0_201(Derived &) = CopyValue : r0_200 +# 831| r0_202(Derived &) = Call : func:r0_196, this:r0_195, 0:r0_201 +# 831| mu0_203(unknown) = ^CallSideEffect : ~mu0_2 +# 831| r0_204(glval) = CopyValue : r0_202 +# 832| r0_205(glval) = VariableAddress[pb] : +# 832| r0_206(Base *) = Load : &:r0_205, ~mu0_2 +# 832| r0_207(Middle *) = ConvertToDerived[Middle : Base] : r0_206 +# 832| r0_208(Derived *) = ConvertToDerived[Derived : Middle] : r0_207 +# 832| r0_209(glval) = VariableAddress[pd] : +# 832| mu0_210(Derived *) = Store : &:r0_209, r0_208 +# 832| r0_211(glval) = CopyValue : r0_209 +# 833| r0_212(glval) = VariableAddress[pb] : +# 833| r0_213(Base *) = Load : &:r0_212, ~mu0_2 +# 833| r0_214(Middle *) = ConvertToDerived[Middle : Base] : r0_213 +# 833| r0_215(Derived *) = ConvertToDerived[Derived : Middle] : r0_214 +# 833| r0_216(glval) = VariableAddress[pd] : +# 833| mu0_217(Derived *) = Store : &:r0_216, r0_215 +# 833| r0_218(glval) = CopyValue : r0_216 +# 834| r0_219(glval) = VariableAddress[pb] : +# 834| r0_220(Base *) = Load : &:r0_219, ~mu0_2 +# 834| r0_221(Derived *) = Convert : r0_220 +# 834| r0_222(glval) = VariableAddress[pd] : +# 834| mu0_223(Derived *) = Store : &:r0_222, r0_221 +# 834| r0_224(glval) = CopyValue : r0_222 +# 836| r0_225(glval) = VariableAddress[pmv] : +# 836| r0_226(MiddleVB1 *) = Constant[0] : +# 836| mu0_227(MiddleVB1 *) = Store : &:r0_225, r0_226 +# 837| r0_228(glval) = VariableAddress[pdv] : +# 837| r0_229(DerivedVB *) = Constant[0] : +# 837| mu0_230(DerivedVB *) = Store : &:r0_228, r0_229 +# 838| r0_231(glval) = VariableAddress[pmv] : +# 838| r0_232(MiddleVB1 *) = Load : &:r0_231, ~mu0_2 +# 838| r0_233(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_232 +# 838| r0_234(glval) = VariableAddress[pb] : +# 838| mu0_235(Base *) = Store : &:r0_234, r0_233 +# 838| r0_236(glval) = CopyValue : r0_234 +# 839| r0_237(glval) = VariableAddress[pdv] : +# 839| r0_238(DerivedVB *) = Load : &:r0_237, ~mu0_2 +# 839| r0_239(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_238 +# 839| r0_240(glval) = VariableAddress[pb] : +# 839| mu0_241(Base *) = Store : &:r0_240, r0_239 +# 839| r0_242(glval) = CopyValue : r0_240 +# 840| v0_243(void) = NoOp : +# 799| v0_244(void) = ReturnVoid : +# 799| v0_245(void) = UnmodeledUse : mu* +# 799| v0_246(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -3826,42 +4070,48 @@ ir.cpp: # 851| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 # 853| r0_11(glval) = VariableAddress[pb] : # 853| r0_12(glval) = VariableAddress[b] : -# 853| mu0_13(PolymorphicBase *) = Store : &:r0_11, r0_12 -# 854| r0_14(glval) = VariableAddress[pd] : -# 854| r0_15(glval) = VariableAddress[d] : -# 854| mu0_16(PolymorphicDerived *) = Store : &:r0_14, r0_15 -# 857| r0_17(glval) = VariableAddress[pd] : -# 857| r0_18(PolymorphicDerived *) = Load : &:r0_17, ~mu0_2 -# 857| r0_19(PolymorphicBase *) = CheckedConvertOrNull : r0_18 -# 857| r0_20(glval) = VariableAddress[pb] : -# 857| mu0_21(PolymorphicBase *) = Store : &:r0_20, r0_19 -# 858| r0_22(glval) = VariableAddress[rb] : -# 858| r0_23(glval) = VariableAddress[d] : -# 858| r0_24(glval) = CheckedConvertOrThrow : r0_23 -# 858| mu0_25(PolymorphicBase &) = Store : &:r0_22, r0_24 -# 860| r0_26(glval) = VariableAddress[pb] : -# 860| r0_27(PolymorphicBase *) = Load : &:r0_26, ~mu0_2 -# 860| r0_28(PolymorphicDerived *) = CheckedConvertOrNull : r0_27 -# 860| r0_29(glval) = VariableAddress[pd] : -# 860| mu0_30(PolymorphicDerived *) = Store : &:r0_29, r0_28 -# 861| r0_31(glval) = VariableAddress[rd] : -# 861| r0_32(glval) = VariableAddress[b] : -# 861| r0_33(glval) = CheckedConvertOrThrow : r0_32 -# 861| mu0_34(PolymorphicDerived &) = Store : &:r0_31, r0_33 -# 863| r0_35(glval) = VariableAddress[pv] : -# 863| r0_36(glval) = VariableAddress[pb] : -# 863| r0_37(PolymorphicBase *) = Load : &:r0_36, ~mu0_2 -# 863| r0_38(void *) = DynamicCastToVoid : r0_37 -# 863| mu0_39(void *) = Store : &:r0_35, r0_38 -# 864| r0_40(glval) = VariableAddress[pcv] : -# 864| r0_41(glval) = VariableAddress[pd] : -# 864| r0_42(PolymorphicDerived *) = Load : &:r0_41, ~mu0_2 -# 864| r0_43(void *) = DynamicCastToVoid : r0_42 -# 864| mu0_44(void *) = Store : &:r0_40, r0_43 -# 865| v0_45(void) = NoOp : -# 849| v0_46(void) = ReturnVoid : -# 849| v0_47(void) = UnmodeledUse : mu* -# 849| v0_48(void) = ExitFunction : +# 853| r0_13(PolymorphicBase *) = CopyValue : r0_12 +# 853| mu0_14(PolymorphicBase *) = Store : &:r0_11, r0_13 +# 854| r0_15(glval) = VariableAddress[pd] : +# 854| r0_16(glval) = VariableAddress[d] : +# 854| r0_17(PolymorphicDerived *) = CopyValue : r0_16 +# 854| mu0_18(PolymorphicDerived *) = Store : &:r0_15, r0_17 +# 857| r0_19(glval) = VariableAddress[pd] : +# 857| r0_20(PolymorphicDerived *) = Load : &:r0_19, ~mu0_2 +# 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 +# 857| r0_22(glval) = VariableAddress[pb] : +# 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 +# 857| r0_24(glval) = CopyValue : r0_22 +# 858| r0_25(glval) = VariableAddress[rb] : +# 858| r0_26(glval) = VariableAddress[d] : +# 858| r0_27(glval) = CheckedConvertOrThrow : r0_26 +# 858| r0_28(PolymorphicBase &) = CopyValue : r0_27 +# 858| mu0_29(PolymorphicBase &) = Store : &:r0_25, r0_28 +# 860| r0_30(glval) = VariableAddress[pb] : +# 860| r0_31(PolymorphicBase *) = Load : &:r0_30, ~mu0_2 +# 860| r0_32(PolymorphicDerived *) = CheckedConvertOrNull : r0_31 +# 860| r0_33(glval) = VariableAddress[pd] : +# 860| mu0_34(PolymorphicDerived *) = Store : &:r0_33, r0_32 +# 860| r0_35(glval) = CopyValue : r0_33 +# 861| r0_36(glval) = VariableAddress[rd] : +# 861| r0_37(glval) = VariableAddress[b] : +# 861| r0_38(glval) = CheckedConvertOrThrow : r0_37 +# 861| r0_39(PolymorphicDerived &) = CopyValue : r0_38 +# 861| mu0_40(PolymorphicDerived &) = Store : &:r0_36, r0_39 +# 863| r0_41(glval) = VariableAddress[pv] : +# 863| r0_42(glval) = VariableAddress[pb] : +# 863| r0_43(PolymorphicBase *) = Load : &:r0_42, ~mu0_2 +# 863| r0_44(void *) = DynamicCastToVoid : r0_43 +# 863| mu0_45(void *) = Store : &:r0_41, r0_44 +# 864| r0_46(glval) = VariableAddress[pcv] : +# 864| r0_47(glval) = VariableAddress[pd] : +# 864| r0_48(PolymorphicDerived *) = Load : &:r0_47, ~mu0_2 +# 864| r0_49(void *) = DynamicCastToVoid : r0_48 +# 864| mu0_50(void *) = Store : &:r0_46, r0_49 +# 865| v0_51(void) = NoOp : +# 849| v0_52(void) = ReturnVoid : +# 849| v0_53(void) = UnmodeledUse : mu* +# 849| v0_54(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -3895,36 +4145,46 @@ ir.cpp: # 874| r0_11(char *) = Convert : r0_10 # 874| r0_12(glval) = VariableAddress[p] : # 874| mu0_13(char *) = Store : &:r0_12, r0_11 -# 875| r0_14(glval) = VariableAddress[a] : -# 875| r0_15(char *) = Convert : r0_14 -# 875| r0_16(int) = Constant[0] : -# 875| r0_17(glval) = PointerAdd[1] : r0_15, r0_16 -# 875| r0_18(char *) = Convert : r0_17 -# 875| r0_19(glval) = VariableAddress[p] : -# 875| mu0_20(char *) = Store : &:r0_19, r0_18 -# 876| r0_21(glval) = StringConstant["test"] : -# 876| r0_22(char *) = Convert : r0_21 -# 876| r0_23(int) = Constant[0] : -# 876| r0_24(glval) = PointerAdd[1] : r0_22, r0_23 -# 876| r0_25(glval) = VariableAddress[p] : -# 876| mu0_26(char *) = Store : &:r0_25, r0_24 -# 877| r0_27(glval) = VariableAddress[ra] : -# 877| r0_28(glval) = VariableAddress[a] : -# 877| mu0_29(char(&)[5]) = Store : &:r0_27, r0_28 -# 878| r0_30(glval) = VariableAddress[rs] : -# 878| r0_31(glval) = StringConstant["test"] : -# 878| mu0_32(char(&)[5]) = Store : &:r0_30, r0_31 -# 879| r0_33(glval) = VariableAddress[pa] : -# 879| r0_34(glval) = VariableAddress[a] : -# 879| r0_35(char(*)[5]) = Convert : r0_34 -# 879| mu0_36(char(*)[5]) = Store : &:r0_33, r0_35 -# 880| r0_37(glval) = StringConstant["test"] : -# 880| r0_38(glval) = VariableAddress[pa] : -# 880| mu0_39(char(*)[5]) = Store : &:r0_38, r0_37 -# 881| v0_40(void) = NoOp : -# 871| v0_41(void) = ReturnVoid : -# 871| v0_42(void) = UnmodeledUse : mu* -# 871| v0_43(void) = ExitFunction : +# 874| r0_14(glval) = CopyValue : r0_12 +# 875| r0_15(glval) = VariableAddress[a] : +# 875| r0_16(char *) = Convert : r0_15 +# 875| r0_17(int) = Constant[0] : +# 875| r0_18(glval) = PointerAdd[1] : r0_16, r0_17 +# 875| r0_19(char *) = CopyValue : r0_18 +# 875| r0_20(char *) = Convert : r0_19 +# 875| r0_21(glval) = VariableAddress[p] : +# 875| mu0_22(char *) = Store : &:r0_21, r0_20 +# 875| r0_23(glval) = CopyValue : r0_21 +# 876| r0_24(glval) = StringConstant["test"] : +# 876| r0_25(char *) = Convert : r0_24 +# 876| r0_26(int) = Constant[0] : +# 876| r0_27(glval) = PointerAdd[1] : r0_25, r0_26 +# 876| r0_28(char *) = CopyValue : r0_27 +# 876| r0_29(glval) = VariableAddress[p] : +# 876| mu0_30(char *) = Store : &:r0_29, r0_28 +# 876| r0_31(glval) = CopyValue : r0_29 +# 877| r0_32(glval) = VariableAddress[ra] : +# 877| r0_33(glval) = VariableAddress[a] : +# 877| r0_34(char(&)[5]) = CopyValue : r0_33 +# 877| mu0_35(char(&)[5]) = Store : &:r0_32, r0_34 +# 878| r0_36(glval) = VariableAddress[rs] : +# 878| r0_37(glval) = StringConstant["test"] : +# 878| r0_38(char(&)[5]) = CopyValue : r0_37 +# 878| mu0_39(char(&)[5]) = Store : &:r0_36, r0_38 +# 879| r0_40(glval) = VariableAddress[pa] : +# 879| r0_41(glval) = VariableAddress[a] : +# 879| r0_42(char(*)[5]) = CopyValue : r0_41 +# 879| r0_43(char(*)[5]) = Convert : r0_42 +# 879| mu0_44(char(*)[5]) = Store : &:r0_40, r0_43 +# 880| r0_45(glval) = StringConstant["test"] : +# 880| r0_46(char(*)[5]) = CopyValue : r0_45 +# 880| r0_47(glval) = VariableAddress[pa] : +# 880| mu0_48(char(*)[5]) = Store : &:r0_47, r0_46 +# 880| r0_49(glval) = CopyValue : r0_47 +# 881| v0_50(void) = NoOp : +# 871| v0_51(void) = ReturnVoid : +# 871| v0_52(void) = UnmodeledUse : mu* +# 871| v0_53(void) = ExitFunction : # 883| void FuncPtrConversions(int(*)(int), void*) # 883| Block 0 @@ -3940,15 +4200,17 @@ ir.cpp: # 884| r0_9(void *) = Convert : r0_8 # 884| r0_10(glval) = VariableAddress[p] : # 884| mu0_11(void *) = Store : &:r0_10, r0_9 -# 885| r0_12(glval) = VariableAddress[p] : -# 885| r0_13(void *) = Load : &:r0_12, ~mu0_2 -# 885| r0_14(..(*)(..)) = Convert : r0_13 -# 885| r0_15(glval<..(*)(..)>) = VariableAddress[pfn] : -# 885| mu0_16(..(*)(..)) = Store : &:r0_15, r0_14 -# 886| v0_17(void) = NoOp : -# 883| v0_18(void) = ReturnVoid : -# 883| v0_19(void) = UnmodeledUse : mu* -# 883| v0_20(void) = ExitFunction : +# 884| r0_12(glval) = CopyValue : r0_10 +# 885| r0_13(glval) = VariableAddress[p] : +# 885| r0_14(void *) = Load : &:r0_13, ~mu0_2 +# 885| r0_15(..(*)(..)) = Convert : r0_14 +# 885| r0_16(glval<..(*)(..)>) = VariableAddress[pfn] : +# 885| mu0_17(..(*)(..)) = Store : &:r0_16, r0_15 +# 885| r0_18(glval<..(*)(..)>) = CopyValue : r0_16 +# 886| v0_19(void) = NoOp : +# 883| v0_20(void) = ReturnVoid : +# 883| v0_21(void) = UnmodeledUse : mu* +# 883| v0_22(void) = ExitFunction : # 888| void VarArgUsage(int) # 888| Block 0 @@ -4246,7 +4508,8 @@ ir.cpp: # 967| mu0_13(bool) = Store : &:r0_7, r0_12 # 967| r0_14(glval) = VariableAddress[b] : # 967| r0_15(bool) = Load : &:r0_14, ~mu0_2 -# 967| v0_16(void) = ConditionalBranch : r0_15 +# 967| r0_16(bool) = CopyValue : r0_15 +# 967| v0_17(void) = ConditionalBranch : r0_16 #-----| False -> Block 2 #-----| True -> Block 1 @@ -4254,6 +4517,7 @@ ir.cpp: # 968| r1_0(int) = Constant[5] : # 968| r1_1(glval) = VariableAddress[x] : # 968| mu1_2(int) = Store : &:r1_1, r1_0 +# 968| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 6 # 970| Block 2 @@ -4268,7 +4532,8 @@ ir.cpp: # 970| r2_8(int) = Load : &:r2_7, ~mu0_2 # 970| r2_9(int) = Constant[0] : # 970| r2_10(bool) = CompareNE : r2_8, r2_9 -# 970| v2_11(void) = ConditionalBranch : r2_10 +# 970| r2_11(bool) = CopyValue : r2_10 +# 970| v2_12(void) = ConditionalBranch : r2_11 #-----| False -> Block 4 #-----| True -> Block 3 @@ -4276,17 +4541,20 @@ ir.cpp: # 971| r3_0(int) = Constant[7] : # 971| r3_1(glval) = VariableAddress[y] : # 971| mu3_2(int) = Store : &:r3_1, r3_0 +# 971| r3_3(glval) = CopyValue : r3_1 #-----| Goto -> Block 6 # 973| Block 4 # 973| r4_0(glval) = VariableAddress[p] : # 973| r4_1(glval) = VariableAddress[x] : -# 973| mu4_2(int *) = Store : &:r4_0, r4_1 -# 973| r4_3(glval) = VariableAddress[p] : -# 973| r4_4(int *) = Load : &:r4_3, ~mu0_2 -# 973| r4_5(int *) = Constant[0] : -# 973| r4_6(bool) = CompareNE : r4_4, r4_5 -# 973| v4_7(void) = ConditionalBranch : r4_6 +# 973| r4_2(int *) = CopyValue : r4_1 +# 973| mu4_3(int *) = Store : &:r4_0, r4_2 +# 973| r4_4(glval) = VariableAddress[p] : +# 973| r4_5(int *) = Load : &:r4_4, ~mu0_2 +# 973| r4_6(int *) = Constant[0] : +# 973| r4_7(bool) = CompareNE : r4_5, r4_6 +# 973| r4_8(bool) = CopyValue : r4_7 +# 973| v4_9(void) = ConditionalBranch : r4_8 #-----| False -> Block 6 #-----| True -> Block 5 @@ -4294,7 +4562,9 @@ ir.cpp: # 974| r5_0(int) = Constant[2] : # 974| r5_1(glval) = VariableAddress[p] : # 974| r5_2(int *) = Load : &:r5_1, ~mu0_2 -# 974| mu5_3(int) = Store : &:r5_2, r5_0 +# 974| r5_3(glval) = CopyValue : r5_2 +# 974| mu5_4(int) = Store : &:r5_3, r5_0 +# 974| r5_5(glval) = CopyValue : r5_3 #-----| Goto -> Block 6 # 976| Block 6 @@ -4330,7 +4600,8 @@ ir.cpp: # 981| r2_8(int) = Load : &:r2_7, ~mu0_2 # 981| r2_9(int) = Constant[0] : # 981| r2_10(bool) = CompareNE : r2_8, r2_9 -# 981| v2_11(void) = ConditionalBranch : r2_10 +# 981| r2_11(bool) = CopyValue : r2_10 +# 981| v2_12(void) = ConditionalBranch : r2_11 #-----| False -> Block 4 #-----| True -> Block 3 @@ -4341,12 +4612,14 @@ ir.cpp: # 983| Block 4 # 983| r4_0(glval) = VariableAddress[p] : # 983| r4_1(glval) = VariableAddress[x] : -# 983| mu4_2(int *) = Store : &:r4_0, r4_1 -# 983| r4_3(glval) = VariableAddress[p] : -# 983| r4_4(int *) = Load : &:r4_3, ~mu0_2 -# 983| r4_5(int *) = Constant[0] : -# 983| r4_6(bool) = CompareNE : r4_4, r4_5 -# 983| v4_7(void) = ConditionalBranch : r4_6 +# 983| r4_2(int *) = CopyValue : r4_1 +# 983| mu4_3(int *) = Store : &:r4_0, r4_2 +# 983| r4_4(glval) = VariableAddress[p] : +# 983| r4_5(int *) = Load : &:r4_4, ~mu0_2 +# 983| r4_6(int *) = Constant[0] : +# 983| r4_7(bool) = CompareNE : r4_5, r4_6 +# 983| r4_8(bool) = CopyValue : r4_7 +# 983| v4_9(void) = ConditionalBranch : r4_8 #-----| False -> Block 6 #-----| True -> Block 5 @@ -4370,7 +4643,8 @@ ir.cpp: # 979| mu7_6(bool) = Store : &:r7_0, r7_5 # 979| r7_7(glval) = VariableAddress[b] : # 979| r7_8(bool) = Load : &:r7_7, ~mu0_2 -# 979| v7_9(void) = ConditionalBranch : r7_8 +# 979| r7_9(bool) = CopyValue : r7_8 +# 979| v7_10(void) = ConditionalBranch : r7_9 #-----| False -> Block 2 #-----| True -> Block 1 @@ -4428,6 +4702,7 @@ ir.cpp: # 995| r1_1(int) = Load : &:r1_0, ~mu0_2 # 995| r1_2(glval) = VariableAddress[w] : # 995| mu1_3(int) = Store : &:r1_2, r1_1 +# 995| r1_4(glval) = CopyValue : r1_2 #-----| Goto -> Block 3 # 997| Block 2 @@ -4435,6 +4710,7 @@ ir.cpp: # 997| r2_1(int) = Load : &:r2_0, ~mu0_2 # 997| r2_2(glval) = VariableAddress[w] : # 997| mu2_3(int) = Store : &:r2_2, r2_1 +# 997| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 999| Block 3 @@ -4544,147 +4820,159 @@ ir.cpp: # 1031| void Lambda(int, String const&) # 1031| Block 0 -# 1031| v0_0(void) = EnterFunction : -# 1031| mu0_1(unknown) = AliasedDefinition : -# 1031| mu0_2(unknown) = UnmodeledDefinition : -# 1031| r0_3(glval) = VariableAddress[x] : -# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 -# 1031| r0_5(glval) = VariableAddress[s] : -# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 -# 1032| r0_7(glval) = VariableAddress[lambda_empty] : -# 1032| r0_8(glval) = VariableAddress[#temp1032:23] : -# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8 -# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2 -# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10 -# 1033| r0_12(char) = Constant[65] : -# 1034| r0_13(glval) = VariableAddress[lambda_ref] : -# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : -# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 -# 1034| r0_16(glval) = FieldAddress[s] : r0_14 -#-----| r0_17(glval) = VariableAddress[s] : -#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 -# 1034| mu0_19(String &) = Store : &:r0_16, r0_18 -# 1034| r0_20(glval) = FieldAddress[x] : r0_14 -#-----| r0_21(glval) = VariableAddress[x] : -#-----| mu0_22(int &) = Store : &:r0_20, r0_21 -# 1034| r0_23(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2 -# 1034| mu0_24(decltype([...](...){...})) = Store : &:r0_13, r0_23 -# 1035| r0_25(glval) = VariableAddress[lambda_ref] : -# 1035| r0_26(glval) = Convert : r0_25 -# 1035| r0_27(glval) = FunctionAddress[operator()] : -# 1035| r0_28(float) = Constant[1.0] : -# 1035| r0_29(char) = Call : func:r0_27, this:r0_26, 0:r0_28 -# 1035| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_31(glval) = VariableAddress[lambda_val] : -# 1036| r0_32(glval) = FunctionAddress[(constructor)] : -# 1036| r0_33(glval) = VariableAddress[#temp1036:21] : -# 1036| mu0_34(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_33 -# 1036| r0_35(glval) = FieldAddress[s] : r0_33 -#-----| r0_36(glval) = FunctionAddress[String] : -#-----| v0_37(void) = Call : func:r0_36, this:r0_35 -#-----| mu0_38(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_39(glval) = FieldAddress[x] : r0_33 -#-----| r0_40(glval) = VariableAddress[x] : -#-----| r0_41(int) = Load : &:r0_40, ~mu0_2 -#-----| mu0_42(int) = Store : &:r0_39, r0_41 -# 1036| r0_43(decltype([...](...){...})) = Load : &:r0_33, ~mu0_2 -# 1036| v0_44(void) = Call : func:r0_32, this:r0_31, 0:r0_43 -# 1036| mu0_45(unknown) = ^CallSideEffect : ~mu0_2 -# 1037| r0_46(glval) = VariableAddress[lambda_val] : -# 1037| r0_47(glval) = Convert : r0_46 -# 1037| r0_48(glval) = FunctionAddress[operator()] : -# 1037| r0_49(float) = Constant[2.0] : -# 1037| r0_50(char) = Call : func:r0_48, this:r0_47, 0:r0_49 -# 1037| mu0_51(unknown) = ^CallSideEffect : ~mu0_2 -# 1038| r0_52(glval) = VariableAddress[lambda_ref_explicit] : -# 1038| r0_53(glval) = VariableAddress[#temp1038:30] : -# 1038| mu0_54(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_53 -# 1038| r0_55(glval) = FieldAddress[s] : r0_53 -# 1038| r0_56(glval) = VariableAddress[s] : -# 1038| r0_57(String &) = Load : &:r0_56, ~mu0_2 -# 1038| mu0_58(String &) = Store : &:r0_55, r0_57 -# 1038| r0_59(decltype([...](...){...})) = Load : &:r0_53, ~mu0_2 -# 1038| mu0_60(decltype([...](...){...})) = Store : &:r0_52, r0_59 -# 1039| r0_61(glval) = VariableAddress[lambda_ref_explicit] : -# 1039| r0_62(glval) = Convert : r0_61 -# 1039| r0_63(glval) = FunctionAddress[operator()] : -# 1039| r0_64(float) = Constant[3.0] : -# 1039| r0_65(char) = Call : func:r0_63, this:r0_62, 0:r0_64 -# 1039| mu0_66(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_67(glval) = VariableAddress[lambda_val_explicit] : -# 1040| r0_68(glval) = FunctionAddress[(constructor)] : -# 1040| r0_69(glval) = VariableAddress[#temp1040:30] : -# 1040| mu0_70(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_69 -# 1040| r0_71(glval) = FieldAddress[s] : r0_69 -#-----| r0_72(glval) = FunctionAddress[String] : -#-----| v0_73(void) = Call : func:r0_72, this:r0_71 -#-----| mu0_74(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_75(decltype([...](...){...})) = Load : &:r0_69, ~mu0_2 -# 1040| v0_76(void) = Call : func:r0_68, this:r0_67, 0:r0_75 -# 1040| mu0_77(unknown) = ^CallSideEffect : ~mu0_2 -# 1041| r0_78(glval) = VariableAddress[lambda_val_explicit] : -# 1041| r0_79(glval) = Convert : r0_78 -# 1041| r0_80(glval) = FunctionAddress[operator()] : -# 1041| r0_81(float) = Constant[4.0] : -# 1041| r0_82(char) = Call : func:r0_80, this:r0_79, 0:r0_81 -# 1041| mu0_83(unknown) = ^CallSideEffect : ~mu0_2 -# 1042| r0_84(glval) = VariableAddress[lambda_mixed_explicit] : -# 1042| r0_85(glval) = VariableAddress[#temp1042:32] : -# 1042| mu0_86(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_85 -# 1042| r0_87(glval) = FieldAddress[s] : r0_85 -# 1042| r0_88(glval) = VariableAddress[s] : -# 1042| r0_89(String &) = Load : &:r0_88, ~mu0_2 -# 1042| mu0_90(String &) = Store : &:r0_87, r0_89 -# 1042| r0_91(glval) = FieldAddress[x] : r0_85 -# 1042| r0_92(glval) = VariableAddress[x] : -# 1042| r0_93(int) = Load : &:r0_92, ~mu0_2 -# 1042| mu0_94(int) = Store : &:r0_91, r0_93 -# 1042| r0_95(decltype([...](...){...})) = Load : &:r0_85, ~mu0_2 -# 1042| mu0_96(decltype([...](...){...})) = Store : &:r0_84, r0_95 -# 1043| r0_97(glval) = VariableAddress[lambda_mixed_explicit] : -# 1043| r0_98(glval) = Convert : r0_97 -# 1043| r0_99(glval) = FunctionAddress[operator()] : -# 1043| r0_100(float) = Constant[5.0] : -# 1043| r0_101(char) = Call : func:r0_99, this:r0_98, 0:r0_100 -# 1043| mu0_102(unknown) = ^CallSideEffect : ~mu0_2 -# 1044| r0_103(glval) = VariableAddress[r] : -# 1044| r0_104(glval) = VariableAddress[x] : -# 1044| r0_105(int) = Load : &:r0_104, ~mu0_2 -# 1044| r0_106(int) = Constant[1] : -# 1044| r0_107(int) = Sub : r0_105, r0_106 -# 1044| mu0_108(int) = Store : &:r0_103, r0_107 -# 1045| r0_109(glval) = VariableAddress[lambda_inits] : -# 1045| r0_110(glval) = VariableAddress[#temp1045:23] : -# 1045| mu0_111(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_110 -# 1045| r0_112(glval) = FieldAddress[s] : r0_110 -# 1045| r0_113(glval) = VariableAddress[s] : -# 1045| r0_114(String &) = Load : &:r0_113, ~mu0_2 -# 1045| mu0_115(String &) = Store : &:r0_112, r0_114 -# 1045| r0_116(glval) = FieldAddress[x] : r0_110 -# 1045| r0_117(glval) = VariableAddress[x] : -# 1045| r0_118(int) = Load : &:r0_117, ~mu0_2 -# 1045| mu0_119(int) = Store : &:r0_116, r0_118 -# 1045| r0_120(glval) = FieldAddress[i] : r0_110 -# 1045| r0_121(glval) = VariableAddress[x] : -# 1045| r0_122(int) = Load : &:r0_121, ~mu0_2 -# 1045| r0_123(int) = Constant[1] : -# 1045| r0_124(int) = Add : r0_122, r0_123 -# 1045| mu0_125(int) = Store : &:r0_120, r0_124 -# 1045| r0_126(glval) = FieldAddress[j] : r0_110 -# 1045| r0_127(glval) = VariableAddress[r] : -# 1045| mu0_128(int &) = Store : &:r0_126, r0_127 -# 1045| r0_129(decltype([...](...){...})) = Load : &:r0_110, ~mu0_2 -# 1045| mu0_130(decltype([...](...){...})) = Store : &:r0_109, r0_129 -# 1046| r0_131(glval) = VariableAddress[lambda_inits] : -# 1046| r0_132(glval) = Convert : r0_131 -# 1046| r0_133(glval) = FunctionAddress[operator()] : -# 1046| r0_134(float) = Constant[6.0] : -# 1046| r0_135(char) = Call : func:r0_133, this:r0_132, 0:r0_134 -# 1046| mu0_136(unknown) = ^CallSideEffect : ~mu0_2 -# 1047| v0_137(void) = NoOp : -# 1031| v0_138(void) = ReturnVoid : -# 1031| v0_139(void) = UnmodeledUse : mu* -# 1031| v0_140(void) = ExitFunction : +# 1031| v0_0(void) = EnterFunction : +# 1031| mu0_1(unknown) = AliasedDefinition : +# 1031| mu0_2(unknown) = UnmodeledDefinition : +# 1031| r0_3(glval) = VariableAddress[x] : +# 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 +# 1031| r0_5(glval) = VariableAddress[s] : +# 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 +# 1032| r0_7(glval) = VariableAddress[lambda_empty] : +# 1032| r0_8(glval) = VariableAddress[#temp1032:23] : +# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8 +# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2 +# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10 +# 1033| r0_12(char) = Constant[65] : +# 1034| r0_13(glval) = VariableAddress[lambda_ref] : +# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : +# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 +# 1034| r0_16(glval) = FieldAddress[s] : r0_14 +#-----| r0_17(glval) = VariableAddress[s] : +#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 +# 1034| r0_19(glval) = CopyValue : r0_18 +# 1034| r0_20(String &) = CopyValue : r0_19 +# 1034| mu0_21(String &) = Store : &:r0_16, r0_20 +# 1034| r0_22(glval) = FieldAddress[x] : r0_14 +#-----| r0_23(glval) = VariableAddress[x] : +#-----| r0_24(int &) = CopyValue : r0_23 +#-----| mu0_25(int &) = Store : &:r0_22, r0_24 +# 1034| r0_26(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2 +# 1034| mu0_27(decltype([...](...){...})) = Store : &:r0_13, r0_26 +# 1035| r0_28(glval) = VariableAddress[lambda_ref] : +# 1035| r0_29(glval) = Convert : r0_28 +# 1035| r0_30(glval) = FunctionAddress[operator()] : +# 1035| r0_31(float) = Constant[1.0] : +# 1035| r0_32(char) = Call : func:r0_30, this:r0_29, 0:r0_31 +# 1035| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| r0_34(glval) = VariableAddress[lambda_val] : +# 1036| r0_35(glval) = FunctionAddress[(constructor)] : +# 1036| r0_36(glval) = VariableAddress[#temp1036:21] : +# 1036| mu0_37(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_36 +# 1036| r0_38(glval) = FieldAddress[s] : r0_36 +#-----| r0_39(glval) = FunctionAddress[String] : +#-----| v0_40(void) = Call : func:r0_39, this:r0_38 +#-----| mu0_41(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| r0_42(glval) = FieldAddress[x] : r0_36 +#-----| r0_43(glval) = VariableAddress[x] : +#-----| r0_44(int) = Load : &:r0_43, ~mu0_2 +#-----| mu0_45(int) = Store : &:r0_42, r0_44 +# 1036| r0_46(decltype([...](...){...})) = Load : &:r0_36, ~mu0_2 +# 1036| r0_47(lambda [] type at line 1036, col. 21 &) = CopyValue : r0_46 +# 1036| v0_48(void) = Call : func:r0_35, this:r0_34, 0:r0_47 +# 1036| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 +# 1037| r0_50(glval) = VariableAddress[lambda_val] : +# 1037| r0_51(glval) = Convert : r0_50 +# 1037| r0_52(glval) = FunctionAddress[operator()] : +# 1037| r0_53(float) = Constant[2.0] : +# 1037| r0_54(char) = Call : func:r0_52, this:r0_51, 0:r0_53 +# 1037| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 +# 1038| r0_56(glval) = VariableAddress[lambda_ref_explicit] : +# 1038| r0_57(glval) = VariableAddress[#temp1038:30] : +# 1038| mu0_58(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_57 +# 1038| r0_59(glval) = FieldAddress[s] : r0_57 +# 1038| r0_60(glval) = VariableAddress[s] : +# 1038| r0_61(String &) = Load : &:r0_60, ~mu0_2 +# 1038| r0_62(glval) = CopyValue : r0_61 +# 1038| r0_63(String &) = CopyValue : r0_62 +# 1038| mu0_64(String &) = Store : &:r0_59, r0_63 +# 1038| r0_65(decltype([...](...){...})) = Load : &:r0_57, ~mu0_2 +# 1038| mu0_66(decltype([...](...){...})) = Store : &:r0_56, r0_65 +# 1039| r0_67(glval) = VariableAddress[lambda_ref_explicit] : +# 1039| r0_68(glval) = Convert : r0_67 +# 1039| r0_69(glval) = FunctionAddress[operator()] : +# 1039| r0_70(float) = Constant[3.0] : +# 1039| r0_71(char) = Call : func:r0_69, this:r0_68, 0:r0_70 +# 1039| mu0_72(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| r0_73(glval) = VariableAddress[lambda_val_explicit] : +# 1040| r0_74(glval) = FunctionAddress[(constructor)] : +# 1040| r0_75(glval) = VariableAddress[#temp1040:30] : +# 1040| mu0_76(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_75 +# 1040| r0_77(glval) = FieldAddress[s] : r0_75 +#-----| r0_78(glval) = FunctionAddress[String] : +#-----| v0_79(void) = Call : func:r0_78, this:r0_77 +#-----| mu0_80(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| r0_81(decltype([...](...){...})) = Load : &:r0_75, ~mu0_2 +# 1040| r0_82(lambda [] type at line 1040, col. 30 &) = CopyValue : r0_81 +# 1040| v0_83(void) = Call : func:r0_74, this:r0_73, 0:r0_82 +# 1040| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 +# 1041| r0_85(glval) = VariableAddress[lambda_val_explicit] : +# 1041| r0_86(glval) = Convert : r0_85 +# 1041| r0_87(glval) = FunctionAddress[operator()] : +# 1041| r0_88(float) = Constant[4.0] : +# 1041| r0_89(char) = Call : func:r0_87, this:r0_86, 0:r0_88 +# 1041| mu0_90(unknown) = ^CallSideEffect : ~mu0_2 +# 1042| r0_91(glval) = VariableAddress[lambda_mixed_explicit] : +# 1042| r0_92(glval) = VariableAddress[#temp1042:32] : +# 1042| mu0_93(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_92 +# 1042| r0_94(glval) = FieldAddress[s] : r0_92 +# 1042| r0_95(glval) = VariableAddress[s] : +# 1042| r0_96(String &) = Load : &:r0_95, ~mu0_2 +# 1042| r0_97(glval) = CopyValue : r0_96 +# 1042| r0_98(String &) = CopyValue : r0_97 +# 1042| mu0_99(String &) = Store : &:r0_94, r0_98 +# 1042| r0_100(glval) = FieldAddress[x] : r0_92 +# 1042| r0_101(glval) = VariableAddress[x] : +# 1042| r0_102(int) = Load : &:r0_101, ~mu0_2 +# 1042| mu0_103(int) = Store : &:r0_100, r0_102 +# 1042| r0_104(decltype([...](...){...})) = Load : &:r0_92, ~mu0_2 +# 1042| mu0_105(decltype([...](...){...})) = Store : &:r0_91, r0_104 +# 1043| r0_106(glval) = VariableAddress[lambda_mixed_explicit] : +# 1043| r0_107(glval) = Convert : r0_106 +# 1043| r0_108(glval) = FunctionAddress[operator()] : +# 1043| r0_109(float) = Constant[5.0] : +# 1043| r0_110(char) = Call : func:r0_108, this:r0_107, 0:r0_109 +# 1043| mu0_111(unknown) = ^CallSideEffect : ~mu0_2 +# 1044| r0_112(glval) = VariableAddress[r] : +# 1044| r0_113(glval) = VariableAddress[x] : +# 1044| r0_114(int) = Load : &:r0_113, ~mu0_2 +# 1044| r0_115(int) = Constant[1] : +# 1044| r0_116(int) = Sub : r0_114, r0_115 +# 1044| mu0_117(int) = Store : &:r0_112, r0_116 +# 1045| r0_118(glval) = VariableAddress[lambda_inits] : +# 1045| r0_119(glval) = VariableAddress[#temp1045:23] : +# 1045| mu0_120(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_119 +# 1045| r0_121(glval) = FieldAddress[s] : r0_119 +# 1045| r0_122(glval) = VariableAddress[s] : +# 1045| r0_123(String &) = Load : &:r0_122, ~mu0_2 +# 1045| r0_124(glval) = CopyValue : r0_123 +# 1045| r0_125(String &) = CopyValue : r0_124 +# 1045| mu0_126(String &) = Store : &:r0_121, r0_125 +# 1045| r0_127(glval) = FieldAddress[x] : r0_119 +# 1045| r0_128(glval) = VariableAddress[x] : +# 1045| r0_129(int) = Load : &:r0_128, ~mu0_2 +# 1045| mu0_130(int) = Store : &:r0_127, r0_129 +# 1045| r0_131(glval) = FieldAddress[i] : r0_119 +# 1045| r0_132(glval) = VariableAddress[x] : +# 1045| r0_133(int) = Load : &:r0_132, ~mu0_2 +# 1045| r0_134(int) = Constant[1] : +# 1045| r0_135(int) = Add : r0_133, r0_134 +# 1045| mu0_136(int) = Store : &:r0_131, r0_135 +# 1045| r0_137(glval) = FieldAddress[j] : r0_119 +# 1045| r0_138(glval) = VariableAddress[r] : +# 1045| r0_139(int &) = CopyValue : r0_138 +# 1045| mu0_140(int &) = Store : &:r0_137, r0_139 +# 1045| r0_141(decltype([...](...){...})) = Load : &:r0_119, ~mu0_2 +# 1045| mu0_142(decltype([...](...){...})) = Store : &:r0_118, r0_141 +# 1046| r0_143(glval) = VariableAddress[lambda_inits] : +# 1046| r0_144(glval) = Convert : r0_143 +# 1046| r0_145(glval) = FunctionAddress[operator()] : +# 1046| r0_146(float) = Constant[6.0] : +# 1046| r0_147(char) = Call : func:r0_145, this:r0_144, 0:r0_146 +# 1046| mu0_148(unknown) = ^CallSideEffect : ~mu0_2 +# 1047| v0_149(void) = NoOp : +# 1031| v0_150(void) = ReturnVoid : +# 1031| v0_151(void) = UnmodeledUse : mu* +# 1031| v0_152(void) = ExitFunction : # 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&) # 1032| Block 0 @@ -4741,20 +5029,21 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1034| r0_10(glval) = FunctionAddress[c_str] : -# 1034| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1034| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_13(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 -#-----| r0_14(glval) = FieldAddress[x] : r0_13 -#-----| r0_15(int &) = Load : &:r0_14, ~mu0_2 -# 1034| r0_16(int) = Load : &:r0_15, ~mu0_2 -# 1034| r0_17(glval) = PointerAdd[1] : r0_11, r0_16 -# 1034| r0_18(char) = Load : &:r0_17, ~mu0_2 -# 1034| mu0_19(char) = Store : &:r0_6, r0_18 -# 1034| r0_20(glval) = VariableAddress[#return] : -# 1034| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 -# 1034| v0_22(void) = UnmodeledUse : mu* -# 1034| v0_23(void) = ExitFunction : +# 1034| r0_10(glval) = CopyValue : r0_9 +# 1034| r0_11(glval) = FunctionAddress[c_str] : +# 1034| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1034| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_14(lambda [] type at line 1034, col. 21 *) = CopyValue : r0_3 +#-----| r0_15(glval) = FieldAddress[x] : r0_14 +#-----| r0_16(int &) = Load : &:r0_15, ~mu0_2 +# 1034| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 1034| r0_18(glval) = PointerAdd[1] : r0_12, r0_17 +# 1034| r0_19(char) = Load : &:r0_18, ~mu0_2 +# 1034| mu0_20(char) = Store : &:r0_6, r0_19 +# 1034| r0_21(glval) = VariableAddress[#return] : +# 1034| v0_22(void) = ReturnValue : &:r0_21, ~mu0_2 +# 1034| v0_23(void) = UnmodeledUse : mu* +# 1034| v0_24(void) = ExitFunction : # 1036| void (void Lambda(int, String const&))::(lambda [] type at line 1036, col. 21)::~() # 1036| Block 0 @@ -4808,17 +5097,18 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1038, col. 30 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1038| r0_10(glval) = FunctionAddress[c_str] : -# 1038| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1038| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 1038| r0_13(int) = Constant[0] : -# 1038| r0_14(glval) = PointerAdd[1] : r0_11, r0_13 -# 1038| r0_15(char) = Load : &:r0_14, ~mu0_2 -# 1038| mu0_16(char) = Store : &:r0_6, r0_15 -# 1038| r0_17(glval) = VariableAddress[#return] : -# 1038| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 -# 1038| v0_19(void) = UnmodeledUse : mu* -# 1038| v0_20(void) = ExitFunction : +# 1038| r0_10(glval) = CopyValue : r0_9 +# 1038| r0_11(glval) = FunctionAddress[c_str] : +# 1038| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1038| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 1038| r0_14(int) = Constant[0] : +# 1038| r0_15(glval) = PointerAdd[1] : r0_12, r0_14 +# 1038| r0_16(char) = Load : &:r0_15, ~mu0_2 +# 1038| mu0_17(char) = Store : &:r0_6, r0_16 +# 1038| r0_18(glval) = VariableAddress[#return] : +# 1038| v0_19(void) = ReturnValue : &:r0_18, ~mu0_2 +# 1038| v0_20(void) = UnmodeledUse : mu* +# 1038| v0_21(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) # 1040| Block 0 @@ -4887,19 +5177,20 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1042| r0_10(glval) = FunctionAddress[c_str] : -# 1042| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1042| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_13(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 -#-----| r0_14(glval) = FieldAddress[x] : r0_13 -#-----| r0_15(int) = Load : &:r0_14, ~mu0_2 -# 1042| r0_16(glval) = PointerAdd[1] : r0_11, r0_15 -# 1042| r0_17(char) = Load : &:r0_16, ~mu0_2 -# 1042| mu0_18(char) = Store : &:r0_6, r0_17 -# 1042| r0_19(glval) = VariableAddress[#return] : -# 1042| v0_20(void) = ReturnValue : &:r0_19, ~mu0_2 -# 1042| v0_21(void) = UnmodeledUse : mu* -# 1042| v0_22(void) = ExitFunction : +# 1042| r0_10(glval) = CopyValue : r0_9 +# 1042| r0_11(glval) = FunctionAddress[c_str] : +# 1042| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1042| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_14(lambda [] type at line 1042, col. 32 *) = CopyValue : r0_3 +#-----| r0_15(glval) = FieldAddress[x] : r0_14 +#-----| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 1042| r0_17(glval) = PointerAdd[1] : r0_12, r0_16 +# 1042| r0_18(char) = Load : &:r0_17, ~mu0_2 +# 1042| mu0_19(char) = Store : &:r0_6, r0_18 +# 1042| r0_20(glval) = VariableAddress[#return] : +# 1042| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 +# 1042| v0_22(void) = UnmodeledUse : mu* +# 1042| v0_23(void) = ExitFunction : # 1045| char (void Lambda(int, String const&))::(lambda [] type at line 1045, col. 23)::operator()(float) const # 1045| Block 0 @@ -4913,28 +5204,29 @@ ir.cpp: #-----| r0_7(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 #-----| r0_8(glval) = FieldAddress[s] : r0_7 #-----| r0_9(String &) = Load : &:r0_8, ~mu0_2 -# 1045| r0_10(glval) = FunctionAddress[c_str] : -# 1045| r0_11(char *) = Call : func:r0_10, this:r0_9 -# 1045| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -#-----| r0_13(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -#-----| r0_14(glval) = FieldAddress[x] : r0_13 -#-----| r0_15(int) = Load : &:r0_14, ~mu0_2 -#-----| r0_16(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -# 1045| r0_17(glval) = FieldAddress[i] : r0_16 -# 1045| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 1045| r0_19(int) = Add : r0_15, r0_18 -#-----| r0_20(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 -# 1045| r0_21(glval) = FieldAddress[j] : r0_20 -# 1045| r0_22(int &) = Load : &:r0_21, ~mu0_2 -# 1045| r0_23(int) = Load : &:r0_22, ~mu0_2 -# 1045| r0_24(int) = Sub : r0_19, r0_23 -# 1045| r0_25(glval) = PointerAdd[1] : r0_11, r0_24 -# 1045| r0_26(char) = Load : &:r0_25, ~mu0_2 -# 1045| mu0_27(char) = Store : &:r0_6, r0_26 -# 1045| r0_28(glval) = VariableAddress[#return] : -# 1045| v0_29(void) = ReturnValue : &:r0_28, ~mu0_2 -# 1045| v0_30(void) = UnmodeledUse : mu* -# 1045| v0_31(void) = ExitFunction : +# 1045| r0_10(glval) = CopyValue : r0_9 +# 1045| r0_11(glval) = FunctionAddress[c_str] : +# 1045| r0_12(char *) = Call : func:r0_11, this:r0_10 +# 1045| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +#-----| r0_14(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +#-----| r0_15(glval) = FieldAddress[x] : r0_14 +#-----| r0_16(int) = Load : &:r0_15, ~mu0_2 +#-----| r0_17(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +# 1045| r0_18(glval) = FieldAddress[i] : r0_17 +# 1045| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 1045| r0_20(int) = Add : r0_16, r0_19 +#-----| r0_21(lambda [] type at line 1045, col. 23 *) = CopyValue : r0_3 +# 1045| r0_22(glval) = FieldAddress[j] : r0_21 +# 1045| r0_23(int &) = Load : &:r0_22, ~mu0_2 +# 1045| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 1045| r0_25(int) = Sub : r0_20, r0_24 +# 1045| r0_26(glval) = PointerAdd[1] : r0_12, r0_25 +# 1045| r0_27(char) = Load : &:r0_26, ~mu0_2 +# 1045| mu0_28(char) = Store : &:r0_6, r0_27 +# 1045| r0_29(glval) = VariableAddress[#return] : +# 1045| v0_30(void) = ReturnValue : &:r0_29, ~mu0_2 +# 1045| v0_31(void) = UnmodeledUse : mu* +# 1045| v0_32(void) = ExitFunction : # 1068| void RangeBasedFor(vector const&) # 1068| Block 0 @@ -4946,132 +5238,144 @@ ir.cpp: # 1069| r0_5(glval &>) = VariableAddress[(__range)] : # 1069| r0_6(glval &>) = VariableAddress[v] : # 1069| r0_7(vector &) = Load : &:r0_6, ~mu0_2 -# 1069| mu0_8(vector &) = Store : &:r0_5, r0_7 -# 1069| r0_9(glval) = VariableAddress[(__begin)] : -#-----| r0_10(glval &>) = VariableAddress[(__range)] : -#-----| r0_11(vector &) = Load : &:r0_10, ~mu0_2 -# 1069| r0_12(glval) = FunctionAddress[begin] : -# 1069| r0_13(iterator) = Call : func:r0_12, this:r0_11 -# 1069| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| mu0_15(iterator) = Store : &:r0_9, r0_13 -# 1069| r0_16(glval) = VariableAddress[(__end)] : -#-----| r0_17(glval &>) = VariableAddress[(__range)] : -#-----| r0_18(vector &) = Load : &:r0_17, ~mu0_2 -# 1069| r0_19(glval) = FunctionAddress[end] : -# 1069| r0_20(iterator) = Call : func:r0_19, this:r0_18 -# 1069| mu0_21(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| mu0_22(iterator) = Store : &:r0_16, r0_20 -#-----| Goto -> Block 1 - -#-----| Block 1 -#-----| r1_0(glval) = VariableAddress[(__begin)] : -#-----| r1_1(glval) = Convert : r1_0 -# 1069| r1_2(glval) = FunctionAddress[operator!=] : -#-----| r1_3(glval) = VariableAddress[(__end)] : -#-----| r1_4(iterator) = Load : &:r1_3, ~mu0_2 -# 1069| r1_5(bool) = Call : func:r1_2, this:r1_1, 0:r1_4 -# 1069| mu1_6(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| v1_7(void) = ConditionalBranch : r1_5 -#-----| False -> Block 5 -#-----| True -> Block 2 +# 1069| r0_8(glval>) = CopyValue : r0_7 +# 1069| r0_9(vector &) = CopyValue : r0_8 +# 1069| mu0_10(vector &) = Store : &:r0_5, r0_9 +# 1069| r0_11(glval) = VariableAddress[(__begin)] : +#-----| r0_12(glval &>) = VariableAddress[(__range)] : +#-----| r0_13(vector &) = Load : &:r0_12, ~mu0_2 +#-----| r0_14(glval>) = CopyValue : r0_13 +# 1069| r0_15(glval) = FunctionAddress[begin] : +# 1069| r0_16(iterator) = Call : func:r0_15, this:r0_14 +# 1069| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| mu0_18(iterator) = Store : &:r0_11, r0_16 +# 1069| r0_19(glval) = VariableAddress[(__end)] : +#-----| r0_20(glval &>) = VariableAddress[(__range)] : +#-----| r0_21(vector &) = Load : &:r0_20, ~mu0_2 +#-----| r0_22(glval>) = CopyValue : r0_21 +# 1069| r0_23(glval) = FunctionAddress[end] : +# 1069| r0_24(iterator) = Call : func:r0_23, this:r0_22 +# 1069| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| mu0_26(iterator) = Store : &:r0_19, r0_24 +#-----| Goto -> Block 3 -# 1069| Block 2 -# 1069| r2_0(glval) = VariableAddress[e] : -#-----| r2_1(glval) = VariableAddress[(__begin)] : -#-----| r2_2(glval) = Convert : r2_1 -# 1069| r2_3(glval) = FunctionAddress[operator*] : -# 1069| r2_4(int &) = Call : func:r2_3, this:r2_2 -# 1069| mu2_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1069| r2_6(int) = Load : &:r2_4, ~mu0_2 -# 1069| mu2_7(int) = Store : &:r2_0, r2_6 -# 1070| r2_8(glval) = VariableAddress[e] : -# 1070| r2_9(int) = Load : &:r2_8, ~mu0_2 -# 1070| r2_10(int) = Constant[0] : -# 1070| r2_11(bool) = CompareGT : r2_9, r2_10 -# 1070| v2_12(void) = ConditionalBranch : r2_11 -#-----| False -> Block 4 -#-----| True -> Block 3 +# 1077| Block 1 +# 1077| v1_0(void) = NoOp : +#-----| Goto -> Block 2 -# 1071| Block 3 -# 1071| v3_0(void) = NoOp : -#-----| Goto -> Block 4 +# 1079| Block 2 +# 1079| v2_0(void) = NoOp : +# 1080| v2_1(void) = NoOp : +# 1068| v2_2(void) = ReturnVoid : +# 1068| v2_3(void) = UnmodeledUse : mu* +# 1068| v2_4(void) = ExitFunction : + +#-----| Block 3 +#-----| r3_0(glval) = VariableAddress[(__begin)] : +#-----| r3_1(glval) = Convert : r3_0 +# 1069| r3_2(glval) = FunctionAddress[operator!=] : +#-----| r3_3(glval) = VariableAddress[(__end)] : +#-----| r3_4(iterator) = Load : &:r3_3, ~mu0_2 +# 1069| r3_5(bool) = Call : func:r3_2, this:r3_1, 0:r3_4 +# 1069| mu3_6(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| v3_7(void) = ConditionalBranch : r3_5 +#-----| False -> Block 7 +#-----| True -> Block 4 # 1069| Block 4 -# 1069| v4_0(void) = NoOp : -#-----| r4_1(glval) = VariableAddress[(__begin)] : -# 1069| r4_2(glval) = FunctionAddress[operator++] : -# 1069| r4_3(iterator &) = Call : func:r4_2, this:r4_1 -# 1069| mu4_4(unknown) = ^CallSideEffect : ~mu0_2 -#-----| Goto (back edge) -> Block 1 +# 1069| r4_0(glval) = VariableAddress[e] : +#-----| r4_1(glval) = VariableAddress[(__begin)] : +#-----| r4_2(glval) = Convert : r4_1 +# 1069| r4_3(glval) = FunctionAddress[operator*] : +# 1069| r4_4(int &) = Call : func:r4_3, this:r4_2 +# 1069| mu4_5(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| r4_6(int) = Load : &:r4_4, ~mu0_2 +# 1069| mu4_7(int) = Store : &:r4_0, r4_6 +# 1070| r4_8(glval) = VariableAddress[e] : +# 1070| r4_9(int) = Load : &:r4_8, ~mu0_2 +# 1070| r4_10(int) = Constant[0] : +# 1070| r4_11(bool) = CompareGT : r4_9, r4_10 +# 1070| v4_12(void) = ConditionalBranch : r4_11 +#-----| False -> Block 6 +#-----| True -> Block 5 -# 1075| Block 5 -# 1075| r5_0(glval &>) = VariableAddress[(__range)] : -# 1075| r5_1(glval &>) = VariableAddress[v] : -# 1075| r5_2(vector &) = Load : &:r5_1, ~mu0_2 -# 1075| mu5_3(vector &) = Store : &:r5_0, r5_2 -# 1075| r5_4(glval) = VariableAddress[(__begin)] : -#-----| r5_5(glval &>) = VariableAddress[(__range)] : -#-----| r5_6(vector &) = Load : &:r5_5, ~mu0_2 -# 1075| r5_7(glval) = FunctionAddress[begin] : -# 1075| r5_8(iterator) = Call : func:r5_7, this:r5_6 -# 1075| mu5_9(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| mu5_10(iterator) = Store : &:r5_4, r5_8 -# 1075| r5_11(glval) = VariableAddress[(__end)] : -#-----| r5_12(glval &>) = VariableAddress[(__range)] : -#-----| r5_13(vector &) = Load : &:r5_12, ~mu0_2 -# 1075| r5_14(glval) = FunctionAddress[end] : -# 1075| r5_15(iterator) = Call : func:r5_14, this:r5_13 -# 1075| mu5_16(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| mu5_17(iterator) = Store : &:r5_11, r5_15 +# 1071| Block 5 +# 1071| v5_0(void) = NoOp : #-----| Goto -> Block 6 -#-----| Block 6 -#-----| r6_0(glval) = VariableAddress[(__begin)] : -#-----| r6_1(glval) = Convert : r6_0 -# 1075| r6_2(glval) = FunctionAddress[operator!=] : -#-----| r6_3(glval) = VariableAddress[(__end)] : -#-----| r6_4(iterator) = Load : &:r6_3, ~mu0_2 -# 1075| r6_5(bool) = Call : func:r6_2, this:r6_1, 0:r6_4 -# 1075| mu6_6(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| v6_7(void) = ConditionalBranch : r6_5 -#-----| False -> Block 10 -#-----| True -> Block 8 - -#-----| Block 7 -#-----| r7_0(glval) = VariableAddress[(__begin)] : -# 1075| r7_1(glval) = FunctionAddress[operator++] : -# 1075| r7_2(iterator &) = Call : func:r7_1, this:r7_0 -# 1075| mu7_3(unknown) = ^CallSideEffect : ~mu0_2 -#-----| Goto (back edge) -> Block 6 - -# 1075| Block 8 -# 1075| r8_0(glval) = VariableAddress[e] : -#-----| r8_1(glval) = VariableAddress[(__begin)] : -#-----| r8_2(glval) = Convert : r8_1 -# 1075| r8_3(glval) = FunctionAddress[operator*] : -# 1075| r8_4(int &) = Call : func:r8_3, this:r8_2 -# 1075| mu8_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1075| r8_6(glval) = Convert : r8_4 -# 1075| mu8_7(int &) = Store : &:r8_0, r8_6 -# 1076| r8_8(glval) = VariableAddress[e] : -# 1076| r8_9(int &) = Load : &:r8_8, ~mu0_2 -# 1076| r8_10(int) = Load : &:r8_9, ~mu0_2 -# 1076| r8_11(int) = Constant[5] : -# 1076| r8_12(bool) = CompareLT : r8_10, r8_11 -# 1076| v8_13(void) = ConditionalBranch : r8_12 -#-----| False -> Block 7 -#-----| True -> Block 9 +# 1069| Block 6 +# 1069| v6_0(void) = NoOp : +#-----| r6_1(glval) = VariableAddress[(__begin)] : +# 1069| r6_2(glval) = FunctionAddress[operator++] : +# 1069| r6_3(iterator &) = Call : func:r6_2, this:r6_1 +# 1069| mu6_4(unknown) = ^CallSideEffect : ~mu0_2 +# 1069| r6_5(glval) = CopyValue : r6_3 +#-----| Goto (back edge) -> Block 3 -# 1077| Block 9 -# 1077| v9_0(void) = NoOp : -#-----| Goto -> Block 10 +# 1075| Block 7 +# 1075| r7_0(glval &>) = VariableAddress[(__range)] : +# 1075| r7_1(glval &>) = VariableAddress[v] : +# 1075| r7_2(vector &) = Load : &:r7_1, ~mu0_2 +# 1075| r7_3(glval>) = CopyValue : r7_2 +# 1075| r7_4(vector &) = CopyValue : r7_3 +# 1075| mu7_5(vector &) = Store : &:r7_0, r7_4 +# 1075| r7_6(glval) = VariableAddress[(__begin)] : +#-----| r7_7(glval &>) = VariableAddress[(__range)] : +#-----| r7_8(vector &) = Load : &:r7_7, ~mu0_2 +#-----| r7_9(glval>) = CopyValue : r7_8 +# 1075| r7_10(glval) = FunctionAddress[begin] : +# 1075| r7_11(iterator) = Call : func:r7_10, this:r7_9 +# 1075| mu7_12(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| mu7_13(iterator) = Store : &:r7_6, r7_11 +# 1075| r7_14(glval) = VariableAddress[(__end)] : +#-----| r7_15(glval &>) = VariableAddress[(__range)] : +#-----| r7_16(vector &) = Load : &:r7_15, ~mu0_2 +#-----| r7_17(glval>) = CopyValue : r7_16 +# 1075| r7_18(glval) = FunctionAddress[end] : +# 1075| r7_19(iterator) = Call : func:r7_18, this:r7_17 +# 1075| mu7_20(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| mu7_21(iterator) = Store : &:r7_14, r7_19 +#-----| Goto -> Block 8 -# 1079| Block 10 -# 1079| v10_0(void) = NoOp : -# 1080| v10_1(void) = NoOp : -# 1068| v10_2(void) = ReturnVoid : -# 1068| v10_3(void) = UnmodeledUse : mu* -# 1068| v10_4(void) = ExitFunction : +#-----| Block 8 +#-----| r8_0(glval) = VariableAddress[(__begin)] : +#-----| r8_1(glval) = Convert : r8_0 +# 1075| r8_2(glval) = FunctionAddress[operator!=] : +#-----| r8_3(glval) = VariableAddress[(__end)] : +#-----| r8_4(iterator) = Load : &:r8_3, ~mu0_2 +# 1075| r8_5(bool) = Call : func:r8_2, this:r8_1, 0:r8_4 +# 1075| mu8_6(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| v8_7(void) = ConditionalBranch : r8_5 +#-----| False -> Block 2 +#-----| True -> Block 10 + +#-----| Block 9 +#-----| r9_0(glval) = VariableAddress[(__begin)] : +# 1075| r9_1(glval) = FunctionAddress[operator++] : +# 1075| r9_2(iterator &) = Call : func:r9_1, this:r9_0 +# 1075| mu9_3(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| r9_4(glval) = CopyValue : r9_2 +#-----| Goto (back edge) -> Block 8 + +# 1075| Block 10 +# 1075| r10_0(glval) = VariableAddress[e] : +#-----| r10_1(glval) = VariableAddress[(__begin)] : +#-----| r10_2(glval) = Convert : r10_1 +# 1075| r10_3(glval) = FunctionAddress[operator*] : +# 1075| r10_4(int &) = Call : func:r10_3, this:r10_2 +# 1075| mu10_5(unknown) = ^CallSideEffect : ~mu0_2 +# 1075| r10_6(glval) = CopyValue : r10_4 +# 1075| r10_7(glval) = Convert : r10_6 +# 1075| r10_8(int &) = CopyValue : r10_7 +# 1075| mu10_9(int &) = Store : &:r10_0, r10_8 +# 1076| r10_10(glval) = VariableAddress[e] : +# 1076| r10_11(int &) = Load : &:r10_10, ~mu0_2 +# 1076| r10_12(int) = Load : &:r10_11, ~mu0_2 +# 1076| r10_13(int) = Constant[5] : +# 1076| r10_14(bool) = CompareLT : r10_12, r10_13 +# 1076| v10_15(void) = ConditionalBranch : r10_14 +#-----| False -> Block 9 +#-----| True -> Block 1 # 1099| int AsmStmt(int) # 1099| Block 0 @@ -5154,6 +5458,7 @@ ir.cpp: # 1130| r2_2(int) = Constant[1] : # 1130| r2_3(int) = Add : r2_1, r2_2 # 1130| mu2_4(int) = Store : &:r2_0, r2_3 +# 1130| r2_5(glval) = CopyValue : r2_0 #-----| Goto (back edge) -> Block 1 # 1130| Block 3 @@ -5219,6 +5524,7 @@ ir.cpp: # 1140| r6_4(int) = Load : &:r6_3, ~mu0_2 # 1140| r6_5(glval) = VariableAddress[x] : # 1140| mu6_6(int) = Store : &:r6_5, r6_4 +# 1140| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 1140| Block 7 @@ -5235,6 +5541,7 @@ ir.cpp: # 1142| r8_0(int) = Constant[7] : # 1142| r8_1(glval) = VariableAddress[x] : # 1142| mu8_2(int) = Store : &:r8_1, r8_0 +# 1142| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 13 # 1144| Block 9 @@ -5309,28 +5616,30 @@ ir.cpp: # 1156| r0_34(int) = Load : &:r0_33, ~mu0_2 # 1156| r0_35(glval) = PointerAdd[4] : r0_32, r0_34 # 1156| mu0_36(int) = Store : &:r0_35, r0_31 -# 1157| r0_37(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : -# 1157| r0_38(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1157| r0_39(__attribute((vector_size(16))) int) = Load : &:r0_38, ~mu0_2 -# 1157| r0_40(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1157| r0_41(__attribute((vector_size(16))) int) = Load : &:r0_40, ~mu0_2 -#-----| r0_42(int) = Constant[3] : -# 1157| r0_43(int) = Constant[2] : -# 1157| r0_44(int) = Constant[1] : -# 1157| r0_45(int) = Constant[0] : -# 1157| r0_46(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_39, 1:r0_41, 2:r0_42, 3:r0_43, 4:r0_44, 5:r0_45 -# 1157| mu0_47(__attribute((vector_size(16))) int) = Store : &:r0_37, r0_46 -# 1158| r0_48(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1158| r0_49(__attribute((vector_size(16))) int) = Load : &:r0_48, ~mu0_2 -# 1158| r0_50(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : -# 1158| r0_51(__attribute((vector_size(16))) int) = Load : &:r0_50, ~mu0_2 -# 1158| r0_52(__attribute((vector_size(16))) int) = Add : r0_49, r0_51 -# 1158| r0_53(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : -# 1158| mu0_54(__attribute((vector_size(16))) int) = Store : &:r0_53, r0_52 -# 1159| v0_55(void) = NoOp : -# 1153| v0_56(void) = ReturnVoid : -# 1153| v0_57(void) = UnmodeledUse : mu* -# 1153| v0_58(void) = ExitFunction : +# 1156| r0_37(glval) = CopyValue : r0_35 +# 1157| r0_38(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : +# 1157| r0_39(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1157| r0_40(__attribute((vector_size(16))) int) = Load : &:r0_39, ~mu0_2 +# 1157| r0_41(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1157| r0_42(__attribute((vector_size(16))) int) = Load : &:r0_41, ~mu0_2 +#-----| r0_43(int) = Constant[3] : +# 1157| r0_44(int) = Constant[2] : +# 1157| r0_45(int) = Constant[1] : +# 1157| r0_46(int) = Constant[0] : +# 1157| r0_47(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_40, 1:r0_42, 2:r0_43, 3:r0_44, 4:r0_45, 5:r0_46 +# 1157| mu0_48(__attribute((vector_size(16))) int) = Store : &:r0_38, r0_47 +# 1158| r0_49(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1158| r0_50(__attribute((vector_size(16))) int) = Load : &:r0_49, ~mu0_2 +# 1158| r0_51(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4_shuffle] : +# 1158| r0_52(__attribute((vector_size(16))) int) = Load : &:r0_51, ~mu0_2 +# 1158| r0_53(__attribute((vector_size(16))) int) = Add : r0_50, r0_52 +# 1158| r0_54(glval<__attribute((vector_size(16))) int>) = VariableAddress[vi4] : +# 1158| mu0_55(__attribute((vector_size(16))) int) = Store : &:r0_54, r0_53 +# 1158| r0_56(glval<__attribute((vector_size(16))) int>) = CopyValue : r0_54 +# 1159| v0_57(void) = NoOp : +# 1153| v0_58(void) = ReturnVoid : +# 1153| v0_59(void) = UnmodeledUse : mu* +# 1153| v0_60(void) = ExitFunction : perf-regression.cpp: # 6| void Big::Big() diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index fe11d99f31f6..f3f5101dcb47 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -211,8 +211,10 @@ ssa.cpp: # 70| r1_3(int) = Constant[1] : # 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3 # 70| m1_5(char *) = Store : &:r1_1, r1_4 -# 70| m1_6(char) = Store : &:r1_2, r1_0 -# 70| m1_7(unknown) = Chi : total:m3_0, partial:m1_6 +# 70| r1_6(glval) = CopyValue : r1_2 +# 70| m1_7(char) = Store : &:r1_6, r1_0 +# 70| m1_8(unknown) = Chi : total:m3_0, partial:m1_7 +# 70| r1_9(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -222,7 +224,7 @@ ssa.cpp: # 68| v2_3(void) = ExitFunction : # 69| Block 3 -# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_7 +# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_8 # 69| m3_1(int) = Phi : from 0:m0_4, from 1:m3_7 # 69| m3_2(char *) = Phi : from 0:m0_6, from 1:m1_5 # 69| r3_3(glval) = VariableAddress[n] : @@ -262,20 +264,23 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 81| r1_3(int) = Constant[4] : -# 81| r1_4(glval) = VariableAddress[y] : -# 81| m1_5(int) = Store : &:r1_4, r1_3 +# 80| r1_3(glval) = CopyValue : r1_1 +# 81| r1_4(int) = Constant[4] : +# 81| r1_5(glval) = VariableAddress[y] : +# 81| m1_6(int) = Store : &:r1_5, r1_4 +# 81| r1_7(glval) = CopyValue : r1_5 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 +# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -323,14 +328,15 @@ ssa.cpp: # 96| m0_9(Point) = Store : &:r0_6, r0_8 # 97| r0_10(glval) = FunctionAddress[Escape] : # 97| r0_11(glval) = VariableAddress[a] : -# 97| r0_12(void *) = Convert : r0_11 -# 97| v0_13(void) = Call : func:r0_10, 0:r0_12 -# 97| m0_14(unknown) = ^CallSideEffect : ~m0_5 -# 97| m0_15(unknown) = Chi : total:m0_5, partial:m0_14 -# 98| v0_16(void) = NoOp : -# 95| v0_17(void) = ReturnVoid : -# 95| v0_18(void) = UnmodeledUse : mu* -# 95| v0_19(void) = ExitFunction : +# 97| r0_12(Point *) = CopyValue : r0_11 +# 97| r0_13(void *) = Convert : r0_12 +# 97| v0_14(void) = Call : func:r0_10, 0:r0_13 +# 97| m0_15(unknown) = ^CallSideEffect : ~m0_5 +# 97| m0_16(unknown) = Chi : total:m0_5, partial:m0_15 +# 98| v0_17(void) = NoOp : +# 95| v0_18(void) = ReturnVoid : +# 95| v0_19(void) = UnmodeledUse : mu* +# 95| v0_20(void) = ExitFunction : # 100| void MustTotallyOverlap(Point) # 100| Block 0 @@ -374,14 +380,15 @@ ssa.cpp: # 107| m0_15(int) = Store : &:r0_11, r0_14 # 108| r0_16(glval) = FunctionAddress[Escape] : # 108| r0_17(glval) = VariableAddress[a] : -# 108| r0_18(void *) = Convert : r0_17 -# 108| v0_19(void) = Call : func:r0_16, 0:r0_18 -# 108| m0_20(unknown) = ^CallSideEffect : ~m0_5 -# 108| m0_21(unknown) = Chi : total:m0_5, partial:m0_20 -# 109| v0_22(void) = NoOp : -# 105| v0_23(void) = ReturnVoid : -# 105| v0_24(void) = UnmodeledUse : mu* -# 105| v0_25(void) = ExitFunction : +# 108| r0_18(Point *) = CopyValue : r0_17 +# 108| r0_19(void *) = Convert : r0_18 +# 108| v0_20(void) = Call : func:r0_16, 0:r0_19 +# 108| m0_21(unknown) = ^CallSideEffect : ~m0_5 +# 108| m0_22(unknown) = Chi : total:m0_5, partial:m0_21 +# 109| v0_23(void) = NoOp : +# 105| v0_24(void) = ReturnVoid : +# 105| v0_25(void) = UnmodeledUse : mu* +# 105| v0_26(void) = ExitFunction : # 111| void MayPartiallyOverlap(int, int) # 111| Block 0 @@ -441,14 +448,15 @@ ssa.cpp: # 118| m0_23(Point) = Store : &:r0_20, r0_22 # 119| r0_24(glval) = FunctionAddress[Escape] : # 119| r0_25(glval) = VariableAddress[a] : -# 119| r0_26(void *) = Convert : r0_25 -# 119| v0_27(void) = Call : func:r0_24, 0:r0_26 -# 119| m0_28(unknown) = ^CallSideEffect : ~m0_19 -# 119| m0_29(unknown) = Chi : total:m0_19, partial:m0_28 -# 120| v0_30(void) = NoOp : -# 116| v0_31(void) = ReturnVoid : -# 116| v0_32(void) = UnmodeledUse : mu* -# 116| v0_33(void) = ExitFunction : +# 119| r0_26(Point *) = CopyValue : r0_25 +# 119| r0_27(void *) = Convert : r0_26 +# 119| v0_28(void) = Call : func:r0_24, 0:r0_27 +# 119| m0_29(unknown) = ^CallSideEffect : ~m0_19 +# 119| m0_30(unknown) = Chi : total:m0_19, partial:m0_29 +# 120| v0_31(void) = NoOp : +# 116| v0_32(void) = ReturnVoid : +# 116| v0_33(void) = UnmodeledUse : mu* +# 116| v0_34(void) = ExitFunction : # 122| void MergeMustExactlyOverlap(bool, int, int) # 122| Block 0 @@ -484,6 +492,7 @@ ssa.cpp: # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| m1_4(int) = Store : &:r1_3, r1_1 # 125| m1_5(Point) = Chi : total:m0_18, partial:m1_4 +# 125| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -493,6 +502,7 @@ ssa.cpp: # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| m2_4(int) = Store : &:r2_3, r2_1 # 128| m2_5(Point) = Chi : total:m0_18, partial:m2_4 +# 128| r2_6(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -546,6 +556,7 @@ ssa.cpp: # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| m1_4(int) = Store : &:r1_3, r1_1 # 137| m1_5(Point) = Chi : total:m0_18, partial:m1_4 +# 137| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -553,6 +564,7 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| m2_3(Point) = Store : &:r2_2, r2_1 +# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -602,6 +614,7 @@ ssa.cpp: # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| m1_4(int) = Store : &:r1_3, r1_1 # 148| m1_5(Point) = Chi : total:m0_18, partial:m1_4 +# 148| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -609,6 +622,7 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| m2_3(Point) = Store : &:r2_2, r2_1 +# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -657,6 +671,7 @@ ssa.cpp: # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| m1_5(int) = Store : &:r1_4, r1_1 # 159| m1_6(Rect) = Chi : total:m0_18, partial:m1_5 +# 159| r1_7(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -664,6 +679,7 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| m2_3(Rect) = Store : &:r2_2, r2_1 +# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -698,19 +714,22 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| m0_17(int) = Store : &:r0_16, r0_14 -# 175| r0_18(glval) = VariableAddress[w] : -# 175| r0_19(glval) = FieldAddress[f] : r0_18 -# 175| r0_20(int) = Load : &:r0_19, m0_17 -# 175| r0_21(glval) = VariableAddress[a] : -# 175| m0_22(int) = Store : &:r0_21, r0_20 -# 176| r0_23(glval) = VariableAddress[w] : -# 176| r0_24(Wrapper) = Load : &:r0_23, ~m0_17 -# 176| r0_25(glval) = VariableAddress[x] : -# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 -# 177| v0_27(void) = NoOp : -# 171| v0_28(void) = ReturnVoid : -# 171| v0_29(void) = UnmodeledUse : mu* -# 171| v0_30(void) = ExitFunction : +# 174| r0_18(glval) = CopyValue : r0_16 +# 175| r0_19(glval) = VariableAddress[w] : +# 175| r0_20(glval) = FieldAddress[f] : r0_19 +# 175| r0_21(int) = Load : &:r0_20, m0_17 +# 175| r0_22(glval) = VariableAddress[a] : +# 175| m0_23(int) = Store : &:r0_22, r0_21 +# 175| r0_24(glval) = CopyValue : r0_22 +# 176| r0_25(glval) = VariableAddress[w] : +# 176| r0_26(Wrapper) = Load : &:r0_25, ~m0_17 +# 176| r0_27(glval) = VariableAddress[x] : +# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 +# 176| r0_29(glval) = CopyValue : r0_27 +# 177| v0_30(void) = NoOp : +# 171| v0_31(void) = ReturnVoid : +# 171| v0_32(void) = UnmodeledUse : mu* +# 171| v0_33(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -791,19 +810,21 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 201| r0_30(glval) = FunctionAddress[abs] : -# 201| r0_31(glval) = VariableAddress[x] : -# 201| r0_32(int) = Load : &:r0_31, m0_8 -# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 -# 201| r0_34(glval) = VariableAddress[ret] : -# 201| r0_35(int) = Load : &:r0_34, m0_29 -# 201| r0_36(int) = Add : r0_35, r0_33 -# 201| m0_37(int) = Store : &:r0_34, r0_36 -# 202| r0_38(glval) = VariableAddress[#return] : -# 202| r0_39(glval) = VariableAddress[ret] : -# 202| r0_40(int) = Load : &:r0_39, m0_37 -# 202| m0_41(int) = Store : &:r0_38, r0_40 -# 198| r0_42(glval) = VariableAddress[#return] : -# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 -# 198| v0_44(void) = UnmodeledUse : mu* -# 198| v0_45(void) = ExitFunction : +# 200| r0_30(glval) = CopyValue : r0_26 +# 201| r0_31(glval) = FunctionAddress[abs] : +# 201| r0_32(glval) = VariableAddress[x] : +# 201| r0_33(int) = Load : &:r0_32, m0_8 +# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 +# 201| r0_35(glval) = VariableAddress[ret] : +# 201| r0_36(int) = Load : &:r0_35, m0_29 +# 201| r0_37(int) = Add : r0_36, r0_34 +# 201| m0_38(int) = Store : &:r0_35, r0_37 +# 201| r0_39(glval) = CopyValue : r0_35 +# 202| r0_40(glval) = VariableAddress[#return] : +# 202| r0_41(glval) = VariableAddress[ret] : +# 202| r0_42(int) = Load : &:r0_41, m0_38 +# 202| m0_43(int) = Store : &:r0_40, r0_42 +# 198| r0_44(glval) = VariableAddress[#return] : +# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 +# 198| v0_46(void) = UnmodeledUse : mu* +# 198| v0_47(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index ce0d93233404..57330c88ce97 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -214,7 +214,9 @@ ssa.cpp: # 70| r1_3(int) = Constant[1] : # 70| r1_4(char *) = PointerAdd[1] : r1_2, r1_3 # 70| m1_5(char *) = Store : &:r1_1, r1_4 -# 70| mu1_6(char) = Store : &:r1_2, r1_0 +# 70| r1_6(glval) = CopyValue : r1_2 +# 70| mu1_7(char) = Store : &:r1_6, r1_0 +# 70| r1_8(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -263,20 +265,23 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 81| r1_3(int) = Constant[4] : -# 81| r1_4(glval) = VariableAddress[y] : -# 81| m1_5(int) = Store : &:r1_4, r1_3 +# 80| r1_3(glval) = CopyValue : r1_1 +# 81| r1_4(int) = Constant[4] : +# 81| r1_5(glval) = VariableAddress[y] : +# 81| m1_6(int) = Store : &:r1_5, r1_4 +# 81| r1_7(glval) = CopyValue : r1_5 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 +# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -323,13 +328,14 @@ ssa.cpp: # 96| m0_8(Point) = Store : &:r0_5, r0_7 # 97| r0_9(glval) = FunctionAddress[Escape] : # 97| r0_10(glval) = VariableAddress[a] : -# 97| r0_11(void *) = Convert : r0_10 -# 97| v0_12(void) = Call : func:r0_9, 0:r0_11 -# 97| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 98| v0_14(void) = NoOp : -# 95| v0_15(void) = ReturnVoid : -# 95| v0_16(void) = UnmodeledUse : mu* -# 95| v0_17(void) = ExitFunction : +# 97| r0_11(Point *) = CopyValue : r0_10 +# 97| r0_12(void *) = Convert : r0_11 +# 97| v0_13(void) = Call : func:r0_9, 0:r0_12 +# 97| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 +# 98| v0_15(void) = NoOp : +# 95| v0_16(void) = ReturnVoid : +# 95| v0_17(void) = UnmodeledUse : mu* +# 95| v0_18(void) = ExitFunction : # 100| void MustTotallyOverlap(Point) # 100| Block 0 @@ -372,13 +378,14 @@ ssa.cpp: # 107| m0_14(int) = Store : &:r0_10, r0_13 # 108| r0_15(glval) = FunctionAddress[Escape] : # 108| r0_16(glval) = VariableAddress[a] : -# 108| r0_17(void *) = Convert : r0_16 -# 108| v0_18(void) = Call : func:r0_15, 0:r0_17 -# 108| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 109| v0_20(void) = NoOp : -# 105| v0_21(void) = ReturnVoid : -# 105| v0_22(void) = UnmodeledUse : mu* -# 105| v0_23(void) = ExitFunction : +# 108| r0_17(Point *) = CopyValue : r0_16 +# 108| r0_18(void *) = Convert : r0_17 +# 108| v0_19(void) = Call : func:r0_15, 0:r0_18 +# 108| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 109| v0_21(void) = NoOp : +# 105| v0_22(void) = ReturnVoid : +# 105| v0_23(void) = UnmodeledUse : mu* +# 105| v0_24(void) = ExitFunction : # 111| void MayPartiallyOverlap(int, int) # 111| Block 0 @@ -433,13 +440,14 @@ ssa.cpp: # 118| m0_20(Point) = Store : &:r0_17, r0_19 # 119| r0_21(glval) = FunctionAddress[Escape] : # 119| r0_22(glval) = VariableAddress[a] : -# 119| r0_23(void *) = Convert : r0_22 -# 119| v0_24(void) = Call : func:r0_21, 0:r0_23 -# 119| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 120| v0_26(void) = NoOp : -# 116| v0_27(void) = ReturnVoid : -# 116| v0_28(void) = UnmodeledUse : mu* -# 116| v0_29(void) = ExitFunction : +# 119| r0_23(Point *) = CopyValue : r0_22 +# 119| r0_24(void *) = Convert : r0_23 +# 119| v0_25(void) = Call : func:r0_21, 0:r0_24 +# 119| mu0_26(unknown) = ^CallSideEffect : ~mu0_2 +# 120| v0_27(void) = NoOp : +# 116| v0_28(void) = ReturnVoid : +# 116| v0_29(void) = UnmodeledUse : mu* +# 116| v0_30(void) = ExitFunction : # 122| void MergeMustExactlyOverlap(bool, int, int) # 122| Block 0 @@ -472,6 +480,7 @@ ssa.cpp: # 125| r1_2(glval) = VariableAddress[a] : # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| mu1_4(int) = Store : &:r1_3, r1_1 +# 125| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -480,6 +489,7 @@ ssa.cpp: # 128| r2_2(glval) = VariableAddress[a] : # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| mu2_4(int) = Store : &:r2_3, r2_1 +# 128| r2_5(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -528,6 +538,7 @@ ssa.cpp: # 137| r1_2(glval) = VariableAddress[a] : # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| mu1_4(int) = Store : &:r1_3, r1_1 +# 137| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -535,6 +546,7 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| mu2_3(Point) = Store : &:r2_2, r2_1 +# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -579,6 +591,7 @@ ssa.cpp: # 148| r1_2(glval) = VariableAddress[a] : # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| mu1_4(int) = Store : &:r1_3, r1_1 +# 148| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -586,6 +599,7 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| mu2_3(Point) = Store : &:r2_2, r2_1 +# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -630,6 +644,7 @@ ssa.cpp: # 159| r1_3(glval) = FieldAddress[topLeft] : r1_2 # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| mu1_5(int) = Store : &:r1_4, r1_1 +# 159| r1_6(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -637,6 +652,7 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| mu2_3(Rect) = Store : &:r2_2, r2_1 +# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -670,19 +686,22 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| mu0_17(int) = Store : &:r0_16, r0_14 -# 175| r0_18(glval) = VariableAddress[w] : -# 175| r0_19(glval) = FieldAddress[f] : r0_18 -# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 175| r0_21(glval) = VariableAddress[a] : -# 175| m0_22(int) = Store : &:r0_21, r0_20 -# 176| r0_23(glval) = VariableAddress[w] : -# 176| r0_24(Wrapper) = Load : &:r0_23, ~mu0_2 -# 176| r0_25(glval) = VariableAddress[x] : -# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 -# 177| v0_27(void) = NoOp : -# 171| v0_28(void) = ReturnVoid : -# 171| v0_29(void) = UnmodeledUse : mu* -# 171| v0_30(void) = ExitFunction : +# 174| r0_18(glval) = CopyValue : r0_16 +# 175| r0_19(glval) = VariableAddress[w] : +# 175| r0_20(glval) = FieldAddress[f] : r0_19 +# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 175| r0_22(glval) = VariableAddress[a] : +# 175| m0_23(int) = Store : &:r0_22, r0_21 +# 175| r0_24(glval) = CopyValue : r0_22 +# 176| r0_25(glval) = VariableAddress[w] : +# 176| r0_26(Wrapper) = Load : &:r0_25, ~mu0_2 +# 176| r0_27(glval) = VariableAddress[x] : +# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 +# 176| r0_29(glval) = CopyValue : r0_27 +# 177| v0_30(void) = NoOp : +# 171| v0_31(void) = ReturnVoid : +# 171| v0_32(void) = UnmodeledUse : mu* +# 171| v0_33(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -757,19 +776,21 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 201| r0_30(glval) = FunctionAddress[abs] : -# 201| r0_31(glval) = VariableAddress[x] : -# 201| r0_32(int) = Load : &:r0_31, m0_8 -# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 -# 201| r0_34(glval) = VariableAddress[ret] : -# 201| r0_35(int) = Load : &:r0_34, m0_29 -# 201| r0_36(int) = Add : r0_35, r0_33 -# 201| m0_37(int) = Store : &:r0_34, r0_36 -# 202| r0_38(glval) = VariableAddress[#return] : -# 202| r0_39(glval) = VariableAddress[ret] : -# 202| r0_40(int) = Load : &:r0_39, m0_37 -# 202| m0_41(int) = Store : &:r0_38, r0_40 -# 198| r0_42(glval) = VariableAddress[#return] : -# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 -# 198| v0_44(void) = UnmodeledUse : mu* -# 198| v0_45(void) = ExitFunction : +# 200| r0_30(glval) = CopyValue : r0_26 +# 201| r0_31(glval) = FunctionAddress[abs] : +# 201| r0_32(glval) = VariableAddress[x] : +# 201| r0_33(int) = Load : &:r0_32, m0_8 +# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 +# 201| r0_35(glval) = VariableAddress[ret] : +# 201| r0_36(int) = Load : &:r0_35, m0_29 +# 201| r0_37(int) = Add : r0_36, r0_34 +# 201| m0_38(int) = Store : &:r0_35, r0_37 +# 201| r0_39(glval) = CopyValue : r0_35 +# 202| r0_40(glval) = VariableAddress[#return] : +# 202| r0_41(glval) = VariableAddress[ret] : +# 202| r0_42(int) = Load : &:r0_41, m0_38 +# 202| m0_43(int) = Store : &:r0_40, r0_42 +# 198| r0_44(glval) = VariableAddress[#return] : +# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 +# 198| v0_46(void) = UnmodeledUse : mu* +# 198| v0_47(void) = ExitFunction : From a34c0d4200667c9a9c5ee6bd769ca4e8cff7311e Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Mon, 23 Sep 2019 15:39:32 +0200 Subject: [PATCH 0007/2538] C++: Autoformat TranslatedExpr.qll --- .../code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index e9e7cf59cb09..fb6cc3f8570b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -2556,8 +2556,8 @@ predicate exprNeedsCopyIfNotLoaded(Expr expr) { expr instanceof AddressOfExpr or expr instanceof BuiltInOperationBuiltInAddressOf - // No case for ParenthesisExpr to avoid getting too many instructions or + // No case for ParenthesisExpr to avoid getting too many instructions expr instanceof ReferenceDereferenceExpr or expr instanceof ReferenceToExpr From 61b372b062d3f0262cbe90c3cb96de21e9276f28 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Mon, 23 Sep 2019 17:30:05 +0100 Subject: [PATCH 0008/2538] Add Go to supported languages topic and update release number --- docs/language/global-sphinx-files/global-conf.py | 4 ++-- docs/language/support/versions-compilers.csv | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/language/global-sphinx-files/global-conf.py b/docs/language/global-sphinx-files/global-conf.py index 260783d9117b..84912a8c538c 100644 --- a/docs/language/global-sphinx-files/global-conf.py +++ b/docs/language/global-sphinx-files/global-conf.py @@ -56,9 +56,9 @@ def setup(sphinx): # built documents. # # The short X.Y version. -version = u'1.22' +version = u'1.22.1' # The full version, including alpha/beta/rc tags. -release = u'1.22' +release = u'1.22.1' copyright = u'2019 Semmle Ltd' author = u'Semmle Ltd' diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv index 4a59214c47f9..b70ac87335fd 100644 --- a/docs/language/support/versions-compilers.csv +++ b/docs/language/support/versions-compilers.csv @@ -10,6 +10,7 @@ C#,C# up to 7.3. with .NET up to 4.8 [3]_.,"Microsoft Visual Studio up to 2019, .NET Core up to 2.2","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" COBOL,ANSI 85 or newer [4]_.,Not applicable,"``.cbl``, ``.CBL``, ``.cpy``, ``.CPY``, ``.copy``, ``.COPY``" +Go, "Go up to 1.13", "Go 1.11 or more recent", ``.go`` Java,"Java 6 to 12 [5]_.","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [6]_.",``.java`` From b75bf06649df642ed47b5686ed874c82834ea632 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 24 Sep 2019 13:00:21 +0200 Subject: [PATCH 0009/2538] C++: Accept test changes in other IR tests --- .../signanalysis/SignAnalysis.expected | 30 ++ .../syntax-zoo/aliased_ssa_sanity.expected | 2 +- .../syntax-zoo/raw_sanity.expected | 21 +- .../syntax-zoo/unaliased_ssa_sanity.expected | 2 +- .../GlobalValueNumbering/ir_gvn.expected | 258 ++++++++++-------- 5 files changed, 190 insertions(+), 123 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected index cdc15c4b45a9..4dc280b6ca9b 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected @@ -13,6 +13,7 @@ | bounded_bounds.c:16:12:16:12 | Load: x | negative strictlyNegative | | bounded_bounds.c:16:12:16:12 | Store: x | negative strictlyNegative | | inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive | +| inline_assembly.c:10:3:10:7 | CopyValue: ... = ... | positive strictlyPositive | | inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive | | inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive | | inline_assembly.c:12:32:12:32 | Load: y | positive strictlyPositive | @@ -27,8 +28,10 @@ | minmax.c:18:37:18:37 | Load: x | positive strictlyPositive | | minmax.c:18:40:18:40 | Load: y | positive strictlyPositive | | minmax.c:18:43:18:43 | Load: z | positive strictlyPositive | +| minmax.c:20:2:24:3 | CopyValue: ... = ... | positive | | minmax.c:20:2:24:3 | Store: ... = ... | positive | | minmax.c:20:6:24:3 | CopyValue: (statement expression) | positive | +| minmax.c:22:18:22:22 | CopyValue: ... = ... | positive strictlyPositive | | minmax.c:22:18:22:22 | Store: ... = ... | positive strictlyPositive | | minmax.c:22:22:22:22 | Load: x | positive strictlyPositive | | minmax.c:23:3:23:3 | Load: t | positive | @@ -37,6 +40,7 @@ | minmax.c:26:40:26:40 | Load: y | positive strictlyPositive | | minmax.c:26:43:26:43 | Load: z | positive | | test.c:7:10:7:10 | Phi: p | positive | +| test.c:8:5:8:19 | CopyValue: ... = ... | positive strictlyPositive | | test.c:8:5:8:19 | Store: ... = ... | positive strictlyPositive | | test.c:8:13:8:17 | Load: count | positive | | test.c:8:13:8:19 | Add: ... + ... | positive strictlyPositive | @@ -44,6 +48,7 @@ | test.c:10:10:10:14 | Load: count | positive | | test.c:10:10:10:14 | Store: count | positive | | test.c:15:10:15:10 | Phi: p | positive | +| test.c:16:5:16:26 | CopyValue: ... = ... | positive | | test.c:16:5:16:26 | Store: ... = ... | positive | | test.c:16:13:16:26 | Rem: ... % ... | positive | | test.c:16:14:16:18 | Load: count | positive | @@ -57,6 +62,7 @@ | test.c:24:5:24:11 | Constant: ... ++ | positive strictlyPositive | | test.c:24:5:24:11 | Load: ... ++ | positive | | test.c:24:5:24:11 | Store: ... ++ | positive strictlyPositive | +| test.c:25:5:25:22 | CopyValue: ... = ... | positive | | test.c:25:5:25:22 | Store: ... = ... | positive | | test.c:25:13:25:17 | Load: count | positive strictlyPositive | | test.c:25:13:25:22 | Rem: ... % ... | positive | @@ -67,6 +73,7 @@ | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:19:33:19 | Constant: 2 | positive strictlyPositive | +| test.c:33:22:33:28 | CopyValue: ... = ... | positive strictlyPositive | | test.c:33:22:33:28 | Store: ... = ... | positive strictlyPositive | | test.c:33:26:33:26 | Load: i | positive | | test.c:33:26:33:28 | Add: ... + ... | positive strictlyPositive | @@ -101,6 +108,7 @@ | test.c:51:15:51:17 | Add: ... + ... | positive strictlyPositive | | test.c:51:17:51:17 | Constant: 2 | positive strictlyPositive | | test.c:51:21:51:21 | Constant: 4 | positive strictlyPositive | +| test.c:51:24:51:30 | CopyValue: ... = ... | positive strictlyPositive | | test.c:51:24:51:30 | Store: ... = ... | positive strictlyPositive | | test.c:51:28:51:28 | Load: i | positive | | test.c:51:28:51:30 | Add: ... + ... | positive strictlyPositive | @@ -459,6 +467,7 @@ | test.c:343:5:343:7 | Constant: ... ++ | positive strictlyPositive | | test.c:343:5:343:7 | Load: ... ++ | positive | | test.c:343:5:343:7 | Store: ... ++ | positive strictlyPositive | +| test.c:345:3:345:7 | CopyValue: ... = ... | positive strictlyPositive | | test.c:345:3:345:7 | Store: ... = ... | positive strictlyPositive | | test.c:345:7:345:7 | Load: i | positive strictlyPositive | | test.c:346:7:346:7 | Load: x | positive | @@ -474,6 +483,7 @@ | test.c:356:36:356:37 | Uninitialized: definition of y6 | positive | | test.c:356:40:356:41 | Uninitialized: definition of y7 | positive | | test.c:356:44:356:45 | Uninitialized: definition of y8 | positive | +| test.c:357:3:357:23 | CopyValue: ... = ... | positive | | test.c:357:3:357:23 | Store: ... = ... | positive | | test.c:357:8:357:8 | Load: x | positive | | test.c:357:8:357:23 | Load: ... ? ... : ... | positive | @@ -483,6 +493,7 @@ | test.c:357:12:357:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:357:18:357:18 | Load: x | positive | | test.c:357:22:357:23 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:358:3:358:24 | CopyValue: ... = ... | positive | | test.c:358:3:358:24 | Store: ... = ... | positive | | test.c:358:8:358:8 | Load: x | positive | | test.c:358:8:358:24 | Load: ... ? ... : ... | positive | @@ -494,6 +505,7 @@ | test.c:358:24:358:24 | Load: x | positive | | test.c:365:7:365:7 | Load: x | positive | | test.c:365:11:365:13 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:366:5:366:15 | CopyValue: ... = ... | positive | | test.c:366:5:366:15 | Store: ... = ... | positive | | test.c:366:10:366:10 | Load: x | positive | | test.c:366:10:366:15 | Load: ... ? ... : ... | positive | @@ -501,6 +513,7 @@ | test.c:366:10:366:15 | Store: ... ? ... : ... | positive | | test.c:366:10:366:15 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:366:15:366:15 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:367:5:367:17 | CopyValue: ... = ... | positive | | test.c:367:5:367:17 | Store: ... = ... | positive | | test.c:367:10:367:10 | Load: x | positive | | test.c:367:10:367:17 | Load: ... ? ... : ... | positive | @@ -508,6 +521,7 @@ | test.c:367:10:367:17 | Store: ... ? ... : ... | positive | | test.c:367:10:367:17 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:367:15:367:17 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:368:5:368:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:368:5:368:21 | Store: ... = ... | positive strictlyPositive | | test.c:368:10:368:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:368:10:368:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -515,6 +529,7 @@ | test.c:368:11:368:13 | Add: ... + ... | positive strictlyPositive | | test.c:368:13:368:13 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:368:19:368:21 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:369:5:369:36 | CopyValue: ... = ... | positive strictlyPositive | | test.c:369:5:369:36 | Store: ... = ... | positive strictlyPositive | | test.c:369:10:369:36 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:369:10:369:36 | Load: ... ? ... : ... | positive strictlyPositive | @@ -524,6 +539,7 @@ | test.c:369:27:369:29 | Add: ... + ... | positive strictlyPositive | | test.c:369:29:369:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:369:36:369:36 | Constant: 5 | positive strictlyPositive | +| test.c:370:5:370:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:370:5:370:38 | Store: ... = ... | positive strictlyPositive | | test.c:370:10:370:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:370:10:370:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -533,6 +549,7 @@ | test.c:370:27:370:29 | Add: ... + ... | positive strictlyPositive | | test.c:370:29:370:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:370:36:370:38 | Constant: 500 | positive strictlyPositive | +| test.c:371:5:371:39 | CopyValue: ... = ... | positive strictlyPositive | | test.c:371:5:371:39 | Store: ... = ... | positive strictlyPositive | | test.c:371:10:371:39 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:371:10:371:39 | Load: ... ? ... : ... | positive strictlyPositive | @@ -570,6 +587,7 @@ | test.c:378:24:378:25 | Uninitialized: definition of y3 | positive | | test.c:378:28:378:29 | Uninitialized: definition of y4 | positive | | test.c:378:32:378:33 | Uninitialized: definition of y5 | positive | +| test.c:379:3:379:24 | CopyValue: ... = ... | positive strictlyPositive | | test.c:379:3:379:24 | Store: ... = ... | positive strictlyPositive | | test.c:379:8:379:8 | Load: x | positive | | test.c:379:8:379:24 | Load: ... ? ... : ... | positive strictlyPositive | @@ -579,6 +597,7 @@ | test.c:379:12:379:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:379:18:379:18 | Load: x | positive strictlyPositive | | test.c:379:22:379:24 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:380:3:380:25 | CopyValue: ... = ... | positive strictlyPositive | | test.c:380:3:380:25 | Store: ... = ... | positive strictlyPositive | | test.c:380:8:380:8 | Load: x | positive | | test.c:380:8:380:25 | Load: ... ? ... : ... | positive strictlyPositive | @@ -588,14 +607,18 @@ | test.c:380:13:380:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:19:380:21 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:25:380:25 | Load: x | positive strictlyPositive | +| test.c:381:3:381:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:381:3:381:11 | Store: ... = ... | positive strictlyPositive | | test.c:381:8:381:11 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:382:3:382:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:382:3:382:11 | Store: ... = ... | positive strictlyPositive | | test.c:382:8:382:11 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:383:3:383:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:383:3:383:11 | Store: ... = ... | positive strictlyPositive | | test.c:383:8:383:11 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:384:7:384:7 | Load: x | positive | | test.c:384:12:384:14 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:385:5:385:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:385:5:385:21 | Store: ... = ... | positive strictlyPositive | | test.c:385:10:385:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:385:10:385:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -603,6 +626,7 @@ | test.c:385:11:385:15 | Sub: ... - ... | positive | | test.c:385:13:385:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:385:21:385:21 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:386:5:386:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:386:5:386:21 | Store: ... = ... | positive strictlyPositive | | test.c:386:10:386:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:386:10:386:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -610,6 +634,7 @@ | test.c:386:11:386:15 | Sub: ... - ... | positive | | test.c:386:13:386:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:386:21:386:21 | Constant: (unsigned int)... | positive strictlyPositive | +| test.c:387:5:387:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:387:5:387:38 | Store: ... = ... | positive strictlyPositive | | test.c:387:10:387:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:387:10:387:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -644,17 +669,22 @@ | test.c:394:34:394:36 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:395:16:395:17 | Uninitialized: definition of y1 | positive | | test.c:396:16:396:17 | Uninitialized: definition of y2 | positive | +| test.c:397:3:397:15 | CopyValue: ... = ... | positive strictlyPositive | | test.c:397:3:397:15 | Store: ... = ... | positive strictlyPositive | | test.c:397:9:397:11 | Add: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Constant: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Load: ++ ... | positive | | test.c:397:9:397:11 | Store: ++ ... | positive strictlyPositive | +| test.c:397:9:397:14 | CopyValue: ... , ... | positive strictlyPositive | | test.c:397:14:397:14 | Load: y | positive strictlyPositive | +| test.c:398:3:398:23 | CopyValue: ... = ... | positive strictlyPositive | | test.c:398:3:398:23 | Store: ... = ... | positive strictlyPositive | | test.c:398:9:398:11 | Add: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Constant: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Load: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Store: ... ++ | positive strictlyPositive | +| test.c:398:9:398:19 | CopyValue: ... , ... | positive strictlyPositive | +| test.c:398:9:398:22 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Store: ... += ... | positive strictlyPositive | diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 5e76fb042be7..a8f98105b08d 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -21,7 +21,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | Chi: call to C | | ms_try_mix.cpp:48:10:48:13 | Chi: call to C | | pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | +| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index b9c4bd7eba5e..e8b34aff7269 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -1,9 +1,10 @@ missingOperand -| condition_decls.cpp:16:6:16:20 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | -| condition_decls.cpp:26:3:36:3 | Switch: switch (...) ... | Instruction 'Switch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | -| condition_decls.cpp:41:9:41:23 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | -| condition_decls.cpp:48:39:48:53 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | +| condition_decls.cpp:16:6:16:20 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | +| condition_decls.cpp:26:10:26:24 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | +| condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | +| condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | +| misc.c:220:3:223:3 | CopyValue: ... = ... | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | @@ -47,13 +48,13 @@ instructionWithoutSuccessor | misc.c:222:10:222:10 | Store: 2 | | ms_assume.cpp:20:12:20:12 | Constant: (bool)... | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | -| ms_try_except.cpp:7:13:7:17 | Store: ... = ... | +| ms_try_except.cpp:7:13:7:17 | CopyValue: ... = ... | | ms_try_except.cpp:9:19:9:19 | Load: j | -| ms_try_except.cpp:10:13:10:17 | Store: ... = ... | -| ms_try_except.cpp:14:13:14:17 | Store: ... = ... | -| ms_try_except.cpp:17:13:17:17 | Store: ... = ... | +| ms_try_except.cpp:10:13:10:17 | CopyValue: ... = ... | +| ms_try_except.cpp:14:13:14:17 | CopyValue: ... = ... | +| ms_try_except.cpp:17:13:17:17 | CopyValue: ... = ... | | ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | -| ms_try_except.cpp:20:9:20:13 | Store: ... = ... | +| ms_try_except.cpp:20:9:20:13 | CopyValue: ... = ... | | ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | | ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | | ms_try_mix.cpp:18:16:18:19 | CallSideEffect: call to C | @@ -75,7 +76,7 @@ instructionWithoutSuccessor | static_init_templates.cpp:97:27:97:36 | Convert: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | +| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | | stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index ab5362cb06c5..c8cee7b2a7c6 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -30,7 +30,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | | ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C | | pointer_to_member.cpp:35:11:35:21 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | +| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 8be4cf4e2c11..4bc9f90cc60e 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -40,34 +40,40 @@ test.cpp: # 5| valnum = r0_7 # 5| m0_19(int) = Store : &:r0_18, r0_17 # 5| valnum = r0_17 -# 6| r0_20(glval) = VariableAddress[p0] : +# 5| r0_20(glval) = CopyValue : r0_18 +# 5| valnum = r0_7 +# 6| r0_21(glval) = VariableAddress[p0] : # 6| valnum = r0_3 -# 6| r0_21(int) = Load : &:r0_20, m0_4 +# 6| r0_22(int) = Load : &:r0_21, m0_4 # 6| valnum = m0_4 -# 6| r0_22(glval) = VariableAddress[p1] : +# 6| r0_23(glval) = VariableAddress[p1] : # 6| valnum = r0_5 -# 6| r0_23(int) = Load : &:r0_22, m0_6 +# 6| r0_24(int) = Load : &:r0_23, m0_6 # 6| valnum = m0_6 -# 6| r0_24(int) = Add : r0_21, r0_23 +# 6| r0_25(int) = Add : r0_22, r0_24 # 6| valnum = r0_17 -# 6| r0_25(glval) = VariableAddress[x] : +# 6| r0_26(glval) = VariableAddress[x] : # 6| valnum = r0_7 -# 6| m0_26(int) = Store : &:r0_25, r0_24 +# 6| m0_27(int) = Store : &:r0_26, r0_25 # 6| valnum = r0_17 -# 7| r0_27(glval) = VariableAddress[x] : +# 6| r0_28(glval) = CopyValue : r0_26 +# 6| valnum = r0_7 +# 7| r0_29(glval) = VariableAddress[x] : # 7| valnum = r0_7 -# 7| r0_28(int) = Load : &:r0_27, m0_26 +# 7| r0_30(int) = Load : &:r0_29, m0_27 # 7| valnum = r0_17 -# 7| r0_29(glval) = VariableAddress[y] : +# 7| r0_31(glval) = VariableAddress[y] : # 7| valnum = r0_9 -# 7| m0_30(int) = Store : &:r0_29, r0_28 +# 7| m0_32(int) = Store : &:r0_31, r0_30 # 7| valnum = r0_17 -# 8| v0_31(void) = NoOp : -# 1| r0_32(glval) = VariableAddress[#return] : +# 7| r0_33(glval) = CopyValue : r0_31 +# 7| valnum = r0_9 +# 8| v0_34(void) = NoOp : +# 1| r0_35(glval) = VariableAddress[#return] : # 1| valnum = unique -# 1| v0_33(void) = ReturnValue : &:r0_32 -# 1| v0_34(void) = UnmodeledUse : mu* -# 1| v0_35(void) = ExitFunction : +# 1| v0_36(void) = ReturnValue : &:r0_35 +# 1| v0_37(void) = UnmodeledUse : mu* +# 1| v0_38(void) = ExitFunction : # 12| int test01(int, int) # 12| Block 0 @@ -116,40 +122,46 @@ test.cpp: # 16| valnum = r0_7 # 16| m0_22(int) = Store : &:r0_21, r0_20 # 16| valnum = r0_20 -# 17| r0_23(glval) = VariableAddress[p0] : +# 16| r0_23(glval) = CopyValue : r0_21 +# 16| valnum = r0_7 +# 17| r0_24(glval) = VariableAddress[p0] : # 17| valnum = r0_3 -# 17| r0_24(int) = Load : &:r0_23, m0_4 +# 17| r0_25(int) = Load : &:r0_24, m0_4 # 17| valnum = m0_4 -# 17| r0_25(glval) = VariableAddress[p1] : +# 17| r0_26(glval) = VariableAddress[p1] : # 17| valnum = r0_5 -# 17| r0_26(int) = Load : &:r0_25, m0_6 +# 17| r0_27(int) = Load : &:r0_26, m0_6 # 17| valnum = m0_6 -# 17| r0_27(int) = Add : r0_24, r0_26 +# 17| r0_28(int) = Add : r0_25, r0_27 # 17| valnum = r0_17 -# 17| r0_28(glval) = VariableAddress[global01] : +# 17| r0_29(glval) = VariableAddress[global01] : # 17| valnum = r0_18 -# 17| r0_29(int) = Load : &:r0_28, ~m0_1 +# 17| r0_30(int) = Load : &:r0_29, ~m0_1 # 17| valnum = unique -# 17| r0_30(int) = Add : r0_27, r0_29 -# 17| valnum = r0_30 -# 17| r0_31(glval) = VariableAddress[x] : +# 17| r0_31(int) = Add : r0_28, r0_30 +# 17| valnum = r0_31 +# 17| r0_32(glval) = VariableAddress[x] : +# 17| valnum = r0_7 +# 17| m0_33(int) = Store : &:r0_32, r0_31 +# 17| valnum = r0_31 +# 17| r0_34(glval) = CopyValue : r0_32 # 17| valnum = r0_7 -# 17| m0_32(int) = Store : &:r0_31, r0_30 -# 17| valnum = r0_30 -# 18| r0_33(glval) = VariableAddress[x] : +# 18| r0_35(glval) = VariableAddress[x] : # 18| valnum = r0_7 -# 18| r0_34(int) = Load : &:r0_33, m0_32 -# 18| valnum = r0_30 -# 18| r0_35(glval) = VariableAddress[y] : +# 18| r0_36(int) = Load : &:r0_35, m0_33 +# 18| valnum = r0_31 +# 18| r0_37(glval) = VariableAddress[y] : # 18| valnum = r0_9 -# 18| m0_36(int) = Store : &:r0_35, r0_34 -# 18| valnum = r0_30 -# 19| v0_37(void) = NoOp : -# 12| r0_38(glval) = VariableAddress[#return] : +# 18| m0_38(int) = Store : &:r0_37, r0_36 +# 18| valnum = r0_31 +# 18| r0_39(glval) = CopyValue : r0_37 +# 18| valnum = r0_9 +# 19| v0_40(void) = NoOp : +# 12| r0_41(glval) = VariableAddress[#return] : # 12| valnum = unique -# 12| v0_39(void) = ReturnValue : &:r0_38 -# 12| v0_40(void) = UnmodeledUse : mu* -# 12| v0_41(void) = ExitFunction : +# 12| v0_42(void) = ReturnValue : &:r0_41 +# 12| v0_43(void) = UnmodeledUse : mu* +# 12| v0_44(void) = ExitFunction : # 25| int test02(int, int) # 25| Block 0 @@ -198,47 +210,53 @@ test.cpp: # 29| valnum = r0_7 # 29| m0_22(int) = Store : &:r0_21, r0_20 # 29| valnum = r0_20 -# 30| r0_23(glval) = FunctionAddress[change_global02] : +# 29| r0_23(glval) = CopyValue : r0_21 +# 29| valnum = r0_7 +# 30| r0_24(glval) = FunctionAddress[change_global02] : # 30| valnum = unique -# 30| v0_24(void) = Call : func:r0_23 -# 30| m0_25(unknown) = ^CallSideEffect : ~m0_1 +# 30| v0_25(void) = Call : func:r0_24 +# 30| m0_26(unknown) = ^CallSideEffect : ~m0_1 # 30| valnum = unique -# 30| m0_26(unknown) = Chi : total:m0_1, partial:m0_25 +# 30| m0_27(unknown) = Chi : total:m0_1, partial:m0_26 # 30| valnum = unique -# 31| r0_27(glval) = VariableAddress[p0] : +# 31| r0_28(glval) = VariableAddress[p0] : # 31| valnum = r0_3 -# 31| r0_28(int) = Load : &:r0_27, m0_4 +# 31| r0_29(int) = Load : &:r0_28, m0_4 # 31| valnum = m0_4 -# 31| r0_29(glval) = VariableAddress[p1] : +# 31| r0_30(glval) = VariableAddress[p1] : # 31| valnum = r0_5 -# 31| r0_30(int) = Load : &:r0_29, m0_6 +# 31| r0_31(int) = Load : &:r0_30, m0_6 # 31| valnum = m0_6 -# 31| r0_31(int) = Add : r0_28, r0_30 +# 31| r0_32(int) = Add : r0_29, r0_31 # 31| valnum = r0_17 -# 31| r0_32(glval) = VariableAddress[global02] : +# 31| r0_33(glval) = VariableAddress[global02] : # 31| valnum = r0_18 -# 31| r0_33(int) = Load : &:r0_32, ~m0_26 +# 31| r0_34(int) = Load : &:r0_33, ~m0_27 # 31| valnum = unique -# 31| r0_34(int) = Add : r0_31, r0_33 -# 31| valnum = r0_34 -# 31| r0_35(glval) = VariableAddress[x] : +# 31| r0_35(int) = Add : r0_32, r0_34 +# 31| valnum = r0_35 +# 31| r0_36(glval) = VariableAddress[x] : +# 31| valnum = r0_7 +# 31| m0_37(int) = Store : &:r0_36, r0_35 +# 31| valnum = r0_35 +# 31| r0_38(glval) = CopyValue : r0_36 # 31| valnum = r0_7 -# 31| m0_36(int) = Store : &:r0_35, r0_34 -# 31| valnum = r0_34 -# 32| r0_37(glval) = VariableAddress[x] : +# 32| r0_39(glval) = VariableAddress[x] : # 32| valnum = r0_7 -# 32| r0_38(int) = Load : &:r0_37, m0_36 -# 32| valnum = r0_34 -# 32| r0_39(glval) = VariableAddress[y] : +# 32| r0_40(int) = Load : &:r0_39, m0_37 +# 32| valnum = r0_35 +# 32| r0_41(glval) = VariableAddress[y] : # 32| valnum = r0_9 -# 32| m0_40(int) = Store : &:r0_39, r0_38 -# 32| valnum = r0_34 -# 33| v0_41(void) = NoOp : -# 25| r0_42(glval) = VariableAddress[#return] : +# 32| m0_42(int) = Store : &:r0_41, r0_40 +# 32| valnum = r0_35 +# 32| r0_43(glval) = CopyValue : r0_41 +# 32| valnum = r0_9 +# 33| v0_44(void) = NoOp : +# 25| r0_45(glval) = VariableAddress[#return] : # 25| valnum = unique -# 25| v0_43(void) = ReturnValue : &:r0_42 -# 25| v0_44(void) = UnmodeledUse : mu* -# 25| v0_45(void) = ExitFunction : +# 25| v0_46(void) = ReturnValue : &:r0_45 +# 25| v0_47(void) = UnmodeledUse : mu* +# 25| v0_48(void) = ExitFunction : # 39| int test03(int, int, int*) # 39| Block 0 @@ -291,50 +309,60 @@ test.cpp: # 43| valnum = r0_9 # 43| m0_24(int) = Store : &:r0_23, r0_22 # 43| valnum = r0_22 -# 44| r0_25(int) = Constant[0] : -# 44| valnum = r0_25 -# 44| r0_26(glval) = VariableAddress[p2] : +# 43| r0_25(glval) = CopyValue : r0_23 +# 43| valnum = r0_9 +# 44| r0_26(int) = Constant[0] : +# 44| valnum = r0_26 +# 44| r0_27(glval) = VariableAddress[p2] : # 44| valnum = r0_7 -# 44| r0_27(int *) = Load : &:r0_26, m0_8 +# 44| r0_28(int *) = Load : &:r0_27, m0_8 # 44| valnum = m0_8 -# 44| m0_28(int) = Store : &:r0_27, r0_25 -# 44| valnum = r0_25 -# 44| m0_29(unknown) = Chi : total:m0_1, partial:m0_28 +# 44| r0_29(glval) = CopyValue : r0_28 +# 44| valnum = m0_8 +# 44| m0_30(int) = Store : &:r0_29, r0_26 +# 44| valnum = r0_26 +# 44| m0_31(unknown) = Chi : total:m0_1, partial:m0_30 # 44| valnum = unique -# 45| r0_30(glval) = VariableAddress[p0] : +# 44| r0_32(glval) = CopyValue : r0_29 +# 44| valnum = m0_8 +# 45| r0_33(glval) = VariableAddress[p0] : # 45| valnum = r0_3 -# 45| r0_31(int) = Load : &:r0_30, m0_4 +# 45| r0_34(int) = Load : &:r0_33, m0_4 # 45| valnum = m0_4 -# 45| r0_32(glval) = VariableAddress[p1] : +# 45| r0_35(glval) = VariableAddress[p1] : # 45| valnum = r0_5 -# 45| r0_33(int) = Load : &:r0_32, m0_6 +# 45| r0_36(int) = Load : &:r0_35, m0_6 # 45| valnum = m0_6 -# 45| r0_34(int) = Add : r0_31, r0_33 +# 45| r0_37(int) = Add : r0_34, r0_36 # 45| valnum = r0_19 -# 45| r0_35(glval) = VariableAddress[global03] : +# 45| r0_38(glval) = VariableAddress[global03] : # 45| valnum = r0_20 -# 45| r0_36(int) = Load : &:r0_35, ~m0_29 +# 45| r0_39(int) = Load : &:r0_38, ~m0_31 # 45| valnum = unique -# 45| r0_37(int) = Add : r0_34, r0_36 -# 45| valnum = r0_37 -# 45| r0_38(glval) = VariableAddress[x] : +# 45| r0_40(int) = Add : r0_37, r0_39 +# 45| valnum = r0_40 +# 45| r0_41(glval) = VariableAddress[x] : +# 45| valnum = r0_9 +# 45| m0_42(int) = Store : &:r0_41, r0_40 +# 45| valnum = r0_40 +# 45| r0_43(glval) = CopyValue : r0_41 # 45| valnum = r0_9 -# 45| m0_39(int) = Store : &:r0_38, r0_37 -# 45| valnum = r0_37 -# 46| r0_40(glval) = VariableAddress[x] : +# 46| r0_44(glval) = VariableAddress[x] : # 46| valnum = r0_9 -# 46| r0_41(int) = Load : &:r0_40, m0_39 -# 46| valnum = r0_37 -# 46| r0_42(glval) = VariableAddress[y] : +# 46| r0_45(int) = Load : &:r0_44, m0_42 +# 46| valnum = r0_40 +# 46| r0_46(glval) = VariableAddress[y] : # 46| valnum = r0_11 -# 46| m0_43(int) = Store : &:r0_42, r0_41 -# 46| valnum = r0_37 -# 47| v0_44(void) = NoOp : -# 39| r0_45(glval) = VariableAddress[#return] : +# 46| m0_47(int) = Store : &:r0_46, r0_45 +# 46| valnum = r0_40 +# 46| r0_48(glval) = CopyValue : r0_46 +# 46| valnum = r0_11 +# 47| v0_49(void) = NoOp : +# 39| r0_50(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_46(void) = ReturnValue : &:r0_45 -# 39| v0_47(void) = UnmodeledUse : mu* -# 39| v0_48(void) = ExitFunction : +# 39| v0_51(void) = ReturnValue : &:r0_50 +# 39| v0_52(void) = UnmodeledUse : mu* +# 39| v0_53(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -391,6 +419,8 @@ test.cpp: # 55| valnum = r0_7 # 55| m2_3(char *) = Store : &:r2_2, r2_1 # 55| valnum = m0_6 +# 55| r2_4(glval) = CopyValue : r2_2 +# 55| valnum = r0_7 #-----| Goto -> Block 3 # 56| Block 3 @@ -572,6 +602,8 @@ test.cpp: # 80| valnum = r0_5 # 80| m1_6(signed short) = Store : &:r1_5, r1_4 # 80| valnum = r1_4 +# 80| r1_7(glval) = CopyValue : r1_5 +# 80| valnum = r0_5 #-----| Goto -> Block 2 # 82| Block 2 @@ -648,10 +680,12 @@ test.cpp: # 88| valnum = r0_9 # 88| m3_4(int) = Store : &:r3_3, r3_2 # 88| valnum = m3_0 -# 89| v3_5(void) = NoOp : -# 84| v3_6(void) = ReturnVoid : -# 84| v3_7(void) = UnmodeledUse : mu* -# 84| v3_8(void) = ExitFunction : +# 88| r3_5(glval) = CopyValue : r3_3 +# 88| valnum = r0_9 +# 89| v3_6(void) = NoOp : +# 84| v3_7(void) = ReturnVoid : +# 84| v3_8(void) = UnmodeledUse : mu* +# 84| v3_9(void) = ExitFunction : # 91| int regression_test00() # 91| Block 0 @@ -668,21 +702,23 @@ test.cpp: # 92| valnum = r0_3 # 92| m0_6(int) = Store : &:r0_5, r0_4 # 92| valnum = r0_4 -# 92| m0_7(int) = Store : &:r0_3, r0_4 +# 92| r0_7(int) = CopyValue : r0_4 +# 92| valnum = r0_4 +# 92| m0_8(int) = Store : &:r0_3, r0_7 # 92| valnum = r0_4 -# 93| r0_8(glval) = VariableAddress[#return] : -# 93| valnum = r0_8 -# 93| r0_9(glval) = VariableAddress[x] : +# 93| r0_9(glval) = VariableAddress[#return] : +# 93| valnum = r0_9 +# 93| r0_10(glval) = VariableAddress[x] : # 93| valnum = r0_3 -# 93| r0_10(int) = Load : &:r0_9, m0_7 +# 93| r0_11(int) = Load : &:r0_10, m0_8 # 93| valnum = r0_4 -# 93| m0_11(int) = Store : &:r0_8, r0_10 +# 93| m0_12(int) = Store : &:r0_9, r0_11 # 93| valnum = r0_4 -# 91| r0_12(glval) = VariableAddress[#return] : -# 91| valnum = r0_8 -# 91| v0_13(void) = ReturnValue : &:r0_12, m0_11 -# 91| v0_14(void) = UnmodeledUse : mu* -# 91| v0_15(void) = ExitFunction : +# 91| r0_13(glval) = VariableAddress[#return] : +# 91| valnum = r0_9 +# 91| v0_14(void) = ReturnValue : &:r0_13, m0_12 +# 91| v0_15(void) = UnmodeledUse : mu* +# 91| v0_16(void) = ExitFunction : # 104| int inheritanceConversions(Derived*) # 104| Block 0 From 9511465f04ef80c6f1b0afe914e54d6b625bdc97 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 26 Sep 2019 11:16:24 +0200 Subject: [PATCH 0010/2538] Learn QL: Minor formatting fix in python/statements-expressions (cherry picked from commit c47a4e0c44eba9f24ffb5490986188347e1372f5) --- docs/language/learn-ql/python/statements-expressions.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 2d45abde73a6..9f1a15a6d1af 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -72,7 +72,7 @@ An ``if`` statement where one branch is composed of just ``pass`` statements cou To find statements like this we can run the following query: -**Find ``if`` statements with empty branches** +**Find 'if' statements with empty branches** .. code-block:: ql From 94d876e8a3664c4fba6f48f7f10f937885900759 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 25 Sep 2019 18:20:48 +0200 Subject: [PATCH 0011/2538] Learn QL: Fix query link in Python Points-to tutorial (cherry picked from commit c6c565bc373e1353830ea731823feea024b4c4c8) --- docs/language/learn-ql/python/pointsto-type-infer.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index 6ca1bde67c84..bcbab5204776 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -173,7 +173,7 @@ Many of the results shown will have ``cls`` as ``NoneType``. It is more informat not cls.hasAttribute("__iter__") select loop, cls, origin -➤ `See this in the query console `__. This reports the same results, but with a third column showing the source of the ``None`` values. +➤ `See this in the query console `__. This reports the same results, but with a third column showing the source of the ``None`` values. Finding calls using call-graph analysis ---------------------------------------------------- From 3a4cef646de30c263d4fdc86c34b377cbe8129db Mon Sep 17 00:00:00 2001 From: james Date: Thu, 26 Sep 2019 16:04:01 +0100 Subject: [PATCH 0012/2538] docs: fix some formatting issues --- .../learn-ql/cpp/conversions-classes.rst | 2 +- docs/language/learn-ql/cpp/function-classes.rst | 4 ++++ .../learn-ql/cpp/introduce-libraries-cpp.rst | 4 ++++ .../learn-ql/cpp/zero-space-terminator.rst | 4 ++++ docs/language/learn-ql/csharp/ql-for-csharp.rst | 15 --------------- docs/language/learn-ql/java/call-graph.rst | 2 ++ .../learn-ql/java/expressions-statements.rst | 2 ++ .../learn-ql/java/introduce-libraries-java.rst | 10 +++++++++- .../learn-ql/java/types-class-hierarchy.rst | 2 ++ .../javascript/introduce-libraries-js.rst | 2 +- docs/language/learn-ql/python/functions.rst | 2 ++ .../python/introduce-libraries-python.rst | 16 ++++++++-------- .../learn-ql/python/pointsto-type-infer.rst | 9 +++++---- .../learn-ql/python/statements-expressions.rst | 8 ++++---- 14 files changed, 48 insertions(+), 34 deletions(-) diff --git a/docs/language/learn-ql/cpp/conversions-classes.rst b/docs/language/learn-ql/cpp/conversions-classes.rst index 512d967a53f9..28032a932d24 100644 --- a/docs/language/learn-ql/cpp/conversions-classes.rst +++ b/docs/language/learn-ql/cpp/conversions-classes.rst @@ -128,7 +128,7 @@ Unlike the earlier versions of the query, this query would return each side of t Note - In general, QL predicates named ``getAXxx`` exploit the ability to return multiple results (multiple instances of ``Xxx``) whereas plain ``getXxx`` predicates usually return at most one specific instance of ``Xxx``. + In general, QL predicates named ``getAXxx`` exploit the ability to return multiple results (multiple instances of ``Xxx``) whereas plain ``getXxx`` predicates usually return at most one specific instance of ``Xxx``. Classes ------- diff --git a/docs/language/learn-ql/cpp/function-classes.rst b/docs/language/learn-ql/cpp/function-classes.rst index 5dde2546995c..4b9db11351be 100644 --- a/docs/language/learn-ql/cpp/function-classes.rst +++ b/docs/language/learn-ql/cpp/function-classes.rst @@ -60,6 +60,10 @@ This query returns fewer results. However, if you examine the results then you c For example, there is a more complicated LGTM `query `__ that finds unused static functions. To see the QL code for this query, click **Open in query console** at the top of the page. +.. pull-quote:: + + Tip + You can explore the definition of an element in the standard QL libraries and see what predicates are available. Use the keyboard **F3** button to open the definition of any element. Alternatively, hover over the element and click **Jump to definition** in the tooltip displayed. The library file is opened in a new tab with the definition highlighted. Finding a specific function diff --git a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst index 01f8b244684c..5c287bd7115a 100644 --- a/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst +++ b/docs/language/learn-ql/cpp/introduce-libraries-cpp.rst @@ -12,6 +12,10 @@ There is an extensive QL library for analyzing C/C++ code. The QL classes in thi The rest of this topic briefly summarizes the most important QL classes and predicates provided by this library. +.. pull-quote:: + + Tip + You can find related classes and features using the query console's auto-complete feature. You can also press **F3** to jump to the definition of any element (QL library files are opened in new tabs in the console). Summary of the library classes diff --git a/docs/language/learn-ql/cpp/zero-space-terminator.rst b/docs/language/learn-ql/cpp/zero-space-terminator.rst index f2d0ae36dbdd..c5c578633e13 100644 --- a/docs/language/learn-ql/cpp/zero-space-terminator.rst +++ b/docs/language/learn-ql/cpp/zero-space-terminator.rst @@ -87,6 +87,10 @@ Now we can write a query using these classes: Note that there is no need to check whether anything is added to the ``strlen`` expression, as it would be in the corrected C code ``malloc(strlen(string) + 1)``. This is because the corrected code would in fact be an ``AddExpr`` containing a ``StrlenCall``, not an instance of ``StrlenCall`` itself. A side-effect of this approach is that we omit certain unlikely patterns such as ``malloc(strlen(string) + 0``). In practice we can always come back and extend our query to cover this pattern if it is a concern. +.. pull-quote:: + + Tip + For some projects, this query may not return any results. Possibly the project you are querying does not have any problems of this kind, but it is also important to make sure the query itself is working properly. One solution is to set up a test project with examples of correct and incorrect code to run the query against (the C code at the very top of this page makes a good starting point). Another approach is to test each part of the query individually to make sure everything is working. When you have defined the basic query then you can refine the query to include further coding patterns or to exclude false positives: diff --git a/docs/language/learn-ql/csharp/ql-for-csharp.rst b/docs/language/learn-ql/csharp/ql-for-csharp.rst index 56d8f7ef0171..879d8c151078 100644 --- a/docs/language/learn-ql/csharp/ql-for-csharp.rst +++ b/docs/language/learn-ql/csharp/ql-for-csharp.rst @@ -14,23 +14,8 @@ These topics provide an overview of the QL C# libraries and show examples of how - :doc:`Introducing the C# libraries ` introduces the standard libraries used to write queries for C# code. -.. raw:: html - - - - :doc:`Tutorial: Analyzing data flow in C# ` demonstrates how to write queries using the standard QL for C# data flow and taint tracking libraries. -.. raw:: html - - - -.. raw:: html - - - -.. raw:: html - - Other resources --------------- diff --git a/docs/language/learn-ql/java/call-graph.rst b/docs/language/learn-ql/java/call-graph.rst index b0c721b1fd7b..3cea5294c0e3 100644 --- a/docs/language/learn-ql/java/call-graph.rst +++ b/docs/language/learn-ql/java/call-graph.rst @@ -78,6 +78,8 @@ Given this API, we can easily write a query that finds methods that are not call ➤ `See this in the query console `__. This simple query typically returns a large number of results. +.. pull-quote:: + Note We have to use ``polyCalls`` instead of ``calls`` here: we want to be reasonably sure that ``callee`` is not called, either directly or via overriding. diff --git a/docs/language/learn-ql/java/expressions-statements.rst b/docs/language/learn-ql/java/expressions-statements.rst index c8882c41792a..0034868f01a8 100644 --- a/docs/language/learn-ql/java/expressions-statements.rst +++ b/docs/language/learn-ql/java/expressions-statements.rst @@ -18,6 +18,8 @@ Specifically, consider the following code snippet: If ``l`` is bigger than 2\ :sup:`31`\ - 1 (the largest positive value of type ``int``), then this loop will never terminate: ``i`` will start at zero, being incremented all the way up to 2\ :sup:`31`\ - 1, which is still smaller than ``l``. When it is incremented once more, an arithmetic overflow occurs, and ``i`` becomes -2\ :sup:`31`\, which also is smaller than ``l``! Eventually, ``i`` will reach zero again, and the cycle repeats. +.. pull-quote:: + More about overflow All primitive numeric types have a maximum value, beyond which they will wrap around to their lowest possible value (called an "overflow"). For ``int``, this maximum value is 2\ :sup:`31`\ - 1. Type ``long`` can accommodate larger values up to a maximum of 2\ :sup:`63`\ - 1. In this example, this means that ``l`` can take on a value that is higher than the maximum for type ``int``; ``i`` will never be able to reach this value, instead overflowing and returning to a low value. diff --git a/docs/language/learn-ql/java/introduce-libraries-java.rst b/docs/language/learn-ql/java/introduce-libraries-java.rst index 32863b099e0b..ef20dd47ccfe 100644 --- a/docs/language/learn-ql/java/introduce-libraries-java.rst +++ b/docs/language/learn-ql/java/introduce-libraries-java.rst @@ -14,6 +14,10 @@ The library is implemented as a set of QL modules, that is, files with the exten The rest of this topic briefly summarizes the most important QL classes and predicates provided by this library. +.. pull-quote:: + + Note + The example queries in this topic illustrate the types of results returned by different library classes. The results themselves are not interesting but can be used as the basis for developing a more complex query. The tutorial topics show how you can take a simple query and fine-tune it to find precisely the results you're interested in. Summary of the library classes @@ -315,7 +319,11 @@ Class ``Javadoc`` represents an entire Javadoc comment as a tree of ``JavadocEle ➤ `See this in the query console `__. None of the LGTM.com demo projects uses the ``@author`` tag on private fields. - Note that on line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment. +.. pull-quote:: + + Note + + On line 5 we used ``getParent+`` to capture tags that are nested at any depth within the Javadoc comment. For more information on working with Javadoc, see the :doc:`tutorial on Javadoc `. diff --git a/docs/language/learn-ql/java/types-class-hierarchy.rst b/docs/language/learn-ql/java/types-class-hierarchy.rst index df50e600cf96..9855a0391b28 100644 --- a/docs/language/learn-ql/java/types-class-hierarchy.rst +++ b/docs/language/learn-ql/java/types-class-hierarchy.rst @@ -32,6 +32,8 @@ To determine ancestor types (including immediate super types, and also *their* s ➤ `See this in the query console `__. If this query were run on the example snippet above, the query would return ``A``, ``I``, and ``java.lang.Object``. +.. pull-quote:: + Tip If you want to see the location of ``B`` as well as ``A``, you can replace ``B.getASupertype+()`` with ``B.getASupertype*()`` and re-run the query. diff --git a/docs/language/learn-ql/javascript/introduce-libraries-js.rst b/docs/language/learn-ql/javascript/introduce-libraries-js.rst index 0e3a7e5acdd7..0858cbb5f8d8 100644 --- a/docs/language/learn-ql/javascript/introduce-libraries-js.rst +++ b/docs/language/learn-ql/javascript/introduce-libraries-js.rst @@ -224,7 +224,7 @@ The `TopLevel `__, `Class `__ and `Function `__ which are all subclasses of ``Scope``. +A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class and function are represented by the three classes `Module `__, `Class `__ and `Function `__, which are all subclasses of ``Scope``. - ``Scope`` @@ -110,12 +110,12 @@ Examples Each syntactic element in Python source is recorded in the snapshot. These can be queried via the corresponding class. Let us start with a couple of simple examples. -1. Finding all finally blocks -''''''''''''''''''''''''''''' +1. Finding all ``finally`` blocks +''''''''''''''''''''''''''''''''' For our first example, we can find all ``finally`` blocks by using the ``Try`` class: -**Find all ``finally`` blocks** +**Find all** ``finally`` **blocks** .. code-block:: ql @@ -126,8 +126,8 @@ For our first example, we can find all ``finally`` blocks by using the ``Try`` c ➤ `See this in the query console `__. Many projects include examples of this pattern. -2. Finding 'except' blocks that do nothing -'''''''''''''''''''''''''''''''''''''''''' +2. Finding ``except`` blocks that do nothing +'''''''''''''''''''''''''''''''''''''''''''' For our second example, we can use a simplified version of a query from the standard query set. We look for all ``except`` blocks that do nothing. @@ -137,7 +137,7 @@ A block that does nothing is one that contains no statements except ``pass`` sta not exists(Stmt s | s = ex.getAStmt() | not s instanceof Pass) -where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass`` statements. Instead of using the double negative, **"no**\ *statements that are*\ **not**\ *pass statements"*, this can also be expressed positively, "all statements must be pass statements." The positive form is expressed in QL using the ``forall`` quantifier: +where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass`` statements. Instead of using the double negative, *no statements that are not pass statements*, this can also be expressed positively, *all statements must be pass statements*. The positive form is expressed in QL using the ``forall`` quantifier: .. code-block:: ql @@ -145,7 +145,7 @@ where ``ex`` is an ``ExceptStmt`` and ``Pass`` is the class representing ``pass` Both forms are equivalent. Using the positive QL expression, the whole query looks like this: -**Find pass-only ``except`` blocks** +**Find pass-only** ``except`` **blocks** .. code-block:: ql diff --git a/docs/language/learn-ql/python/pointsto-type-infer.rst b/docs/language/learn-ql/python/pointsto-type-infer.rst index bcbab5204776..1b5817f85347 100644 --- a/docs/language/learn-ql/python/pointsto-type-infer.rst +++ b/docs/language/learn-ql/python/pointsto-type-infer.rst @@ -37,7 +37,8 @@ The predicate ``ControlFlowNode.pointsTo(...)`` shows which object a control flo predicate pointsTo(Context context, Value object, ControlFlowNode origin) ``object`` is an object that the control flow node refers to, and ``origin`` is where the object comes from, which is useful for displaying meaningful results. - The third form includes the ``context`` in which the control flow node refers to the ``object``. This form can usually be ignored. + +The third form includes the ``context`` in which the control flow node refers to the ``object``. This form can usually be ignored. .. pull-quote:: @@ -62,7 +63,7 @@ We want to find ``except`` blocks in a ``try`` statement that are in the wrong o First we can write a query to find ordered pairs of ``except`` blocks for a ``try`` statement. -**Ordered except blocks in same ``try`` statement** +**Ordered except blocks in same** ``try`` **statement** .. code-block:: ql @@ -81,7 +82,7 @@ Here ``ex1`` and ``ex2`` are both ``except`` handlers in the ``try`` statement ` The results of this query need to be filtered to return only results where ``ex1`` is more general than ``ex2``. We can use the fact that an ``except`` block is more general than another block if the class it handles is a superclass of the other. -**More general ``except`` block** +**More general** ``except`` **block** .. code-block:: ql @@ -102,7 +103,7 @@ ensures that ``cls1`` is a ``ClassValue`` that the ``except`` block would handle Combining the parts of the query we get this: -**More general ``except`` block precedes more specific** +**More general** ``except`` **block precedes more specific** .. code-block:: ql diff --git a/docs/language/learn-ql/python/statements-expressions.rst b/docs/language/learn-ql/python/statements-expressions.rst index 9f1a15a6d1af..622733ceb1bf 100644 --- a/docs/language/learn-ql/python/statements-expressions.rst +++ b/docs/language/learn-ql/python/statements-expressions.rst @@ -143,7 +143,7 @@ Python implementations commonly cache small integers and single character string We can check for these as follows: -**Find comparisons to integer or string literals using ``is``** +**Find comparisons to integer or string literals using** ``is`` .. code-block:: ql @@ -158,6 +158,8 @@ We can check for these as follows: The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` checks that the first comparison operator is "is" and that the first comparator is a literal. +.. pull-quote:: + Tip We have to use ``cmp.getOp(0)`` and ``cmp.getComparator(0)``\ as there is no ``cmp.getOp()`` or ``cmp.getComparator()``. The reason for this is that a ``Compare`` expression can have multiple operators. For example, the expression ``3 < x < 7`` has two operators and two comparators. You use ``cmp.getComparator(0)`` to get the first comparator (in this example the ``3``) and ``cmp.getComparator(1)`` to get the second comparator (in this example the ``7``). @@ -253,9 +255,7 @@ checks that the value of the attribute (the expression to the left of the dot in Class and function definitions ------------------------------ -As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the ``ClassDef`` class (which represents a ``class`` statement) subclasses ``Assign``. The ``Class`` class, which represents the body of the class, can be accessed via the ``ClassDef.getDefinedClass()`` - -``FunctionDef``, ``Function`` are handled similarly. +As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the ``ClassDef`` class (which represents a ``class`` statement) subclasses ``Assign``. The ``Class`` class, which represents the body of the class, can be accessed via the ``ClassDef.getDefinedClass()``. ``FunctionDef`` and ``Function`` are handled similarly. Here is the relevant part of the class hierarchy: From ff78feeeeaec99bdf779242c33e25f57c7bcab29 Mon Sep 17 00:00:00 2001 From: james Date: Mon, 30 Sep 2019 11:51:17 +0100 Subject: [PATCH 0013/2538] docs: version number and small css tweaks --- .../slides-semmle-2/static/theme/css/default.css | 5 +++-- docs/language/ql-training/conf.py | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index 2c05ea5e93b0..e3664d42e06b 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -485,6 +485,7 @@ ul { margin-left: 2.2em; margin-bottom: 1em; position: relative; + width: 90%; } /* line 300, ../scss/default.scss */ ul li { @@ -1569,7 +1570,7 @@ p.first.admonition-title { text-align: left; font-size: 0.8em; width: 100%; - overflow: scroll; + overflow: auto; border: 1px solid black; } @@ -1608,7 +1609,7 @@ p.first.admonition-title { display: block; position: fixed; top: 0; - right: -1%; + right: 0; font-size: 1.2em; } diff --git a/docs/language/ql-training/conf.py b/docs/language/ql-training/conf.py index de712cd06a44..8f8a13569b51 100644 --- a/docs/language/ql-training/conf.py +++ b/docs/language/ql-training/conf.py @@ -86,9 +86,9 @@ def setup(sphinx): # built documents. # # The short X.Y version. -version = u'1.21' +version = u'1.22' # The full version, including alpha/beta/rc tags. -release = u'1.21' +release = u'1.22' copyright = u'2019 Semmle Ltd' author = u'Semmle Ltd' From bace8c723db477d9aace46b3dd8d80c68aa12601 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 1 Oct 2019 14:53:37 -0700 Subject: [PATCH 0014/2538] C++: side effect instrs for constructor qualifiers This adds IndirectMustWriteSideEffects for constructor qualifiers. The introduced sanity failures result from constructor calls without qualifier operands in the IR --- .../raw/internal/TranslatedCall.qll | 30 + .../raw/internal/TranslatedElement.qll | 2 +- .../ir/ir/aliased_ssa_sanity.expected | 4 + .../test/library-tests/ir/ir/raw_ir.expected | 1258 +++++++++-------- .../library-tests/ir/ir/raw_sanity.expected | 4 + .../ir/ir/unaliased_ssa_sanity.expected | 4 + .../syntax-zoo/aliased_ssa_sanity.expected | 41 +- .../syntax-zoo/raw_sanity.expected | 50 +- .../syntax-zoo/unaliased_ssa_sanity.expected | 47 +- 9 files changed, 799 insertions(+), 641 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 4a7aa607f574..0ee86785b52e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -374,6 +374,35 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { override Function getFunction() { result = expr.getEnclosingFunction() } } +class TranslatedStructorCallSideEffects extends TranslatedSideEffects { + TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() } + + override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type t, boolean isGLValue) { + opcode instanceof Opcode::IndirectMustWriteSideEffect and + tag instanceof OnlyInstructionTag and + t = expr.getTarget().getDeclaringType() and + isGLValue = false + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { + ( + if exists(getChild(0)) + then result = getChild(0).getFirstInstruction() + else result = getParent().getChildSuccessor(this) + ) and + tag = OnlyInstructionTag() and + kind instanceof GotoEdge + } + + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + + override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag instanceof OnlyInstructionTag and + operandTag instanceof AddressOperandTag and + result = getParent().(TranslatedStructorCall).getQualifierResult() + } +} + class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEffect { Call call; Expr arg; @@ -537,3 +566,4 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff */ override Function getFunction() { result = arg.getEnclosingFunction() } } + diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 01ed6a4d5911..db34d69f4c85 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -372,7 +372,7 @@ newtype TTranslatedElement = // The declaration/initialization part of a `ConditionDeclExpr` TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or // The side effects of a `Call` { - TTranslatedSideEffects(Call expr) { exists(TTranslatedArgumentSideEffect(expr, _, _, _)) } or // A precise side effect of an argument to a `Call` { + TTranslatedSideEffects(Call expr) { exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or expr instanceof ConstructorCall } or // A precise side effect of an argument to a `Call` { TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) { ( expr = call.getArgument(n).getFullyConverted() diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index ae680785ce64..283f13d4bf44 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -1,4 +1,8 @@ missingOperand +| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 3bff2bff6907..55a8cc56e01d 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2715,31 +2715,34 @@ ir.cpp: # 616| r0_4(glval) = FunctionAddress[String] : # 616| v0_5(void) = Call : func:r0_4, this:r0_3 # 616| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 617| r0_7(glval) = VariableAddress[s2] : -# 617| r0_8(glval) = FunctionAddress[String] : -# 617| r0_9(glval) = StringConstant["hello"] : -# 617| r0_10(char *) = Convert : r0_9 -# 617| v0_11(void) = Call : func:r0_8, this:r0_7, 0:r0_10 -# 617| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 617| v0_13(void) = ^IndirectReadSideEffect[0] : &:r0_10, ~mu0_2 -# 617| mu0_14(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_10 -# 618| r0_15(glval) = VariableAddress[s3] : -# 618| r0_16(glval) = FunctionAddress[ReturnObject] : -# 618| r0_17(String) = Call : func:r0_16 -# 618| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 -# 618| mu0_19(String) = Store : &:r0_15, r0_17 -# 619| r0_20(glval) = VariableAddress[s4] : -# 619| r0_21(glval) = FunctionAddress[String] : -# 619| r0_22(glval) = StringConstant["test"] : -# 619| r0_23(char *) = Convert : r0_22 -# 619| v0_24(void) = Call : func:r0_21, this:r0_20, 0:r0_23 -# 619| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 619| v0_26(void) = ^IndirectReadSideEffect[0] : &:r0_23, ~mu0_2 -# 619| mu0_27(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_23 -# 620| v0_28(void) = NoOp : -# 615| v0_29(void) = ReturnVoid : -# 615| v0_30(void) = UnmodeledUse : mu* -# 615| v0_31(void) = ExitFunction : +# 616| mu0_7(String) = ^IndirectMustWriteSideEffect : &:r0_3 +# 617| r0_8(glval) = VariableAddress[s2] : +# 617| r0_9(glval) = FunctionAddress[String] : +# 617| r0_10(glval) = StringConstant["hello"] : +# 617| r0_11(char *) = Convert : r0_10 +# 617| v0_12(void) = Call : func:r0_9, this:r0_8, 0:r0_11 +# 617| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 617| mu0_14(String) = ^IndirectMustWriteSideEffect : &:r0_8 +# 617| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 +# 617| mu0_16(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 +# 618| r0_17(glval) = VariableAddress[s3] : +# 618| r0_18(glval) = FunctionAddress[ReturnObject] : +# 618| r0_19(String) = Call : func:r0_18 +# 618| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 618| mu0_21(String) = Store : &:r0_17, r0_19 +# 619| r0_22(glval) = VariableAddress[s4] : +# 619| r0_23(glval) = FunctionAddress[String] : +# 619| r0_24(glval) = StringConstant["test"] : +# 619| r0_25(char *) = Convert : r0_24 +# 619| v0_26(void) = Call : func:r0_23, this:r0_22, 0:r0_25 +# 619| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 +# 619| mu0_28(String) = ^IndirectMustWriteSideEffect : &:r0_22 +# 619| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 +# 619| mu0_30(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 +# 620| v0_31(void) = NoOp : +# 615| v0_32(void) = ReturnVoid : +# 615| v0_33(void) = UnmodeledUse : mu* +# 615| v0_34(void) = ExitFunction : # 622| void CallMethods(String&, String*, String) # 622| Block 0 @@ -2915,24 +2918,26 @@ ir.cpp: # 663| r0_8(glval) = FunctionAddress[String] : # 663| v0_9(void) = Call : func:r0_8, this:r0_7 # 663| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 660| r0_11(glval) = FieldAddress[m_c] : r0_3 -# 660| r0_12(char) = Constant[3] : -# 660| mu0_13(char) = Store : &:r0_11, r0_12 -# 661| r0_14(glval) = FieldAddress[m_e] : r0_3 -# 661| r0_15(void *) = Constant[0] : -# 661| mu0_16(void *) = Store : &:r0_14, r0_15 -# 662| r0_17(glval) = FieldAddress[m_f] : r0_3 -# 662| r0_18(glval) = FunctionAddress[String] : -# 662| r0_19(glval) = StringConstant["test"] : -# 662| r0_20(char *) = Convert : r0_19 -# 662| v0_21(void) = Call : func:r0_18, this:r0_17, 0:r0_20 -# 662| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 -# 662| v0_23(void) = ^IndirectReadSideEffect[0] : &:r0_20, ~mu0_2 -# 662| mu0_24(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_20 -# 664| v0_25(void) = NoOp : -# 658| v0_26(void) = ReturnVoid : -# 658| v0_27(void) = UnmodeledUse : mu* -# 658| v0_28(void) = ExitFunction : +# 663| mu0_11(String) = ^IndirectMustWriteSideEffect : &:r0_7 +# 660| r0_12(glval) = FieldAddress[m_c] : r0_3 +# 660| r0_13(char) = Constant[3] : +# 660| mu0_14(char) = Store : &:r0_12, r0_13 +# 661| r0_15(glval) = FieldAddress[m_e] : r0_3 +# 661| r0_16(void *) = Constant[0] : +# 661| mu0_17(void *) = Store : &:r0_15, r0_16 +# 662| r0_18(glval) = FieldAddress[m_f] : r0_3 +# 662| r0_19(glval) = FunctionAddress[String] : +# 662| r0_20(glval) = StringConstant["test"] : +# 662| r0_21(char *) = Convert : r0_20 +# 662| v0_22(void) = Call : func:r0_19, this:r0_18, 0:r0_21 +# 662| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 +# 662| mu0_24(String) = ^IndirectMustWriteSideEffect : &:r0_18 +# 662| v0_25(void) = ^IndirectReadSideEffect[0] : &:r0_21, ~mu0_2 +# 662| mu0_26(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_21 +# 664| v0_27(void) = NoOp : +# 658| v0_28(void) = ReturnVoid : +# 658| v0_29(void) = UnmodeledUse : mu* +# 658| v0_30(void) = ExitFunction : # 675| int DerefReference(int&) # 675| Block 0 @@ -3201,9 +3206,10 @@ ir.cpp: # 731| r7_3(char *) = Convert : r7_2 # 731| v7_4(void) = Call : func:r7_1, this:r7_0, 0:r7_3 # 731| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 -# 731| v7_6(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 -# 731| mu7_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 -# 731| v7_8(void) = ThrowValue : &:r7_0, ~mu0_2 +# 731| mu7_6(String) = ^IndirectMustWriteSideEffect : &:r7_0 +# 731| v7_7(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 +# 731| mu7_8(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 +# 731| v7_9(void) = ThrowValue : &:r7_0, ~mu0_2 #-----| Exception -> Block 9 # 733| Block 8 @@ -3226,9 +3232,10 @@ ir.cpp: # 736| r10_5(char *) = Load : &:r10_4, ~mu0_2 # 736| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 # 736| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 736| v10_8(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 -# 736| mu10_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 -# 736| v10_10(void) = ThrowValue : &:r10_2, ~mu0_2 +# 736| mu10_8(String) = ^IndirectMustWriteSideEffect : &:r10_2 +# 736| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 +# 736| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 +# 736| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 #-----| Exception -> Block 2 # 738| Block 11 @@ -3282,35 +3289,37 @@ ir.cpp: # 745| void Base::Base(Base const&) # 745| Block 0 -# 745| v0_0(void) = EnterFunction : -# 745| mu0_1(unknown) = AliasedDefinition : -# 745| mu0_2(unknown) = UnmodeledDefinition : -# 745| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 -# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 -# 745| r0_7(glval) = FunctionAddress[String] : -# 745| v0_8(void) = Call : func:r0_7, this:r0_6 -# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 745| v0_10(void) = NoOp : -# 745| v0_11(void) = ReturnVoid : -# 745| v0_12(void) = UnmodeledUse : mu* -# 745| v0_13(void) = ExitFunction : +# 745| v0_0(void) = EnterFunction : +# 745| mu0_1(unknown) = AliasedDefinition : +# 745| mu0_2(unknown) = UnmodeledDefinition : +# 745| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 +# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 +# 745| r0_7(glval) = FunctionAddress[String] : +# 745| v0_8(void) = Call : func:r0_7, this:r0_6 +# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 +# 745| mu0_10(String) = ^IndirectMustWriteSideEffect : &:r0_6 +# 745| v0_11(void) = NoOp : +# 745| v0_12(void) = ReturnVoid : +# 745| v0_13(void) = UnmodeledUse : mu* +# 745| v0_14(void) = ExitFunction : # 748| void Base::Base() # 748| Block 0 -# 748| v0_0(void) = EnterFunction : -# 748| mu0_1(unknown) = AliasedDefinition : -# 748| mu0_2(unknown) = UnmodeledDefinition : -# 748| r0_3(glval) = InitializeThis : -# 748| r0_4(glval) = FieldAddress[base_s] : r0_3 -# 748| r0_5(glval) = FunctionAddress[String] : -# 748| v0_6(void) = Call : func:r0_5, this:r0_4 -# 748| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 749| v0_8(void) = NoOp : -# 748| v0_9(void) = ReturnVoid : -# 748| v0_10(void) = UnmodeledUse : mu* -# 748| v0_11(void) = ExitFunction : +# 748| v0_0(void) = EnterFunction : +# 748| mu0_1(unknown) = AliasedDefinition : +# 748| mu0_2(unknown) = UnmodeledDefinition : +# 748| r0_3(glval) = InitializeThis : +# 748| r0_4(glval) = FieldAddress[base_s] : r0_3 +# 748| r0_5(glval) = FunctionAddress[String] : +# 748| v0_6(void) = Call : func:r0_5, this:r0_4 +# 748| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 748| mu0_8(String) = ^IndirectMustWriteSideEffect : &:r0_4 +# 749| v0_9(void) = NoOp : +# 748| v0_10(void) = ReturnVoid : +# 748| v0_11(void) = UnmodeledUse : mu* +# 748| v0_12(void) = ExitFunction : # 750| void Base::~Base() # 750| Block 0 @@ -3369,22 +3378,24 @@ ir.cpp: # 757| void Middle::Middle() # 757| Block 0 -# 757| v0_0(void) = EnterFunction : -# 757| mu0_1(unknown) = AliasedDefinition : -# 757| mu0_2(unknown) = UnmodeledDefinition : -# 757| r0_3(glval) = InitializeThis : -# 757| r0_4(glval) = ConvertToBase[Middle : Base] : r0_3 -# 757| r0_5(glval) = FunctionAddress[Base] : -# 757| v0_6(void) = Call : func:r0_5, this:r0_4 -# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 757| r0_8(glval) = FieldAddress[middle_s] : r0_3 -# 757| r0_9(glval) = FunctionAddress[String] : -# 757| v0_10(void) = Call : func:r0_9, this:r0_8 -# 757| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 758| v0_12(void) = NoOp : -# 757| v0_13(void) = ReturnVoid : -# 757| v0_14(void) = UnmodeledUse : mu* -# 757| v0_15(void) = ExitFunction : +# 757| v0_0(void) = EnterFunction : +# 757| mu0_1(unknown) = AliasedDefinition : +# 757| mu0_2(unknown) = UnmodeledDefinition : +# 757| r0_3(glval) = InitializeThis : +# 757| r0_4(glval) = ConvertToBase[Middle : Base] : r0_3 +# 757| r0_5(glval) = FunctionAddress[Base] : +# 757| v0_6(void) = Call : func:r0_5, this:r0_4 +# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 757| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 757| r0_9(glval) = FieldAddress[middle_s] : r0_3 +# 757| r0_10(glval) = FunctionAddress[String] : +# 757| v0_11(void) = Call : func:r0_10, this:r0_9 +# 757| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 757| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 758| v0_14(void) = NoOp : +# 757| v0_15(void) = ReturnVoid : +# 757| v0_16(void) = UnmodeledUse : mu* +# 757| v0_17(void) = ExitFunction : # 759| void Middle::~Middle() # 759| Block 0 @@ -3447,22 +3458,24 @@ ir.cpp: # 766| void Derived::Derived() # 766| Block 0 -# 766| v0_0(void) = EnterFunction : -# 766| mu0_1(unknown) = AliasedDefinition : -# 766| mu0_2(unknown) = UnmodeledDefinition : -# 766| r0_3(glval) = InitializeThis : -# 766| r0_4(glval) = ConvertToBase[Derived : Middle] : r0_3 -# 766| r0_5(glval) = FunctionAddress[Middle] : -# 766| v0_6(void) = Call : func:r0_5, this:r0_4 -# 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 766| r0_8(glval) = FieldAddress[derived_s] : r0_3 -# 766| r0_9(glval) = FunctionAddress[String] : -# 766| v0_10(void) = Call : func:r0_9, this:r0_8 -# 766| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 767| v0_12(void) = NoOp : -# 766| v0_13(void) = ReturnVoid : -# 766| v0_14(void) = UnmodeledUse : mu* -# 766| v0_15(void) = ExitFunction : +# 766| v0_0(void) = EnterFunction : +# 766| mu0_1(unknown) = AliasedDefinition : +# 766| mu0_2(unknown) = UnmodeledDefinition : +# 766| r0_3(glval) = InitializeThis : +# 766| r0_4(glval) = ConvertToBase[Derived : Middle] : r0_3 +# 766| r0_5(glval) = FunctionAddress[Middle] : +# 766| v0_6(void) = Call : func:r0_5, this:r0_4 +# 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 766| mu0_8(Middle) = ^IndirectMustWriteSideEffect : &:r0_4 +# 766| r0_9(glval) = FieldAddress[derived_s] : r0_3 +# 766| r0_10(glval) = FunctionAddress[String] : +# 766| v0_11(void) = Call : func:r0_10, this:r0_9 +# 766| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 766| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 767| v0_14(void) = NoOp : +# 766| v0_15(void) = ReturnVoid : +# 766| v0_16(void) = UnmodeledUse : mu* +# 766| v0_17(void) = ExitFunction : # 768| void Derived::~Derived() # 768| Block 0 @@ -3493,14 +3506,16 @@ ir.cpp: # 775| r0_5(glval) = FunctionAddress[Base] : # 775| v0_6(void) = Call : func:r0_5, this:r0_4 # 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 775| r0_8(glval) = FieldAddress[middlevb1_s] : r0_3 -# 775| r0_9(glval) = FunctionAddress[String] : -# 775| v0_10(void) = Call : func:r0_9, this:r0_8 -# 775| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 776| v0_12(void) = NoOp : -# 775| v0_13(void) = ReturnVoid : -# 775| v0_14(void) = UnmodeledUse : mu* -# 775| v0_15(void) = ExitFunction : +# 775| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 775| r0_9(glval) = FieldAddress[middlevb1_s] : r0_3 +# 775| r0_10(glval) = FunctionAddress[String] : +# 775| v0_11(void) = Call : func:r0_10, this:r0_9 +# 775| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 775| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 776| v0_14(void) = NoOp : +# 775| v0_15(void) = ReturnVoid : +# 775| v0_16(void) = UnmodeledUse : mu* +# 775| v0_17(void) = ExitFunction : # 777| void MiddleVB1::~MiddleVB1() # 777| Block 0 @@ -3531,14 +3546,16 @@ ir.cpp: # 784| r0_5(glval) = FunctionAddress[Base] : # 784| v0_6(void) = Call : func:r0_5, this:r0_4 # 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 784| r0_8(glval) = FieldAddress[middlevb2_s] : r0_3 -# 784| r0_9(glval) = FunctionAddress[String] : -# 784| v0_10(void) = Call : func:r0_9, this:r0_8 -# 784| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 785| v0_12(void) = NoOp : -# 784| v0_13(void) = ReturnVoid : -# 784| v0_14(void) = UnmodeledUse : mu* -# 784| v0_15(void) = ExitFunction : +# 784| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 784| r0_9(glval) = FieldAddress[middlevb2_s] : r0_3 +# 784| r0_10(glval) = FunctionAddress[String] : +# 784| v0_11(void) = Call : func:r0_10, this:r0_9 +# 784| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 784| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 785| v0_14(void) = NoOp : +# 784| v0_15(void) = ReturnVoid : +# 784| v0_16(void) = UnmodeledUse : mu* +# 784| v0_17(void) = ExitFunction : # 786| void MiddleVB2::~MiddleVB2() # 786| Block 0 @@ -3569,22 +3586,26 @@ ir.cpp: # 793| r0_5(glval) = FunctionAddress[Base] : # 793| v0_6(void) = Call : func:r0_5, this:r0_4 # 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_8(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 -# 793| r0_9(glval) = FunctionAddress[MiddleVB1] : -# 793| v0_10(void) = Call : func:r0_9, this:r0_8 -# 793| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_12(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 -# 793| r0_13(glval) = FunctionAddress[MiddleVB2] : -# 793| v0_14(void) = Call : func:r0_13, this:r0_12 -# 793| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 -# 793| r0_16(glval) = FieldAddress[derivedvb_s] : r0_3 -# 793| r0_17(glval) = FunctionAddress[String] : -# 793| v0_18(void) = Call : func:r0_17, this:r0_16 -# 793| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 794| v0_20(void) = NoOp : -# 793| v0_21(void) = ReturnVoid : -# 793| v0_22(void) = UnmodeledUse : mu* -# 793| v0_23(void) = ExitFunction : +# 793| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 793| r0_9(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 +# 793| r0_10(glval) = FunctionAddress[MiddleVB1] : +# 793| v0_11(void) = Call : func:r0_10, this:r0_9 +# 793| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 793| mu0_13(MiddleVB1) = ^IndirectMustWriteSideEffect : &:r0_9 +# 793| r0_14(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 +# 793| r0_15(glval) = FunctionAddress[MiddleVB2] : +# 793| v0_16(void) = Call : func:r0_15, this:r0_14 +# 793| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 793| mu0_18(MiddleVB2) = ^IndirectMustWriteSideEffect : &:r0_14 +# 793| r0_19(glval) = FieldAddress[derivedvb_s] : r0_3 +# 793| r0_20(glval) = FunctionAddress[String] : +# 793| v0_21(void) = Call : func:r0_20, this:r0_19 +# 793| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 +# 793| mu0_23(String) = ^IndirectMustWriteSideEffect : &:r0_19 +# 794| v0_24(void) = NoOp : +# 793| v0_25(void) = ReturnVoid : +# 793| v0_26(void) = UnmodeledUse : mu* +# 793| v0_27(void) = ExitFunction : # 795| void DerivedVB::~DerivedVB() # 795| Block 0 @@ -3622,251 +3643,258 @@ ir.cpp: # 800| r0_4(glval) = FunctionAddress[Base] : # 800| v0_5(void) = Call : func:r0_4, this:r0_3 # 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 801| r0_7(glval) = VariableAddress[m] : -# 801| r0_8(glval) = FunctionAddress[Middle] : -# 801| v0_9(void) = Call : func:r0_8, this:r0_7 -# 801| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 802| r0_11(glval) = VariableAddress[d] : -# 802| r0_12(glval) = FunctionAddress[Derived] : -# 802| v0_13(void) = Call : func:r0_12, this:r0_11 -# 802| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 804| r0_15(glval) = VariableAddress[pb] : -# 804| r0_16(glval) = VariableAddress[b] : -# 804| mu0_17(Base *) = Store : &:r0_15, r0_16 -# 805| r0_18(glval) = VariableAddress[pm] : -# 805| r0_19(glval) = VariableAddress[m] : -# 805| mu0_20(Middle *) = Store : &:r0_18, r0_19 -# 806| r0_21(glval) = VariableAddress[pd] : -# 806| r0_22(glval) = VariableAddress[d] : -# 806| mu0_23(Derived *) = Store : &:r0_21, r0_22 -# 808| r0_24(glval) = VariableAddress[b] : -# 808| r0_25(glval) = FunctionAddress[operator=] : -# 808| r0_26(glval) = VariableAddress[m] : -# 808| r0_27(glval) = ConvertToBase[Middle : Base] : r0_26 -# 808| r0_28(Base &) = Call : func:r0_25, this:r0_24, 0:r0_27 -# 808| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 -# 808| v0_30(void) = ^IndirectReadSideEffect[-1] : &:r0_24, ~mu0_2 -# 808| v0_31(void) = ^IndirectReadSideEffect[0] : &:r0_27, ~mu0_2 -# 808| mu0_32(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_24 -# 808| mu0_33(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_27 -# 809| r0_34(glval) = VariableAddress[b] : -# 809| r0_35(glval) = FunctionAddress[operator=] : -# 809| r0_36(glval) = FunctionAddress[Base] : -# 809| r0_37(glval) = VariableAddress[m] : -# 809| r0_38(glval) = ConvertToBase[Middle : Base] : r0_37 -# 809| v0_39(void) = Call : func:r0_36, 0:r0_38 -# 809| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_41(void) = ^IndirectReadSideEffect[0] : &:r0_38, ~mu0_2 -# 809| mu0_42(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_38 -# 809| r0_43(glval) = Convert : v0_39 -# 809| r0_44(Base &) = Call : func:r0_35, this:r0_34, 0:r0_43 -# 809| mu0_45(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_46(void) = ^IndirectReadSideEffect[-1] : &:r0_34, ~mu0_2 -# 809| v0_47(void) = ^IndirectReadSideEffect[0] : &:r0_43, ~mu0_2 -# 809| mu0_48(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_34 -# 809| mu0_49(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_43 -# 810| r0_50(glval) = VariableAddress[b] : -# 810| r0_51(glval) = FunctionAddress[operator=] : -# 810| r0_52(glval) = FunctionAddress[Base] : -# 810| r0_53(glval) = VariableAddress[m] : -# 810| r0_54(glval) = ConvertToBase[Middle : Base] : r0_53 -# 810| v0_55(void) = Call : func:r0_52, 0:r0_54 -# 810| mu0_56(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_57(void) = ^IndirectReadSideEffect[0] : &:r0_54, ~mu0_2 -# 810| mu0_58(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_54 -# 810| r0_59(glval) = Convert : v0_55 -# 810| r0_60(Base &) = Call : func:r0_51, this:r0_50, 0:r0_59 -# 810| mu0_61(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_62(void) = ^IndirectReadSideEffect[-1] : &:r0_50, ~mu0_2 -# 810| v0_63(void) = ^IndirectReadSideEffect[0] : &:r0_59, ~mu0_2 -# 810| mu0_64(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_50 -# 810| mu0_65(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_59 -# 811| r0_66(glval) = VariableAddress[pm] : -# 811| r0_67(Middle *) = Load : &:r0_66, ~mu0_2 -# 811| r0_68(Base *) = ConvertToBase[Middle : Base] : r0_67 -# 811| r0_69(glval) = VariableAddress[pb] : -# 811| mu0_70(Base *) = Store : &:r0_69, r0_68 -# 812| r0_71(glval) = VariableAddress[pm] : -# 812| r0_72(Middle *) = Load : &:r0_71, ~mu0_2 -# 812| r0_73(Base *) = ConvertToBase[Middle : Base] : r0_72 -# 812| r0_74(glval) = VariableAddress[pb] : -# 812| mu0_75(Base *) = Store : &:r0_74, r0_73 -# 813| r0_76(glval) = VariableAddress[pm] : -# 813| r0_77(Middle *) = Load : &:r0_76, ~mu0_2 -# 813| r0_78(Base *) = ConvertToBase[Middle : Base] : r0_77 -# 813| r0_79(glval) = VariableAddress[pb] : -# 813| mu0_80(Base *) = Store : &:r0_79, r0_78 -# 814| r0_81(glval) = VariableAddress[pm] : -# 814| r0_82(Middle *) = Load : &:r0_81, ~mu0_2 -# 814| r0_83(Base *) = Convert : r0_82 -# 814| r0_84(glval) = VariableAddress[pb] : -# 814| mu0_85(Base *) = Store : &:r0_84, r0_83 -# 816| r0_86(glval) = VariableAddress[m] : -# 816| r0_87(glval) = FunctionAddress[operator=] : -# 816| r0_88(glval) = VariableAddress[b] : -# 816| r0_89(glval) = ConvertToDerived[Middle : Base] : r0_88 -# 816| r0_90(glval) = Convert : r0_89 -# 816| r0_91(Middle &) = Call : func:r0_87, this:r0_86, 0:r0_90 -# 816| mu0_92(unknown) = ^CallSideEffect : ~mu0_2 -# 816| v0_93(void) = ^IndirectReadSideEffect[-1] : &:r0_86, ~mu0_2 -# 816| v0_94(void) = ^IndirectReadSideEffect[0] : &:r0_90, ~mu0_2 -# 816| mu0_95(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_86 -# 816| mu0_96(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_90 -# 817| r0_97(glval) = VariableAddress[m] : -# 817| r0_98(glval) = FunctionAddress[operator=] : -# 817| r0_99(glval) = VariableAddress[b] : -# 817| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 -# 817| r0_101(glval) = Convert : r0_100 -# 817| r0_102(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_101 -# 817| mu0_103(unknown) = ^CallSideEffect : ~mu0_2 -# 817| v0_104(void) = ^IndirectReadSideEffect[-1] : &:r0_97, ~mu0_2 -# 817| v0_105(void) = ^IndirectReadSideEffect[0] : &:r0_101, ~mu0_2 -# 817| mu0_106(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 -# 817| mu0_107(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_101 -# 818| r0_108(glval) = VariableAddress[pb] : -# 818| r0_109(Base *) = Load : &:r0_108, ~mu0_2 -# 818| r0_110(Middle *) = ConvertToDerived[Middle : Base] : r0_109 -# 818| r0_111(glval) = VariableAddress[pm] : -# 818| mu0_112(Middle *) = Store : &:r0_111, r0_110 -# 819| r0_113(glval) = VariableAddress[pb] : -# 819| r0_114(Base *) = Load : &:r0_113, ~mu0_2 -# 819| r0_115(Middle *) = ConvertToDerived[Middle : Base] : r0_114 -# 819| r0_116(glval) = VariableAddress[pm] : -# 819| mu0_117(Middle *) = Store : &:r0_116, r0_115 -# 820| r0_118(glval) = VariableAddress[pb] : -# 820| r0_119(Base *) = Load : &:r0_118, ~mu0_2 -# 820| r0_120(Middle *) = Convert : r0_119 -# 820| r0_121(glval) = VariableAddress[pm] : -# 820| mu0_122(Middle *) = Store : &:r0_121, r0_120 -# 822| r0_123(glval) = VariableAddress[b] : -# 822| r0_124(glval) = FunctionAddress[operator=] : -# 822| r0_125(glval) = VariableAddress[d] : -# 822| r0_126(glval) = ConvertToBase[Derived : Middle] : r0_125 -# 822| r0_127(glval) = ConvertToBase[Middle : Base] : r0_126 -# 822| r0_128(Base &) = Call : func:r0_124, this:r0_123, 0:r0_127 -# 822| mu0_129(unknown) = ^CallSideEffect : ~mu0_2 -# 822| v0_130(void) = ^IndirectReadSideEffect[-1] : &:r0_123, ~mu0_2 -# 822| v0_131(void) = ^IndirectReadSideEffect[0] : &:r0_127, ~mu0_2 -# 822| mu0_132(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_123 -# 822| mu0_133(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_127 -# 823| r0_134(glval) = VariableAddress[b] : -# 823| r0_135(glval) = FunctionAddress[operator=] : -# 823| r0_136(glval) = FunctionAddress[Base] : -# 823| r0_137(glval) = VariableAddress[d] : -# 823| r0_138(glval) = ConvertToBase[Derived : Middle] : r0_137 -# 823| r0_139(glval) = ConvertToBase[Middle : Base] : r0_138 -# 823| v0_140(void) = Call : func:r0_136, 0:r0_139 -# 823| mu0_141(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_142(void) = ^IndirectReadSideEffect[0] : &:r0_139, ~mu0_2 -# 823| mu0_143(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_139 -# 823| r0_144(glval) = Convert : v0_140 -# 823| r0_145(Base &) = Call : func:r0_135, this:r0_134, 0:r0_144 +# 800| mu0_7(Base) = ^IndirectMustWriteSideEffect : &:r0_3 +# 801| r0_8(glval) = VariableAddress[m] : +# 801| r0_9(glval) = FunctionAddress[Middle] : +# 801| v0_10(void) = Call : func:r0_9, this:r0_8 +# 801| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 801| mu0_12(Middle) = ^IndirectMustWriteSideEffect : &:r0_8 +# 802| r0_13(glval) = VariableAddress[d] : +# 802| r0_14(glval) = FunctionAddress[Derived] : +# 802| v0_15(void) = Call : func:r0_14, this:r0_13 +# 802| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +# 802| mu0_17(Derived) = ^IndirectMustWriteSideEffect : &:r0_13 +# 804| r0_18(glval) = VariableAddress[pb] : +# 804| r0_19(glval) = VariableAddress[b] : +# 804| mu0_20(Base *) = Store : &:r0_18, r0_19 +# 805| r0_21(glval) = VariableAddress[pm] : +# 805| r0_22(glval) = VariableAddress[m] : +# 805| mu0_23(Middle *) = Store : &:r0_21, r0_22 +# 806| r0_24(glval) = VariableAddress[pd] : +# 806| r0_25(glval) = VariableAddress[d] : +# 806| mu0_26(Derived *) = Store : &:r0_24, r0_25 +# 808| r0_27(glval) = VariableAddress[b] : +# 808| r0_28(glval) = FunctionAddress[operator=] : +# 808| r0_29(glval) = VariableAddress[m] : +# 808| r0_30(glval) = ConvertToBase[Middle : Base] : r0_29 +# 808| r0_31(Base &) = Call : func:r0_28, this:r0_27, 0:r0_30 +# 808| mu0_32(unknown) = ^CallSideEffect : ~mu0_2 +# 808| v0_33(void) = ^IndirectReadSideEffect[-1] : &:r0_27, ~mu0_2 +# 808| v0_34(void) = ^IndirectReadSideEffect[0] : &:r0_30, ~mu0_2 +# 808| mu0_35(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 +# 808| mu0_36(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_30 +# 809| r0_37(glval) = VariableAddress[b] : +# 809| r0_38(glval) = FunctionAddress[operator=] : +# 809| r0_39(glval) = FunctionAddress[Base] : +# 809| r0_40(glval) = VariableAddress[m] : +# 809| r0_41(glval) = ConvertToBase[Middle : Base] : r0_40 +# 809| v0_42(void) = Call : func:r0_39, 0:r0_41 +# 809| mu0_43(unknown) = ^CallSideEffect : ~mu0_2 +# 809| mu0_44(Base) = ^IndirectMustWriteSideEffect : +# 809| v0_45(void) = ^IndirectReadSideEffect[0] : &:r0_41, ~mu0_2 +# 809| mu0_46(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_41 +# 809| r0_47(glval) = Convert : v0_42 +# 809| r0_48(Base &) = Call : func:r0_38, this:r0_37, 0:r0_47 +# 809| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 +# 809| v0_50(void) = ^IndirectReadSideEffect[-1] : &:r0_37, ~mu0_2 +# 809| v0_51(void) = ^IndirectReadSideEffect[0] : &:r0_47, ~mu0_2 +# 809| mu0_52(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_37 +# 809| mu0_53(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_47 +# 810| r0_54(glval) = VariableAddress[b] : +# 810| r0_55(glval) = FunctionAddress[operator=] : +# 810| r0_56(glval) = FunctionAddress[Base] : +# 810| r0_57(glval) = VariableAddress[m] : +# 810| r0_58(glval) = ConvertToBase[Middle : Base] : r0_57 +# 810| v0_59(void) = Call : func:r0_56, 0:r0_58 +# 810| mu0_60(unknown) = ^CallSideEffect : ~mu0_2 +# 810| mu0_61(Base) = ^IndirectMustWriteSideEffect : +# 810| v0_62(void) = ^IndirectReadSideEffect[0] : &:r0_58, ~mu0_2 +# 810| mu0_63(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_58 +# 810| r0_64(glval) = Convert : v0_59 +# 810| r0_65(Base &) = Call : func:r0_55, this:r0_54, 0:r0_64 +# 810| mu0_66(unknown) = ^CallSideEffect : ~mu0_2 +# 810| v0_67(void) = ^IndirectReadSideEffect[-1] : &:r0_54, ~mu0_2 +# 810| v0_68(void) = ^IndirectReadSideEffect[0] : &:r0_64, ~mu0_2 +# 810| mu0_69(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_54 +# 810| mu0_70(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_64 +# 811| r0_71(glval) = VariableAddress[pm] : +# 811| r0_72(Middle *) = Load : &:r0_71, ~mu0_2 +# 811| r0_73(Base *) = ConvertToBase[Middle : Base] : r0_72 +# 811| r0_74(glval) = VariableAddress[pb] : +# 811| mu0_75(Base *) = Store : &:r0_74, r0_73 +# 812| r0_76(glval) = VariableAddress[pm] : +# 812| r0_77(Middle *) = Load : &:r0_76, ~mu0_2 +# 812| r0_78(Base *) = ConvertToBase[Middle : Base] : r0_77 +# 812| r0_79(glval) = VariableAddress[pb] : +# 812| mu0_80(Base *) = Store : &:r0_79, r0_78 +# 813| r0_81(glval) = VariableAddress[pm] : +# 813| r0_82(Middle *) = Load : &:r0_81, ~mu0_2 +# 813| r0_83(Base *) = ConvertToBase[Middle : Base] : r0_82 +# 813| r0_84(glval) = VariableAddress[pb] : +# 813| mu0_85(Base *) = Store : &:r0_84, r0_83 +# 814| r0_86(glval) = VariableAddress[pm] : +# 814| r0_87(Middle *) = Load : &:r0_86, ~mu0_2 +# 814| r0_88(Base *) = Convert : r0_87 +# 814| r0_89(glval) = VariableAddress[pb] : +# 814| mu0_90(Base *) = Store : &:r0_89, r0_88 +# 816| r0_91(glval) = VariableAddress[m] : +# 816| r0_92(glval) = FunctionAddress[operator=] : +# 816| r0_93(glval) = VariableAddress[b] : +# 816| r0_94(glval) = ConvertToDerived[Middle : Base] : r0_93 +# 816| r0_95(glval) = Convert : r0_94 +# 816| r0_96(Middle &) = Call : func:r0_92, this:r0_91, 0:r0_95 +# 816| mu0_97(unknown) = ^CallSideEffect : ~mu0_2 +# 816| v0_98(void) = ^IndirectReadSideEffect[-1] : &:r0_91, ~mu0_2 +# 816| v0_99(void) = ^IndirectReadSideEffect[0] : &:r0_95, ~mu0_2 +# 816| mu0_100(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_91 +# 816| mu0_101(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_95 +# 817| r0_102(glval) = VariableAddress[m] : +# 817| r0_103(glval) = FunctionAddress[operator=] : +# 817| r0_104(glval) = VariableAddress[b] : +# 817| r0_105(glval) = ConvertToDerived[Middle : Base] : r0_104 +# 817| r0_106(glval) = Convert : r0_105 +# 817| r0_107(Middle &) = Call : func:r0_103, this:r0_102, 0:r0_106 +# 817| mu0_108(unknown) = ^CallSideEffect : ~mu0_2 +# 817| v0_109(void) = ^IndirectReadSideEffect[-1] : &:r0_102, ~mu0_2 +# 817| v0_110(void) = ^IndirectReadSideEffect[0] : &:r0_106, ~mu0_2 +# 817| mu0_111(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_102 +# 817| mu0_112(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_106 +# 818| r0_113(glval) = VariableAddress[pb] : +# 818| r0_114(Base *) = Load : &:r0_113, ~mu0_2 +# 818| r0_115(Middle *) = ConvertToDerived[Middle : Base] : r0_114 +# 818| r0_116(glval) = VariableAddress[pm] : +# 818| mu0_117(Middle *) = Store : &:r0_116, r0_115 +# 819| r0_118(glval) = VariableAddress[pb] : +# 819| r0_119(Base *) = Load : &:r0_118, ~mu0_2 +# 819| r0_120(Middle *) = ConvertToDerived[Middle : Base] : r0_119 +# 819| r0_121(glval) = VariableAddress[pm] : +# 819| mu0_122(Middle *) = Store : &:r0_121, r0_120 +# 820| r0_123(glval) = VariableAddress[pb] : +# 820| r0_124(Base *) = Load : &:r0_123, ~mu0_2 +# 820| r0_125(Middle *) = Convert : r0_124 +# 820| r0_126(glval) = VariableAddress[pm] : +# 820| mu0_127(Middle *) = Store : &:r0_126, r0_125 +# 822| r0_128(glval) = VariableAddress[b] : +# 822| r0_129(glval) = FunctionAddress[operator=] : +# 822| r0_130(glval) = VariableAddress[d] : +# 822| r0_131(glval) = ConvertToBase[Derived : Middle] : r0_130 +# 822| r0_132(glval) = ConvertToBase[Middle : Base] : r0_131 +# 822| r0_133(Base &) = Call : func:r0_129, this:r0_128, 0:r0_132 +# 822| mu0_134(unknown) = ^CallSideEffect : ~mu0_2 +# 822| v0_135(void) = ^IndirectReadSideEffect[-1] : &:r0_128, ~mu0_2 +# 822| v0_136(void) = ^IndirectReadSideEffect[0] : &:r0_132, ~mu0_2 +# 822| mu0_137(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_128 +# 822| mu0_138(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_132 +# 823| r0_139(glval) = VariableAddress[b] : +# 823| r0_140(glval) = FunctionAddress[operator=] : +# 823| r0_141(glval) = FunctionAddress[Base] : +# 823| r0_142(glval) = VariableAddress[d] : +# 823| r0_143(glval) = ConvertToBase[Derived : Middle] : r0_142 +# 823| r0_144(glval) = ConvertToBase[Middle : Base] : r0_143 +# 823| v0_145(void) = Call : func:r0_141, 0:r0_144 # 823| mu0_146(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_147(void) = ^IndirectReadSideEffect[-1] : &:r0_134, ~mu0_2 +# 823| mu0_147(Base) = ^IndirectMustWriteSideEffect : # 823| v0_148(void) = ^IndirectReadSideEffect[0] : &:r0_144, ~mu0_2 -# 823| mu0_149(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_134 -# 823| mu0_150(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_144 -# 824| r0_151(glval) = VariableAddress[b] : -# 824| r0_152(glval) = FunctionAddress[operator=] : -# 824| r0_153(glval) = FunctionAddress[Base] : -# 824| r0_154(glval) = VariableAddress[d] : -# 824| r0_155(glval) = ConvertToBase[Derived : Middle] : r0_154 -# 824| r0_156(glval) = ConvertToBase[Middle : Base] : r0_155 -# 824| v0_157(void) = Call : func:r0_153, 0:r0_156 -# 824| mu0_158(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_159(void) = ^IndirectReadSideEffect[0] : &:r0_156, ~mu0_2 -# 824| mu0_160(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_156 -# 824| r0_161(glval) = Convert : v0_157 -# 824| r0_162(Base &) = Call : func:r0_152, this:r0_151, 0:r0_161 -# 824| mu0_163(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_164(void) = ^IndirectReadSideEffect[-1] : &:r0_151, ~mu0_2 -# 824| v0_165(void) = ^IndirectReadSideEffect[0] : &:r0_161, ~mu0_2 -# 824| mu0_166(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 -# 824| mu0_167(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_161 -# 825| r0_168(glval) = VariableAddress[pd] : -# 825| r0_169(Derived *) = Load : &:r0_168, ~mu0_2 -# 825| r0_170(Middle *) = ConvertToBase[Derived : Middle] : r0_169 -# 825| r0_171(Base *) = ConvertToBase[Middle : Base] : r0_170 -# 825| r0_172(glval) = VariableAddress[pb] : -# 825| mu0_173(Base *) = Store : &:r0_172, r0_171 -# 826| r0_174(glval) = VariableAddress[pd] : -# 826| r0_175(Derived *) = Load : &:r0_174, ~mu0_2 -# 826| r0_176(Middle *) = ConvertToBase[Derived : Middle] : r0_175 -# 826| r0_177(Base *) = ConvertToBase[Middle : Base] : r0_176 -# 826| r0_178(glval) = VariableAddress[pb] : -# 826| mu0_179(Base *) = Store : &:r0_178, r0_177 -# 827| r0_180(glval) = VariableAddress[pd] : -# 827| r0_181(Derived *) = Load : &:r0_180, ~mu0_2 -# 827| r0_182(Middle *) = ConvertToBase[Derived : Middle] : r0_181 -# 827| r0_183(Base *) = ConvertToBase[Middle : Base] : r0_182 -# 827| r0_184(glval) = VariableAddress[pb] : -# 827| mu0_185(Base *) = Store : &:r0_184, r0_183 -# 828| r0_186(glval) = VariableAddress[pd] : -# 828| r0_187(Derived *) = Load : &:r0_186, ~mu0_2 -# 828| r0_188(Base *) = Convert : r0_187 -# 828| r0_189(glval) = VariableAddress[pb] : -# 828| mu0_190(Base *) = Store : &:r0_189, r0_188 -# 830| r0_191(glval) = VariableAddress[d] : -# 830| r0_192(glval) = FunctionAddress[operator=] : -# 830| r0_193(glval) = VariableAddress[b] : -# 830| r0_194(glval) = ConvertToDerived[Middle : Base] : r0_193 -# 830| r0_195(glval) = ConvertToDerived[Derived : Middle] : r0_194 -# 830| r0_196(glval) = Convert : r0_195 -# 830| r0_197(Derived &) = Call : func:r0_192, this:r0_191, 0:r0_196 -# 830| mu0_198(unknown) = ^CallSideEffect : ~mu0_2 -# 830| v0_199(void) = ^IndirectReadSideEffect[-1] : &:r0_191, ~mu0_2 -# 830| v0_200(void) = ^IndirectReadSideEffect[0] : &:r0_196, ~mu0_2 -# 830| mu0_201(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_191 -# 830| mu0_202(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_196 -# 831| r0_203(glval) = VariableAddress[d] : -# 831| r0_204(glval) = FunctionAddress[operator=] : -# 831| r0_205(glval) = VariableAddress[b] : -# 831| r0_206(glval) = ConvertToDerived[Middle : Base] : r0_205 -# 831| r0_207(glval) = ConvertToDerived[Derived : Middle] : r0_206 -# 831| r0_208(glval) = Convert : r0_207 -# 831| r0_209(Derived &) = Call : func:r0_204, this:r0_203, 0:r0_208 -# 831| mu0_210(unknown) = ^CallSideEffect : ~mu0_2 -# 831| v0_211(void) = ^IndirectReadSideEffect[-1] : &:r0_203, ~mu0_2 -# 831| v0_212(void) = ^IndirectReadSideEffect[0] : &:r0_208, ~mu0_2 -# 831| mu0_213(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_203 -# 831| mu0_214(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_208 -# 832| r0_215(glval) = VariableAddress[pb] : -# 832| r0_216(Base *) = Load : &:r0_215, ~mu0_2 -# 832| r0_217(Middle *) = ConvertToDerived[Middle : Base] : r0_216 -# 832| r0_218(Derived *) = ConvertToDerived[Derived : Middle] : r0_217 -# 832| r0_219(glval) = VariableAddress[pd] : -# 832| mu0_220(Derived *) = Store : &:r0_219, r0_218 -# 833| r0_221(glval) = VariableAddress[pb] : -# 833| r0_222(Base *) = Load : &:r0_221, ~mu0_2 -# 833| r0_223(Middle *) = ConvertToDerived[Middle : Base] : r0_222 -# 833| r0_224(Derived *) = ConvertToDerived[Derived : Middle] : r0_223 -# 833| r0_225(glval) = VariableAddress[pd] : -# 833| mu0_226(Derived *) = Store : &:r0_225, r0_224 -# 834| r0_227(glval) = VariableAddress[pb] : -# 834| r0_228(Base *) = Load : &:r0_227, ~mu0_2 -# 834| r0_229(Derived *) = Convert : r0_228 -# 834| r0_230(glval) = VariableAddress[pd] : -# 834| mu0_231(Derived *) = Store : &:r0_230, r0_229 -# 836| r0_232(glval) = VariableAddress[pmv] : -# 836| r0_233(MiddleVB1 *) = Constant[0] : -# 836| mu0_234(MiddleVB1 *) = Store : &:r0_232, r0_233 -# 837| r0_235(glval) = VariableAddress[pdv] : -# 837| r0_236(DerivedVB *) = Constant[0] : -# 837| mu0_237(DerivedVB *) = Store : &:r0_235, r0_236 -# 838| r0_238(glval) = VariableAddress[pmv] : -# 838| r0_239(MiddleVB1 *) = Load : &:r0_238, ~mu0_2 -# 838| r0_240(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_239 -# 838| r0_241(glval) = VariableAddress[pb] : -# 838| mu0_242(Base *) = Store : &:r0_241, r0_240 -# 839| r0_243(glval) = VariableAddress[pdv] : -# 839| r0_244(DerivedVB *) = Load : &:r0_243, ~mu0_2 -# 839| r0_245(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_244 -# 839| r0_246(glval) = VariableAddress[pb] : -# 839| mu0_247(Base *) = Store : &:r0_246, r0_245 -# 840| v0_248(void) = NoOp : -# 799| v0_249(void) = ReturnVoid : -# 799| v0_250(void) = UnmodeledUse : mu* -# 799| v0_251(void) = ExitFunction : +# 823| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_144 +# 823| r0_150(glval) = Convert : v0_145 +# 823| r0_151(Base &) = Call : func:r0_140, this:r0_139, 0:r0_150 +# 823| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_153(void) = ^IndirectReadSideEffect[-1] : &:r0_139, ~mu0_2 +# 823| v0_154(void) = ^IndirectReadSideEffect[0] : &:r0_150, ~mu0_2 +# 823| mu0_155(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_139 +# 823| mu0_156(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_150 +# 824| r0_157(glval) = VariableAddress[b] : +# 824| r0_158(glval) = FunctionAddress[operator=] : +# 824| r0_159(glval) = FunctionAddress[Base] : +# 824| r0_160(glval) = VariableAddress[d] : +# 824| r0_161(glval) = ConvertToBase[Derived : Middle] : r0_160 +# 824| r0_162(glval) = ConvertToBase[Middle : Base] : r0_161 +# 824| v0_163(void) = Call : func:r0_159, 0:r0_162 +# 824| mu0_164(unknown) = ^CallSideEffect : ~mu0_2 +# 824| mu0_165(Base) = ^IndirectMustWriteSideEffect : +# 824| v0_166(void) = ^IndirectReadSideEffect[0] : &:r0_162, ~mu0_2 +# 824| mu0_167(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_162 +# 824| r0_168(glval) = Convert : v0_163 +# 824| r0_169(Base &) = Call : func:r0_158, this:r0_157, 0:r0_168 +# 824| mu0_170(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_171(void) = ^IndirectReadSideEffect[-1] : &:r0_157, ~mu0_2 +# 824| v0_172(void) = ^IndirectReadSideEffect[0] : &:r0_168, ~mu0_2 +# 824| mu0_173(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_157 +# 824| mu0_174(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_168 +# 825| r0_175(glval) = VariableAddress[pd] : +# 825| r0_176(Derived *) = Load : &:r0_175, ~mu0_2 +# 825| r0_177(Middle *) = ConvertToBase[Derived : Middle] : r0_176 +# 825| r0_178(Base *) = ConvertToBase[Middle : Base] : r0_177 +# 825| r0_179(glval) = VariableAddress[pb] : +# 825| mu0_180(Base *) = Store : &:r0_179, r0_178 +# 826| r0_181(glval) = VariableAddress[pd] : +# 826| r0_182(Derived *) = Load : &:r0_181, ~mu0_2 +# 826| r0_183(Middle *) = ConvertToBase[Derived : Middle] : r0_182 +# 826| r0_184(Base *) = ConvertToBase[Middle : Base] : r0_183 +# 826| r0_185(glval) = VariableAddress[pb] : +# 826| mu0_186(Base *) = Store : &:r0_185, r0_184 +# 827| r0_187(glval) = VariableAddress[pd] : +# 827| r0_188(Derived *) = Load : &:r0_187, ~mu0_2 +# 827| r0_189(Middle *) = ConvertToBase[Derived : Middle] : r0_188 +# 827| r0_190(Base *) = ConvertToBase[Middle : Base] : r0_189 +# 827| r0_191(glval) = VariableAddress[pb] : +# 827| mu0_192(Base *) = Store : &:r0_191, r0_190 +# 828| r0_193(glval) = VariableAddress[pd] : +# 828| r0_194(Derived *) = Load : &:r0_193, ~mu0_2 +# 828| r0_195(Base *) = Convert : r0_194 +# 828| r0_196(glval) = VariableAddress[pb] : +# 828| mu0_197(Base *) = Store : &:r0_196, r0_195 +# 830| r0_198(glval) = VariableAddress[d] : +# 830| r0_199(glval) = FunctionAddress[operator=] : +# 830| r0_200(glval) = VariableAddress[b] : +# 830| r0_201(glval) = ConvertToDerived[Middle : Base] : r0_200 +# 830| r0_202(glval) = ConvertToDerived[Derived : Middle] : r0_201 +# 830| r0_203(glval) = Convert : r0_202 +# 830| r0_204(Derived &) = Call : func:r0_199, this:r0_198, 0:r0_203 +# 830| mu0_205(unknown) = ^CallSideEffect : ~mu0_2 +# 830| v0_206(void) = ^IndirectReadSideEffect[-1] : &:r0_198, ~mu0_2 +# 830| v0_207(void) = ^IndirectReadSideEffect[0] : &:r0_203, ~mu0_2 +# 830| mu0_208(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_198 +# 830| mu0_209(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_203 +# 831| r0_210(glval) = VariableAddress[d] : +# 831| r0_211(glval) = FunctionAddress[operator=] : +# 831| r0_212(glval) = VariableAddress[b] : +# 831| r0_213(glval) = ConvertToDerived[Middle : Base] : r0_212 +# 831| r0_214(glval) = ConvertToDerived[Derived : Middle] : r0_213 +# 831| r0_215(glval) = Convert : r0_214 +# 831| r0_216(Derived &) = Call : func:r0_211, this:r0_210, 0:r0_215 +# 831| mu0_217(unknown) = ^CallSideEffect : ~mu0_2 +# 831| v0_218(void) = ^IndirectReadSideEffect[-1] : &:r0_210, ~mu0_2 +# 831| v0_219(void) = ^IndirectReadSideEffect[0] : &:r0_215, ~mu0_2 +# 831| mu0_220(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_210 +# 831| mu0_221(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_215 +# 832| r0_222(glval) = VariableAddress[pb] : +# 832| r0_223(Base *) = Load : &:r0_222, ~mu0_2 +# 832| r0_224(Middle *) = ConvertToDerived[Middle : Base] : r0_223 +# 832| r0_225(Derived *) = ConvertToDerived[Derived : Middle] : r0_224 +# 832| r0_226(glval) = VariableAddress[pd] : +# 832| mu0_227(Derived *) = Store : &:r0_226, r0_225 +# 833| r0_228(glval) = VariableAddress[pb] : +# 833| r0_229(Base *) = Load : &:r0_228, ~mu0_2 +# 833| r0_230(Middle *) = ConvertToDerived[Middle : Base] : r0_229 +# 833| r0_231(Derived *) = ConvertToDerived[Derived : Middle] : r0_230 +# 833| r0_232(glval) = VariableAddress[pd] : +# 833| mu0_233(Derived *) = Store : &:r0_232, r0_231 +# 834| r0_234(glval) = VariableAddress[pb] : +# 834| r0_235(Base *) = Load : &:r0_234, ~mu0_2 +# 834| r0_236(Derived *) = Convert : r0_235 +# 834| r0_237(glval) = VariableAddress[pd] : +# 834| mu0_238(Derived *) = Store : &:r0_237, r0_236 +# 836| r0_239(glval) = VariableAddress[pmv] : +# 836| r0_240(MiddleVB1 *) = Constant[0] : +# 836| mu0_241(MiddleVB1 *) = Store : &:r0_239, r0_240 +# 837| r0_242(glval) = VariableAddress[pdv] : +# 837| r0_243(DerivedVB *) = Constant[0] : +# 837| mu0_244(DerivedVB *) = Store : &:r0_242, r0_243 +# 838| r0_245(glval) = VariableAddress[pmv] : +# 838| r0_246(MiddleVB1 *) = Load : &:r0_245, ~mu0_2 +# 838| r0_247(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_246 +# 838| r0_248(glval) = VariableAddress[pb] : +# 838| mu0_249(Base *) = Store : &:r0_248, r0_247 +# 839| r0_250(glval) = VariableAddress[pdv] : +# 839| r0_251(DerivedVB *) = Load : &:r0_250, ~mu0_2 +# 839| r0_252(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_251 +# 839| r0_253(glval) = VariableAddress[pb] : +# 839| mu0_254(Base *) = Store : &:r0_253, r0_252 +# 840| v0_255(void) = NoOp : +# 799| v0_256(void) = ReturnVoid : +# 799| v0_257(void) = UnmodeledUse : mu* +# 799| v0_258(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -3889,10 +3917,11 @@ ir.cpp: # 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : # 846| v0_6(void) = Call : func:r0_5, this:r0_4 # 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 846| v0_8(void) = NoOp : -# 846| v0_9(void) = ReturnVoid : -# 846| v0_10(void) = UnmodeledUse : mu* -# 846| v0_11(void) = ExitFunction : +# 846| mu0_8(PolymorphicBase) = ^IndirectMustWriteSideEffect : &:r0_4 +# 846| v0_9(void) = NoOp : +# 846| v0_10(void) = ReturnVoid : +# 846| v0_11(void) = UnmodeledUse : mu* +# 846| v0_12(void) = ExitFunction : # 846| void PolymorphicDerived::~PolymorphicDerived() # 846| Block 0 @@ -3918,48 +3947,50 @@ ir.cpp: #-----| r0_4(glval) = FunctionAddress[PolymorphicBase] : #-----| v0_5(void) = Call : func:r0_4, this:r0_3 #-----| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 851| r0_7(glval) = VariableAddress[d] : -# 851| r0_8(glval) = FunctionAddress[PolymorphicDerived] : -# 851| v0_9(void) = Call : func:r0_8, this:r0_7 -# 851| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 853| r0_11(glval) = VariableAddress[pb] : -# 853| r0_12(glval) = VariableAddress[b] : -# 853| mu0_13(PolymorphicBase *) = Store : &:r0_11, r0_12 -# 854| r0_14(glval) = VariableAddress[pd] : -# 854| r0_15(glval) = VariableAddress[d] : -# 854| mu0_16(PolymorphicDerived *) = Store : &:r0_14, r0_15 -# 857| r0_17(glval) = VariableAddress[pd] : -# 857| r0_18(PolymorphicDerived *) = Load : &:r0_17, ~mu0_2 -# 857| r0_19(PolymorphicBase *) = CheckedConvertOrNull : r0_18 -# 857| r0_20(glval) = VariableAddress[pb] : -# 857| mu0_21(PolymorphicBase *) = Store : &:r0_20, r0_19 -# 858| r0_22(glval) = VariableAddress[rb] : -# 858| r0_23(glval) = VariableAddress[d] : -# 858| r0_24(glval) = CheckedConvertOrThrow : r0_23 -# 858| mu0_25(PolymorphicBase &) = Store : &:r0_22, r0_24 -# 860| r0_26(glval) = VariableAddress[pb] : -# 860| r0_27(PolymorphicBase *) = Load : &:r0_26, ~mu0_2 -# 860| r0_28(PolymorphicDerived *) = CheckedConvertOrNull : r0_27 -# 860| r0_29(glval) = VariableAddress[pd] : -# 860| mu0_30(PolymorphicDerived *) = Store : &:r0_29, r0_28 -# 861| r0_31(glval) = VariableAddress[rd] : -# 861| r0_32(glval) = VariableAddress[b] : -# 861| r0_33(glval) = CheckedConvertOrThrow : r0_32 -# 861| mu0_34(PolymorphicDerived &) = Store : &:r0_31, r0_33 -# 863| r0_35(glval) = VariableAddress[pv] : -# 863| r0_36(glval) = VariableAddress[pb] : -# 863| r0_37(PolymorphicBase *) = Load : &:r0_36, ~mu0_2 -# 863| r0_38(void *) = DynamicCastToVoid : r0_37 -# 863| mu0_39(void *) = Store : &:r0_35, r0_38 -# 864| r0_40(glval) = VariableAddress[pcv] : -# 864| r0_41(glval) = VariableAddress[pd] : -# 864| r0_42(PolymorphicDerived *) = Load : &:r0_41, ~mu0_2 -# 864| r0_43(void *) = DynamicCastToVoid : r0_42 -# 864| mu0_44(void *) = Store : &:r0_40, r0_43 -# 865| v0_45(void) = NoOp : -# 849| v0_46(void) = ReturnVoid : -# 849| v0_47(void) = UnmodeledUse : mu* -# 849| v0_48(void) = ExitFunction : +#-----| mu0_7(PolymorphicBase) = ^IndirectMustWriteSideEffect : &:r0_3 +# 851| r0_8(glval) = VariableAddress[d] : +# 851| r0_9(glval) = FunctionAddress[PolymorphicDerived] : +# 851| v0_10(void) = Call : func:r0_9, this:r0_8 +# 851| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 851| mu0_12(PolymorphicDerived) = ^IndirectMustWriteSideEffect : &:r0_8 +# 853| r0_13(glval) = VariableAddress[pb] : +# 853| r0_14(glval) = VariableAddress[b] : +# 853| mu0_15(PolymorphicBase *) = Store : &:r0_13, r0_14 +# 854| r0_16(glval) = VariableAddress[pd] : +# 854| r0_17(glval) = VariableAddress[d] : +# 854| mu0_18(PolymorphicDerived *) = Store : &:r0_16, r0_17 +# 857| r0_19(glval) = VariableAddress[pd] : +# 857| r0_20(PolymorphicDerived *) = Load : &:r0_19, ~mu0_2 +# 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 +# 857| r0_22(glval) = VariableAddress[pb] : +# 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 +# 858| r0_24(glval) = VariableAddress[rb] : +# 858| r0_25(glval) = VariableAddress[d] : +# 858| r0_26(glval) = CheckedConvertOrThrow : r0_25 +# 858| mu0_27(PolymorphicBase &) = Store : &:r0_24, r0_26 +# 860| r0_28(glval) = VariableAddress[pb] : +# 860| r0_29(PolymorphicBase *) = Load : &:r0_28, ~mu0_2 +# 860| r0_30(PolymorphicDerived *) = CheckedConvertOrNull : r0_29 +# 860| r0_31(glval) = VariableAddress[pd] : +# 860| mu0_32(PolymorphicDerived *) = Store : &:r0_31, r0_30 +# 861| r0_33(glval) = VariableAddress[rd] : +# 861| r0_34(glval) = VariableAddress[b] : +# 861| r0_35(glval) = CheckedConvertOrThrow : r0_34 +# 861| mu0_36(PolymorphicDerived &) = Store : &:r0_33, r0_35 +# 863| r0_37(glval) = VariableAddress[pv] : +# 863| r0_38(glval) = VariableAddress[pb] : +# 863| r0_39(PolymorphicBase *) = Load : &:r0_38, ~mu0_2 +# 863| r0_40(void *) = DynamicCastToVoid : r0_39 +# 863| mu0_41(void *) = Store : &:r0_37, r0_40 +# 864| r0_42(glval) = VariableAddress[pcv] : +# 864| r0_43(glval) = VariableAddress[pd] : +# 864| r0_44(PolymorphicDerived *) = Load : &:r0_43, ~mu0_2 +# 864| r0_45(void *) = DynamicCastToVoid : r0_44 +# 864| mu0_46(void *) = Store : &:r0_42, r0_45 +# 865| v0_47(void) = NoOp : +# 849| v0_48(void) = ReturnVoid : +# 849| v0_49(void) = UnmodeledUse : mu* +# 849| v0_50(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -3972,12 +4003,13 @@ ir.cpp: # 868| r0_6(char *) = Convert : r0_5 # 868| v0_7(void) = Call : func:r0_4, this:r0_3, 0:r0_6 # 868| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 868| v0_9(void) = ^IndirectReadSideEffect[0] : &:r0_6, ~mu0_2 -# 868| mu0_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_6 -# 869| v0_11(void) = NoOp : -# 867| v0_12(void) = ReturnVoid : -# 867| v0_13(void) = UnmodeledUse : mu* -# 867| v0_14(void) = ExitFunction : +# 868| mu0_9(String) = ^IndirectMustWriteSideEffect : &:r0_3 +# 868| v0_10(void) = ^IndirectReadSideEffect[0] : &:r0_6, ~mu0_2 +# 868| mu0_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_6 +# 869| v0_12(void) = NoOp : +# 867| v0_13(void) = ReturnVoid : +# 867| v0_14(void) = UnmodeledUse : mu* +# 867| v0_15(void) = ExitFunction : # 871| void ArrayConversions() # 871| Block 0 @@ -4178,38 +4210,40 @@ ir.cpp: # 944| r0_26(glval) = FunctionAddress[String] : # 944| v0_27(void) = Call : func:r0_26, this:r0_25 # 944| mu0_28(unknown) = ^CallSideEffect : ~mu0_2 -# 945| r0_29(glval) = FunctionAddress[operator new] : -# 945| r0_30(unsigned long) = Constant[8] : -# 945| r0_31(float) = Constant[1.0] : -# 945| r0_32(void *) = Call : func:r0_29, 0:r0_30, 1:r0_31 -# 945| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 -# 945| r0_34(String *) = Convert : r0_32 -# 945| r0_35(glval) = FunctionAddress[String] : -# 945| r0_36(glval) = StringConstant["hello"] : -# 945| r0_37(char *) = Convert : r0_36 -# 945| v0_38(void) = Call : func:r0_35, this:r0_34, 0:r0_37 -# 945| mu0_39(unknown) = ^CallSideEffect : ~mu0_2 -# 945| v0_40(void) = ^IndirectReadSideEffect[0] : &:r0_37, ~mu0_2 -# 945| mu0_41(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_37 -# 946| r0_42(glval) = FunctionAddress[operator new] : -# 946| r0_43(unsigned long) = Constant[256] : -# 946| r0_44(align_val_t) = Constant[128] : -# 946| r0_45(void *) = Call : func:r0_42, 0:r0_43, 1:r0_44 -# 946| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 -# 946| r0_47(Overaligned *) = Convert : r0_45 -# 947| r0_48(glval) = FunctionAddress[operator new] : -# 947| r0_49(unsigned long) = Constant[256] : -# 947| r0_50(align_val_t) = Constant[128] : -# 947| r0_51(float) = Constant[1.0] : -# 947| r0_52(void *) = Call : func:r0_48, 0:r0_49, 1:r0_50, 2:r0_51 -# 947| mu0_53(unknown) = ^CallSideEffect : ~mu0_2 -# 947| r0_54(Overaligned *) = Convert : r0_52 -# 947| r0_55(Overaligned) = Constant[0] : -# 947| mu0_56(Overaligned) = Store : &:r0_54, r0_55 -# 948| v0_57(void) = NoOp : -# 940| v0_58(void) = ReturnVoid : -# 940| v0_59(void) = UnmodeledUse : mu* -# 940| v0_60(void) = ExitFunction : +# 944| mu0_29(String) = ^IndirectMustWriteSideEffect : &:r0_25 +# 945| r0_30(glval) = FunctionAddress[operator new] : +# 945| r0_31(unsigned long) = Constant[8] : +# 945| r0_32(float) = Constant[1.0] : +# 945| r0_33(void *) = Call : func:r0_30, 0:r0_31, 1:r0_32 +# 945| mu0_34(unknown) = ^CallSideEffect : ~mu0_2 +# 945| r0_35(String *) = Convert : r0_33 +# 945| r0_36(glval) = FunctionAddress[String] : +# 945| r0_37(glval) = StringConstant["hello"] : +# 945| r0_38(char *) = Convert : r0_37 +# 945| v0_39(void) = Call : func:r0_36, this:r0_35, 0:r0_38 +# 945| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 +# 945| mu0_41(String) = ^IndirectMustWriteSideEffect : &:r0_35 +# 945| v0_42(void) = ^IndirectReadSideEffect[0] : &:r0_38, ~mu0_2 +# 945| mu0_43(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_38 +# 946| r0_44(glval) = FunctionAddress[operator new] : +# 946| r0_45(unsigned long) = Constant[256] : +# 946| r0_46(align_val_t) = Constant[128] : +# 946| r0_47(void *) = Call : func:r0_44, 0:r0_45, 1:r0_46 +# 946| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 +# 946| r0_49(Overaligned *) = Convert : r0_47 +# 947| r0_50(glval) = FunctionAddress[operator new] : +# 947| r0_51(unsigned long) = Constant[256] : +# 947| r0_52(align_val_t) = Constant[128] : +# 947| r0_53(float) = Constant[1.0] : +# 947| r0_54(void *) = Call : func:r0_50, 0:r0_51, 1:r0_52, 2:r0_53 +# 947| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 +# 947| r0_56(Overaligned *) = Convert : r0_54 +# 947| r0_57(Overaligned) = Constant[0] : +# 947| mu0_58(Overaligned) = Store : &:r0_56, r0_57 +# 948| v0_59(void) = NoOp : +# 940| v0_60(void) = ReturnVoid : +# 940| v0_61(void) = UnmodeledUse : mu* +# 940| v0_62(void) = ExitFunction : # 950| void OperatorNewArray(int) # 950| Block 0 @@ -4687,122 +4721,126 @@ ir.cpp: #-----| r0_38(glval) = FunctionAddress[String] : #-----| v0_39(void) = Call : func:r0_38, this:r0_37 #-----| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_41(glval) = FieldAddress[x] : r0_35 -#-----| r0_42(glval) = VariableAddress[x] : -#-----| r0_43(int) = Load : &:r0_42, ~mu0_2 -#-----| mu0_44(int) = Store : &:r0_41, r0_43 -# 1036| r0_45(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 -# 1036| v0_46(void) = Call : func:r0_34, this:r0_33, 0:r0_45 -# 1036| mu0_47(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| v0_48(void) = ^IndirectReadSideEffect[0] : &:r0_45, ~mu0_2 -# 1036| mu0_49(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_45 -# 1037| r0_50(glval) = VariableAddress[lambda_val] : -# 1037| r0_51(glval) = Convert : r0_50 -# 1037| r0_52(glval) = FunctionAddress[operator()] : -# 1037| r0_53(float) = Constant[2.0] : -# 1037| r0_54(char) = Call : func:r0_52, this:r0_51, 0:r0_53 -# 1037| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 -# 1037| v0_56(void) = ^IndirectReadSideEffect[-1] : &:r0_51, ~mu0_2 -# 1037| mu0_57(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_51 -# 1038| r0_58(glval) = VariableAddress[lambda_ref_explicit] : -# 1038| r0_59(glval) = VariableAddress[#temp1038:30] : -# 1038| mu0_60(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_59 -# 1038| r0_61(glval) = FieldAddress[s] : r0_59 -# 1038| r0_62(glval) = VariableAddress[s] : -# 1038| r0_63(String &) = Load : &:r0_62, ~mu0_2 -# 1038| mu0_64(String &) = Store : &:r0_61, r0_63 -# 1038| r0_65(decltype([...](...){...})) = Load : &:r0_59, ~mu0_2 -# 1038| mu0_66(decltype([...](...){...})) = Store : &:r0_58, r0_65 -# 1039| r0_67(glval) = VariableAddress[lambda_ref_explicit] : -# 1039| r0_68(glval) = Convert : r0_67 -# 1039| r0_69(glval) = FunctionAddress[operator()] : -# 1039| r0_70(float) = Constant[3.0] : -# 1039| r0_71(char) = Call : func:r0_69, this:r0_68, 0:r0_70 -# 1039| mu0_72(unknown) = ^CallSideEffect : ~mu0_2 -# 1039| v0_73(void) = ^IndirectReadSideEffect[-1] : &:r0_68, ~mu0_2 -# 1039| mu0_74(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_68 -# 1040| r0_75(glval) = VariableAddress[lambda_val_explicit] : -# 1040| r0_76(glval) = FunctionAddress[(constructor)] : -# 1040| r0_77(glval) = VariableAddress[#temp1040:30] : -# 1040| mu0_78(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_77 -# 1040| r0_79(glval) = FieldAddress[s] : r0_77 -#-----| r0_80(glval) = FunctionAddress[String] : -#-----| v0_81(void) = Call : func:r0_80, this:r0_79 -#-----| mu0_82(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_83(decltype([...](...){...})) = Load : &:r0_77, ~mu0_2 -# 1040| v0_84(void) = Call : func:r0_76, this:r0_75, 0:r0_83 -# 1040| mu0_85(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| v0_86(void) = ^IndirectReadSideEffect[0] : &:r0_83, ~mu0_2 -# 1040| mu0_87(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_83 -# 1041| r0_88(glval) = VariableAddress[lambda_val_explicit] : -# 1041| r0_89(glval) = Convert : r0_88 -# 1041| r0_90(glval) = FunctionAddress[operator()] : -# 1041| r0_91(float) = Constant[4.0] : -# 1041| r0_92(char) = Call : func:r0_90, this:r0_89, 0:r0_91 -# 1041| mu0_93(unknown) = ^CallSideEffect : ~mu0_2 -# 1041| v0_94(void) = ^IndirectReadSideEffect[-1] : &:r0_89, ~mu0_2 -# 1041| mu0_95(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_89 -# 1042| r0_96(glval) = VariableAddress[lambda_mixed_explicit] : -# 1042| r0_97(glval) = VariableAddress[#temp1042:32] : -# 1042| mu0_98(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_97 -# 1042| r0_99(glval) = FieldAddress[s] : r0_97 -# 1042| r0_100(glval) = VariableAddress[s] : -# 1042| r0_101(String &) = Load : &:r0_100, ~mu0_2 -# 1042| mu0_102(String &) = Store : &:r0_99, r0_101 -# 1042| r0_103(glval) = FieldAddress[x] : r0_97 -# 1042| r0_104(glval) = VariableAddress[x] : -# 1042| r0_105(int) = Load : &:r0_104, ~mu0_2 -# 1042| mu0_106(int) = Store : &:r0_103, r0_105 -# 1042| r0_107(decltype([...](...){...})) = Load : &:r0_97, ~mu0_2 -# 1042| mu0_108(decltype([...](...){...})) = Store : &:r0_96, r0_107 -# 1043| r0_109(glval) = VariableAddress[lambda_mixed_explicit] : -# 1043| r0_110(glval) = Convert : r0_109 -# 1043| r0_111(glval) = FunctionAddress[operator()] : -# 1043| r0_112(float) = Constant[5.0] : -# 1043| r0_113(char) = Call : func:r0_111, this:r0_110, 0:r0_112 -# 1043| mu0_114(unknown) = ^CallSideEffect : ~mu0_2 -# 1043| v0_115(void) = ^IndirectReadSideEffect[-1] : &:r0_110, ~mu0_2 -# 1043| mu0_116(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 -# 1044| r0_117(glval) = VariableAddress[r] : -# 1044| r0_118(glval) = VariableAddress[x] : -# 1044| r0_119(int) = Load : &:r0_118, ~mu0_2 -# 1044| r0_120(int) = Constant[1] : -# 1044| r0_121(int) = Sub : r0_119, r0_120 -# 1044| mu0_122(int) = Store : &:r0_117, r0_121 -# 1045| r0_123(glval) = VariableAddress[lambda_inits] : -# 1045| r0_124(glval) = VariableAddress[#temp1045:23] : -# 1045| mu0_125(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_124 -# 1045| r0_126(glval) = FieldAddress[s] : r0_124 -# 1045| r0_127(glval) = VariableAddress[s] : -# 1045| r0_128(String &) = Load : &:r0_127, ~mu0_2 -# 1045| mu0_129(String &) = Store : &:r0_126, r0_128 -# 1045| r0_130(glval) = FieldAddress[x] : r0_124 -# 1045| r0_131(glval) = VariableAddress[x] : -# 1045| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 1045| mu0_133(int) = Store : &:r0_130, r0_132 -# 1045| r0_134(glval) = FieldAddress[i] : r0_124 +#-----| mu0_41(String) = ^IndirectMustWriteSideEffect : &:r0_37 +# 1036| r0_42(glval) = FieldAddress[x] : r0_35 +#-----| r0_43(glval) = VariableAddress[x] : +#-----| r0_44(int) = Load : &:r0_43, ~mu0_2 +#-----| mu0_45(int) = Store : &:r0_42, r0_44 +# 1036| r0_46(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 +# 1036| v0_47(void) = Call : func:r0_34, this:r0_33, 0:r0_46 +# 1036| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| mu0_49(decltype([...](...){...})) = ^IndirectMustWriteSideEffect : &:r0_33 +# 1036| v0_50(void) = ^IndirectReadSideEffect[0] : &:r0_46, ~mu0_2 +# 1036| mu0_51(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_46 +# 1037| r0_52(glval) = VariableAddress[lambda_val] : +# 1037| r0_53(glval) = Convert : r0_52 +# 1037| r0_54(glval) = FunctionAddress[operator()] : +# 1037| r0_55(float) = Constant[2.0] : +# 1037| r0_56(char) = Call : func:r0_54, this:r0_53, 0:r0_55 +# 1037| mu0_57(unknown) = ^CallSideEffect : ~mu0_2 +# 1037| v0_58(void) = ^IndirectReadSideEffect[-1] : &:r0_53, ~mu0_2 +# 1037| mu0_59(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_53 +# 1038| r0_60(glval) = VariableAddress[lambda_ref_explicit] : +# 1038| r0_61(glval) = VariableAddress[#temp1038:30] : +# 1038| mu0_62(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_61 +# 1038| r0_63(glval) = FieldAddress[s] : r0_61 +# 1038| r0_64(glval) = VariableAddress[s] : +# 1038| r0_65(String &) = Load : &:r0_64, ~mu0_2 +# 1038| mu0_66(String &) = Store : &:r0_63, r0_65 +# 1038| r0_67(decltype([...](...){...})) = Load : &:r0_61, ~mu0_2 +# 1038| mu0_68(decltype([...](...){...})) = Store : &:r0_60, r0_67 +# 1039| r0_69(glval) = VariableAddress[lambda_ref_explicit] : +# 1039| r0_70(glval) = Convert : r0_69 +# 1039| r0_71(glval) = FunctionAddress[operator()] : +# 1039| r0_72(float) = Constant[3.0] : +# 1039| r0_73(char) = Call : func:r0_71, this:r0_70, 0:r0_72 +# 1039| mu0_74(unknown) = ^CallSideEffect : ~mu0_2 +# 1039| v0_75(void) = ^IndirectReadSideEffect[-1] : &:r0_70, ~mu0_2 +# 1039| mu0_76(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_70 +# 1040| r0_77(glval) = VariableAddress[lambda_val_explicit] : +# 1040| r0_78(glval) = FunctionAddress[(constructor)] : +# 1040| r0_79(glval) = VariableAddress[#temp1040:30] : +# 1040| mu0_80(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_79 +# 1040| r0_81(glval) = FieldAddress[s] : r0_79 +#-----| r0_82(glval) = FunctionAddress[String] : +#-----| v0_83(void) = Call : func:r0_82, this:r0_81 +#-----| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 +#-----| mu0_85(String) = ^IndirectMustWriteSideEffect : &:r0_81 +# 1040| r0_86(decltype([...](...){...})) = Load : &:r0_79, ~mu0_2 +# 1040| v0_87(void) = Call : func:r0_78, this:r0_77, 0:r0_86 +# 1040| mu0_88(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| mu0_89(decltype([...](...){...})) = ^IndirectMustWriteSideEffect : &:r0_77 +# 1040| v0_90(void) = ^IndirectReadSideEffect[0] : &:r0_86, ~mu0_2 +# 1040| mu0_91(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_86 +# 1041| r0_92(glval) = VariableAddress[lambda_val_explicit] : +# 1041| r0_93(glval) = Convert : r0_92 +# 1041| r0_94(glval) = FunctionAddress[operator()] : +# 1041| r0_95(float) = Constant[4.0] : +# 1041| r0_96(char) = Call : func:r0_94, this:r0_93, 0:r0_95 +# 1041| mu0_97(unknown) = ^CallSideEffect : ~mu0_2 +# 1041| v0_98(void) = ^IndirectReadSideEffect[-1] : &:r0_93, ~mu0_2 +# 1041| mu0_99(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_93 +# 1042| r0_100(glval) = VariableAddress[lambda_mixed_explicit] : +# 1042| r0_101(glval) = VariableAddress[#temp1042:32] : +# 1042| mu0_102(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_101 +# 1042| r0_103(glval) = FieldAddress[s] : r0_101 +# 1042| r0_104(glval) = VariableAddress[s] : +# 1042| r0_105(String &) = Load : &:r0_104, ~mu0_2 +# 1042| mu0_106(String &) = Store : &:r0_103, r0_105 +# 1042| r0_107(glval) = FieldAddress[x] : r0_101 +# 1042| r0_108(glval) = VariableAddress[x] : +# 1042| r0_109(int) = Load : &:r0_108, ~mu0_2 +# 1042| mu0_110(int) = Store : &:r0_107, r0_109 +# 1042| r0_111(decltype([...](...){...})) = Load : &:r0_101, ~mu0_2 +# 1042| mu0_112(decltype([...](...){...})) = Store : &:r0_100, r0_111 +# 1043| r0_113(glval) = VariableAddress[lambda_mixed_explicit] : +# 1043| r0_114(glval) = Convert : r0_113 +# 1043| r0_115(glval) = FunctionAddress[operator()] : +# 1043| r0_116(float) = Constant[5.0] : +# 1043| r0_117(char) = Call : func:r0_115, this:r0_114, 0:r0_116 +# 1043| mu0_118(unknown) = ^CallSideEffect : ~mu0_2 +# 1043| v0_119(void) = ^IndirectReadSideEffect[-1] : &:r0_114, ~mu0_2 +# 1043| mu0_120(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_114 +# 1044| r0_121(glval) = VariableAddress[r] : +# 1044| r0_122(glval) = VariableAddress[x] : +# 1044| r0_123(int) = Load : &:r0_122, ~mu0_2 +# 1044| r0_124(int) = Constant[1] : +# 1044| r0_125(int) = Sub : r0_123, r0_124 +# 1044| mu0_126(int) = Store : &:r0_121, r0_125 +# 1045| r0_127(glval) = VariableAddress[lambda_inits] : +# 1045| r0_128(glval) = VariableAddress[#temp1045:23] : +# 1045| mu0_129(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_128 +# 1045| r0_130(glval) = FieldAddress[s] : r0_128 +# 1045| r0_131(glval) = VariableAddress[s] : +# 1045| r0_132(String &) = Load : &:r0_131, ~mu0_2 +# 1045| mu0_133(String &) = Store : &:r0_130, r0_132 +# 1045| r0_134(glval) = FieldAddress[x] : r0_128 # 1045| r0_135(glval) = VariableAddress[x] : # 1045| r0_136(int) = Load : &:r0_135, ~mu0_2 -# 1045| r0_137(int) = Constant[1] : -# 1045| r0_138(int) = Add : r0_136, r0_137 -# 1045| mu0_139(int) = Store : &:r0_134, r0_138 -# 1045| r0_140(glval) = FieldAddress[j] : r0_124 -# 1045| r0_141(glval) = VariableAddress[r] : -# 1045| mu0_142(int &) = Store : &:r0_140, r0_141 -# 1045| r0_143(decltype([...](...){...})) = Load : &:r0_124, ~mu0_2 -# 1045| mu0_144(decltype([...](...){...})) = Store : &:r0_123, r0_143 -# 1046| r0_145(glval) = VariableAddress[lambda_inits] : -# 1046| r0_146(glval) = Convert : r0_145 -# 1046| r0_147(glval) = FunctionAddress[operator()] : -# 1046| r0_148(float) = Constant[6.0] : -# 1046| r0_149(char) = Call : func:r0_147, this:r0_146, 0:r0_148 -# 1046| mu0_150(unknown) = ^CallSideEffect : ~mu0_2 -# 1046| v0_151(void) = ^IndirectReadSideEffect[-1] : &:r0_146, ~mu0_2 -# 1046| mu0_152(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_146 -# 1047| v0_153(void) = NoOp : -# 1031| v0_154(void) = ReturnVoid : -# 1031| v0_155(void) = UnmodeledUse : mu* -# 1031| v0_156(void) = ExitFunction : +# 1045| mu0_137(int) = Store : &:r0_134, r0_136 +# 1045| r0_138(glval) = FieldAddress[i] : r0_128 +# 1045| r0_139(glval) = VariableAddress[x] : +# 1045| r0_140(int) = Load : &:r0_139, ~mu0_2 +# 1045| r0_141(int) = Constant[1] : +# 1045| r0_142(int) = Add : r0_140, r0_141 +# 1045| mu0_143(int) = Store : &:r0_138, r0_142 +# 1045| r0_144(glval) = FieldAddress[j] : r0_128 +# 1045| r0_145(glval) = VariableAddress[r] : +# 1045| mu0_146(int &) = Store : &:r0_144, r0_145 +# 1045| r0_147(decltype([...](...){...})) = Load : &:r0_128, ~mu0_2 +# 1045| mu0_148(decltype([...](...){...})) = Store : &:r0_127, r0_147 +# 1046| r0_149(glval) = VariableAddress[lambda_inits] : +# 1046| r0_150(glval) = Convert : r0_149 +# 1046| r0_151(glval) = FunctionAddress[operator()] : +# 1046| r0_152(float) = Constant[6.0] : +# 1046| r0_153(char) = Call : func:r0_151, this:r0_150, 0:r0_152 +# 1046| mu0_154(unknown) = ^CallSideEffect : ~mu0_2 +# 1046| v0_155(void) = ^IndirectReadSideEffect[-1] : &:r0_150, ~mu0_2 +# 1046| mu0_156(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_150 +# 1047| v0_157(void) = NoOp : +# 1031| v0_158(void) = ReturnVoid : +# 1031| v0_159(void) = UnmodeledUse : mu* +# 1031| v0_160(void) = ExitFunction : # 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&) # 1032| Block 0 @@ -4946,20 +4984,21 @@ ir.cpp: # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) # 1040| Block 0 -# 1040| v0_0(void) = EnterFunction : -# 1040| mu0_1(unknown) = AliasedDefinition : -# 1040| mu0_2(unknown) = UnmodeledDefinition : -# 1040| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 -# 1040| r0_6(glval) = FieldAddress[s] : r0_3 -# 1040| r0_7(glval) = FunctionAddress[String] : -# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 -# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| v0_10(void) = NoOp : -# 1040| v0_11(void) = ReturnVoid : -# 1040| v0_12(void) = UnmodeledUse : mu* -# 1040| v0_13(void) = ExitFunction : +# 1040| v0_0(void) = EnterFunction : +# 1040| mu0_1(unknown) = AliasedDefinition : +# 1040| mu0_2(unknown) = UnmodeledDefinition : +# 1040| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 +# 1040| r0_6(glval) = FieldAddress[s] : r0_3 +# 1040| r0_7(glval) = FunctionAddress[String] : +# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 +# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| mu0_10(String) = ^IndirectMustWriteSideEffect : &:r0_6 +# 1040| v0_11(void) = NoOp : +# 1040| v0_12(void) = ReturnVoid : +# 1040| v0_13(void) = UnmodeledUse : mu* +# 1040| v0_14(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~() # 1040| Block 0 @@ -5378,9 +5417,10 @@ ir.cpp: # 1140| r7_3(char *) = Convert : r7_2 # 1140| v7_4(void) = Call : func:r7_1, this:r7_0, 0:r7_3 # 1140| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1140| v7_6(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 -# 1140| mu7_7(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 -# 1140| v7_8(void) = ThrowValue : &:r7_0, ~mu0_2 +# 1140| mu7_6(String) = ^IndirectMustWriteSideEffect : &:r7_0 +# 1140| v7_7(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 +# 1140| mu7_8(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 +# 1140| v7_9(void) = ThrowValue : &:r7_0, ~mu0_2 #-----| Exception -> Block 9 # 1142| Block 8 @@ -5403,9 +5443,10 @@ ir.cpp: # 1145| r10_5(char *) = Load : &:r10_4, ~mu0_2 # 1145| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 # 1145| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 1145| v10_8(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 -# 1145| mu10_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 -# 1145| v10_10(void) = ThrowValue : &:r10_2, ~mu0_2 +# 1145| mu10_8(String) = ^IndirectMustWriteSideEffect : &:r10_2 +# 1145| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 +# 1145| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 +# 1145| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 #-----| Exception -> Block 2 # 1147| Block 11 @@ -5544,11 +5585,12 @@ perf-regression.cpp: # 10| r0_9(glval) = FunctionAddress[Big] : # 10| v0_10(void) = Call : func:r0_9, this:r0_8 # 10| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 10| mu0_12(Big *) = Store : &:r0_3, r0_8 -# 12| r0_13(glval) = VariableAddress[#return] : -# 12| r0_14(int) = Constant[0] : -# 12| mu0_15(int) = Store : &:r0_13, r0_14 -# 9| r0_16(glval) = VariableAddress[#return] : -# 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 -# 9| v0_18(void) = UnmodeledUse : mu* -# 9| v0_19(void) = ExitFunction : +# 10| mu0_12(Big) = ^IndirectMustWriteSideEffect : &:r0_8 +# 10| mu0_13(Big *) = Store : &:r0_3, r0_8 +# 12| r0_14(glval) = VariableAddress[#return] : +# 12| r0_15(int) = Constant[0] : +# 12| mu0_16(int) = Store : &:r0_14, r0_15 +# 9| r0_17(glval) = VariableAddress[#return] : +# 9| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 +# 9| v0_19(void) = UnmodeledUse : mu* +# 9| v0_20(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected index ae680785ce64..283f13d4bf44 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected @@ -1,4 +1,8 @@ missingOperand +| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index ae680785ce64..283f13d4bf44 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -1,4 +1,8 @@ missingOperand +| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 5fb356f5701f..c7c6e1128789 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -1,10 +1,33 @@ missingOperand +| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| cpp11.cpp:77:19:77:21 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | +| cpp11.cpp:82:11:82:14 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:17:82:55 | IndirectMustWriteSideEffect: call to (constructor) | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:45:82:48 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:82:51:82:51 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:88:25:88:30 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| cpp11.cpp:88:33:88:38 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| destructors.cpp:51:36:51:38 | IndirectMustWriteSideEffect: call to C | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | +| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | allocators.cpp:14:5:14:8 | IR: main | int main() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| try_catch.cpp:13:5:13:16 | ThrowValue: throw ... | Instruction 'ThrowValue' is missing an expected operand with tag 'Load' in function '$@'. | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() | unexpectedOperand duplicateOperand missingPhiOperand @@ -13,10 +36,10 @@ missingOperandType instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | assume0.cpp:7:2:7:2 | Chi: call to f | -| condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt | -| condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | IndirectMustWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | | misc.c:219:47:219:48 | InitializeParameter: sp | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 426424a5fd46..6d832e6a8314 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -3,6 +3,34 @@ missingOperand | condition_decls.cpp:26:3:36:3 | Switch: switch (...) ... | Instruction 'Switch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | | condition_decls.cpp:41:9:41:23 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | | condition_decls.cpp:48:39:48:53 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | +| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| cpp11.cpp:77:19:77:21 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | +| cpp11.cpp:82:11:82:14 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:17:82:55 | IndirectMustWriteSideEffect: call to (constructor) | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:45:82:48 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:82:51:82:51 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:88:25:88:30 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| cpp11.cpp:88:33:88:38 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| destructors.cpp:51:36:51:38 | IndirectMustWriteSideEffect: call to C | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | +| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | @@ -26,11 +54,11 @@ instructionWithoutSuccessor | VacuousDestructorCall.cpp:4:3:4:3 | Load: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | | assume0.cpp:9:11:9:11 | Constant: (bool)... | -| condition_decls.cpp:16:19:16:20 | CallSideEffect: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | IndirectMustWriteSideEffect: call to BoxedInt | | condition_decls.cpp:26:19:26:20 | IndirectMayWriteSideEffect: bi | -| condition_decls.cpp:26:23:26:24 | CallSideEffect: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | CallSideEffect: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | CallSideEffect: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | IndirectMustWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | @@ -54,16 +82,16 @@ instructionWithoutSuccessor | ms_try_except.cpp:17:13:17:17 | Store: ... = ... | | ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | | ms_try_except.cpp:20:9:20:13 | Store: ... = ... | -| ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | +| ms_try_mix.cpp:11:12:11:15 | IndirectMustWriteSideEffect: call to C | | ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | -| ms_try_mix.cpp:18:16:18:19 | CallSideEffect: call to C | +| ms_try_mix.cpp:18:16:18:19 | IndirectMustWriteSideEffect: call to C | | ms_try_mix.cpp:20:15:20:39 | Constant: 1 | -| ms_try_mix.cpp:21:16:21:19 | CallSideEffect: call to C | -| ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | +| ms_try_mix.cpp:21:16:21:19 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:28:12:28:15 | IndirectMustWriteSideEffect: call to C | | ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | -| ms_try_mix.cpp:35:16:35:19 | CallSideEffect: call to C | -| ms_try_mix.cpp:38:16:38:19 | CallSideEffect: call to C | -| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C | +| ms_try_mix.cpp:35:16:35:19 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:38:16:38:19 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:48:10:48:13 | IndirectMustWriteSideEffect: call to C | | ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | | ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 22a395b3f89f..51c69186d92f 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -1,10 +1,33 @@ missingOperand +| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| cpp11.cpp:77:19:77:21 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | +| cpp11.cpp:82:11:82:14 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:17:82:55 | IndirectMustWriteSideEffect: call to (constructor) | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:45:82:48 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:82:51:82:51 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:88:25:88:30 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| cpp11.cpp:88:33:88:38 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| destructors.cpp:51:36:51:38 | IndirectMustWriteSideEffect: call to C | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | +| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | allocators.cpp:14:5:14:8 | IR: main | int main() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| parameterinitializer.cpp:27:3:27:6 | IndirectReadSideEffect: my_c | Instruction 'IndirectReadSideEffect' is missing an expected operand with tag 'SideEffect' in function '$@'. | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| try_catch.cpp:13:5:13:16 | ThrowValue: throw ... | Instruction 'ThrowValue' is missing an expected operand with tag 'Load' in function '$@'. | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() | unexpectedOperand duplicateOperand missingPhiOperand @@ -22,17 +45,17 @@ missingOperandType instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | -| condition_decls.cpp:16:19:16:20 | CallSideEffect: call to BoxedInt | -| condition_decls.cpp:26:23:26:24 | CallSideEffect: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | CallSideEffect: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | CallSideEffect: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | IndirectMustWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | | misc.c:219:47:219:48 | InitializeParameter: sp | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | -| ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | -| ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | -| ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C | +| ms_try_mix.cpp:11:12:11:15 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:28:12:28:15 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:48:10:48:13 | IndirectMustWriteSideEffect: call to C | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | From 56ed2f618d932f221976391dd46f754ca208fbe0 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Wed, 2 Oct 2019 09:05:31 +0100 Subject: [PATCH 0015/2538] Add alias for easier user-searching --- docs/language/support/versions-compilers.csv | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/support/versions-compilers.csv b/docs/language/support/versions-compilers.csv index b70ac87335fd..74f69d662b6f 100644 --- a/docs/language/support/versions-compilers.csv +++ b/docs/language/support/versions-compilers.csv @@ -10,7 +10,7 @@ C#,C# up to 7.3. with .NET up to 4.8 [3]_.,"Microsoft Visual Studio up to 2019, .NET Core up to 2.2","``.sln``, ``.csproj``, ``.cs``, ``.cshtml``, ``.xaml``" COBOL,ANSI 85 or newer [4]_.,Not applicable,"``.cbl``, ``.CBL``, ``.cpy``, ``.CPY``, ``.copy``, ``.COPY``" -Go, "Go up to 1.13", "Go 1.11 or more recent", ``.go`` +Go (aka Golang), "Go up to 1.13", "Go 1.11 or more recent", ``.go`` Java,"Java 6 to 12 [5]_.","javac (OpenJDK and Oracle JDK), Eclipse compiler for Java (ECJ) [6]_.",``.java`` From 53f522c7f66284cdcb034bb5bdc5d4a4dd72fe1b Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 2 Oct 2019 10:11:58 -0700 Subject: [PATCH 0016/2538] C++: respond to PR comments and autoformat --- .../raw/internal/TranslatedCall.qll | 3 +- .../raw/internal/TranslatedElement.qll | 6 +- .../ir/ir/aliased_ssa_sanity.expected | 8 +- .../test/library-tests/ir/ir/raw_ir.expected | 164 +++++++++--------- .../library-tests/ir/ir/raw_sanity.expected | 8 +- .../ir/ir/unaliased_ssa_sanity.expected | 8 +- .../syntax-zoo/aliased_ssa_sanity.expected | 64 +++---- .../syntax-zoo/raw_sanity.expected | 78 ++++----- .../syntax-zoo/unaliased_ssa_sanity.expected | 70 ++++---- 9 files changed, 205 insertions(+), 204 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 0ee86785b52e..08f782db9fcd 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -378,7 +378,7 @@ class TranslatedStructorCallSideEffects extends TranslatedSideEffects { TranslatedStructorCallSideEffects() { getParent().(TranslatedStructorCall).hasQualifier() } override predicate hasInstruction(Opcode opcode, InstructionTag tag, Type t, boolean isGLValue) { - opcode instanceof Opcode::IndirectMustWriteSideEffect and + opcode instanceof Opcode::IndirectMayWriteSideEffect and tag instanceof OnlyInstructionTag and t = expr.getTarget().getDeclaringType() and isGLValue = false @@ -566,4 +566,3 @@ class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEff */ override Function getFunction() { result = arg.getEnclosingFunction() } } - diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index db34d69f4c85..817566780951 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -371,8 +371,10 @@ newtype TTranslatedElement = TTranslatedAllocationSize(NewOrNewArrayExpr newExpr) { not ignoreExpr(newExpr) } or // The declaration/initialization part of a `ConditionDeclExpr` TTranslatedConditionDecl(ConditionDeclExpr expr) { not ignoreExpr(expr) } or - // The side effects of a `Call` { - TTranslatedSideEffects(Call expr) { exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or expr instanceof ConstructorCall } or // A precise side effect of an argument to a `Call` { + // The side effects of a `Call` + TTranslatedSideEffects(Call expr) { + exists(TTranslatedArgumentSideEffect(expr, _, _, _)) or expr instanceof ConstructorCall + } or // A precise side effect of an argument to a `Call` TTranslatedArgumentSideEffect(Call call, Expr expr, int n, boolean isWrite) { ( expr = call.getArgument(n).getFullyConverted() diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index 283f13d4bf44..d86f9a053346 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -1,8 +1,8 @@ missingOperand -| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 55a8cc56e01d..b4a798f6e736 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2715,14 +2715,14 @@ ir.cpp: # 616| r0_4(glval) = FunctionAddress[String] : # 616| v0_5(void) = Call : func:r0_4, this:r0_3 # 616| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 616| mu0_7(String) = ^IndirectMustWriteSideEffect : &:r0_3 +# 616| mu0_7(String) = ^IndirectMayWriteSideEffect : &:r0_3 # 617| r0_8(glval) = VariableAddress[s2] : # 617| r0_9(glval) = FunctionAddress[String] : # 617| r0_10(glval) = StringConstant["hello"] : # 617| r0_11(char *) = Convert : r0_10 # 617| v0_12(void) = Call : func:r0_9, this:r0_8, 0:r0_11 # 617| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 617| mu0_14(String) = ^IndirectMustWriteSideEffect : &:r0_8 +# 617| mu0_14(String) = ^IndirectMayWriteSideEffect : &:r0_8 # 617| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 # 617| mu0_16(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 # 618| r0_17(glval) = VariableAddress[s3] : @@ -2736,7 +2736,7 @@ ir.cpp: # 619| r0_25(char *) = Convert : r0_24 # 619| v0_26(void) = Call : func:r0_23, this:r0_22, 0:r0_25 # 619| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 -# 619| mu0_28(String) = ^IndirectMustWriteSideEffect : &:r0_22 +# 619| mu0_28(String) = ^IndirectMayWriteSideEffect : &:r0_22 # 619| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 # 619| mu0_30(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 # 620| v0_31(void) = NoOp : @@ -2918,7 +2918,7 @@ ir.cpp: # 663| r0_8(glval) = FunctionAddress[String] : # 663| v0_9(void) = Call : func:r0_8, this:r0_7 # 663| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 663| mu0_11(String) = ^IndirectMustWriteSideEffect : &:r0_7 +# 663| mu0_11(String) = ^IndirectMayWriteSideEffect : &:r0_7 # 660| r0_12(glval) = FieldAddress[m_c] : r0_3 # 660| r0_13(char) = Constant[3] : # 660| mu0_14(char) = Store : &:r0_12, r0_13 @@ -2931,7 +2931,7 @@ ir.cpp: # 662| r0_21(char *) = Convert : r0_20 # 662| v0_22(void) = Call : func:r0_19, this:r0_18, 0:r0_21 # 662| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 -# 662| mu0_24(String) = ^IndirectMustWriteSideEffect : &:r0_18 +# 662| mu0_24(String) = ^IndirectMayWriteSideEffect : &:r0_18 # 662| v0_25(void) = ^IndirectReadSideEffect[0] : &:r0_21, ~mu0_2 # 662| mu0_26(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_21 # 664| v0_27(void) = NoOp : @@ -3206,7 +3206,7 @@ ir.cpp: # 731| r7_3(char *) = Convert : r7_2 # 731| v7_4(void) = Call : func:r7_1, this:r7_0, 0:r7_3 # 731| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 -# 731| mu7_6(String) = ^IndirectMustWriteSideEffect : &:r7_0 +# 731| mu7_6(String) = ^IndirectMayWriteSideEffect : &:r7_0 # 731| v7_7(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 # 731| mu7_8(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 # 731| v7_9(void) = ThrowValue : &:r7_0, ~mu0_2 @@ -3232,7 +3232,7 @@ ir.cpp: # 736| r10_5(char *) = Load : &:r10_4, ~mu0_2 # 736| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 # 736| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 736| mu10_8(String) = ^IndirectMustWriteSideEffect : &:r10_2 +# 736| mu10_8(String) = ^IndirectMayWriteSideEffect : &:r10_2 # 736| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 # 736| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 # 736| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 @@ -3289,37 +3289,37 @@ ir.cpp: # 745| void Base::Base(Base const&) # 745| Block 0 -# 745| v0_0(void) = EnterFunction : -# 745| mu0_1(unknown) = AliasedDefinition : -# 745| mu0_2(unknown) = UnmodeledDefinition : -# 745| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 -# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 -# 745| r0_7(glval) = FunctionAddress[String] : -# 745| v0_8(void) = Call : func:r0_7, this:r0_6 -# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 745| mu0_10(String) = ^IndirectMustWriteSideEffect : &:r0_6 -# 745| v0_11(void) = NoOp : -# 745| v0_12(void) = ReturnVoid : -# 745| v0_13(void) = UnmodeledUse : mu* -# 745| v0_14(void) = ExitFunction : +# 745| v0_0(void) = EnterFunction : +# 745| mu0_1(unknown) = AliasedDefinition : +# 745| mu0_2(unknown) = UnmodeledDefinition : +# 745| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 +# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 +# 745| r0_7(glval) = FunctionAddress[String] : +# 745| v0_8(void) = Call : func:r0_7, this:r0_6 +# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 +# 745| mu0_10(String) = ^IndirectMayWriteSideEffect : &:r0_6 +# 745| v0_11(void) = NoOp : +# 745| v0_12(void) = ReturnVoid : +# 745| v0_13(void) = UnmodeledUse : mu* +# 745| v0_14(void) = ExitFunction : # 748| void Base::Base() # 748| Block 0 -# 748| v0_0(void) = EnterFunction : -# 748| mu0_1(unknown) = AliasedDefinition : -# 748| mu0_2(unknown) = UnmodeledDefinition : -# 748| r0_3(glval) = InitializeThis : -# 748| r0_4(glval) = FieldAddress[base_s] : r0_3 -# 748| r0_5(glval) = FunctionAddress[String] : -# 748| v0_6(void) = Call : func:r0_5, this:r0_4 -# 748| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 748| mu0_8(String) = ^IndirectMustWriteSideEffect : &:r0_4 -# 749| v0_9(void) = NoOp : -# 748| v0_10(void) = ReturnVoid : -# 748| v0_11(void) = UnmodeledUse : mu* -# 748| v0_12(void) = ExitFunction : +# 748| v0_0(void) = EnterFunction : +# 748| mu0_1(unknown) = AliasedDefinition : +# 748| mu0_2(unknown) = UnmodeledDefinition : +# 748| r0_3(glval) = InitializeThis : +# 748| r0_4(glval) = FieldAddress[base_s] : r0_3 +# 748| r0_5(glval) = FunctionAddress[String] : +# 748| v0_6(void) = Call : func:r0_5, this:r0_4 +# 748| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 748| mu0_8(String) = ^IndirectMayWriteSideEffect : &:r0_4 +# 749| v0_9(void) = NoOp : +# 748| v0_10(void) = ReturnVoid : +# 748| v0_11(void) = UnmodeledUse : mu* +# 748| v0_12(void) = ExitFunction : # 750| void Base::~Base() # 750| Block 0 @@ -3386,12 +3386,12 @@ ir.cpp: # 757| r0_5(glval) = FunctionAddress[Base] : # 757| v0_6(void) = Call : func:r0_5, this:r0_4 # 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 757| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 757| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 # 757| r0_9(glval) = FieldAddress[middle_s] : r0_3 # 757| r0_10(glval) = FunctionAddress[String] : # 757| v0_11(void) = Call : func:r0_10, this:r0_9 # 757| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 757| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 757| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 # 758| v0_14(void) = NoOp : # 757| v0_15(void) = ReturnVoid : # 757| v0_16(void) = UnmodeledUse : mu* @@ -3466,12 +3466,12 @@ ir.cpp: # 766| r0_5(glval) = FunctionAddress[Middle] : # 766| v0_6(void) = Call : func:r0_5, this:r0_4 # 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 766| mu0_8(Middle) = ^IndirectMustWriteSideEffect : &:r0_4 +# 766| mu0_8(Middle) = ^IndirectMayWriteSideEffect : &:r0_4 # 766| r0_9(glval) = FieldAddress[derived_s] : r0_3 # 766| r0_10(glval) = FunctionAddress[String] : # 766| v0_11(void) = Call : func:r0_10, this:r0_9 # 766| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 766| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 766| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 # 767| v0_14(void) = NoOp : # 766| v0_15(void) = ReturnVoid : # 766| v0_16(void) = UnmodeledUse : mu* @@ -3506,12 +3506,12 @@ ir.cpp: # 775| r0_5(glval) = FunctionAddress[Base] : # 775| v0_6(void) = Call : func:r0_5, this:r0_4 # 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 775| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 775| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 # 775| r0_9(glval) = FieldAddress[middlevb1_s] : r0_3 # 775| r0_10(glval) = FunctionAddress[String] : # 775| v0_11(void) = Call : func:r0_10, this:r0_9 # 775| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 775| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 775| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 # 776| v0_14(void) = NoOp : # 775| v0_15(void) = ReturnVoid : # 775| v0_16(void) = UnmodeledUse : mu* @@ -3546,12 +3546,12 @@ ir.cpp: # 784| r0_5(glval) = FunctionAddress[Base] : # 784| v0_6(void) = Call : func:r0_5, this:r0_4 # 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 784| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 784| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 # 784| r0_9(glval) = FieldAddress[middlevb2_s] : r0_3 # 784| r0_10(glval) = FunctionAddress[String] : # 784| v0_11(void) = Call : func:r0_10, this:r0_9 # 784| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 784| mu0_13(String) = ^IndirectMustWriteSideEffect : &:r0_9 +# 784| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 # 785| v0_14(void) = NoOp : # 784| v0_15(void) = ReturnVoid : # 784| v0_16(void) = UnmodeledUse : mu* @@ -3586,22 +3586,22 @@ ir.cpp: # 793| r0_5(glval) = FunctionAddress[Base] : # 793| v0_6(void) = Call : func:r0_5, this:r0_4 # 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_8(Base) = ^IndirectMustWriteSideEffect : &:r0_4 +# 793| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 # 793| r0_9(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 # 793| r0_10(glval) = FunctionAddress[MiddleVB1] : # 793| v0_11(void) = Call : func:r0_10, this:r0_9 # 793| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_13(MiddleVB1) = ^IndirectMustWriteSideEffect : &:r0_9 +# 793| mu0_13(MiddleVB1) = ^IndirectMayWriteSideEffect : &:r0_9 # 793| r0_14(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 # 793| r0_15(glval) = FunctionAddress[MiddleVB2] : # 793| v0_16(void) = Call : func:r0_15, this:r0_14 # 793| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_18(MiddleVB2) = ^IndirectMustWriteSideEffect : &:r0_14 +# 793| mu0_18(MiddleVB2) = ^IndirectMayWriteSideEffect : &:r0_14 # 793| r0_19(glval) = FieldAddress[derivedvb_s] : r0_3 # 793| r0_20(glval) = FunctionAddress[String] : # 793| v0_21(void) = Call : func:r0_20, this:r0_19 # 793| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_23(String) = ^IndirectMustWriteSideEffect : &:r0_19 +# 793| mu0_23(String) = ^IndirectMayWriteSideEffect : &:r0_19 # 794| v0_24(void) = NoOp : # 793| v0_25(void) = ReturnVoid : # 793| v0_26(void) = UnmodeledUse : mu* @@ -3643,17 +3643,17 @@ ir.cpp: # 800| r0_4(glval) = FunctionAddress[Base] : # 800| v0_5(void) = Call : func:r0_4, this:r0_3 # 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 800| mu0_7(Base) = ^IndirectMustWriteSideEffect : &:r0_3 +# 800| mu0_7(Base) = ^IndirectMayWriteSideEffect : &:r0_3 # 801| r0_8(glval) = VariableAddress[m] : # 801| r0_9(glval) = FunctionAddress[Middle] : # 801| v0_10(void) = Call : func:r0_9, this:r0_8 # 801| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 801| mu0_12(Middle) = ^IndirectMustWriteSideEffect : &:r0_8 +# 801| mu0_12(Middle) = ^IndirectMayWriteSideEffect : &:r0_8 # 802| r0_13(glval) = VariableAddress[d] : # 802| r0_14(glval) = FunctionAddress[Derived] : # 802| v0_15(void) = Call : func:r0_14, this:r0_13 # 802| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 -# 802| mu0_17(Derived) = ^IndirectMustWriteSideEffect : &:r0_13 +# 802| mu0_17(Derived) = ^IndirectMayWriteSideEffect : &:r0_13 # 804| r0_18(glval) = VariableAddress[pb] : # 804| r0_19(glval) = VariableAddress[b] : # 804| mu0_20(Base *) = Store : &:r0_18, r0_19 @@ -3680,7 +3680,7 @@ ir.cpp: # 809| r0_41(glval) = ConvertToBase[Middle : Base] : r0_40 # 809| v0_42(void) = Call : func:r0_39, 0:r0_41 # 809| mu0_43(unknown) = ^CallSideEffect : ~mu0_2 -# 809| mu0_44(Base) = ^IndirectMustWriteSideEffect : +# 809| mu0_44(Base) = ^IndirectMayWriteSideEffect : # 809| v0_45(void) = ^IndirectReadSideEffect[0] : &:r0_41, ~mu0_2 # 809| mu0_46(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_41 # 809| r0_47(glval) = Convert : v0_42 @@ -3697,7 +3697,7 @@ ir.cpp: # 810| r0_58(glval) = ConvertToBase[Middle : Base] : r0_57 # 810| v0_59(void) = Call : func:r0_56, 0:r0_58 # 810| mu0_60(unknown) = ^CallSideEffect : ~mu0_2 -# 810| mu0_61(Base) = ^IndirectMustWriteSideEffect : +# 810| mu0_61(Base) = ^IndirectMayWriteSideEffect : # 810| v0_62(void) = ^IndirectReadSideEffect[0] : &:r0_58, ~mu0_2 # 810| mu0_63(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_58 # 810| r0_64(glval) = Convert : v0_59 @@ -3783,7 +3783,7 @@ ir.cpp: # 823| r0_144(glval) = ConvertToBase[Middle : Base] : r0_143 # 823| v0_145(void) = Call : func:r0_141, 0:r0_144 # 823| mu0_146(unknown) = ^CallSideEffect : ~mu0_2 -# 823| mu0_147(Base) = ^IndirectMustWriteSideEffect : +# 823| mu0_147(Base) = ^IndirectMayWriteSideEffect : # 823| v0_148(void) = ^IndirectReadSideEffect[0] : &:r0_144, ~mu0_2 # 823| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_144 # 823| r0_150(glval) = Convert : v0_145 @@ -3801,7 +3801,7 @@ ir.cpp: # 824| r0_162(glval) = ConvertToBase[Middle : Base] : r0_161 # 824| v0_163(void) = Call : func:r0_159, 0:r0_162 # 824| mu0_164(unknown) = ^CallSideEffect : ~mu0_2 -# 824| mu0_165(Base) = ^IndirectMustWriteSideEffect : +# 824| mu0_165(Base) = ^IndirectMayWriteSideEffect : # 824| v0_166(void) = ^IndirectReadSideEffect[0] : &:r0_162, ~mu0_2 # 824| mu0_167(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_162 # 824| r0_168(glval) = Convert : v0_163 @@ -3917,7 +3917,7 @@ ir.cpp: # 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : # 846| v0_6(void) = Call : func:r0_5, this:r0_4 # 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 846| mu0_8(PolymorphicBase) = ^IndirectMustWriteSideEffect : &:r0_4 +# 846| mu0_8(PolymorphicBase) = ^IndirectMayWriteSideEffect : &:r0_4 # 846| v0_9(void) = NoOp : # 846| v0_10(void) = ReturnVoid : # 846| v0_11(void) = UnmodeledUse : mu* @@ -3947,12 +3947,12 @@ ir.cpp: #-----| r0_4(glval) = FunctionAddress[PolymorphicBase] : #-----| v0_5(void) = Call : func:r0_4, this:r0_3 #-----| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_7(PolymorphicBase) = ^IndirectMustWriteSideEffect : &:r0_3 +#-----| mu0_7(PolymorphicBase) = ^IndirectMayWriteSideEffect : &:r0_3 # 851| r0_8(glval) = VariableAddress[d] : # 851| r0_9(glval) = FunctionAddress[PolymorphicDerived] : # 851| v0_10(void) = Call : func:r0_9, this:r0_8 # 851| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 851| mu0_12(PolymorphicDerived) = ^IndirectMustWriteSideEffect : &:r0_8 +# 851| mu0_12(PolymorphicDerived) = ^IndirectMayWriteSideEffect : &:r0_8 # 853| r0_13(glval) = VariableAddress[pb] : # 853| r0_14(glval) = VariableAddress[b] : # 853| mu0_15(PolymorphicBase *) = Store : &:r0_13, r0_14 @@ -4003,7 +4003,7 @@ ir.cpp: # 868| r0_6(char *) = Convert : r0_5 # 868| v0_7(void) = Call : func:r0_4, this:r0_3, 0:r0_6 # 868| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 868| mu0_9(String) = ^IndirectMustWriteSideEffect : &:r0_3 +# 868| mu0_9(String) = ^IndirectMayWriteSideEffect : &:r0_3 # 868| v0_10(void) = ^IndirectReadSideEffect[0] : &:r0_6, ~mu0_2 # 868| mu0_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_6 # 869| v0_12(void) = NoOp : @@ -4210,7 +4210,7 @@ ir.cpp: # 944| r0_26(glval) = FunctionAddress[String] : # 944| v0_27(void) = Call : func:r0_26, this:r0_25 # 944| mu0_28(unknown) = ^CallSideEffect : ~mu0_2 -# 944| mu0_29(String) = ^IndirectMustWriteSideEffect : &:r0_25 +# 944| mu0_29(String) = ^IndirectMayWriteSideEffect : &:r0_25 # 945| r0_30(glval) = FunctionAddress[operator new] : # 945| r0_31(unsigned long) = Constant[8] : # 945| r0_32(float) = Constant[1.0] : @@ -4222,7 +4222,7 @@ ir.cpp: # 945| r0_38(char *) = Convert : r0_37 # 945| v0_39(void) = Call : func:r0_36, this:r0_35, 0:r0_38 # 945| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 945| mu0_41(String) = ^IndirectMustWriteSideEffect : &:r0_35 +# 945| mu0_41(String) = ^IndirectMayWriteSideEffect : &:r0_35 # 945| v0_42(void) = ^IndirectReadSideEffect[0] : &:r0_38, ~mu0_2 # 945| mu0_43(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_38 # 946| r0_44(glval) = FunctionAddress[operator new] : @@ -4721,7 +4721,7 @@ ir.cpp: #-----| r0_38(glval) = FunctionAddress[String] : #-----| v0_39(void) = Call : func:r0_38, this:r0_37 #-----| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_41(String) = ^IndirectMustWriteSideEffect : &:r0_37 +#-----| mu0_41(String) = ^IndirectMayWriteSideEffect : &:r0_37 # 1036| r0_42(glval) = FieldAddress[x] : r0_35 #-----| r0_43(glval) = VariableAddress[x] : #-----| r0_44(int) = Load : &:r0_43, ~mu0_2 @@ -4729,7 +4729,7 @@ ir.cpp: # 1036| r0_46(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 # 1036| v0_47(void) = Call : func:r0_34, this:r0_33, 0:r0_46 # 1036| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| mu0_49(decltype([...](...){...})) = ^IndirectMustWriteSideEffect : &:r0_33 +# 1036| mu0_49(decltype([...](...){...})) = ^IndirectMayWriteSideEffect : &:r0_33 # 1036| v0_50(void) = ^IndirectReadSideEffect[0] : &:r0_46, ~mu0_2 # 1036| mu0_51(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_46 # 1037| r0_52(glval) = VariableAddress[lambda_val] : @@ -4765,11 +4765,11 @@ ir.cpp: #-----| r0_82(glval) = FunctionAddress[String] : #-----| v0_83(void) = Call : func:r0_82, this:r0_81 #-----| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_85(String) = ^IndirectMustWriteSideEffect : &:r0_81 +#-----| mu0_85(String) = ^IndirectMayWriteSideEffect : &:r0_81 # 1040| r0_86(decltype([...](...){...})) = Load : &:r0_79, ~mu0_2 # 1040| v0_87(void) = Call : func:r0_78, this:r0_77, 0:r0_86 # 1040| mu0_88(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| mu0_89(decltype([...](...){...})) = ^IndirectMustWriteSideEffect : &:r0_77 +# 1040| mu0_89(decltype([...](...){...})) = ^IndirectMayWriteSideEffect : &:r0_77 # 1040| v0_90(void) = ^IndirectReadSideEffect[0] : &:r0_86, ~mu0_2 # 1040| mu0_91(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_86 # 1041| r0_92(glval) = VariableAddress[lambda_val_explicit] : @@ -4984,21 +4984,21 @@ ir.cpp: # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) # 1040| Block 0 -# 1040| v0_0(void) = EnterFunction : -# 1040| mu0_1(unknown) = AliasedDefinition : -# 1040| mu0_2(unknown) = UnmodeledDefinition : -# 1040| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 -# 1040| r0_6(glval) = FieldAddress[s] : r0_3 -# 1040| r0_7(glval) = FunctionAddress[String] : -# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 -# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| mu0_10(String) = ^IndirectMustWriteSideEffect : &:r0_6 -# 1040| v0_11(void) = NoOp : -# 1040| v0_12(void) = ReturnVoid : -# 1040| v0_13(void) = UnmodeledUse : mu* -# 1040| v0_14(void) = ExitFunction : +# 1040| v0_0(void) = EnterFunction : +# 1040| mu0_1(unknown) = AliasedDefinition : +# 1040| mu0_2(unknown) = UnmodeledDefinition : +# 1040| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 +# 1040| r0_6(glval) = FieldAddress[s] : r0_3 +# 1040| r0_7(glval) = FunctionAddress[String] : +# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 +# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| mu0_10(String) = ^IndirectMayWriteSideEffect : &:r0_6 +# 1040| v0_11(void) = NoOp : +# 1040| v0_12(void) = ReturnVoid : +# 1040| v0_13(void) = UnmodeledUse : mu* +# 1040| v0_14(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~() # 1040| Block 0 @@ -5417,7 +5417,7 @@ ir.cpp: # 1140| r7_3(char *) = Convert : r7_2 # 1140| v7_4(void) = Call : func:r7_1, this:r7_0, 0:r7_3 # 1140| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1140| mu7_6(String) = ^IndirectMustWriteSideEffect : &:r7_0 +# 1140| mu7_6(String) = ^IndirectMayWriteSideEffect : &:r7_0 # 1140| v7_7(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 # 1140| mu7_8(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 # 1140| v7_9(void) = ThrowValue : &:r7_0, ~mu0_2 @@ -5443,7 +5443,7 @@ ir.cpp: # 1145| r10_5(char *) = Load : &:r10_4, ~mu0_2 # 1145| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 # 1145| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 1145| mu10_8(String) = ^IndirectMustWriteSideEffect : &:r10_2 +# 1145| mu10_8(String) = ^IndirectMayWriteSideEffect : &:r10_2 # 1145| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 # 1145| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 # 1145| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 @@ -5585,7 +5585,7 @@ perf-regression.cpp: # 10| r0_9(glval) = FunctionAddress[Big] : # 10| v0_10(void) = Call : func:r0_9, this:r0_8 # 10| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 10| mu0_12(Big) = ^IndirectMustWriteSideEffect : &:r0_8 +# 10| mu0_12(Big) = ^IndirectMayWriteSideEffect : &:r0_8 # 10| mu0_13(Big *) = Store : &:r0_3, r0_8 # 12| r0_14(glval) = VariableAddress[#return] : # 12| r0_15(int) = Constant[0] : diff --git a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected index 283f13d4bf44..d86f9a053346 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected @@ -1,8 +1,8 @@ missingOperand -| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index 283f13d4bf44..d86f9a053346 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -1,8 +1,8 @@ missingOperand -| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | unexpectedOperand duplicateOperand missingPhiOperand diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index c7c6e1128789..552c0693ad4c 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -1,32 +1,32 @@ missingOperand -| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| cpp11.cpp:77:19:77:21 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | -| cpp11.cpp:82:11:82:14 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:17:82:55 | IndirectMustWriteSideEffect: call to (constructor) | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:45:82:48 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:82:51:82:51 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:88:25:88:30 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp11.cpp:88:33:88:38 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| destructors.cpp:51:36:51:38 | IndirectMustWriteSideEffect: call to C | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | +| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| cpp11.cpp:88:33:88:38 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| destructors.cpp:51:36:51:38 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | +| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | unexpectedOperand duplicateOperand @@ -36,10 +36,10 @@ missingOperandType instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | assume0.cpp:7:2:7:2 | Chi: call to f | -| condition_decls.cpp:16:19:16:20 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:26:23:26:24 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | | misc.c:219:47:219:48 | InitializeParameter: sp | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 6d832e6a8314..2b3d6b07fc1b 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -3,34 +3,34 @@ missingOperand | condition_decls.cpp:26:3:36:3 | Switch: switch (...) ... | Instruction 'Switch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | | condition_decls.cpp:41:9:41:23 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | | condition_decls.cpp:48:39:48:53 | ConditionalBranch: (condition decl) | Instruction 'ConditionalBranch' is missing an expected operand with tag 'Condition' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| cpp11.cpp:77:19:77:21 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | -| cpp11.cpp:82:11:82:14 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:17:82:55 | IndirectMustWriteSideEffect: call to (constructor) | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:45:82:48 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:82:51:82:51 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:88:25:88:30 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp11.cpp:88:33:88:38 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| destructors.cpp:51:36:51:38 | IndirectMustWriteSideEffect: call to C | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | +| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| cpp11.cpp:88:33:88:38 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| destructors.cpp:51:36:51:38 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | +| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | @@ -54,11 +54,11 @@ instructionWithoutSuccessor | VacuousDestructorCall.cpp:4:3:4:3 | Load: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | | assume0.cpp:9:11:9:11 | Constant: (bool)... | -| condition_decls.cpp:16:19:16:20 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | | condition_decls.cpp:26:19:26:20 | IndirectMayWriteSideEffect: bi | -| condition_decls.cpp:26:23:26:24 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | file://:0:0:0:0 | CompareNE: (bool)... | | file://:0:0:0:0 | CompareNE: (bool)... | @@ -82,16 +82,16 @@ instructionWithoutSuccessor | ms_try_except.cpp:17:13:17:17 | Store: ... = ... | | ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | | ms_try_except.cpp:20:9:20:13 | Store: ... = ... | -| ms_try_mix.cpp:11:12:11:15 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | | ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | -| ms_try_mix.cpp:18:16:18:19 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:18:16:18:19 | IndirectMayWriteSideEffect: call to C | | ms_try_mix.cpp:20:15:20:39 | Constant: 1 | -| ms_try_mix.cpp:21:16:21:19 | IndirectMustWriteSideEffect: call to C | -| ms_try_mix.cpp:28:12:28:15 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:21:16:21:19 | IndirectMayWriteSideEffect: call to C | +| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | | ms_try_mix.cpp:33:13:33:19 | ThrowValue: throw ... | -| ms_try_mix.cpp:35:16:35:19 | IndirectMustWriteSideEffect: call to C | -| ms_try_mix.cpp:38:16:38:19 | IndirectMustWriteSideEffect: call to C | -| ms_try_mix.cpp:48:10:48:13 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:35:16:35:19 | IndirectMayWriteSideEffect: call to C | +| ms_try_mix.cpp:38:16:38:19 | IndirectMayWriteSideEffect: call to C | +| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | | ms_try_mix.cpp:51:5:51:11 | ThrowValue: throw ... | | ms_try_mix.cpp:53:13:54:3 | NoOp: { ... } | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 51c69186d92f..e984a30e3c5a 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -1,32 +1,32 @@ missingOperand -| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:9:30:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMustWriteSideEffect: call to C1 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMustWriteSideEffect: call to C2 | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| cpp11.cpp:77:19:77:21 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | -| cpp11.cpp:82:11:82:14 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:17:82:55 | IndirectMustWriteSideEffect: call to (constructor) | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:45:82:48 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:82:51:82:51 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:88:25:88:30 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp11.cpp:88:33:88:38 | IndirectMustWriteSideEffect: call to Val | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| destructors.cpp:51:36:51:38 | IndirectMustWriteSideEffect: call to C | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| ir.cpp:809:7:809:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMustWriteSideEffect: call to Base | Instruction 'IndirectMustWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | +| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | +| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | +| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | +| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | +| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| cpp11.cpp:88:33:88:38 | IndirectMayWriteSideEffect: call to Val | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | +| destructors.cpp:51:36:51:38 | IndirectMayWriteSideEffect: call to C | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | +| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | +| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | unexpectedOperand duplicateOperand @@ -45,17 +45,17 @@ missingOperandType instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | -| condition_decls.cpp:16:19:16:20 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:26:23:26:24 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | IndirectMustWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | IndirectMustWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | | misc.c:219:47:219:48 | InitializeParameter: sp | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | -| ms_try_mix.cpp:11:12:11:15 | IndirectMustWriteSideEffect: call to C | -| ms_try_mix.cpp:28:12:28:15 | IndirectMustWriteSideEffect: call to C | -| ms_try_mix.cpp:48:10:48:13 | IndirectMustWriteSideEffect: call to C | +| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | +| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | +| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | | stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | From 98b97b09be3ac7aa0a9d67f61ee5a40da84e6ea7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 11 Jul 2019 13:48:51 -0700 Subject: [PATCH 0017/2538] C++: add hasGlobalOrStdName to Declaration --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index fa061b239cc4..55d9a39dbdc4 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -119,6 +119,11 @@ abstract class Declaration extends Locatable, @declaration { /** Holds if this declaration has the given name in the global namespace. */ predicate hasGlobalName(string name) { this.hasQualifiedName("", "", name) } + /** Holds if this declaration has the given name in the global namespace or the `std` namespace. */ + predicate hasGlobalOrStdName(string name) { + this.hasQualifiedName("std", "", name) + } + /** Gets a specifier of this declaration. */ abstract Specifier getASpecifier(); From bff68a00ac074a08fce4112a6f59288a440f09f5 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 11 Jul 2019 15:57:26 -0700 Subject: [PATCH 0018/2538] C++: Add Declaration.hasStdName --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 55d9a39dbdc4..7c38acc564ee 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -119,9 +119,17 @@ abstract class Declaration extends Locatable, @declaration { /** Holds if this declaration has the given name in the global namespace. */ predicate hasGlobalName(string name) { this.hasQualifiedName("", "", name) } + + /** Holds if this declaration has the given name in the `std` namespace. */ + predicate hasStdName(string name) { + this.hasQualifiedName("std", "", name) + } + /** Holds if this declaration has the given name in the global namespace or the `std` namespace. */ predicate hasGlobalOrStdName(string name) { - this.hasQualifiedName("std", "", name) + this.hasGlobalName(name) + or + this.hasStdName(name) } /** Gets a specifier of this declaration. */ From 03f72d207cbcc02cedc5973d9ffcb0cd2f00ea00 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 11 Jul 2019 16:00:41 -0700 Subject: [PATCH 0019/2538] C++: use Declaration.hasGlobalOrStdName --- .../src/Critical/DescriptorMayNotBeClosed.ql | 2 +- cpp/ql/src/Critical/DescriptorNeverClosed.ql | 2 +- cpp/ql/src/Critical/MemoryMayNotBeFreed.ql | 4 +- cpp/ql/src/Critical/OverflowCalculated.ql | 9 ++- cpp/ql/src/Critical/OverflowDestination.ql | 2 +- cpp/ql/src/Critical/OverflowStatic.ql | 16 ++--- cpp/ql/src/Critical/SizeCheck.ql | 4 +- cpp/ql/src/Critical/SizeCheck2.ql | 4 +- cpp/ql/src/Critical/UseAfterFree.ql | 2 +- cpp/ql/src/DefaultOptions.qll | 4 +- .../src/Security/CWE/CWE-022/TaintedPath.ql | 7 ++- cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql | 4 +- .../CWE/CWE-121/UnterminatedVarargsCall.ql | 2 +- .../CWE/CWE-131/NoSpaceForZeroTerminator.ql | 5 +- .../Security/CWE/CWE-497/ExposedSystemData.ql | 60 +++++++++---------- .../CWE/CWE-676/DangerousFunctionOverflow.ql | 2 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql | 4 +- cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql | 4 +- cpp/ql/src/semmle/code/cpp/Function.qll | 2 +- cpp/ql/src/semmle/code/cpp/commons/Alloc.qll | 16 +++-- .../semmle/code/cpp/commons/Environment.qll | 2 +- cpp/ql/src/semmle/code/cpp/commons/File.qll | 12 ++-- .../code/cpp/commons/StringAnalysis.qll | 4 +- .../code/cpp/controlflow/Dereferenced.qll | 2 +- .../semmle/code/cpp/controlflow/Nullness.qll | 4 +- .../cpp/models/implementations/Printf.qll | 22 +++---- .../code/cpp/models/implementations/Pure.qll | 4 +- .../code/cpp/security/CommandExecution.qll | 2 +- .../semmle/code/cpp/security/FileWrite.qll | 2 +- .../semmle/code/cpp/security/OutputWrite.qll | 4 +- .../src/semmle/code/cpp/security/Security.qll | 14 +++-- .../code/cpp/security/TaintTracking.qll | 36 +++++------ 32 files changed, 138 insertions(+), 125 deletions(-) diff --git a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql index 9c93e066119c..47401c6eea57 100644 --- a/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql +++ b/cpp/ql/src/Critical/DescriptorMayNotBeClosed.ql @@ -13,7 +13,7 @@ import semmle.code.cpp.pointsto.PointsTo import Negativity predicate closeCall(FunctionCall fc, Variable v) { - fc.getTarget().hasGlobalName("close") and v.getAnAccess() = fc.getArgument(0) + fc.getTarget().hasGlobalOrStdName("close") and v.getAnAccess() = fc.getArgument(0) or exists(FunctionCall midcall, Function mid, int arg | fc.getArgument(arg) = v.getAnAccess() and diff --git a/cpp/ql/src/Critical/DescriptorNeverClosed.ql b/cpp/ql/src/Critical/DescriptorNeverClosed.ql index b52af1bf2a3d..f06708f4ae36 100644 --- a/cpp/ql/src/Critical/DescriptorNeverClosed.ql +++ b/cpp/ql/src/Critical/DescriptorNeverClosed.ql @@ -13,7 +13,7 @@ import semmle.code.cpp.pointsto.PointsTo predicate closed(Expr e) { exists(FunctionCall fc | - fc.getTarget().hasGlobalName("close") and + fc.getTarget().hasGlobalOrStdName("close") and fc.getArgument(0) = e ) } diff --git a/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql b/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql index 9bba8e9896d6..2bede6819126 100644 --- a/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql +++ b/cpp/ql/src/Critical/MemoryMayNotBeFreed.ql @@ -53,7 +53,7 @@ predicate allocCallOrIndirect(Expr e) { * can cause memory leaks. */ predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode verified) { - reallocCall.getTarget().hasGlobalName("realloc") and + reallocCall.getTarget().hasGlobalOrStdName("realloc") and reallocCall.getArgument(0) = v.getAnAccess() and ( exists(Variable newV, ControlFlowNode node | @@ -79,7 +79,7 @@ predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode predicate freeCallOrIndirect(ControlFlowNode n, Variable v) { // direct free call freeCall(n, v.getAnAccess()) and - not n.(FunctionCall).getTarget().hasGlobalName("realloc") + not n.(FunctionCall).getTarget().hasGlobalOrStdName("realloc") or // verified realloc call verifiedRealloc(_, v, n) diff --git a/cpp/ql/src/Critical/OverflowCalculated.ql b/cpp/ql/src/Critical/OverflowCalculated.ql index 36ee0140cf7e..c528be8ca242 100644 --- a/cpp/ql/src/Critical/OverflowCalculated.ql +++ b/cpp/ql/src/Critical/OverflowCalculated.ql @@ -14,8 +14,7 @@ import cpp class MallocCall extends FunctionCall { MallocCall() { - this.getTarget().hasGlobalName("malloc") or - this.getTarget().hasQualifiedName("std", "malloc") + this.getTarget().hasGlobalOrStdName("malloc") } Expr getAllocatedSize() { @@ -36,12 +35,12 @@ predicate spaceProblem(FunctionCall append, string msg) { malloc.getAllocatedSize() = add and buffer.getAnAccess() = strlen.getStringExpr() and ( - insert.getTarget().hasGlobalName("strcpy") or + insert.getTarget().hasGlobalOrStdName("strcpy") or insert.getTarget().hasGlobalName("strncpy") ) and ( - append.getTarget().hasGlobalName("strcat") or - append.getTarget().hasGlobalName("strncat") + append.getTarget().hasGlobalOrStdName("strcat") or + append.getTarget().hasGlobalOrStdName("strncat") ) and malloc.getASuccessor+() = insert and insert.getArgument(1) = buffer.getAnAccess() and diff --git a/cpp/ql/src/Critical/OverflowDestination.ql b/cpp/ql/src/Critical/OverflowDestination.ql index d7b02b5d8d58..ad925daed628 100644 --- a/cpp/ql/src/Critical/OverflowDestination.ql +++ b/cpp/ql/src/Critical/OverflowDestination.ql @@ -25,7 +25,7 @@ import semmle.code.cpp.security.TaintTracking predicate sourceSized(FunctionCall fc, Expr src) { exists(string name | (name = "strncpy" or name = "strncat" or name = "memcpy" or name = "memmove") and - fc.getTarget().hasGlobalName(name) + fc.getTarget().hasGlobalOrStdName(name) ) and exists(Expr dest, Expr size, Variable v | fc.getArgument(0) = dest and diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index 1892d5acff1f..8cee25007972 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -58,21 +58,21 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) { } predicate bufferAndSizeFunction(Function f, int buf, int size) { - f.hasGlobalName("read") and buf = 1 and size = 2 + f.hasGlobalOrStdName("read") and buf = 1 and size = 2 or - f.hasGlobalName("fgets") and buf = 0 and size = 1 + f.hasGlobalOrStdName("fgets") and buf = 0 and size = 1 or - f.hasGlobalName("strncpy") and buf = 0 and size = 2 + f.hasGlobalOrStdName("strncpy") and buf = 0 and size = 2 or - f.hasGlobalName("strncat") and buf = 0 and size = 2 + f.hasGlobalOrStdName("strncat") and buf = 0 and size = 2 or - f.hasGlobalName("memcpy") and buf = 0 and size = 2 + f.hasGlobalOrStdName("memcpy") and buf = 0 and size = 2 or - f.hasGlobalName("memmove") and buf = 0 and size = 2 + f.hasGlobalOrStdName("memmove") and buf = 0 and size = 2 or - f.hasGlobalName("snprintf") and buf = 0 and size = 1 + f.hasGlobalOrStdName("snprintf") and buf = 0 and size = 1 or - f.hasGlobalName("vsnprintf") and buf = 0 and size = 1 + f.hasGlobalOrStdName("vsnprintf") and buf = 0 and size = 1 } class CallWithBufferSize extends FunctionCall { diff --git a/cpp/ql/src/Critical/SizeCheck.ql b/cpp/ql/src/Critical/SizeCheck.ql index da841b73c9bc..313763ba56cc 100644 --- a/cpp/ql/src/Critical/SizeCheck.ql +++ b/cpp/ql/src/Critical/SizeCheck.ql @@ -17,12 +17,12 @@ import cpp class Allocation extends FunctionCall { Allocation() { exists(string name | - this.getTarget().hasGlobalName(name) and + this.getTarget().hasGlobalOrStdName(name) and (name = "malloc" or name = "calloc" or name = "realloc") ) } - private string getName() { this.getTarget().hasGlobalName(result) } + private string getName() { this.getTarget().hasGlobalOrStdName(result) } int getSize() { this.getName() = "malloc" and diff --git a/cpp/ql/src/Critical/SizeCheck2.ql b/cpp/ql/src/Critical/SizeCheck2.ql index 3cb5d1d28b00..1b716d79d49e 100644 --- a/cpp/ql/src/Critical/SizeCheck2.ql +++ b/cpp/ql/src/Critical/SizeCheck2.ql @@ -17,12 +17,12 @@ import cpp class Allocation extends FunctionCall { Allocation() { exists(string name | - this.getTarget().hasGlobalName(name) and + this.getTarget().hasGlobalOrStdName(name) and (name = "malloc" or name = "calloc" or name = "realloc") ) } - private string getName() { this.getTarget().hasGlobalName(result) } + private string getName() { this.getTarget().hasGlobalOrStdName(result) } int getSize() { this.getName() = "malloc" and diff --git a/cpp/ql/src/Critical/UseAfterFree.ql b/cpp/ql/src/Critical/UseAfterFree.ql index db78c206ea1a..9efbb6c3b447 100644 --- a/cpp/ql/src/Critical/UseAfterFree.ql +++ b/cpp/ql/src/Critical/UseAfterFree.ql @@ -16,7 +16,7 @@ import semmle.code.cpp.controlflow.LocalScopeVariableReachability predicate isFreeExpr(Expr e, LocalScopeVariable v) { exists(VariableAccess va | va.getTarget() = v | exists(FunctionCall fc | fc = e | - fc.getTarget().hasGlobalName("free") and + fc.getTarget().hasGlobalOrStdName("free") and va = fc.getArgument(0) ) or diff --git a/cpp/ql/src/DefaultOptions.qll b/cpp/ql/src/DefaultOptions.qll index 27e5584369e2..3e03ec9ee659 100644 --- a/cpp/ql/src/DefaultOptions.qll +++ b/cpp/ql/src/DefaultOptions.qll @@ -59,7 +59,7 @@ class Options extends string { predicate exits(Function f) { f.getAnAttribute().hasName("noreturn") or - exists(string name | f.hasGlobalName(name) | + exists(string name | f.hasGlobalOrStdName(name) | name = "exit" or name = "_exit" or name = "abort" or @@ -91,7 +91,7 @@ class Options extends string { * By default holds only for `fgets`. */ predicate alwaysCheckReturnValue(Function f) { - f.hasGlobalName("fgets") or + f.hasGlobalOrStdName("fgets") or CustomOptions::alwaysCheckReturnValue(f) // old Options.qll } diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 096b1468bb9a..fba0ddda4a13 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -34,8 +34,13 @@ class FileFunction extends FunctionWithWrappers { nme.matches("CreateFile%") ) or + exists(string nme | this.hasStdName(nme) | + nme = "fopen" or + nme = "open" + ) + or // on any of the fstream classes, or filebuf - exists(string nme | this.getDeclaringType().getSimpleName() = nme | + exists(string nme | this.getDeclaringType().hasStdName(nme) | nme = "basic_fstream" or nme = "basic_ifstream" or nme = "basic_ofstream" or diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql index 4469517c369b..8b7fb83df81d 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.ql @@ -17,8 +17,8 @@ import semmle.code.cpp.security.TaintTracking /** A call that prints its arguments to `stdout`. */ class PrintStdoutCall extends FunctionCall { PrintStdoutCall() { - getTarget().hasGlobalName("puts") or - getTarget().hasGlobalName("printf") + getTarget().hasGlobalOrStdName("puts") or + getTarget().hasGlobalOrStdName("printf") } } diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index 473f0f72f122..77225ad05776 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -66,7 +66,7 @@ class VarargsFunction extends Function { } predicate isWhitelisted() { - this.hasGlobalName("open") or + this.hasGlobalOrStdName("open") or this.hasGlobalName("fcntl") or this.hasGlobalName("ptrace") } diff --git a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql index 575752f0b74e..ff17daca05c3 100644 --- a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql +++ b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.ql @@ -19,10 +19,7 @@ import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.models.implementations.Memcpy class MallocCall extends FunctionCall { - MallocCall() { - this.getTarget().hasGlobalName("malloc") or - this.getTarget().hasQualifiedName("std", "malloc") - } + MallocCall() { this.getTarget().hasGlobalOrStdName("malloc") } Expr getAllocatedSize() { if this.getArgument(0) instanceof VariableAccess diff --git a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql index fa74c85555d7..63eca2922977 100644 --- a/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql +++ b/cpp/ql/src/Security/CWE/CWE-497/ExposedSystemData.ql @@ -190,11 +190,11 @@ private predicate windowsSystemInfo(FunctionCall source, Element use) { // void WINAPI GetSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); // void WINAPI GetNativeSystemInfo(_Out_ LPSYSTEM_INFO lpSystemInfo); ( - source.getTarget().hasName("GetVersionEx") or - source.getTarget().hasName("GetVersionExA") or - source.getTarget().hasName("GetVersionExW") or - source.getTarget().hasName("GetSystemInfo") or - source.getTarget().hasName("GetNativeSystemInfo") + source.getTarget().hasGlobalName("GetVersionEx") or + source.getTarget().hasGlobalName("GetVersionExA") or + source.getTarget().hasGlobalName("GetVersionExW") or + source.getTarget().hasGlobalName("GetSystemInfo") or + source.getTarget().hasGlobalName("GetNativeSystemInfo") ) and use = source.getArgument(0) } @@ -216,9 +216,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _In_ BOOL fCreate // ); ( - source.getTarget().hasName("SHGetSpecialFolderPath") or - source.getTarget().hasName("SHGetSpecialFolderPathA") or - source.getTarget().hasName("SHGetSpecialFolderPathW") + source.getTarget().hasGlobalName("SHGetSpecialFolderPath") or + source.getTarget().hasGlobalName("SHGetSpecialFolderPathA") or + source.getTarget().hasGlobalName("SHGetSpecialFolderPathW") ) and use = source.getArgument(1) or @@ -228,7 +228,7 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _In_opt_ HANDLE hToken, // _Out_ PWSTR *ppszPath // ); - source.getTarget().hasName("SHGetKnownFolderPath") and + source.getTarget().hasGlobalName("SHGetKnownFolderPath") and use = source.getArgument(3) or // HRESULT SHGetFolderPath( @@ -239,9 +239,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _Out_ LPTSTR pszPath // ); ( - source.getTarget().hasName("SHGetFolderPath") or - source.getTarget().hasName("SHGetFolderPathA") or - source.getTarget().hasName("SHGetFolderPathW") + source.getTarget().hasGlobalName("SHGetFolderPath") or + source.getTarget().hasGlobalName("SHGetFolderPathA") or + source.getTarget().hasGlobalName("SHGetFolderPathW") ) and use = source.getArgument(4) or @@ -254,9 +254,9 @@ private predicate windowsFolderPath(FunctionCall source, Element use) { // _Out_ LPTSTR pszPath // ); ( - source.getTarget().hasName("SHGetFolderPathAndSubDir") or - source.getTarget().hasName("SHGetFolderPathAndSubDirA") or - source.getTarget().hasName("SHGetFolderPathAndSubDirW") + source.getTarget().hasGlobalName("SHGetFolderPathAndSubDir") or + source.getTarget().hasGlobalName("SHGetFolderPathAndSubDirA") or + source.getTarget().hasGlobalName("SHGetFolderPathAndSubDirW") ) and use = source.getArgument(5) } @@ -273,9 +273,9 @@ class WindowsFolderPath extends SystemData { private predicate logonUser(FunctionCall source, VariableAccess use) { ( - source.getTarget().hasName("LogonUser") or - source.getTarget().hasName("LogonUserW") or - source.getTarget().hasName("LogonUserA") + source.getTarget().hasGlobalName("LogonUser") or + source.getTarget().hasGlobalName("LogonUserW") or + source.getTarget().hasGlobalName("LogonUserA") ) and use = source.getAnArgument() } @@ -297,9 +297,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Inout_opt_ PLONG lpcbValue // ); ( - source.getTarget().hasName("RegQueryValue") or - source.getTarget().hasName("RegQueryValueA") or - source.getTarget().hasName("RegQueryValueW") + source.getTarget().hasGlobalName("RegQueryValue") or + source.getTarget().hasGlobalName("RegQueryValueA") or + source.getTarget().hasGlobalName("RegQueryValueW") ) and use = source.getArgument(2) or @@ -311,9 +311,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Inout_opt_ LPDWORD ldwTotsize // ); ( - source.getTarget().hasName("RegQueryMultipleValues") or - source.getTarget().hasName("RegQueryMultipleValuesA") or - source.getTarget().hasName("RegQueryMultipleValuesW") + source.getTarget().hasGlobalName("RegQueryMultipleValues") or + source.getTarget().hasGlobalName("RegQueryMultipleValuesA") or + source.getTarget().hasGlobalName("RegQueryMultipleValuesW") ) and use = source.getArgument(3) or @@ -326,9 +326,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Inout_opt_ LPDWORD lpcbData // ); ( - source.getTarget().hasName("RegQueryValueEx") or - source.getTarget().hasName("RegQueryValueExA") or - source.getTarget().hasName("RegQueryValueExW") + source.getTarget().hasGlobalName("RegQueryValueEx") or + source.getTarget().hasGlobalName("RegQueryValueExA") or + source.getTarget().hasGlobalName("RegQueryValueExW") ) and use = source.getArgument(4) or @@ -342,9 +342,9 @@ private predicate regQuery(FunctionCall source, VariableAccess use) { // _Inout_opt_ LPDWORD pcbData // ); ( - source.getTarget().hasName("RegGetValue") or - source.getTarget().hasName("RegGetValueA") or - source.getTarget().hasName("RegGetValueW") + source.getTarget().hasGlobalName("RegGetValue") or + source.getTarget().hasGlobalName("RegGetValueA") or + source.getTarget().hasGlobalName("RegGetValueW") ) and use = source.getArgument(5) } diff --git a/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql b/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql index 84d7b48e265a..fe9b56bd5217 100644 --- a/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql +++ b/cpp/ql/src/Security/CWE/CWE-676/DangerousFunctionOverflow.ql @@ -15,5 +15,5 @@ import cpp from FunctionCall call, Function target where call.getTarget() = target and - target.hasGlobalName("gets") + target.hasGlobalOrStdName("gets") select call, "gets does not guard against buffer overflow" diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql index 4b1f45185d17..f2512b93003f 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 79.ql @@ -22,7 +22,7 @@ predicate acquireExpr(Expr acquire, string kind) { exists(FunctionCall fc, Function f, string name | fc = acquire and f = fc.getTarget() and - f.hasGlobalName(name) and + f.hasGlobalOrStdName(name) and ( name = "fopen" and kind = "file" @@ -46,7 +46,7 @@ predicate releaseExpr(Expr release, Expr resource, string kind) { exists(FunctionCall fc, Function f, string name | fc = release and f = fc.getTarget() and - f.hasGlobalName(name) and + f.hasGlobalOrStdName(name) and ( name = "fclose" and resource = fc.getArgument(0) and diff --git a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql index 501101f706c6..872a7443e6ea 100644 --- a/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql +++ b/cpp/ql/src/jsf/4.10 Classes/AV Rule 97.ql @@ -22,8 +22,8 @@ predicate containsArray(Type t) { or containsArray(t.getUnderlyingType()) and not exists(TypedefType allowed | allowed = t | - allowed.hasGlobalName("jmp_buf") or - allowed.hasGlobalName("va_list") + allowed.hasGlobalOrStdName("jmp_buf") or + allowed.hasGlobalOrStdName("va_list") ) } diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 94d11d63575c..8c86d6b12671 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -434,7 +434,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { // ... and likewise for destructors. this.(Destructor).getADestruction().mayBeGloballyImpure() else - not exists(string name | this.hasGlobalName(name) | + not exists(string name | this.hasGlobalOrStdName(name) | // Unless it's a function that we know is side-effect-free, it may // have side-effects. name = "strcmp" or diff --git a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll index e90aea377818..618afd624c47 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll @@ -5,13 +5,17 @@ import cpp */ predicate allocationFunction(Function f) { exists(string name | - f.hasGlobalName(name) and + f.hasGlobalOrStdName(name) and ( name = "malloc" or name = "calloc" or name = "realloc" or name = "strdup" or - name = "wcsdup" or + name = "wcsdup" + ) + or + f.hasGlobalName(name) and + ( name = "_strdup" or name = "_wcsdup" or name = "_mbsdup" or @@ -59,7 +63,7 @@ predicate allocationCall(FunctionCall fc) { allocationFunction(fc.getTarget()) and ( // realloc(ptr, 0) only frees the pointer - fc.getTarget().hasGlobalName("realloc") implies not fc.getArgument(1).getValue() = "0" + fc.getTarget().hasGlobalOrStdName("realloc") implies not fc.getArgument(1).getValue() = "0" ) } @@ -73,7 +77,10 @@ predicate freeFunction(Function f, int argNum) { name = "free" and argNum = 0 or name = "realloc" and argNum = 0 - or + ) + or + f.hasGlobalOrStdName(name) and + ( name = "ExFreePoolWithTag" and argNum = 0 or name = "ExFreeToLookasideListEx" and argNum = 1 @@ -188,3 +195,4 @@ predicate isDeallocationExpr(Expr e) { e instanceof DeleteExpr or e instanceof DeleteArrayExpr } + diff --git a/cpp/ql/src/semmle/code/cpp/commons/Environment.qll b/cpp/ql/src/semmle/code/cpp/commons/Environment.qll index e36244f4d5c7..f3f1759dd5c0 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Environment.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Environment.qll @@ -28,7 +28,7 @@ class EnvironmentRead extends Expr { private predicate readsEnvironment(Expr read, string sourceDescription) { exists(FunctionCall call, string name | read = call and - call.getTarget().hasGlobalName(name) and + call.getTarget().hasGlobalOrStdName(name) and (name = "getenv" or name = "secure_getenv" or name = "_wgetenv") and sourceDescription = name ) diff --git a/cpp/ql/src/semmle/code/cpp/commons/File.qll b/cpp/ql/src/semmle/code/cpp/commons/File.qll index 192918d25b34..05b4cfeaac49 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/File.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/File.qll @@ -5,8 +5,8 @@ import cpp */ predicate fopenCall(FunctionCall fc) { exists(Function f | f = fc.getTarget() | - f.hasGlobalName("fopen") or - f.hasGlobalName("open") or + f.hasGlobalOrStdName("fopen") or + f.hasGlobalOrStdName("open") or f.hasGlobalName("_open") or f.hasGlobalName("_wopen") or f.hasGlobalName("CreateFile") or @@ -23,16 +23,16 @@ predicate fopenCall(FunctionCall fc) { */ predicate fcloseCall(FunctionCall fc, Expr closed) { exists(Function f | f = fc.getTarget() | - f.hasGlobalName("fclose") and + f.hasGlobalOrStdName("fclose") and closed = fc.getArgument(0) or - f.hasGlobalName("close") and + f.hasGlobalOrStdName("close") and closed = fc.getArgument(0) or - f.hasGlobalName("_close") and + f.hasGlobalOrStdName("_close") and closed = fc.getArgument(0) or - f.hasGlobalName("CloseHandle") and + f.hasGlobalOrStdName("CloseHandle") and closed = fc.getArgument(0) ) } diff --git a/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll b/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll index e10e52df07d5..772bb42e3192 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/StringAnalysis.qll @@ -53,8 +53,8 @@ class AnalysedString extends Expr { */ class StrlenCall extends FunctionCall { StrlenCall() { - this.getTarget().hasGlobalName("strlen") or - this.getTarget().hasGlobalName("wcslen") or + this.getTarget().hasGlobalOrStdName("strlen") or + this.getTarget().hasGlobalOrStdName("wcslen") or this.getTarget().hasGlobalName("_mbslen") or this.getTarget().hasGlobalName("_mbslen_l") or this.getTarget().hasGlobalName("_mbstrlen") or diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll index cfd3efa91f33..69c5963af302 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Dereferenced.qll @@ -6,7 +6,7 @@ import Nullness */ predicate callDereferences(FunctionCall fc, int i) { exists(string name | - fc.getTarget().hasGlobalName(name) and + fc.getTarget().hasGlobalOrStdName(name) and ( name = "bcopy" and i in [0 .. 1] or diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll b/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll index 54b14aadd9de..caaa5b54e8c6 100644 --- a/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll +++ b/cpp/ql/src/semmle/code/cpp/controlflow/Nullness.qll @@ -264,9 +264,9 @@ predicate callMayReturnNull(Call call) { * Holds if `f` may, directly or indirectly, return a null literal. */ predicate mayReturnNull(Function f) { - f.hasGlobalName("malloc") + f.hasGlobalOrStdName("malloc") or - f.hasGlobalName("calloc") + f.hasGlobalOrStdName("calloc") or // f.hasGlobalName("strchr") // or diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll index 5654c1a9c997..58721897802f 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Printf.qll @@ -7,9 +7,9 @@ class Printf extends FormattingFunction { Printf() { this instanceof TopLevelFunction and ( - hasGlobalName("printf") or + hasGlobalOrStdName("printf") or hasGlobalName("printf_s") or - hasGlobalName("wprintf") or + hasGlobalOrStdName("wprintf") or hasGlobalName("wprintf_s") or hasGlobalName("g_printf") ) and @@ -19,7 +19,7 @@ class Printf extends FormattingFunction { override int getFormatParameterIndex() { result = 0 } override predicate isWideCharDefault() { - hasGlobalName("wprintf") or + hasGlobalOrStdName("wprintf") or hasGlobalName("wprintf_s") } } @@ -31,8 +31,8 @@ class Fprintf extends FormattingFunction { Fprintf() { this instanceof TopLevelFunction and ( - hasGlobalName("fprintf") or - hasGlobalName("fwprintf") or + hasGlobalOrStdName("fprintf") or + hasGlobalOrStdName("fwprintf") or hasGlobalName("g_fprintf") ) and not exists(getDefinition().getFile().getRelativePath()) @@ -40,7 +40,7 @@ class Fprintf extends FormattingFunction { override int getFormatParameterIndex() { result = 1 } - override predicate isWideCharDefault() { hasGlobalName("fwprintf") } + override predicate isWideCharDefault() { hasGlobalOrStdName("fwprintf") } override int getOutputParameterIndex() { result = 0 } } @@ -52,10 +52,10 @@ class Sprintf extends FormattingFunction { Sprintf() { this instanceof TopLevelFunction and ( - hasGlobalName("sprintf") or + hasGlobalOrStdName("sprintf") or hasGlobalName("_sprintf_l") or hasGlobalName("__swprintf_l") or - hasGlobalName("wsprintf") or + hasGlobalOrStdName("wsprintf") or hasGlobalName("g_strdup_printf") or hasGlobalName("g_sprintf") or hasGlobalName("__builtin___sprintf_chk") @@ -99,8 +99,8 @@ class Snprintf extends FormattingFunction { Snprintf() { this instanceof TopLevelFunction and ( - hasGlobalName("snprintf") or // C99 defines snprintf - hasGlobalName("swprintf") or // The s version of wide-char printf is also always the n version + hasGlobalOrStdName("snprintf") or // C99 defines snprintf + hasGlobalOrStdName("swprintf") or // The s version of wide-char printf is also always the n version // Microsoft has _snprintf as well as several other variations hasGlobalName("sprintf_s") or hasGlobalName("snprintf_s") or @@ -160,7 +160,7 @@ class Snprintf extends FormattingFunction { */ predicate returnsFullFormatLength() { ( - hasGlobalName("snprintf") or + hasGlobalOrStdName("snprintf") or hasGlobalName("g_snprintf") or hasGlobalName("__builtin___snprintf_chk") or hasGlobalName("snprintf_s") diff --git a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll index c5729c5d0f65..59b8c25700f9 100644 --- a/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll +++ b/cpp/ql/src/semmle/code/cpp/models/implementations/Pure.qll @@ -6,7 +6,7 @@ import semmle.code.cpp.models.interfaces.SideEffect class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideEffectFunction { PureStrFunction() { exists(string name | - hasGlobalName(name) and + hasGlobalOrStdName(name) and ( name = "atof" or name = "atoi" or @@ -75,7 +75,7 @@ class PureStrFunction extends AliasFunction, ArrayFunction, TaintFunction, SideE class PureFunction extends TaintFunction, SideEffectFunction { PureFunction() { exists(string name | - hasGlobalName(name) and + hasGlobalOrStdName(name) and ( name = "abs" or name = "labs" diff --git a/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll b/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll index 9988e20290c7..c7bea7eede7d 100644 --- a/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll +++ b/cpp/ql/src/semmle/code/cpp/security/CommandExecution.qll @@ -8,7 +8,7 @@ import semmle.code.cpp.security.FunctionWithWrappers */ class SystemFunction extends FunctionWithWrappers { SystemFunction() { - hasGlobalName("system") or + hasGlobalOrStdName("system") or hasGlobalName("popen") or // Windows variants hasGlobalName("_popen") or diff --git a/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll b/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll index 6363e3a5d143..219f3d0a75b7 100644 --- a/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/FileWrite.qll @@ -125,7 +125,7 @@ private predicate fileWrite(Call write, Expr source, Expr dest) { exists(Function f, int s, int d | f = write.getTarget() and source = write.getArgument(s) and dest = write.getArgument(d) | - exists(string name | f.hasGlobalName(name) | + exists(string name | f.hasGlobalOrStdName(name) | // named functions name = "fwrite" and s = 0 and d = 3 or diff --git a/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll b/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll index 751a7a71ec7a..06abfdb454da 100644 --- a/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll +++ b/cpp/ql/src/semmle/code/cpp/security/OutputWrite.qll @@ -63,8 +63,8 @@ private predicate outputWrite(Expr write, Expr source) { or // puts, putchar ( - f.hasGlobalName("puts") or - f.hasGlobalName("putchar") + f.hasGlobalOrStdName("puts") or + f.hasGlobalOrStdName("putchar") ) and arg = 0 or diff --git a/cpp/ql/src/semmle/code/cpp/security/Security.qll b/cpp/ql/src/semmle/code/cpp/security/Security.qll index 1a1c1d61ce82..c2b967071a69 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Security.qll @@ -70,7 +70,7 @@ class SecurityOptions extends string { */ predicate userInputArgument(FunctionCall functionCall, int arg) { exists(string fname | - functionCall.getTarget().hasGlobalName(fname) and + functionCall.getTarget().hasGlobalOrStdName(fname) and exists(functionCall.getArgument(arg)) and ( fname = "read" and arg = 1 @@ -83,6 +83,14 @@ class SecurityOptions extends string { or fname = "gets" and arg = 0 or + fname = "scanf" and arg >= 1 + or + fname = "fscanf" and arg >= 2 + ) + or + functionCall.getTarget().hasGlobalName(fname) and + exists(functionCall.getArgument(arg)) and + ( fname = "getaddrinfo" and arg = 3 or fname = "recv" and arg = 1 @@ -91,10 +99,6 @@ class SecurityOptions extends string { (arg = 1 or arg = 4 or arg = 5) or fname = "recvmsg" and arg = 1 - or - fname = "scanf" and arg >= 1 - or - fname = "fscanf" and arg >= 2 ) ) } diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll index 1ef0a6f7092d..b7bdd1416c7c 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll @@ -425,35 +425,35 @@ private int maxArgIndex(Function f) { /** Functions that copy the value of one argument to another */ private predicate copyValueBetweenArguments(Function f, int sourceArg, int destArg) { - f.hasGlobalName("memcpy") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("memcpy") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("__builtin___memcpy_chk") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("memmove") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("memmove") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("strcat") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("strcat") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("_mbscat") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("wcsncat") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("wcscat") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("strncat") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("strncat") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("_mbsncat") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("wcsncat") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("strcpy") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("strcpy") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("_mbscpy") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("wcscpy") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("wcscpy") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("strncpy") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("strncpy") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("_mbsncpy") and sourceArg = 1 and destArg = 0 or - f.hasGlobalName("wcsncpy") and sourceArg = 1 and destArg = 0 + f.hasGlobalOrStdName("wcsncpy") and sourceArg = 1 and destArg = 0 or f.hasGlobalName("inet_aton") and sourceArg = 0 and destArg = 1 or @@ -473,31 +473,31 @@ private predicate returnArgument(Function f, int sourceArg) { or f.hasGlobalName("__builtin___memcpy_chk") and sourceArg = 0 or - f.hasGlobalName("memmove") and sourceArg = 0 + f.hasGlobalOrStdName("memmove") and sourceArg = 0 or - f.hasGlobalName("strcat") and sourceArg = 0 + f.hasGlobalOrStdName("strcat") and sourceArg = 0 or f.hasGlobalName("_mbscat") and sourceArg = 0 or - f.hasGlobalName("wcsncat") and sourceArg = 0 + f.hasGlobalOrStdName("wcsncat") and sourceArg = 0 or - f.hasGlobalName("strncat") and sourceArg = 0 + f.hasGlobalOrStdName("strncat") and sourceArg = 0 or f.hasGlobalName("_mbsncat") and sourceArg = 0 or - f.hasGlobalName("wcsncat") and sourceArg = 0 + f.hasGlobalOrStdName("wcsncat") and sourceArg = 0 or - f.hasGlobalName("strcpy") and sourceArg = 0 + f.hasGlobalOrStdName("strcpy") and sourceArg = 0 or f.hasGlobalName("_mbscpy") and sourceArg = 0 or - f.hasGlobalName("wcscpy") and sourceArg = 0 + f.hasGlobalOrStdName("wcscpy") and sourceArg = 0 or - f.hasGlobalName("strncpy") and sourceArg = 0 + f.hasGlobalOrStdName("strncpy") and sourceArg = 0 or f.hasGlobalName("_mbsncpy") and sourceArg = 0 or - f.hasGlobalName("wcsncpy") and sourceArg = 0 + f.hasGlobalOrStdName("wcsncpy") and sourceArg = 0 or f.hasGlobalName("inet_ntoa") and sourceArg = 0 or From 68c38ba34af4d29b86379bb1aea1109230c7dc47 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 12 Jul 2019 10:34:15 -0700 Subject: [PATCH 0020/2538] C++: Add change note --- change-notes/1.23/analysis-cpp.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 5a97e1347bb3..f0f0889c2823 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -42,3 +42,5 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. clarity (e.g. `isOutReturnPointer()` to `isReturnValueDeref()`). The existing member predicates have been deprecated, and will be removed in a future release. Code that uses the old member predicates should be updated to use the corresponding new member predicate. +* The predicates `Declaration.hasStdName()` and `Declaration.hasGlobalOrStdName` + have been added, simplifying handling of C++ standard library functions. From 4018ed67a60168975d311560274b0225b51630ec Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 2 Oct 2019 11:21:10 -0700 Subject: [PATCH 0021/2538] C++: respond to PR comments --- cpp/ql/src/Critical/OverflowCalculated.ql | 2 +- cpp/ql/src/Critical/OverflowStatic.ql | 2 +- cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql | 5 +---- cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql | 2 +- cpp/ql/src/semmle/code/cpp/commons/File.qll | 4 ++-- cpp/ql/src/semmle/code/cpp/security/Security.qll | 4 ++-- cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll | 2 +- 7 files changed, 9 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Critical/OverflowCalculated.ql b/cpp/ql/src/Critical/OverflowCalculated.ql index c528be8ca242..0ad898decd5f 100644 --- a/cpp/ql/src/Critical/OverflowCalculated.ql +++ b/cpp/ql/src/Critical/OverflowCalculated.ql @@ -36,7 +36,7 @@ predicate spaceProblem(FunctionCall append, string msg) { buffer.getAnAccess() = strlen.getStringExpr() and ( insert.getTarget().hasGlobalOrStdName("strcpy") or - insert.getTarget().hasGlobalName("strncpy") + insert.getTarget().hasGlobalOrStdName("strncpy") ) and ( append.getTarget().hasGlobalOrStdName("strcat") or diff --git a/cpp/ql/src/Critical/OverflowStatic.ql b/cpp/ql/src/Critical/OverflowStatic.ql index 8cee25007972..82ffc879331e 100644 --- a/cpp/ql/src/Critical/OverflowStatic.ql +++ b/cpp/ql/src/Critical/OverflowStatic.ql @@ -58,7 +58,7 @@ predicate overflowOffsetInLoop(BufferAccess bufaccess, string msg) { } predicate bufferAndSizeFunction(Function f, int buf, int size) { - f.hasGlobalOrStdName("read") and buf = 1 and size = 2 + f.hasGlobalName("read") and buf = 1 and size = 2 or f.hasGlobalOrStdName("fgets") and buf = 0 and size = 1 or diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index fba0ddda4a13..5d02533124a0 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -34,10 +34,7 @@ class FileFunction extends FunctionWithWrappers { nme.matches("CreateFile%") ) or - exists(string nme | this.hasStdName(nme) | - nme = "fopen" or - nme = "open" - ) + this.hasStdName("fopen") or // on any of the fstream classes, or filebuf exists(string nme | this.getDeclaringType().hasStdName(nme) | diff --git a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql index 77225ad05776..473f0f72f122 100644 --- a/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql +++ b/cpp/ql/src/Security/CWE/CWE-121/UnterminatedVarargsCall.ql @@ -66,7 +66,7 @@ class VarargsFunction extends Function { } predicate isWhitelisted() { - this.hasGlobalOrStdName("open") or + this.hasGlobalName("open") or this.hasGlobalName("fcntl") or this.hasGlobalName("ptrace") } diff --git a/cpp/ql/src/semmle/code/cpp/commons/File.qll b/cpp/ql/src/semmle/code/cpp/commons/File.qll index 05b4cfeaac49..ea8f8b9dc654 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/File.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/File.qll @@ -26,10 +26,10 @@ predicate fcloseCall(FunctionCall fc, Expr closed) { f.hasGlobalOrStdName("fclose") and closed = fc.getArgument(0) or - f.hasGlobalOrStdName("close") and + f.hasGlobalName("close") and closed = fc.getArgument(0) or - f.hasGlobalOrStdName("_close") and + f.hasGlobalName("_close") and closed = fc.getArgument(0) or f.hasGlobalOrStdName("CloseHandle") and diff --git a/cpp/ql/src/semmle/code/cpp/security/Security.qll b/cpp/ql/src/semmle/code/cpp/security/Security.qll index c2b967071a69..c12a70b52c6a 100644 --- a/cpp/ql/src/semmle/code/cpp/security/Security.qll +++ b/cpp/ql/src/semmle/code/cpp/security/Security.qll @@ -73,8 +73,6 @@ class SecurityOptions extends string { functionCall.getTarget().hasGlobalOrStdName(fname) and exists(functionCall.getArgument(arg)) and ( - fname = "read" and arg = 1 - or fname = "fread" and arg = 0 or fname = "fgets" and arg = 0 @@ -91,6 +89,8 @@ class SecurityOptions extends string { functionCall.getTarget().hasGlobalName(fname) and exists(functionCall.getArgument(arg)) and ( + fname = "read" and arg = 1 + or fname = "getaddrinfo" and arg = 3 or fname = "recv" and arg = 1 diff --git a/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll b/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll index b7bdd1416c7c..31d8ad00f9cd 100644 --- a/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/security/TaintTracking.qll @@ -459,7 +459,7 @@ private predicate copyValueBetweenArguments(Function f, int sourceArg, int destA or f.hasGlobalName("inet_pton") and sourceArg = 1 and destArg = 2 or - f.hasGlobalName("strftime") and sourceArg in [2 .. maxArgIndex(f)] and destArg = 0 + f.hasGlobalOrStdName("strftime") and sourceArg in [2 .. maxArgIndex(f)] and destArg = 0 or exists(FormattingFunction ff | ff = f | sourceArg in [ff.getFormatParameterIndex() .. maxArgIndex(f)] and From 47b9c497fa0b0728ea9d4b3e1006dc2597d9af51 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 3 Oct 2019 12:25:41 -0700 Subject: [PATCH 0022/2538] C++: IR SSA tests for explicit constructor calls --- .../ir/ssa/aliased_ssa_ir.expected | 69 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 13 ++++ .../ir/ssa/unaliased_ssa_ir.expected | 64 +++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 9d005c57ca8f..adf2d6b40926 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -846,3 +846,72 @@ ssa.cpp: # 207| v0_24(void) = ReturnValue : &:r0_23, m0_22 # 207| v0_25(void) = UnmodeledUse : mu* # 207| v0_26(void) = ExitFunction : + +# 215| void Constructible::Constructible(int) +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| m0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 215| r0_3(glval) = InitializeThis : +# 215| r0_4(glval) = VariableAddress[x] : +# 215| m0_5(int) = InitializeParameter[x] : &:r0_4 +# 215| v0_6(void) = NoOp : +# 215| v0_7(void) = ReturnVoid : +# 215| v0_8(void) = UnmodeledUse : mu* +# 215| v0_9(void) = ExitFunction : + +# 216| void Constructible::g() +# 216| Block 0 +# 216| v0_0(void) = EnterFunction : +# 216| m0_1(unknown) = AliasedDefinition : +# 216| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = InitializeThis : +# 216| v0_4(void) = NoOp : +# 216| v0_5(void) = ReturnVoid : +# 216| v0_6(void) = UnmodeledUse : mu* +# 216| v0_7(void) = ExitFunction : + +# 219| void ExplicitConstructorCalls() +# 219| Block 0 +# 219| v0_0(void) = EnterFunction : +# 219| m0_1(unknown) = AliasedDefinition : +# 219| mu0_2(unknown) = UnmodeledDefinition : +# 220| r0_3(glval) = VariableAddress[c] : +# 220| r0_4(glval) = FunctionAddress[Constructible] : +# 220| r0_5(int) = Constant[1] : +# 220| v0_6(void) = Call : func:r0_4, this:r0_3, 0:r0_5 +# 220| m0_7(unknown) = ^CallSideEffect : ~m0_1 +# 220| m0_8(unknown) = Chi : total:m0_1, partial:m0_7 +# 220| m0_9(Constructible) = ^IndirectMayWriteSideEffect : &:r0_3 +# 221| r0_10(glval) = VariableAddress[c] : +# 221| r0_11(glval) = FunctionAddress[g] : +# 221| v0_12(void) = Call : func:r0_11, this:r0_10 +# 221| m0_13(unknown) = ^CallSideEffect : ~m0_8 +# 221| m0_14(unknown) = Chi : total:m0_8, partial:m0_13 +# 221| v0_15(void) = ^IndirectReadSideEffect[-1] : &:r0_10, m0_9 +# 221| m0_16(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +# 222| r0_17(glval) = VariableAddress[c] : +# 222| r0_18(glval) = FunctionAddress[g] : +# 222| v0_19(void) = Call : func:r0_18, this:r0_17 +# 222| m0_20(unknown) = ^CallSideEffect : ~m0_14 +# 222| m0_21(unknown) = Chi : total:m0_14, partial:m0_20 +# 222| v0_22(void) = ^IndirectReadSideEffect[-1] : &:r0_17, m0_16 +# 222| m0_23(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_17 +# 223| r0_24(glval) = VariableAddress[c2] : +# 223| r0_25(glval) = FunctionAddress[Constructible] : +# 223| r0_26(int) = Constant[2] : +# 223| v0_27(void) = Call : func:r0_25, this:r0_24, 0:r0_26 +# 223| m0_28(unknown) = ^CallSideEffect : ~m0_21 +# 223| m0_29(unknown) = Chi : total:m0_21, partial:m0_28 +# 223| m0_30(Constructible) = ^IndirectMayWriteSideEffect : &:r0_24 +# 224| r0_31(glval) = VariableAddress[c2] : +# 224| r0_32(glval) = FunctionAddress[g] : +# 224| v0_33(void) = Call : func:r0_32, this:r0_31 +# 224| m0_34(unknown) = ^CallSideEffect : ~m0_29 +# 224| m0_35(unknown) = Chi : total:m0_29, partial:m0_34 +# 224| v0_36(void) = ^IndirectReadSideEffect[-1] : &:r0_31, m0_30 +# 224| m0_37(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_31 +# 225| v0_38(void) = NoOp : +# 219| v0_39(void) = ReturnVoid : +# 219| v0_40(void) = UnmodeledUse : mu* +# 219| v0_41(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 4dfb0a2f6cdf..cd6df07e3a7f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -210,3 +210,16 @@ int ModeledCallTarget(int x) { return y; } +class Constructible { + public: + Constructible(int x) {}; + void g() {} +}; + +void ExplicitConstructorCalls() { + Constructible c(1); + c.g(); + c.g(); + Constructible c2 = Constructible(2); + c2.g(); +} diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index a68690c70559..63db25f8d807 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -806,3 +806,67 @@ ssa.cpp: # 207| v0_21(void) = ReturnValue : &:r0_20, m0_19 # 207| v0_22(void) = UnmodeledUse : mu* # 207| v0_23(void) = ExitFunction : + +# 215| void Constructible::Constructible(int) +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| mu0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 215| r0_3(glval) = InitializeThis : +# 215| r0_4(glval) = VariableAddress[x] : +# 215| m0_5(int) = InitializeParameter[x] : &:r0_4 +# 215| v0_6(void) = NoOp : +# 215| v0_7(void) = ReturnVoid : +# 215| v0_8(void) = UnmodeledUse : mu* +# 215| v0_9(void) = ExitFunction : + +# 216| void Constructible::g() +# 216| Block 0 +# 216| v0_0(void) = EnterFunction : +# 216| mu0_1(unknown) = AliasedDefinition : +# 216| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = InitializeThis : +# 216| v0_4(void) = NoOp : +# 216| v0_5(void) = ReturnVoid : +# 216| v0_6(void) = UnmodeledUse : mu* +# 216| v0_7(void) = ExitFunction : + +# 219| void ExplicitConstructorCalls() +# 219| Block 0 +# 219| v0_0(void) = EnterFunction : +# 219| mu0_1(unknown) = AliasedDefinition : +# 219| mu0_2(unknown) = UnmodeledDefinition : +# 220| r0_3(glval) = VariableAddress[c] : +# 220| r0_4(glval) = FunctionAddress[Constructible] : +# 220| r0_5(int) = Constant[1] : +# 220| v0_6(void) = Call : func:r0_4, this:r0_3, 0:r0_5 +# 220| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 220| m0_8(Constructible) = ^IndirectMayWriteSideEffect : &:r0_3 +# 221| r0_9(glval) = VariableAddress[c] : +# 221| r0_10(glval) = FunctionAddress[g] : +# 221| v0_11(void) = Call : func:r0_10, this:r0_9 +# 221| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 221| v0_13(void) = ^IndirectReadSideEffect[-1] : &:r0_9, m0_8 +# 221| m0_14(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +# 222| r0_15(glval) = VariableAddress[c] : +# 222| r0_16(glval) = FunctionAddress[g] : +# 222| v0_17(void) = Call : func:r0_16, this:r0_15 +# 222| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 222| v0_19(void) = ^IndirectReadSideEffect[-1] : &:r0_15, m0_14 +# 222| m0_20(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_15 +# 223| r0_21(glval) = VariableAddress[c2] : +# 223| r0_22(glval) = FunctionAddress[Constructible] : +# 223| r0_23(int) = Constant[2] : +# 223| v0_24(void) = Call : func:r0_22, this:r0_21, 0:r0_23 +# 223| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 +# 223| m0_26(Constructible) = ^IndirectMayWriteSideEffect : &:r0_21 +# 224| r0_27(glval) = VariableAddress[c2] : +# 224| r0_28(glval) = FunctionAddress[g] : +# 224| v0_29(void) = Call : func:r0_28, this:r0_27 +# 224| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 +# 224| v0_31(void) = ^IndirectReadSideEffect[-1] : &:r0_27, m0_26 +# 224| m0_32(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 +# 225| v0_33(void) = NoOp : +# 219| v0_34(void) = ReturnVoid : +# 219| v0_35(void) = UnmodeledUse : mu* +# 219| v0_36(void) = ExitFunction : From a76c4d9b3b0831f186d43ba341007c2be83afc69 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 3 Oct 2019 12:39:32 -0700 Subject: [PATCH 0023/2538] C++: index for constructor qualifier side effects --- .../cpp/ir/implementation/raw/internal/TranslatedCall.qll | 5 +++++ cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected | 4 ++-- cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected | 4 ++-- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 08f782db9fcd..64e6c1ca806b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -401,6 +401,11 @@ class TranslatedStructorCallSideEffects extends TranslatedSideEffects { operandTag instanceof AddressOperandTag and result = getParent().(TranslatedStructorCall).getQualifierResult() } + + final override int getInstructionIndex(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = -1 + } } class TranslatedSideEffect extends TranslatedElement, TTranslatedArgumentSideEffect { diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index adf2d6b40926..be58a43a4155 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -882,7 +882,7 @@ ssa.cpp: # 220| v0_6(void) = Call : func:r0_4, this:r0_3, 0:r0_5 # 220| m0_7(unknown) = ^CallSideEffect : ~m0_1 # 220| m0_8(unknown) = Chi : total:m0_1, partial:m0_7 -# 220| m0_9(Constructible) = ^IndirectMayWriteSideEffect : &:r0_3 +# 220| m0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 # 221| r0_10(glval) = VariableAddress[c] : # 221| r0_11(glval) = FunctionAddress[g] : # 221| v0_12(void) = Call : func:r0_11, this:r0_10 @@ -903,7 +903,7 @@ ssa.cpp: # 223| v0_27(void) = Call : func:r0_25, this:r0_24, 0:r0_26 # 223| m0_28(unknown) = ^CallSideEffect : ~m0_21 # 223| m0_29(unknown) = Chi : total:m0_21, partial:m0_28 -# 223| m0_30(Constructible) = ^IndirectMayWriteSideEffect : &:r0_24 +# 223| m0_30(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_24 # 224| r0_31(glval) = VariableAddress[c2] : # 224| r0_32(glval) = FunctionAddress[g] : # 224| v0_33(void) = Call : func:r0_32, this:r0_31 diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 63db25f8d807..6006ee380365 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -841,7 +841,7 @@ ssa.cpp: # 220| r0_5(int) = Constant[1] : # 220| v0_6(void) = Call : func:r0_4, this:r0_3, 0:r0_5 # 220| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 220| m0_8(Constructible) = ^IndirectMayWriteSideEffect : &:r0_3 +# 220| m0_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 # 221| r0_9(glval) = VariableAddress[c] : # 221| r0_10(glval) = FunctionAddress[g] : # 221| v0_11(void) = Call : func:r0_10, this:r0_9 @@ -859,7 +859,7 @@ ssa.cpp: # 223| r0_23(int) = Constant[2] : # 223| v0_24(void) = Call : func:r0_22, this:r0_21, 0:r0_23 # 223| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 223| m0_26(Constructible) = ^IndirectMayWriteSideEffect : &:r0_21 +# 223| m0_26(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_21 # 224| r0_27(glval) = VariableAddress[c2] : # 224| r0_28(glval) = FunctionAddress[g] : # 224| v0_29(void) = Call : func:r0_28, this:r0_27 From bc973973dfde5dd3940cb5caf0e3038626f488a3 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 3 Oct 2019 14:43:54 -0700 Subject: [PATCH 0024/2538] C++: accept test changes --- .../test/library-tests/ir/ir/raw_ir.expected | 554 +++++++++--------- 1 file changed, 277 insertions(+), 277 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index b4a798f6e736..933cd6bc2e3e 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2708,41 +2708,41 @@ ir.cpp: # 615| void DeclareObject() # 615| Block 0 -# 615| v0_0(void) = EnterFunction : -# 615| mu0_1(unknown) = AliasedDefinition : -# 615| mu0_2(unknown) = UnmodeledDefinition : -# 616| r0_3(glval) = VariableAddress[s1] : -# 616| r0_4(glval) = FunctionAddress[String] : -# 616| v0_5(void) = Call : func:r0_4, this:r0_3 -# 616| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 616| mu0_7(String) = ^IndirectMayWriteSideEffect : &:r0_3 -# 617| r0_8(glval) = VariableAddress[s2] : -# 617| r0_9(glval) = FunctionAddress[String] : -# 617| r0_10(glval) = StringConstant["hello"] : -# 617| r0_11(char *) = Convert : r0_10 -# 617| v0_12(void) = Call : func:r0_9, this:r0_8, 0:r0_11 -# 617| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 617| mu0_14(String) = ^IndirectMayWriteSideEffect : &:r0_8 -# 617| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 -# 617| mu0_16(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -# 618| r0_17(glval) = VariableAddress[s3] : -# 618| r0_18(glval) = FunctionAddress[ReturnObject] : -# 618| r0_19(String) = Call : func:r0_18 -# 618| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 -# 618| mu0_21(String) = Store : &:r0_17, r0_19 -# 619| r0_22(glval) = VariableAddress[s4] : -# 619| r0_23(glval) = FunctionAddress[String] : -# 619| r0_24(glval) = StringConstant["test"] : -# 619| r0_25(char *) = Convert : r0_24 -# 619| v0_26(void) = Call : func:r0_23, this:r0_22, 0:r0_25 -# 619| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 -# 619| mu0_28(String) = ^IndirectMayWriteSideEffect : &:r0_22 -# 619| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 -# 619| mu0_30(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 -# 620| v0_31(void) = NoOp : -# 615| v0_32(void) = ReturnVoid : -# 615| v0_33(void) = UnmodeledUse : mu* -# 615| v0_34(void) = ExitFunction : +# 615| v0_0(void) = EnterFunction : +# 615| mu0_1(unknown) = AliasedDefinition : +# 615| mu0_2(unknown) = UnmodeledDefinition : +# 616| r0_3(glval) = VariableAddress[s1] : +# 616| r0_4(glval) = FunctionAddress[String] : +# 616| v0_5(void) = Call : func:r0_4, this:r0_3 +# 616| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 +# 616| mu0_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 617| r0_8(glval) = VariableAddress[s2] : +# 617| r0_9(glval) = FunctionAddress[String] : +# 617| r0_10(glval) = StringConstant["hello"] : +# 617| r0_11(char *) = Convert : r0_10 +# 617| v0_12(void) = Call : func:r0_9, this:r0_8, 0:r0_11 +# 617| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 617| mu0_14(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 +# 617| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 +# 617| mu0_16(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 +# 618| r0_17(glval) = VariableAddress[s3] : +# 618| r0_18(glval) = FunctionAddress[ReturnObject] : +# 618| r0_19(String) = Call : func:r0_18 +# 618| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 +# 618| mu0_21(String) = Store : &:r0_17, r0_19 +# 619| r0_22(glval) = VariableAddress[s4] : +# 619| r0_23(glval) = FunctionAddress[String] : +# 619| r0_24(glval) = StringConstant["test"] : +# 619| r0_25(char *) = Convert : r0_24 +# 619| v0_26(void) = Call : func:r0_23, this:r0_22, 0:r0_25 +# 619| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 +# 619| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 +# 619| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 +# 619| mu0_30(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 +# 620| v0_31(void) = NoOp : +# 615| v0_32(void) = ReturnVoid : +# 615| v0_33(void) = UnmodeledUse : mu* +# 615| v0_34(void) = ExitFunction : # 622| void CallMethods(String&, String*, String) # 622| Block 0 @@ -2907,37 +2907,37 @@ ir.cpp: # 658| void C::C() # 658| Block 0 -# 658| v0_0(void) = EnterFunction : -# 658| mu0_1(unknown) = AliasedDefinition : -# 658| mu0_2(unknown) = UnmodeledDefinition : -# 658| r0_3(glval) = InitializeThis : -# 659| r0_4(glval) = FieldAddress[m_a] : r0_3 -# 659| r0_5(int) = Constant[1] : -# 659| mu0_6(int) = Store : &:r0_4, r0_5 -# 663| r0_7(glval) = FieldAddress[m_b] : r0_3 -# 663| r0_8(glval) = FunctionAddress[String] : -# 663| v0_9(void) = Call : func:r0_8, this:r0_7 -# 663| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 -# 663| mu0_11(String) = ^IndirectMayWriteSideEffect : &:r0_7 -# 660| r0_12(glval) = FieldAddress[m_c] : r0_3 -# 660| r0_13(char) = Constant[3] : -# 660| mu0_14(char) = Store : &:r0_12, r0_13 -# 661| r0_15(glval) = FieldAddress[m_e] : r0_3 -# 661| r0_16(void *) = Constant[0] : -# 661| mu0_17(void *) = Store : &:r0_15, r0_16 -# 662| r0_18(glval) = FieldAddress[m_f] : r0_3 -# 662| r0_19(glval) = FunctionAddress[String] : -# 662| r0_20(glval) = StringConstant["test"] : -# 662| r0_21(char *) = Convert : r0_20 -# 662| v0_22(void) = Call : func:r0_19, this:r0_18, 0:r0_21 -# 662| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 -# 662| mu0_24(String) = ^IndirectMayWriteSideEffect : &:r0_18 -# 662| v0_25(void) = ^IndirectReadSideEffect[0] : &:r0_21, ~mu0_2 -# 662| mu0_26(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_21 -# 664| v0_27(void) = NoOp : -# 658| v0_28(void) = ReturnVoid : -# 658| v0_29(void) = UnmodeledUse : mu* -# 658| v0_30(void) = ExitFunction : +# 658| v0_0(void) = EnterFunction : +# 658| mu0_1(unknown) = AliasedDefinition : +# 658| mu0_2(unknown) = UnmodeledDefinition : +# 658| r0_3(glval) = InitializeThis : +# 659| r0_4(glval) = FieldAddress[m_a] : r0_3 +# 659| r0_5(int) = Constant[1] : +# 659| mu0_6(int) = Store : &:r0_4, r0_5 +# 663| r0_7(glval) = FieldAddress[m_b] : r0_3 +# 663| r0_8(glval) = FunctionAddress[String] : +# 663| v0_9(void) = Call : func:r0_8, this:r0_7 +# 663| mu0_10(unknown) = ^CallSideEffect : ~mu0_2 +# 663| mu0_11(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 +# 660| r0_12(glval) = FieldAddress[m_c] : r0_3 +# 660| r0_13(char) = Constant[3] : +# 660| mu0_14(char) = Store : &:r0_12, r0_13 +# 661| r0_15(glval) = FieldAddress[m_e] : r0_3 +# 661| r0_16(void *) = Constant[0] : +# 661| mu0_17(void *) = Store : &:r0_15, r0_16 +# 662| r0_18(glval) = FieldAddress[m_f] : r0_3 +# 662| r0_19(glval) = FunctionAddress[String] : +# 662| r0_20(glval) = StringConstant["test"] : +# 662| r0_21(char *) = Convert : r0_20 +# 662| v0_22(void) = Call : func:r0_19, this:r0_18, 0:r0_21 +# 662| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 +# 662| mu0_24(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_18 +# 662| v0_25(void) = ^IndirectReadSideEffect[0] : &:r0_21, ~mu0_2 +# 662| mu0_26(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_21 +# 664| v0_27(void) = NoOp : +# 658| v0_28(void) = ReturnVoid : +# 658| v0_29(void) = UnmodeledUse : mu* +# 658| v0_30(void) = ExitFunction : # 675| int DerefReference(int&) # 675| Block 0 @@ -3206,7 +3206,7 @@ ir.cpp: # 731| r7_3(char *) = Convert : r7_2 # 731| v7_4(void) = Call : func:r7_1, this:r7_0, 0:r7_3 # 731| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 -# 731| mu7_6(String) = ^IndirectMayWriteSideEffect : &:r7_0 +# 731| mu7_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r7_0 # 731| v7_7(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 # 731| mu7_8(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 # 731| v7_9(void) = ThrowValue : &:r7_0, ~mu0_2 @@ -3224,18 +3224,18 @@ ir.cpp: #-----| Goto -> Block 10 # 735| Block 10 -# 735| r10_0(glval) = VariableAddress[s] : -# 735| mu10_1(char *) = InitializeParameter[s] : &:r10_0 -# 736| r10_2(glval) = VariableAddress[#throw736:5] : -# 736| r10_3(glval) = FunctionAddress[String] : -# 736| r10_4(glval) = VariableAddress[s] : -# 736| r10_5(char *) = Load : &:r10_4, ~mu0_2 -# 736| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 -# 736| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 736| mu10_8(String) = ^IndirectMayWriteSideEffect : &:r10_2 -# 736| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 -# 736| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 -# 736| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 +# 735| r10_0(glval) = VariableAddress[s] : +# 735| mu10_1(char *) = InitializeParameter[s] : &:r10_0 +# 736| r10_2(glval) = VariableAddress[#throw736:5] : +# 736| r10_3(glval) = FunctionAddress[String] : +# 736| r10_4(glval) = VariableAddress[s] : +# 736| r10_5(char *) = Load : &:r10_4, ~mu0_2 +# 736| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 +# 736| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 +# 736| mu10_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r10_2 +# 736| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 +# 736| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 +# 736| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 #-----| Exception -> Block 2 # 738| Block 11 @@ -3289,37 +3289,37 @@ ir.cpp: # 745| void Base::Base(Base const&) # 745| Block 0 -# 745| v0_0(void) = EnterFunction : -# 745| mu0_1(unknown) = AliasedDefinition : -# 745| mu0_2(unknown) = UnmodeledDefinition : -# 745| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 -# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 -# 745| r0_7(glval) = FunctionAddress[String] : -# 745| v0_8(void) = Call : func:r0_7, this:r0_6 -# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 745| mu0_10(String) = ^IndirectMayWriteSideEffect : &:r0_6 -# 745| v0_11(void) = NoOp : -# 745| v0_12(void) = ReturnVoid : -# 745| v0_13(void) = UnmodeledUse : mu* -# 745| v0_14(void) = ExitFunction : +# 745| v0_0(void) = EnterFunction : +# 745| mu0_1(unknown) = AliasedDefinition : +# 745| mu0_2(unknown) = UnmodeledDefinition : +# 745| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 +# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 +# 745| r0_7(glval) = FunctionAddress[String] : +# 745| v0_8(void) = Call : func:r0_7, this:r0_6 +# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 +# 745| mu0_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_6 +# 745| v0_11(void) = NoOp : +# 745| v0_12(void) = ReturnVoid : +# 745| v0_13(void) = UnmodeledUse : mu* +# 745| v0_14(void) = ExitFunction : # 748| void Base::Base() # 748| Block 0 -# 748| v0_0(void) = EnterFunction : -# 748| mu0_1(unknown) = AliasedDefinition : -# 748| mu0_2(unknown) = UnmodeledDefinition : -# 748| r0_3(glval) = InitializeThis : -# 748| r0_4(glval) = FieldAddress[base_s] : r0_3 -# 748| r0_5(glval) = FunctionAddress[String] : -# 748| v0_6(void) = Call : func:r0_5, this:r0_4 -# 748| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 748| mu0_8(String) = ^IndirectMayWriteSideEffect : &:r0_4 -# 749| v0_9(void) = NoOp : -# 748| v0_10(void) = ReturnVoid : -# 748| v0_11(void) = UnmodeledUse : mu* -# 748| v0_12(void) = ExitFunction : +# 748| v0_0(void) = EnterFunction : +# 748| mu0_1(unknown) = AliasedDefinition : +# 748| mu0_2(unknown) = UnmodeledDefinition : +# 748| r0_3(glval) = InitializeThis : +# 748| r0_4(glval) = FieldAddress[base_s] : r0_3 +# 748| r0_5(glval) = FunctionAddress[String] : +# 748| v0_6(void) = Call : func:r0_5, this:r0_4 +# 748| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 748| mu0_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 +# 749| v0_9(void) = NoOp : +# 748| v0_10(void) = ReturnVoid : +# 748| v0_11(void) = UnmodeledUse : mu* +# 748| v0_12(void) = ExitFunction : # 750| void Base::~Base() # 750| Block 0 @@ -3378,24 +3378,24 @@ ir.cpp: # 757| void Middle::Middle() # 757| Block 0 -# 757| v0_0(void) = EnterFunction : -# 757| mu0_1(unknown) = AliasedDefinition : -# 757| mu0_2(unknown) = UnmodeledDefinition : -# 757| r0_3(glval) = InitializeThis : -# 757| r0_4(glval) = ConvertToBase[Middle : Base] : r0_3 -# 757| r0_5(glval) = FunctionAddress[Base] : -# 757| v0_6(void) = Call : func:r0_5, this:r0_4 -# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 757| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 -# 757| r0_9(glval) = FieldAddress[middle_s] : r0_3 -# 757| r0_10(glval) = FunctionAddress[String] : -# 757| v0_11(void) = Call : func:r0_10, this:r0_9 -# 757| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 757| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 -# 758| v0_14(void) = NoOp : -# 757| v0_15(void) = ReturnVoid : -# 757| v0_16(void) = UnmodeledUse : mu* -# 757| v0_17(void) = ExitFunction : +# 757| v0_0(void) = EnterFunction : +# 757| mu0_1(unknown) = AliasedDefinition : +# 757| mu0_2(unknown) = UnmodeledDefinition : +# 757| r0_3(glval) = InitializeThis : +# 757| r0_4(glval) = ConvertToBase[Middle : Base] : r0_3 +# 757| r0_5(glval) = FunctionAddress[Base] : +# 757| v0_6(void) = Call : func:r0_5, this:r0_4 +# 757| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 757| mu0_8(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 +# 757| r0_9(glval) = FieldAddress[middle_s] : r0_3 +# 757| r0_10(glval) = FunctionAddress[String] : +# 757| v0_11(void) = Call : func:r0_10, this:r0_9 +# 757| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 757| mu0_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +# 758| v0_14(void) = NoOp : +# 757| v0_15(void) = ReturnVoid : +# 757| v0_16(void) = UnmodeledUse : mu* +# 757| v0_17(void) = ExitFunction : # 759| void Middle::~Middle() # 759| Block 0 @@ -3466,12 +3466,12 @@ ir.cpp: # 766| r0_5(glval) = FunctionAddress[Middle] : # 766| v0_6(void) = Call : func:r0_5, this:r0_4 # 766| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 766| mu0_8(Middle) = ^IndirectMayWriteSideEffect : &:r0_4 +# 766| mu0_8(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 # 766| r0_9(glval) = FieldAddress[derived_s] : r0_3 # 766| r0_10(glval) = FunctionAddress[String] : # 766| v0_11(void) = Call : func:r0_10, this:r0_9 # 766| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 766| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 +# 766| mu0_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 # 767| v0_14(void) = NoOp : # 766| v0_15(void) = ReturnVoid : # 766| v0_16(void) = UnmodeledUse : mu* @@ -3506,12 +3506,12 @@ ir.cpp: # 775| r0_5(glval) = FunctionAddress[Base] : # 775| v0_6(void) = Call : func:r0_5, this:r0_4 # 775| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 775| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 +# 775| mu0_8(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 # 775| r0_9(glval) = FieldAddress[middlevb1_s] : r0_3 # 775| r0_10(glval) = FunctionAddress[String] : # 775| v0_11(void) = Call : func:r0_10, this:r0_9 # 775| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 775| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 +# 775| mu0_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 # 776| v0_14(void) = NoOp : # 775| v0_15(void) = ReturnVoid : # 775| v0_16(void) = UnmodeledUse : mu* @@ -3546,12 +3546,12 @@ ir.cpp: # 784| r0_5(glval) = FunctionAddress[Base] : # 784| v0_6(void) = Call : func:r0_5, this:r0_4 # 784| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 784| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 +# 784| mu0_8(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 # 784| r0_9(glval) = FieldAddress[middlevb2_s] : r0_3 # 784| r0_10(glval) = FunctionAddress[String] : # 784| v0_11(void) = Call : func:r0_10, this:r0_9 # 784| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 784| mu0_13(String) = ^IndirectMayWriteSideEffect : &:r0_9 +# 784| mu0_13(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 # 785| v0_14(void) = NoOp : # 784| v0_15(void) = ReturnVoid : # 784| v0_16(void) = UnmodeledUse : mu* @@ -3586,22 +3586,22 @@ ir.cpp: # 793| r0_5(glval) = FunctionAddress[Base] : # 793| v0_6(void) = Call : func:r0_5, this:r0_4 # 793| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_8(Base) = ^IndirectMayWriteSideEffect : &:r0_4 +# 793| mu0_8(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 # 793| r0_9(glval) = ConvertToBase[DerivedVB : MiddleVB1] : r0_3 # 793| r0_10(glval) = FunctionAddress[MiddleVB1] : # 793| v0_11(void) = Call : func:r0_10, this:r0_9 # 793| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_13(MiddleVB1) = ^IndirectMayWriteSideEffect : &:r0_9 +# 793| mu0_13(MiddleVB1) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 # 793| r0_14(glval) = ConvertToBase[DerivedVB : MiddleVB2] : r0_3 # 793| r0_15(glval) = FunctionAddress[MiddleVB2] : # 793| v0_16(void) = Call : func:r0_15, this:r0_14 # 793| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_18(MiddleVB2) = ^IndirectMayWriteSideEffect : &:r0_14 +# 793| mu0_18(MiddleVB2) = ^IndirectMayWriteSideEffect[-1] : &:r0_14 # 793| r0_19(glval) = FieldAddress[derivedvb_s] : r0_3 # 793| r0_20(glval) = FunctionAddress[String] : # 793| v0_21(void) = Call : func:r0_20, this:r0_19 # 793| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 -# 793| mu0_23(String) = ^IndirectMayWriteSideEffect : &:r0_19 +# 793| mu0_23(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 # 794| v0_24(void) = NoOp : # 793| v0_25(void) = ReturnVoid : # 793| v0_26(void) = UnmodeledUse : mu* @@ -3643,17 +3643,17 @@ ir.cpp: # 800| r0_4(glval) = FunctionAddress[Base] : # 800| v0_5(void) = Call : func:r0_4, this:r0_3 # 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 800| mu0_7(Base) = ^IndirectMayWriteSideEffect : &:r0_3 +# 800| mu0_7(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 # 801| r0_8(glval) = VariableAddress[m] : # 801| r0_9(glval) = FunctionAddress[Middle] : # 801| v0_10(void) = Call : func:r0_9, this:r0_8 # 801| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 801| mu0_12(Middle) = ^IndirectMayWriteSideEffect : &:r0_8 +# 801| mu0_12(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 # 802| r0_13(glval) = VariableAddress[d] : # 802| r0_14(glval) = FunctionAddress[Derived] : # 802| v0_15(void) = Call : func:r0_14, this:r0_13 # 802| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 -# 802| mu0_17(Derived) = ^IndirectMayWriteSideEffect : &:r0_13 +# 802| mu0_17(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_13 # 804| r0_18(glval) = VariableAddress[pb] : # 804| r0_19(glval) = VariableAddress[b] : # 804| mu0_20(Base *) = Store : &:r0_18, r0_19 @@ -3680,7 +3680,7 @@ ir.cpp: # 809| r0_41(glval) = ConvertToBase[Middle : Base] : r0_40 # 809| v0_42(void) = Call : func:r0_39, 0:r0_41 # 809| mu0_43(unknown) = ^CallSideEffect : ~mu0_2 -# 809| mu0_44(Base) = ^IndirectMayWriteSideEffect : +# 809| mu0_44(Base) = ^IndirectMayWriteSideEffect[-1] : # 809| v0_45(void) = ^IndirectReadSideEffect[0] : &:r0_41, ~mu0_2 # 809| mu0_46(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_41 # 809| r0_47(glval) = Convert : v0_42 @@ -3697,7 +3697,7 @@ ir.cpp: # 810| r0_58(glval) = ConvertToBase[Middle : Base] : r0_57 # 810| v0_59(void) = Call : func:r0_56, 0:r0_58 # 810| mu0_60(unknown) = ^CallSideEffect : ~mu0_2 -# 810| mu0_61(Base) = ^IndirectMayWriteSideEffect : +# 810| mu0_61(Base) = ^IndirectMayWriteSideEffect[-1] : # 810| v0_62(void) = ^IndirectReadSideEffect[0] : &:r0_58, ~mu0_2 # 810| mu0_63(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_58 # 810| r0_64(glval) = Convert : v0_59 @@ -3783,7 +3783,7 @@ ir.cpp: # 823| r0_144(glval) = ConvertToBase[Middle : Base] : r0_143 # 823| v0_145(void) = Call : func:r0_141, 0:r0_144 # 823| mu0_146(unknown) = ^CallSideEffect : ~mu0_2 -# 823| mu0_147(Base) = ^IndirectMayWriteSideEffect : +# 823| mu0_147(Base) = ^IndirectMayWriteSideEffect[-1] : # 823| v0_148(void) = ^IndirectReadSideEffect[0] : &:r0_144, ~mu0_2 # 823| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_144 # 823| r0_150(glval) = Convert : v0_145 @@ -3801,7 +3801,7 @@ ir.cpp: # 824| r0_162(glval) = ConvertToBase[Middle : Base] : r0_161 # 824| v0_163(void) = Call : func:r0_159, 0:r0_162 # 824| mu0_164(unknown) = ^CallSideEffect : ~mu0_2 -# 824| mu0_165(Base) = ^IndirectMayWriteSideEffect : +# 824| mu0_165(Base) = ^IndirectMayWriteSideEffect[-1] : # 824| v0_166(void) = ^IndirectReadSideEffect[0] : &:r0_162, ~mu0_2 # 824| mu0_167(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_162 # 824| r0_168(glval) = Convert : v0_163 @@ -3917,7 +3917,7 @@ ir.cpp: # 846| r0_5(glval) = FunctionAddress[PolymorphicBase] : # 846| v0_6(void) = Call : func:r0_5, this:r0_4 # 846| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 846| mu0_8(PolymorphicBase) = ^IndirectMayWriteSideEffect : &:r0_4 +# 846| mu0_8(PolymorphicBase) = ^IndirectMayWriteSideEffect[-1] : &:r0_4 # 846| v0_9(void) = NoOp : # 846| v0_10(void) = ReturnVoid : # 846| v0_11(void) = UnmodeledUse : mu* @@ -3947,12 +3947,12 @@ ir.cpp: #-----| r0_4(glval) = FunctionAddress[PolymorphicBase] : #-----| v0_5(void) = Call : func:r0_4, this:r0_3 #-----| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_7(PolymorphicBase) = ^IndirectMayWriteSideEffect : &:r0_3 +#-----| mu0_7(PolymorphicBase) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 # 851| r0_8(glval) = VariableAddress[d] : # 851| r0_9(glval) = FunctionAddress[PolymorphicDerived] : # 851| v0_10(void) = Call : func:r0_9, this:r0_8 # 851| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 851| mu0_12(PolymorphicDerived) = ^IndirectMayWriteSideEffect : &:r0_8 +# 851| mu0_12(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 # 853| r0_13(glval) = VariableAddress[pb] : # 853| r0_14(glval) = VariableAddress[b] : # 853| mu0_15(PolymorphicBase *) = Store : &:r0_13, r0_14 @@ -3994,22 +3994,22 @@ ir.cpp: # 867| void String::String() # 867| Block 0 -# 867| v0_0(void) = EnterFunction : -# 867| mu0_1(unknown) = AliasedDefinition : -# 867| mu0_2(unknown) = UnmodeledDefinition : -# 867| r0_3(glval) = InitializeThis : -# 868| r0_4(glval) = FunctionAddress[String] : -# 868| r0_5(glval) = StringConstant[""] : -# 868| r0_6(char *) = Convert : r0_5 -# 868| v0_7(void) = Call : func:r0_4, this:r0_3, 0:r0_6 -# 868| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 868| mu0_9(String) = ^IndirectMayWriteSideEffect : &:r0_3 -# 868| v0_10(void) = ^IndirectReadSideEffect[0] : &:r0_6, ~mu0_2 -# 868| mu0_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_6 -# 869| v0_12(void) = NoOp : -# 867| v0_13(void) = ReturnVoid : -# 867| v0_14(void) = UnmodeledUse : mu* -# 867| v0_15(void) = ExitFunction : +# 867| v0_0(void) = EnterFunction : +# 867| mu0_1(unknown) = AliasedDefinition : +# 867| mu0_2(unknown) = UnmodeledDefinition : +# 867| r0_3(glval) = InitializeThis : +# 868| r0_4(glval) = FunctionAddress[String] : +# 868| r0_5(glval) = StringConstant[""] : +# 868| r0_6(char *) = Convert : r0_5 +# 868| v0_7(void) = Call : func:r0_4, this:r0_3, 0:r0_6 +# 868| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 868| mu0_9(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 868| v0_10(void) = ^IndirectReadSideEffect[0] : &:r0_6, ~mu0_2 +# 868| mu0_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_6 +# 869| v0_12(void) = NoOp : +# 867| v0_13(void) = ReturnVoid : +# 867| v0_14(void) = UnmodeledUse : mu* +# 867| v0_15(void) = ExitFunction : # 871| void ArrayConversions() # 871| Block 0 @@ -4181,69 +4181,69 @@ ir.cpp: # 940| void OperatorNew() # 940| Block 0 -# 940| v0_0(void) = EnterFunction : -# 940| mu0_1(unknown) = AliasedDefinition : -# 940| mu0_2(unknown) = UnmodeledDefinition : -# 941| r0_3(glval) = FunctionAddress[operator new] : -# 941| r0_4(unsigned long) = Constant[4] : -# 941| r0_5(void *) = Call : func:r0_3, 0:r0_4 -# 941| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 941| r0_7(int *) = Convert : r0_5 -# 942| r0_8(glval) = FunctionAddress[operator new] : -# 942| r0_9(unsigned long) = Constant[4] : -# 942| r0_10(float) = Constant[1.0] : -# 942| r0_11(void *) = Call : func:r0_8, 0:r0_9, 1:r0_10 -# 942| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 942| r0_13(int *) = Convert : r0_11 -# 943| r0_14(glval) = FunctionAddress[operator new] : -# 943| r0_15(unsigned long) = Constant[4] : -# 943| r0_16(void *) = Call : func:r0_14, 0:r0_15 -# 943| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 943| r0_18(int *) = Convert : r0_16 -# 943| r0_19(int) = Constant[0] : -# 943| mu0_20(int) = Store : &:r0_18, r0_19 -# 944| r0_21(glval) = FunctionAddress[operator new] : -# 944| r0_22(unsigned long) = Constant[8] : -# 944| r0_23(void *) = Call : func:r0_21, 0:r0_22 -# 944| mu0_24(unknown) = ^CallSideEffect : ~mu0_2 -# 944| r0_25(String *) = Convert : r0_23 -# 944| r0_26(glval) = FunctionAddress[String] : -# 944| v0_27(void) = Call : func:r0_26, this:r0_25 -# 944| mu0_28(unknown) = ^CallSideEffect : ~mu0_2 -# 944| mu0_29(String) = ^IndirectMayWriteSideEffect : &:r0_25 -# 945| r0_30(glval) = FunctionAddress[operator new] : -# 945| r0_31(unsigned long) = Constant[8] : -# 945| r0_32(float) = Constant[1.0] : -# 945| r0_33(void *) = Call : func:r0_30, 0:r0_31, 1:r0_32 -# 945| mu0_34(unknown) = ^CallSideEffect : ~mu0_2 -# 945| r0_35(String *) = Convert : r0_33 -# 945| r0_36(glval) = FunctionAddress[String] : -# 945| r0_37(glval) = StringConstant["hello"] : -# 945| r0_38(char *) = Convert : r0_37 -# 945| v0_39(void) = Call : func:r0_36, this:r0_35, 0:r0_38 -# 945| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 945| mu0_41(String) = ^IndirectMayWriteSideEffect : &:r0_35 -# 945| v0_42(void) = ^IndirectReadSideEffect[0] : &:r0_38, ~mu0_2 -# 945| mu0_43(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_38 -# 946| r0_44(glval) = FunctionAddress[operator new] : -# 946| r0_45(unsigned long) = Constant[256] : -# 946| r0_46(align_val_t) = Constant[128] : -# 946| r0_47(void *) = Call : func:r0_44, 0:r0_45, 1:r0_46 -# 946| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 -# 946| r0_49(Overaligned *) = Convert : r0_47 -# 947| r0_50(glval) = FunctionAddress[operator new] : -# 947| r0_51(unsigned long) = Constant[256] : -# 947| r0_52(align_val_t) = Constant[128] : -# 947| r0_53(float) = Constant[1.0] : -# 947| r0_54(void *) = Call : func:r0_50, 0:r0_51, 1:r0_52, 2:r0_53 -# 947| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 -# 947| r0_56(Overaligned *) = Convert : r0_54 -# 947| r0_57(Overaligned) = Constant[0] : -# 947| mu0_58(Overaligned) = Store : &:r0_56, r0_57 -# 948| v0_59(void) = NoOp : -# 940| v0_60(void) = ReturnVoid : -# 940| v0_61(void) = UnmodeledUse : mu* -# 940| v0_62(void) = ExitFunction : +# 940| v0_0(void) = EnterFunction : +# 940| mu0_1(unknown) = AliasedDefinition : +# 940| mu0_2(unknown) = UnmodeledDefinition : +# 941| r0_3(glval) = FunctionAddress[operator new] : +# 941| r0_4(unsigned long) = Constant[4] : +# 941| r0_5(void *) = Call : func:r0_3, 0:r0_4 +# 941| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 +# 941| r0_7(int *) = Convert : r0_5 +# 942| r0_8(glval) = FunctionAddress[operator new] : +# 942| r0_9(unsigned long) = Constant[4] : +# 942| r0_10(float) = Constant[1.0] : +# 942| r0_11(void *) = Call : func:r0_8, 0:r0_9, 1:r0_10 +# 942| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 +# 942| r0_13(int *) = Convert : r0_11 +# 943| r0_14(glval) = FunctionAddress[operator new] : +# 943| r0_15(unsigned long) = Constant[4] : +# 943| r0_16(void *) = Call : func:r0_14, 0:r0_15 +# 943| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 +# 943| r0_18(int *) = Convert : r0_16 +# 943| r0_19(int) = Constant[0] : +# 943| mu0_20(int) = Store : &:r0_18, r0_19 +# 944| r0_21(glval) = FunctionAddress[operator new] : +# 944| r0_22(unsigned long) = Constant[8] : +# 944| r0_23(void *) = Call : func:r0_21, 0:r0_22 +# 944| mu0_24(unknown) = ^CallSideEffect : ~mu0_2 +# 944| r0_25(String *) = Convert : r0_23 +# 944| r0_26(glval) = FunctionAddress[String] : +# 944| v0_27(void) = Call : func:r0_26, this:r0_25 +# 944| mu0_28(unknown) = ^CallSideEffect : ~mu0_2 +# 944| mu0_29(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +# 945| r0_30(glval) = FunctionAddress[operator new] : +# 945| r0_31(unsigned long) = Constant[8] : +# 945| r0_32(float) = Constant[1.0] : +# 945| r0_33(void *) = Call : func:r0_30, 0:r0_31, 1:r0_32 +# 945| mu0_34(unknown) = ^CallSideEffect : ~mu0_2 +# 945| r0_35(String *) = Convert : r0_33 +# 945| r0_36(glval) = FunctionAddress[String] : +# 945| r0_37(glval) = StringConstant["hello"] : +# 945| r0_38(char *) = Convert : r0_37 +# 945| v0_39(void) = Call : func:r0_36, this:r0_35, 0:r0_38 +# 945| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 +# 945| mu0_41(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_35 +# 945| v0_42(void) = ^IndirectReadSideEffect[0] : &:r0_38, ~mu0_2 +# 945| mu0_43(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_38 +# 946| r0_44(glval) = FunctionAddress[operator new] : +# 946| r0_45(unsigned long) = Constant[256] : +# 946| r0_46(align_val_t) = Constant[128] : +# 946| r0_47(void *) = Call : func:r0_44, 0:r0_45, 1:r0_46 +# 946| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 +# 946| r0_49(Overaligned *) = Convert : r0_47 +# 947| r0_50(glval) = FunctionAddress[operator new] : +# 947| r0_51(unsigned long) = Constant[256] : +# 947| r0_52(align_val_t) = Constant[128] : +# 947| r0_53(float) = Constant[1.0] : +# 947| r0_54(void *) = Call : func:r0_50, 0:r0_51, 1:r0_52, 2:r0_53 +# 947| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 +# 947| r0_56(Overaligned *) = Convert : r0_54 +# 947| r0_57(Overaligned) = Constant[0] : +# 947| mu0_58(Overaligned) = Store : &:r0_56, r0_57 +# 948| v0_59(void) = NoOp : +# 940| v0_60(void) = ReturnVoid : +# 940| v0_61(void) = UnmodeledUse : mu* +# 940| v0_62(void) = ExitFunction : # 950| void OperatorNewArray(int) # 950| Block 0 @@ -4721,7 +4721,7 @@ ir.cpp: #-----| r0_38(glval) = FunctionAddress[String] : #-----| v0_39(void) = Call : func:r0_38, this:r0_37 #-----| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_41(String) = ^IndirectMayWriteSideEffect : &:r0_37 +#-----| mu0_41(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_37 # 1036| r0_42(glval) = FieldAddress[x] : r0_35 #-----| r0_43(glval) = VariableAddress[x] : #-----| r0_44(int) = Load : &:r0_43, ~mu0_2 @@ -4729,7 +4729,7 @@ ir.cpp: # 1036| r0_46(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 # 1036| v0_47(void) = Call : func:r0_34, this:r0_33, 0:r0_46 # 1036| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| mu0_49(decltype([...](...){...})) = ^IndirectMayWriteSideEffect : &:r0_33 +# 1036| mu0_49(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_33 # 1036| v0_50(void) = ^IndirectReadSideEffect[0] : &:r0_46, ~mu0_2 # 1036| mu0_51(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_46 # 1037| r0_52(glval) = VariableAddress[lambda_val] : @@ -4765,11 +4765,11 @@ ir.cpp: #-----| r0_82(glval) = FunctionAddress[String] : #-----| v0_83(void) = Call : func:r0_82, this:r0_81 #-----| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_85(String) = ^IndirectMayWriteSideEffect : &:r0_81 +#-----| mu0_85(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_81 # 1040| r0_86(decltype([...](...){...})) = Load : &:r0_79, ~mu0_2 # 1040| v0_87(void) = Call : func:r0_78, this:r0_77, 0:r0_86 # 1040| mu0_88(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| mu0_89(decltype([...](...){...})) = ^IndirectMayWriteSideEffect : &:r0_77 +# 1040| mu0_89(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_77 # 1040| v0_90(void) = ^IndirectReadSideEffect[0] : &:r0_86, ~mu0_2 # 1040| mu0_91(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_86 # 1041| r0_92(glval) = VariableAddress[lambda_val_explicit] : @@ -4984,21 +4984,21 @@ ir.cpp: # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) # 1040| Block 0 -# 1040| v0_0(void) = EnterFunction : -# 1040| mu0_1(unknown) = AliasedDefinition : -# 1040| mu0_2(unknown) = UnmodeledDefinition : -# 1040| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 -# 1040| r0_6(glval) = FieldAddress[s] : r0_3 -# 1040| r0_7(glval) = FunctionAddress[String] : -# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 -# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| mu0_10(String) = ^IndirectMayWriteSideEffect : &:r0_6 -# 1040| v0_11(void) = NoOp : -# 1040| v0_12(void) = ReturnVoid : -# 1040| v0_13(void) = UnmodeledUse : mu* -# 1040| v0_14(void) = ExitFunction : +# 1040| v0_0(void) = EnterFunction : +# 1040| mu0_1(unknown) = AliasedDefinition : +# 1040| mu0_2(unknown) = UnmodeledDefinition : +# 1040| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 +# 1040| r0_6(glval) = FieldAddress[s] : r0_3 +# 1040| r0_7(glval) = FunctionAddress[String] : +# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 +# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| mu0_10(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_6 +# 1040| v0_11(void) = NoOp : +# 1040| v0_12(void) = ReturnVoid : +# 1040| v0_13(void) = UnmodeledUse : mu* +# 1040| v0_14(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~() # 1040| Block 0 @@ -5417,7 +5417,7 @@ ir.cpp: # 1140| r7_3(char *) = Convert : r7_2 # 1140| v7_4(void) = Call : func:r7_1, this:r7_0, 0:r7_3 # 1140| mu7_5(unknown) = ^CallSideEffect : ~mu0_2 -# 1140| mu7_6(String) = ^IndirectMayWriteSideEffect : &:r7_0 +# 1140| mu7_6(String) = ^IndirectMayWriteSideEffect[-1] : &:r7_0 # 1140| v7_7(void) = ^IndirectReadSideEffect[0] : &:r7_3, ~mu0_2 # 1140| mu7_8(unknown) = ^BufferMayWriteSideEffect[0] : &:r7_3 # 1140| v7_9(void) = ThrowValue : &:r7_0, ~mu0_2 @@ -5435,18 +5435,18 @@ ir.cpp: #-----| Goto -> Block 10 # 1144| Block 10 -# 1144| r10_0(glval) = VariableAddress[s] : -# 1144| mu10_1(char *) = InitializeParameter[s] : &:r10_0 -# 1145| r10_2(glval) = VariableAddress[#throw1145:5] : -# 1145| r10_3(glval) = FunctionAddress[String] : -# 1145| r10_4(glval) = VariableAddress[s] : -# 1145| r10_5(char *) = Load : &:r10_4, ~mu0_2 -# 1145| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 -# 1145| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 1145| mu10_8(String) = ^IndirectMayWriteSideEffect : &:r10_2 -# 1145| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 -# 1145| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 -# 1145| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 +# 1144| r10_0(glval) = VariableAddress[s] : +# 1144| mu10_1(char *) = InitializeParameter[s] : &:r10_0 +# 1145| r10_2(glval) = VariableAddress[#throw1145:5] : +# 1145| r10_3(glval) = FunctionAddress[String] : +# 1145| r10_4(glval) = VariableAddress[s] : +# 1145| r10_5(char *) = Load : &:r10_4, ~mu0_2 +# 1145| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 +# 1145| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 +# 1145| mu10_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r10_2 +# 1145| v10_9(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 +# 1145| mu10_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 +# 1145| v10_11(void) = ThrowValue : &:r10_2, ~mu0_2 #-----| Exception -> Block 2 # 1147| Block 11 @@ -5573,24 +5573,24 @@ perf-regression.cpp: # 9| int main() # 9| Block 0 -# 9| v0_0(void) = EnterFunction : -# 9| mu0_1(unknown) = AliasedDefinition : -# 9| mu0_2(unknown) = UnmodeledDefinition : -# 10| r0_3(glval) = VariableAddress[big] : -# 10| r0_4(glval) = FunctionAddress[operator new] : -# 10| r0_5(unsigned long) = Constant[1073741824] : -# 10| r0_6(void *) = Call : func:r0_4, 0:r0_5 -# 10| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 10| r0_8(Big *) = Convert : r0_6 -# 10| r0_9(glval) = FunctionAddress[Big] : -# 10| v0_10(void) = Call : func:r0_9, this:r0_8 -# 10| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 10| mu0_12(Big) = ^IndirectMayWriteSideEffect : &:r0_8 -# 10| mu0_13(Big *) = Store : &:r0_3, r0_8 -# 12| r0_14(glval) = VariableAddress[#return] : -# 12| r0_15(int) = Constant[0] : -# 12| mu0_16(int) = Store : &:r0_14, r0_15 -# 9| r0_17(glval) = VariableAddress[#return] : -# 9| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 -# 9| v0_19(void) = UnmodeledUse : mu* -# 9| v0_20(void) = ExitFunction : +# 9| v0_0(void) = EnterFunction : +# 9| mu0_1(unknown) = AliasedDefinition : +# 9| mu0_2(unknown) = UnmodeledDefinition : +# 10| r0_3(glval) = VariableAddress[big] : +# 10| r0_4(glval) = FunctionAddress[operator new] : +# 10| r0_5(unsigned long) = Constant[1073741824] : +# 10| r0_6(void *) = Call : func:r0_4, 0:r0_5 +# 10| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 10| r0_8(Big *) = Convert : r0_6 +# 10| r0_9(glval) = FunctionAddress[Big] : +# 10| v0_10(void) = Call : func:r0_9, this:r0_8 +# 10| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 10| mu0_12(Big) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 +# 10| mu0_13(Big *) = Store : &:r0_3, r0_8 +# 12| r0_14(glval) = VariableAddress[#return] : +# 12| r0_15(int) = Constant[0] : +# 12| mu0_16(int) = Store : &:r0_14, r0_15 +# 9| r0_17(glval) = VariableAddress[#return] : +# 9| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 +# 9| v0_19(void) = UnmodeledUse : mu* +# 9| v0_20(void) = ExitFunction : From 4a8e8fa0de4470aaeed94357f70b54b68c0b84a7 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 4 Oct 2019 09:18:19 +0100 Subject: [PATCH 0025/2538] docs: semmle logo --- .../static/theme/css/default.css | 18 +-- .../_static-training/title-slide.svg | 149 +----------------- .../ql-training/cpp/bad-overflow-guard.rst | 4 - .../ql-training/cpp/control-flow-cpp.rst | 4 - .../ql-training/cpp/data-flow-cpp.rst | 4 - .../ql-training/cpp/global-data-flow-cpp.rst | 4 - .../language/ql-training/cpp/intro-ql-cpp.rst | 4 - .../cpp/program-representation-cpp.rst | 4 - docs/language/ql-training/cpp/snprintf.rst | 4 - docs/language/ql-training/index.rst | 4 - .../ql-training/java/apache-struts-java.rst | 4 - .../ql-training/java/data-flow-java.rst | 4 - .../java/global-data-flow-java.rst | 4 - .../ql-training/java/intro-ql-java.rst | 4 - .../java/program-representation-java.rst | 4 - .../ql-training/java/query-injection-java.rst | 4 - docs/language/ql-training/template.rst | 4 - 17 files changed, 4 insertions(+), 223 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index e3664d42e06b..83d3d94e3aa1 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -1301,13 +1301,13 @@ aside.gdbar img { .title-slide hgroup h1 { font-size: 2em; line-height: 1.4; - /*letter-spacing: -3px;*/ color: white; margin: auto; display: block; position: absolute; top: 0; bottom: 10%; + left: 1.25em; height: 0; } /* line 898, ../scss/default.scss */ @@ -1431,31 +1431,19 @@ hgroup .pre { color: #5c31ff; } -/* title slide (deck title, subtitle, semmle logo)*/ +/* title slide (deck title, subtitle)*/ .title-slide { background-image: url("../../title-slide.svg"); background-size: cover; } -.semmle-logo sup { - vertical-align: super; - font-size: 0.3em; - font-weight: 100; -} - -.title-slide .semmle-logo { - color: white; - font-size: 1.2em; - position: absolute; - top: 10%; -} - .title-slide p { color: white; font-size: 1em; position: absolute; bottom: 30%; + left: 2.6em; } .title-slide hgroup .pre { diff --git a/docs/language/ql-training/_static-training/title-slide.svg b/docs/language/ql-training/_static-training/title-slide.svg index 6f9a19f4a1b8..13eb2d34fef2 100644 --- a/docs/language/ql-training/_static-training/title-slide.svg +++ b/docs/language/ql-training/_static-training/title-slide.svg @@ -1,148 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 12f35440906b..3ac9ee55f3b7 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -4,10 +4,6 @@ Example: Bad overflow guard QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index ea8e2c1b1582..e4d17fff8444 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -4,10 +4,6 @@ Analyzing control flow QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Include information slides here .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index 36b5eb6b5254..6ece12d1525d 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -4,10 +4,6 @@ Introduction to data flow Finding string formatting vulnerabilities in C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index 6033581ffc3f..02c37b5fb4c0 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -3,10 +3,6 @@ Introduction to global data flow ================================ QL for C/C++ - -.. container:: semmle-logo - - Semmle :sup:`TM` .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 82eb62a3ba88..fedbed7f0f59 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -4,10 +4,6 @@ Introduction to variant analysis QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 1850e3e5671e..4555d918822e 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -4,10 +4,6 @@ Program representation QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index 77e46933fcbf..5f1a27bf8dba 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -4,10 +4,6 @@ Exercise: ``snprintf`` overflow QL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/index.rst b/docs/language/ql-training/index.rst index 0cc4ca9b024a..6f3aea9a17af 100644 --- a/docs/language/ql-training/index.rst +++ b/docs/language/ql-training/index.rst @@ -1,10 +1,6 @@ QL training and variant analysis examples ========================================= -.. container:: semmle-logo - - Semmle :sup:`TM` - .. toctree:: :glob: :maxdepth: 1 diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 7fcd2e003cdc..c39652fa2a52 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -8,10 +8,6 @@ Exercise: Apache Struts CVE-2017-9805 -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/data-flow-java.rst b/docs/language/ql-training/java/data-flow-java.rst index be9ba98456e3..78e4bf549467 100644 --- a/docs/language/ql-training/java/data-flow-java.rst +++ b/docs/language/ql-training/java/data-flow-java.rst @@ -2,10 +2,6 @@ Introduction to data flow ========================= -.. container:: semmle-logo - - Semmle :sup:`TM` - Finding SPARQL injection vulnerabilities in Java .. rst-class:: setup diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index 665899f84590..6d821d60ea2d 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -4,10 +4,6 @@ Introduction to global data flow QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 392c18309cb8..611be7dfd6e7 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -4,10 +4,6 @@ Introduction to variant analysis QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index d090c30aebe2..ddd8103454f3 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -4,10 +4,6 @@ Program representation QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index 67f7fe21a761..de5d9623bfc4 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -4,10 +4,6 @@ Example: Query injection QL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/template.rst b/docs/language/ql-training/template.rst index 0cce4a114358..21c5abef1449 100644 --- a/docs/language/ql-training/template.rst +++ b/docs/language/ql-training/template.rst @@ -27,10 +27,6 @@ Template slide deck Second subheading -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Set up slide. Include link to QL4E snapshots required for examples .. rst-class:: setup From 5f8a3054d126e4c9b04eb72ec43d71bdb0b79079 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 4 Oct 2019 11:25:54 -0700 Subject: [PATCH 0026/2538] C++: add UninitializedInstructions for direct init --- .../internal/TranslatedDeclarationEntry.qll | 3 +- .../ir/ssa/aliased_ssa_ir.expected | 78 ++++++++++--------- .../ir/ssa/unaliased_ssa_ir.expected | 68 ++++++++-------- 3 files changed, 77 insertions(+), 72 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 1efe8cf9f78d..d42c19626601 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -123,7 +123,8 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali private predicate hasUninitializedInstruction() { not exists(getInitialization()) or - getInitialization() instanceof TranslatedListInitialization + getInitialization() instanceof TranslatedListInitialization or + getInitialization() instanceof TranslatedConstructorInitialization } } diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index be58a43a4155..813d7a9bdcde 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -877,41 +877,43 @@ ssa.cpp: # 219| m0_1(unknown) = AliasedDefinition : # 219| mu0_2(unknown) = UnmodeledDefinition : # 220| r0_3(glval) = VariableAddress[c] : -# 220| r0_4(glval) = FunctionAddress[Constructible] : -# 220| r0_5(int) = Constant[1] : -# 220| v0_6(void) = Call : func:r0_4, this:r0_3, 0:r0_5 -# 220| m0_7(unknown) = ^CallSideEffect : ~m0_1 -# 220| m0_8(unknown) = Chi : total:m0_1, partial:m0_7 -# 220| m0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 221| r0_10(glval) = VariableAddress[c] : -# 221| r0_11(glval) = FunctionAddress[g] : -# 221| v0_12(void) = Call : func:r0_11, this:r0_10 -# 221| m0_13(unknown) = ^CallSideEffect : ~m0_8 -# 221| m0_14(unknown) = Chi : total:m0_8, partial:m0_13 -# 221| v0_15(void) = ^IndirectReadSideEffect[-1] : &:r0_10, m0_9 -# 221| m0_16(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 -# 222| r0_17(glval) = VariableAddress[c] : -# 222| r0_18(glval) = FunctionAddress[g] : -# 222| v0_19(void) = Call : func:r0_18, this:r0_17 -# 222| m0_20(unknown) = ^CallSideEffect : ~m0_14 -# 222| m0_21(unknown) = Chi : total:m0_14, partial:m0_20 -# 222| v0_22(void) = ^IndirectReadSideEffect[-1] : &:r0_17, m0_16 -# 222| m0_23(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_17 -# 223| r0_24(glval) = VariableAddress[c2] : -# 223| r0_25(glval) = FunctionAddress[Constructible] : -# 223| r0_26(int) = Constant[2] : -# 223| v0_27(void) = Call : func:r0_25, this:r0_24, 0:r0_26 -# 223| m0_28(unknown) = ^CallSideEffect : ~m0_21 -# 223| m0_29(unknown) = Chi : total:m0_21, partial:m0_28 -# 223| m0_30(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_24 -# 224| r0_31(glval) = VariableAddress[c2] : -# 224| r0_32(glval) = FunctionAddress[g] : -# 224| v0_33(void) = Call : func:r0_32, this:r0_31 -# 224| m0_34(unknown) = ^CallSideEffect : ~m0_29 -# 224| m0_35(unknown) = Chi : total:m0_29, partial:m0_34 -# 224| v0_36(void) = ^IndirectReadSideEffect[-1] : &:r0_31, m0_30 -# 224| m0_37(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_31 -# 225| v0_38(void) = NoOp : -# 219| v0_39(void) = ReturnVoid : -# 219| v0_40(void) = UnmodeledUse : mu* -# 219| v0_41(void) = ExitFunction : +# 220| m0_4(Constructible) = Uninitialized[c] : &:r0_3 +# 220| r0_5(glval) = FunctionAddress[Constructible] : +# 220| r0_6(int) = Constant[1] : +# 220| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6 +# 220| m0_8(unknown) = ^CallSideEffect : ~m0_1 +# 220| m0_9(unknown) = Chi : total:m0_1, partial:m0_8 +# 220| m0_10(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 221| r0_11(glval) = VariableAddress[c] : +# 221| r0_12(glval) = FunctionAddress[g] : +# 221| v0_13(void) = Call : func:r0_12, this:r0_11 +# 221| m0_14(unknown) = ^CallSideEffect : ~m0_9 +# 221| m0_15(unknown) = Chi : total:m0_9, partial:m0_14 +# 221| v0_16(void) = ^IndirectReadSideEffect[-1] : &:r0_11, m0_10 +# 221| m0_17(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 +# 222| r0_18(glval) = VariableAddress[c] : +# 222| r0_19(glval) = FunctionAddress[g] : +# 222| v0_20(void) = Call : func:r0_19, this:r0_18 +# 222| m0_21(unknown) = ^CallSideEffect : ~m0_15 +# 222| m0_22(unknown) = Chi : total:m0_15, partial:m0_21 +# 222| v0_23(void) = ^IndirectReadSideEffect[-1] : &:r0_18, m0_17 +# 222| m0_24(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_18 +# 223| r0_25(glval) = VariableAddress[c2] : +# 223| m0_26(Constructible) = Uninitialized[c2] : &:r0_25 +# 223| r0_27(glval) = FunctionAddress[Constructible] : +# 223| r0_28(int) = Constant[2] : +# 223| v0_29(void) = Call : func:r0_27, this:r0_25, 0:r0_28 +# 223| m0_30(unknown) = ^CallSideEffect : ~m0_22 +# 223| m0_31(unknown) = Chi : total:m0_22, partial:m0_30 +# 223| m0_32(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 +# 224| r0_33(glval) = VariableAddress[c2] : +# 224| r0_34(glval) = FunctionAddress[g] : +# 224| v0_35(void) = Call : func:r0_34, this:r0_33 +# 224| m0_36(unknown) = ^CallSideEffect : ~m0_31 +# 224| m0_37(unknown) = Chi : total:m0_31, partial:m0_36 +# 224| v0_38(void) = ^IndirectReadSideEffect[-1] : &:r0_33, m0_32 +# 224| m0_39(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_33 +# 225| v0_40(void) = NoOp : +# 219| v0_41(void) = ReturnVoid : +# 219| v0_42(void) = UnmodeledUse : mu* +# 219| v0_43(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 6006ee380365..029c552f5d5b 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -837,36 +837,38 @@ ssa.cpp: # 219| mu0_1(unknown) = AliasedDefinition : # 219| mu0_2(unknown) = UnmodeledDefinition : # 220| r0_3(glval) = VariableAddress[c] : -# 220| r0_4(glval) = FunctionAddress[Constructible] : -# 220| r0_5(int) = Constant[1] : -# 220| v0_6(void) = Call : func:r0_4, this:r0_3, 0:r0_5 -# 220| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 -# 220| m0_8(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 221| r0_9(glval) = VariableAddress[c] : -# 221| r0_10(glval) = FunctionAddress[g] : -# 221| v0_11(void) = Call : func:r0_10, this:r0_9 -# 221| mu0_12(unknown) = ^CallSideEffect : ~mu0_2 -# 221| v0_13(void) = ^IndirectReadSideEffect[-1] : &:r0_9, m0_8 -# 221| m0_14(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 -# 222| r0_15(glval) = VariableAddress[c] : -# 222| r0_16(glval) = FunctionAddress[g] : -# 222| v0_17(void) = Call : func:r0_16, this:r0_15 -# 222| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 -# 222| v0_19(void) = ^IndirectReadSideEffect[-1] : &:r0_15, m0_14 -# 222| m0_20(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_15 -# 223| r0_21(glval) = VariableAddress[c2] : -# 223| r0_22(glval) = FunctionAddress[Constructible] : -# 223| r0_23(int) = Constant[2] : -# 223| v0_24(void) = Call : func:r0_22, this:r0_21, 0:r0_23 -# 223| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -# 223| m0_26(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_21 -# 224| r0_27(glval) = VariableAddress[c2] : -# 224| r0_28(glval) = FunctionAddress[g] : -# 224| v0_29(void) = Call : func:r0_28, this:r0_27 -# 224| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 -# 224| v0_31(void) = ^IndirectReadSideEffect[-1] : &:r0_27, m0_26 -# 224| m0_32(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 -# 225| v0_33(void) = NoOp : -# 219| v0_34(void) = ReturnVoid : -# 219| v0_35(void) = UnmodeledUse : mu* -# 219| v0_36(void) = ExitFunction : +# 220| m0_4(Constructible) = Uninitialized[c] : &:r0_3 +# 220| r0_5(glval) = FunctionAddress[Constructible] : +# 220| r0_6(int) = Constant[1] : +# 220| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6 +# 220| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 +# 220| m0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 221| r0_10(glval) = VariableAddress[c] : +# 221| r0_11(glval) = FunctionAddress[g] : +# 221| v0_12(void) = Call : func:r0_11, this:r0_10 +# 221| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 221| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_10, m0_9 +# 221| m0_15(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +# 222| r0_16(glval) = VariableAddress[c] : +# 222| r0_17(glval) = FunctionAddress[g] : +# 222| v0_18(void) = Call : func:r0_17, this:r0_16 +# 222| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 222| v0_20(void) = ^IndirectReadSideEffect[-1] : &:r0_16, m0_15 +# 222| m0_21(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_16 +# 223| r0_22(glval) = VariableAddress[c2] : +# 223| m0_23(Constructible) = Uninitialized[c2] : &:r0_22 +# 223| r0_24(glval) = FunctionAddress[Constructible] : +# 223| r0_25(int) = Constant[2] : +# 223| v0_26(void) = Call : func:r0_24, this:r0_22, 0:r0_25 +# 223| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 +# 223| m0_28(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 +# 224| r0_29(glval) = VariableAddress[c2] : +# 224| r0_30(glval) = FunctionAddress[g] : +# 224| v0_31(void) = Call : func:r0_30, this:r0_29 +# 224| mu0_32(unknown) = ^CallSideEffect : ~mu0_2 +# 224| v0_33(void) = ^IndirectReadSideEffect[-1] : &:r0_29, m0_28 +# 224| m0_34(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_29 +# 225| v0_35(void) = NoOp : +# 219| v0_36(void) = ReturnVoid : +# 219| v0_37(void) = UnmodeledUse : mu* +# 219| v0_38(void) = ExitFunction : From 3377f88494c7a84569e91dff46eaf61bca7f3c94 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 4 Oct 2019 11:36:47 -0700 Subject: [PATCH 0027/2538] C++: generate Chi nodes on total IndirectMayWrites --- .../aliased_ssa/internal/SSAConstruction.qll | 9 +- .../internal/SSAConstruction.qll | 9 +- .../unaliased_ssa/internal/SimpleSSA.qll | 7 +- .../test/library-tests/ir/ir/raw_ir.expected | 930 +++++++++--------- .../ir/ssa/aliased_ssa_ir.expected | 71 +- .../ir/ssa/unaliased_ssa_ir.expected | 20 +- 6 files changed, 538 insertions(+), 508 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 0fb6676bb424..753cca6b955c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -422,7 +422,11 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) { defLocation.getVirtualVariable() = vvar and // If the definition totally (or exactly) overlaps the virtual variable, then there's no need for a `Chi` // instruction. - Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap + ( + Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap or + def.getResultMemoryAccess() instanceof IndirectMayMemoryAccess or + def.getResultMemoryAccess() instanceof BufferMayMemoryAccess + ) ) } @@ -735,7 +739,8 @@ module DefUse { defLocation = Alias::getResultMemoryLocation(def) and block.getInstruction(index) = def and overlap = Alias::getOverlap(defLocation, useLocation) and - if overlap instanceof MayPartiallyOverlap + if + overlap instanceof MayPartiallyOverlap then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction. else offset = index * 2 // The use will be connected to the definition on the original instruction. ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 0fb6676bb424..753cca6b955c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -422,7 +422,11 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) { defLocation.getVirtualVariable() = vvar and // If the definition totally (or exactly) overlaps the virtual variable, then there's no need for a `Chi` // instruction. - Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap + ( + Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap or + def.getResultMemoryAccess() instanceof IndirectMayMemoryAccess or + def.getResultMemoryAccess() instanceof BufferMayMemoryAccess + ) ) } @@ -735,7 +739,8 @@ module DefUse { defLocation = Alias::getResultMemoryLocation(def) and block.getInstruction(index) = def and overlap = Alias::getOverlap(defLocation, useLocation) and - if overlap instanceof MayPartiallyOverlap + if + overlap instanceof MayPartiallyOverlap then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction. else offset = index * 2 // The use will be connected to the definition on the original instruction. ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll index 7cca5855a209..16ff83deb02c 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SimpleSSA.qll @@ -1,4 +1,5 @@ import AliasAnalysis +private import semmle.code.cpp.ir.implementation.MemoryAccessKind private import cpp private import semmle.code.cpp.ir.implementation.raw.IR private import semmle.code.cpp.ir.internal.IntegerConstant as Ints @@ -34,7 +35,11 @@ private predicate isVariableModeled(IRVariable var) { hasResultMemoryAccess(instr, var, type, bitOffset) | bitOffset = 0 and - type = var.getType() + type = var.getType() and + not ( + instr.getResultMemoryAccess() instanceof IndirectMayMemoryAccess or + instr.getResultMemoryAccess() instanceof BufferMayMemoryAccess + ) ) and forall(MemoryOperand operand, Type type, IntValue bitOffset | hasOperandMemoryAccess(operand, var, type, bitOffset) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 933cd6bc2e3e..aa1e2fa7bd6a 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2712,37 +2712,40 @@ ir.cpp: # 615| mu0_1(unknown) = AliasedDefinition : # 615| mu0_2(unknown) = UnmodeledDefinition : # 616| r0_3(glval) = VariableAddress[s1] : -# 616| r0_4(glval) = FunctionAddress[String] : -# 616| v0_5(void) = Call : func:r0_4, this:r0_3 -# 616| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 616| mu0_7(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 617| r0_8(glval) = VariableAddress[s2] : -# 617| r0_9(glval) = FunctionAddress[String] : -# 617| r0_10(glval) = StringConstant["hello"] : -# 617| r0_11(char *) = Convert : r0_10 -# 617| v0_12(void) = Call : func:r0_9, this:r0_8, 0:r0_11 -# 617| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 617| mu0_14(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 -# 617| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 -# 617| mu0_16(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -# 618| r0_17(glval) = VariableAddress[s3] : -# 618| r0_18(glval) = FunctionAddress[ReturnObject] : -# 618| r0_19(String) = Call : func:r0_18 -# 618| mu0_20(unknown) = ^CallSideEffect : ~mu0_2 -# 618| mu0_21(String) = Store : &:r0_17, r0_19 -# 619| r0_22(glval) = VariableAddress[s4] : -# 619| r0_23(glval) = FunctionAddress[String] : -# 619| r0_24(glval) = StringConstant["test"] : -# 619| r0_25(char *) = Convert : r0_24 -# 619| v0_26(void) = Call : func:r0_23, this:r0_22, 0:r0_25 -# 619| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 -# 619| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 -# 619| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 -# 619| mu0_30(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 -# 620| v0_31(void) = NoOp : -# 615| v0_32(void) = ReturnVoid : -# 615| v0_33(void) = UnmodeledUse : mu* -# 615| v0_34(void) = ExitFunction : +# 616| mu0_4(String) = Uninitialized[s1] : &:r0_3 +# 616| r0_5(glval) = FunctionAddress[String] : +# 616| v0_6(void) = Call : func:r0_5, this:r0_3 +# 616| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 616| mu0_8(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 617| r0_9(glval) = VariableAddress[s2] : +# 617| mu0_10(String) = Uninitialized[s2] : &:r0_9 +# 617| r0_11(glval) = FunctionAddress[String] : +# 617| r0_12(glval) = StringConstant["hello"] : +# 617| r0_13(char *) = Convert : r0_12 +# 617| v0_14(void) = Call : func:r0_11, this:r0_9, 0:r0_13 +# 617| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +# 617| mu0_16(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +# 617| v0_17(void) = ^IndirectReadSideEffect[0] : &:r0_13, ~mu0_2 +# 617| mu0_18(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_13 +# 618| r0_19(glval) = VariableAddress[s3] : +# 618| r0_20(glval) = FunctionAddress[ReturnObject] : +# 618| r0_21(String) = Call : func:r0_20 +# 618| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 +# 618| mu0_23(String) = Store : &:r0_19, r0_21 +# 619| r0_24(glval) = VariableAddress[s4] : +# 619| mu0_25(String) = Uninitialized[s4] : &:r0_24 +# 619| r0_26(glval) = FunctionAddress[String] : +# 619| r0_27(glval) = StringConstant["test"] : +# 619| r0_28(char *) = Convert : r0_27 +# 619| v0_29(void) = Call : func:r0_26, this:r0_24, 0:r0_28 +# 619| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 +# 619| mu0_31(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_24 +# 619| v0_32(void) = ^IndirectReadSideEffect[0] : &:r0_28, ~mu0_2 +# 619| mu0_33(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_28 +# 620| v0_34(void) = NoOp : +# 615| v0_35(void) = ReturnVoid : +# 615| v0_36(void) = UnmodeledUse : mu* +# 615| v0_37(void) = ExitFunction : # 622| void CallMethods(String&, String*, String) # 622| Block 0 @@ -3640,261 +3643,264 @@ ir.cpp: # 799| mu0_1(unknown) = AliasedDefinition : # 799| mu0_2(unknown) = UnmodeledDefinition : # 800| r0_3(glval) = VariableAddress[b] : -# 800| r0_4(glval) = FunctionAddress[Base] : -# 800| v0_5(void) = Call : func:r0_4, this:r0_3 -# 800| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -# 800| mu0_7(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 801| r0_8(glval) = VariableAddress[m] : -# 801| r0_9(glval) = FunctionAddress[Middle] : -# 801| v0_10(void) = Call : func:r0_9, this:r0_8 -# 801| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 801| mu0_12(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 -# 802| r0_13(glval) = VariableAddress[d] : -# 802| r0_14(glval) = FunctionAddress[Derived] : -# 802| v0_15(void) = Call : func:r0_14, this:r0_13 -# 802| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 -# 802| mu0_17(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_13 -# 804| r0_18(glval) = VariableAddress[pb] : -# 804| r0_19(glval) = VariableAddress[b] : -# 804| mu0_20(Base *) = Store : &:r0_18, r0_19 -# 805| r0_21(glval) = VariableAddress[pm] : -# 805| r0_22(glval) = VariableAddress[m] : -# 805| mu0_23(Middle *) = Store : &:r0_21, r0_22 -# 806| r0_24(glval) = VariableAddress[pd] : -# 806| r0_25(glval) = VariableAddress[d] : -# 806| mu0_26(Derived *) = Store : &:r0_24, r0_25 -# 808| r0_27(glval) = VariableAddress[b] : -# 808| r0_28(glval) = FunctionAddress[operator=] : -# 808| r0_29(glval) = VariableAddress[m] : -# 808| r0_30(glval) = ConvertToBase[Middle : Base] : r0_29 -# 808| r0_31(Base &) = Call : func:r0_28, this:r0_27, 0:r0_30 -# 808| mu0_32(unknown) = ^CallSideEffect : ~mu0_2 -# 808| v0_33(void) = ^IndirectReadSideEffect[-1] : &:r0_27, ~mu0_2 -# 808| v0_34(void) = ^IndirectReadSideEffect[0] : &:r0_30, ~mu0_2 -# 808| mu0_35(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_27 -# 808| mu0_36(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_30 -# 809| r0_37(glval) = VariableAddress[b] : -# 809| r0_38(glval) = FunctionAddress[operator=] : -# 809| r0_39(glval) = FunctionAddress[Base] : -# 809| r0_40(glval) = VariableAddress[m] : -# 809| r0_41(glval) = ConvertToBase[Middle : Base] : r0_40 -# 809| v0_42(void) = Call : func:r0_39, 0:r0_41 -# 809| mu0_43(unknown) = ^CallSideEffect : ~mu0_2 -# 809| mu0_44(Base) = ^IndirectMayWriteSideEffect[-1] : -# 809| v0_45(void) = ^IndirectReadSideEffect[0] : &:r0_41, ~mu0_2 -# 809| mu0_46(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_41 -# 809| r0_47(glval) = Convert : v0_42 -# 809| r0_48(Base &) = Call : func:r0_38, this:r0_37, 0:r0_47 -# 809| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 -# 809| v0_50(void) = ^IndirectReadSideEffect[-1] : &:r0_37, ~mu0_2 -# 809| v0_51(void) = ^IndirectReadSideEffect[0] : &:r0_47, ~mu0_2 -# 809| mu0_52(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_37 -# 809| mu0_53(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_47 -# 810| r0_54(glval) = VariableAddress[b] : -# 810| r0_55(glval) = FunctionAddress[operator=] : -# 810| r0_56(glval) = FunctionAddress[Base] : -# 810| r0_57(glval) = VariableAddress[m] : -# 810| r0_58(glval) = ConvertToBase[Middle : Base] : r0_57 -# 810| v0_59(void) = Call : func:r0_56, 0:r0_58 -# 810| mu0_60(unknown) = ^CallSideEffect : ~mu0_2 -# 810| mu0_61(Base) = ^IndirectMayWriteSideEffect[-1] : -# 810| v0_62(void) = ^IndirectReadSideEffect[0] : &:r0_58, ~mu0_2 -# 810| mu0_63(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_58 -# 810| r0_64(glval) = Convert : v0_59 -# 810| r0_65(Base &) = Call : func:r0_55, this:r0_54, 0:r0_64 -# 810| mu0_66(unknown) = ^CallSideEffect : ~mu0_2 -# 810| v0_67(void) = ^IndirectReadSideEffect[-1] : &:r0_54, ~mu0_2 -# 810| v0_68(void) = ^IndirectReadSideEffect[0] : &:r0_64, ~mu0_2 -# 810| mu0_69(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_54 -# 810| mu0_70(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_64 -# 811| r0_71(glval) = VariableAddress[pm] : -# 811| r0_72(Middle *) = Load : &:r0_71, ~mu0_2 -# 811| r0_73(Base *) = ConvertToBase[Middle : Base] : r0_72 -# 811| r0_74(glval) = VariableAddress[pb] : -# 811| mu0_75(Base *) = Store : &:r0_74, r0_73 -# 812| r0_76(glval) = VariableAddress[pm] : -# 812| r0_77(Middle *) = Load : &:r0_76, ~mu0_2 -# 812| r0_78(Base *) = ConvertToBase[Middle : Base] : r0_77 -# 812| r0_79(glval) = VariableAddress[pb] : -# 812| mu0_80(Base *) = Store : &:r0_79, r0_78 -# 813| r0_81(glval) = VariableAddress[pm] : -# 813| r0_82(Middle *) = Load : &:r0_81, ~mu0_2 -# 813| r0_83(Base *) = ConvertToBase[Middle : Base] : r0_82 -# 813| r0_84(glval) = VariableAddress[pb] : -# 813| mu0_85(Base *) = Store : &:r0_84, r0_83 -# 814| r0_86(glval) = VariableAddress[pm] : -# 814| r0_87(Middle *) = Load : &:r0_86, ~mu0_2 -# 814| r0_88(Base *) = Convert : r0_87 -# 814| r0_89(glval) = VariableAddress[pb] : -# 814| mu0_90(Base *) = Store : &:r0_89, r0_88 -# 816| r0_91(glval) = VariableAddress[m] : -# 816| r0_92(glval) = FunctionAddress[operator=] : -# 816| r0_93(glval) = VariableAddress[b] : -# 816| r0_94(glval) = ConvertToDerived[Middle : Base] : r0_93 -# 816| r0_95(glval) = Convert : r0_94 -# 816| r0_96(Middle &) = Call : func:r0_92, this:r0_91, 0:r0_95 -# 816| mu0_97(unknown) = ^CallSideEffect : ~mu0_2 -# 816| v0_98(void) = ^IndirectReadSideEffect[-1] : &:r0_91, ~mu0_2 -# 816| v0_99(void) = ^IndirectReadSideEffect[0] : &:r0_95, ~mu0_2 -# 816| mu0_100(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_91 -# 816| mu0_101(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_95 -# 817| r0_102(glval) = VariableAddress[m] : -# 817| r0_103(glval) = FunctionAddress[operator=] : -# 817| r0_104(glval) = VariableAddress[b] : -# 817| r0_105(glval) = ConvertToDerived[Middle : Base] : r0_104 -# 817| r0_106(glval) = Convert : r0_105 -# 817| r0_107(Middle &) = Call : func:r0_103, this:r0_102, 0:r0_106 -# 817| mu0_108(unknown) = ^CallSideEffect : ~mu0_2 -# 817| v0_109(void) = ^IndirectReadSideEffect[-1] : &:r0_102, ~mu0_2 -# 817| v0_110(void) = ^IndirectReadSideEffect[0] : &:r0_106, ~mu0_2 -# 817| mu0_111(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_102 -# 817| mu0_112(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_106 -# 818| r0_113(glval) = VariableAddress[pb] : -# 818| r0_114(Base *) = Load : &:r0_113, ~mu0_2 -# 818| r0_115(Middle *) = ConvertToDerived[Middle : Base] : r0_114 -# 818| r0_116(glval) = VariableAddress[pm] : -# 818| mu0_117(Middle *) = Store : &:r0_116, r0_115 -# 819| r0_118(glval) = VariableAddress[pb] : -# 819| r0_119(Base *) = Load : &:r0_118, ~mu0_2 -# 819| r0_120(Middle *) = ConvertToDerived[Middle : Base] : r0_119 -# 819| r0_121(glval) = VariableAddress[pm] : -# 819| mu0_122(Middle *) = Store : &:r0_121, r0_120 -# 820| r0_123(glval) = VariableAddress[pb] : -# 820| r0_124(Base *) = Load : &:r0_123, ~mu0_2 -# 820| r0_125(Middle *) = Convert : r0_124 -# 820| r0_126(glval) = VariableAddress[pm] : -# 820| mu0_127(Middle *) = Store : &:r0_126, r0_125 -# 822| r0_128(glval) = VariableAddress[b] : -# 822| r0_129(glval) = FunctionAddress[operator=] : -# 822| r0_130(glval) = VariableAddress[d] : -# 822| r0_131(glval) = ConvertToBase[Derived : Middle] : r0_130 -# 822| r0_132(glval) = ConvertToBase[Middle : Base] : r0_131 -# 822| r0_133(Base &) = Call : func:r0_129, this:r0_128, 0:r0_132 -# 822| mu0_134(unknown) = ^CallSideEffect : ~mu0_2 -# 822| v0_135(void) = ^IndirectReadSideEffect[-1] : &:r0_128, ~mu0_2 -# 822| v0_136(void) = ^IndirectReadSideEffect[0] : &:r0_132, ~mu0_2 -# 822| mu0_137(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_128 -# 822| mu0_138(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_132 -# 823| r0_139(glval) = VariableAddress[b] : -# 823| r0_140(glval) = FunctionAddress[operator=] : -# 823| r0_141(glval) = FunctionAddress[Base] : -# 823| r0_142(glval) = VariableAddress[d] : -# 823| r0_143(glval) = ConvertToBase[Derived : Middle] : r0_142 -# 823| r0_144(glval) = ConvertToBase[Middle : Base] : r0_143 -# 823| v0_145(void) = Call : func:r0_141, 0:r0_144 -# 823| mu0_146(unknown) = ^CallSideEffect : ~mu0_2 -# 823| mu0_147(Base) = ^IndirectMayWriteSideEffect[-1] : -# 823| v0_148(void) = ^IndirectReadSideEffect[0] : &:r0_144, ~mu0_2 -# 823| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_144 -# 823| r0_150(glval) = Convert : v0_145 -# 823| r0_151(Base &) = Call : func:r0_140, this:r0_139, 0:r0_150 -# 823| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_153(void) = ^IndirectReadSideEffect[-1] : &:r0_139, ~mu0_2 -# 823| v0_154(void) = ^IndirectReadSideEffect[0] : &:r0_150, ~mu0_2 -# 823| mu0_155(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_139 -# 823| mu0_156(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_150 -# 824| r0_157(glval) = VariableAddress[b] : -# 824| r0_158(glval) = FunctionAddress[operator=] : -# 824| r0_159(glval) = FunctionAddress[Base] : -# 824| r0_160(glval) = VariableAddress[d] : -# 824| r0_161(glval) = ConvertToBase[Derived : Middle] : r0_160 -# 824| r0_162(glval) = ConvertToBase[Middle : Base] : r0_161 -# 824| v0_163(void) = Call : func:r0_159, 0:r0_162 -# 824| mu0_164(unknown) = ^CallSideEffect : ~mu0_2 -# 824| mu0_165(Base) = ^IndirectMayWriteSideEffect[-1] : -# 824| v0_166(void) = ^IndirectReadSideEffect[0] : &:r0_162, ~mu0_2 -# 824| mu0_167(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_162 -# 824| r0_168(glval) = Convert : v0_163 -# 824| r0_169(Base &) = Call : func:r0_158, this:r0_157, 0:r0_168 -# 824| mu0_170(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_171(void) = ^IndirectReadSideEffect[-1] : &:r0_157, ~mu0_2 -# 824| v0_172(void) = ^IndirectReadSideEffect[0] : &:r0_168, ~mu0_2 -# 824| mu0_173(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_157 -# 824| mu0_174(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_168 -# 825| r0_175(glval) = VariableAddress[pd] : -# 825| r0_176(Derived *) = Load : &:r0_175, ~mu0_2 -# 825| r0_177(Middle *) = ConvertToBase[Derived : Middle] : r0_176 -# 825| r0_178(Base *) = ConvertToBase[Middle : Base] : r0_177 -# 825| r0_179(glval) = VariableAddress[pb] : -# 825| mu0_180(Base *) = Store : &:r0_179, r0_178 -# 826| r0_181(glval) = VariableAddress[pd] : -# 826| r0_182(Derived *) = Load : &:r0_181, ~mu0_2 -# 826| r0_183(Middle *) = ConvertToBase[Derived : Middle] : r0_182 -# 826| r0_184(Base *) = ConvertToBase[Middle : Base] : r0_183 -# 826| r0_185(glval) = VariableAddress[pb] : -# 826| mu0_186(Base *) = Store : &:r0_185, r0_184 -# 827| r0_187(glval) = VariableAddress[pd] : -# 827| r0_188(Derived *) = Load : &:r0_187, ~mu0_2 -# 827| r0_189(Middle *) = ConvertToBase[Derived : Middle] : r0_188 -# 827| r0_190(Base *) = ConvertToBase[Middle : Base] : r0_189 -# 827| r0_191(glval) = VariableAddress[pb] : -# 827| mu0_192(Base *) = Store : &:r0_191, r0_190 -# 828| r0_193(glval) = VariableAddress[pd] : -# 828| r0_194(Derived *) = Load : &:r0_193, ~mu0_2 -# 828| r0_195(Base *) = Convert : r0_194 -# 828| r0_196(glval) = VariableAddress[pb] : -# 828| mu0_197(Base *) = Store : &:r0_196, r0_195 -# 830| r0_198(glval) = VariableAddress[d] : -# 830| r0_199(glval) = FunctionAddress[operator=] : -# 830| r0_200(glval) = VariableAddress[b] : -# 830| r0_201(glval) = ConvertToDerived[Middle : Base] : r0_200 -# 830| r0_202(glval) = ConvertToDerived[Derived : Middle] : r0_201 -# 830| r0_203(glval) = Convert : r0_202 -# 830| r0_204(Derived &) = Call : func:r0_199, this:r0_198, 0:r0_203 -# 830| mu0_205(unknown) = ^CallSideEffect : ~mu0_2 -# 830| v0_206(void) = ^IndirectReadSideEffect[-1] : &:r0_198, ~mu0_2 -# 830| v0_207(void) = ^IndirectReadSideEffect[0] : &:r0_203, ~mu0_2 -# 830| mu0_208(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_198 -# 830| mu0_209(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_203 -# 831| r0_210(glval) = VariableAddress[d] : -# 831| r0_211(glval) = FunctionAddress[operator=] : -# 831| r0_212(glval) = VariableAddress[b] : -# 831| r0_213(glval) = ConvertToDerived[Middle : Base] : r0_212 -# 831| r0_214(glval) = ConvertToDerived[Derived : Middle] : r0_213 -# 831| r0_215(glval) = Convert : r0_214 -# 831| r0_216(Derived &) = Call : func:r0_211, this:r0_210, 0:r0_215 -# 831| mu0_217(unknown) = ^CallSideEffect : ~mu0_2 -# 831| v0_218(void) = ^IndirectReadSideEffect[-1] : &:r0_210, ~mu0_2 -# 831| v0_219(void) = ^IndirectReadSideEffect[0] : &:r0_215, ~mu0_2 -# 831| mu0_220(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_210 -# 831| mu0_221(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_215 -# 832| r0_222(glval) = VariableAddress[pb] : -# 832| r0_223(Base *) = Load : &:r0_222, ~mu0_2 -# 832| r0_224(Middle *) = ConvertToDerived[Middle : Base] : r0_223 -# 832| r0_225(Derived *) = ConvertToDerived[Derived : Middle] : r0_224 -# 832| r0_226(glval) = VariableAddress[pd] : -# 832| mu0_227(Derived *) = Store : &:r0_226, r0_225 -# 833| r0_228(glval) = VariableAddress[pb] : -# 833| r0_229(Base *) = Load : &:r0_228, ~mu0_2 -# 833| r0_230(Middle *) = ConvertToDerived[Middle : Base] : r0_229 -# 833| r0_231(Derived *) = ConvertToDerived[Derived : Middle] : r0_230 -# 833| r0_232(glval) = VariableAddress[pd] : -# 833| mu0_233(Derived *) = Store : &:r0_232, r0_231 -# 834| r0_234(glval) = VariableAddress[pb] : -# 834| r0_235(Base *) = Load : &:r0_234, ~mu0_2 -# 834| r0_236(Derived *) = Convert : r0_235 -# 834| r0_237(glval) = VariableAddress[pd] : -# 834| mu0_238(Derived *) = Store : &:r0_237, r0_236 -# 836| r0_239(glval) = VariableAddress[pmv] : -# 836| r0_240(MiddleVB1 *) = Constant[0] : -# 836| mu0_241(MiddleVB1 *) = Store : &:r0_239, r0_240 -# 837| r0_242(glval) = VariableAddress[pdv] : -# 837| r0_243(DerivedVB *) = Constant[0] : -# 837| mu0_244(DerivedVB *) = Store : &:r0_242, r0_243 -# 838| r0_245(glval) = VariableAddress[pmv] : -# 838| r0_246(MiddleVB1 *) = Load : &:r0_245, ~mu0_2 -# 838| r0_247(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_246 -# 838| r0_248(glval) = VariableAddress[pb] : -# 838| mu0_249(Base *) = Store : &:r0_248, r0_247 -# 839| r0_250(glval) = VariableAddress[pdv] : -# 839| r0_251(DerivedVB *) = Load : &:r0_250, ~mu0_2 -# 839| r0_252(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_251 -# 839| r0_253(glval) = VariableAddress[pb] : -# 839| mu0_254(Base *) = Store : &:r0_253, r0_252 -# 840| v0_255(void) = NoOp : -# 799| v0_256(void) = ReturnVoid : -# 799| v0_257(void) = UnmodeledUse : mu* -# 799| v0_258(void) = ExitFunction : +# 800| mu0_4(Base) = Uninitialized[b] : &:r0_3 +# 800| r0_5(glval) = FunctionAddress[Base] : +# 800| v0_6(void) = Call : func:r0_5, this:r0_3 +# 800| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +# 800| mu0_8(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 801| r0_9(glval) = VariableAddress[m] : +# 801| mu0_10(Middle) = Uninitialized[m] : &:r0_9 +# 801| r0_11(glval) = FunctionAddress[Middle] : +# 801| v0_12(void) = Call : func:r0_11, this:r0_9 +# 801| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 801| mu0_14(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +# 802| r0_15(glval) = VariableAddress[d] : +# 802| mu0_16(Derived) = Uninitialized[d] : &:r0_15 +# 802| r0_17(glval) = FunctionAddress[Derived] : +# 802| v0_18(void) = Call : func:r0_17, this:r0_15 +# 802| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 802| mu0_20(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_15 +# 804| r0_21(glval) = VariableAddress[pb] : +# 804| r0_22(glval) = VariableAddress[b] : +# 804| mu0_23(Base *) = Store : &:r0_21, r0_22 +# 805| r0_24(glval) = VariableAddress[pm] : +# 805| r0_25(glval) = VariableAddress[m] : +# 805| mu0_26(Middle *) = Store : &:r0_24, r0_25 +# 806| r0_27(glval) = VariableAddress[pd] : +# 806| r0_28(glval) = VariableAddress[d] : +# 806| mu0_29(Derived *) = Store : &:r0_27, r0_28 +# 808| r0_30(glval) = VariableAddress[b] : +# 808| r0_31(glval) = FunctionAddress[operator=] : +# 808| r0_32(glval) = VariableAddress[m] : +# 808| r0_33(glval) = ConvertToBase[Middle : Base] : r0_32 +# 808| r0_34(Base &) = Call : func:r0_31, this:r0_30, 0:r0_33 +# 808| mu0_35(unknown) = ^CallSideEffect : ~mu0_2 +# 808| v0_36(void) = ^IndirectReadSideEffect[-1] : &:r0_30, ~mu0_2 +# 808| v0_37(void) = ^IndirectReadSideEffect[0] : &:r0_33, ~mu0_2 +# 808| mu0_38(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_30 +# 808| mu0_39(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_33 +# 809| r0_40(glval) = VariableAddress[b] : +# 809| r0_41(glval) = FunctionAddress[operator=] : +# 809| r0_42(glval) = FunctionAddress[Base] : +# 809| r0_43(glval) = VariableAddress[m] : +# 809| r0_44(glval) = ConvertToBase[Middle : Base] : r0_43 +# 809| v0_45(void) = Call : func:r0_42, 0:r0_44 +# 809| mu0_46(unknown) = ^CallSideEffect : ~mu0_2 +# 809| mu0_47(Base) = ^IndirectMayWriteSideEffect[-1] : +# 809| v0_48(void) = ^IndirectReadSideEffect[0] : &:r0_44, ~mu0_2 +# 809| mu0_49(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_44 +# 809| r0_50(glval) = Convert : v0_45 +# 809| r0_51(Base &) = Call : func:r0_41, this:r0_40, 0:r0_50 +# 809| mu0_52(unknown) = ^CallSideEffect : ~mu0_2 +# 809| v0_53(void) = ^IndirectReadSideEffect[-1] : &:r0_40, ~mu0_2 +# 809| v0_54(void) = ^IndirectReadSideEffect[0] : &:r0_50, ~mu0_2 +# 809| mu0_55(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_40 +# 809| mu0_56(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_50 +# 810| r0_57(glval) = VariableAddress[b] : +# 810| r0_58(glval) = FunctionAddress[operator=] : +# 810| r0_59(glval) = FunctionAddress[Base] : +# 810| r0_60(glval) = VariableAddress[m] : +# 810| r0_61(glval) = ConvertToBase[Middle : Base] : r0_60 +# 810| v0_62(void) = Call : func:r0_59, 0:r0_61 +# 810| mu0_63(unknown) = ^CallSideEffect : ~mu0_2 +# 810| mu0_64(Base) = ^IndirectMayWriteSideEffect[-1] : +# 810| v0_65(void) = ^IndirectReadSideEffect[0] : &:r0_61, ~mu0_2 +# 810| mu0_66(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_61 +# 810| r0_67(glval) = Convert : v0_62 +# 810| r0_68(Base &) = Call : func:r0_58, this:r0_57, 0:r0_67 +# 810| mu0_69(unknown) = ^CallSideEffect : ~mu0_2 +# 810| v0_70(void) = ^IndirectReadSideEffect[-1] : &:r0_57, ~mu0_2 +# 810| v0_71(void) = ^IndirectReadSideEffect[0] : &:r0_67, ~mu0_2 +# 810| mu0_72(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_57 +# 810| mu0_73(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_67 +# 811| r0_74(glval) = VariableAddress[pm] : +# 811| r0_75(Middle *) = Load : &:r0_74, ~mu0_2 +# 811| r0_76(Base *) = ConvertToBase[Middle : Base] : r0_75 +# 811| r0_77(glval) = VariableAddress[pb] : +# 811| mu0_78(Base *) = Store : &:r0_77, r0_76 +# 812| r0_79(glval) = VariableAddress[pm] : +# 812| r0_80(Middle *) = Load : &:r0_79, ~mu0_2 +# 812| r0_81(Base *) = ConvertToBase[Middle : Base] : r0_80 +# 812| r0_82(glval) = VariableAddress[pb] : +# 812| mu0_83(Base *) = Store : &:r0_82, r0_81 +# 813| r0_84(glval) = VariableAddress[pm] : +# 813| r0_85(Middle *) = Load : &:r0_84, ~mu0_2 +# 813| r0_86(Base *) = ConvertToBase[Middle : Base] : r0_85 +# 813| r0_87(glval) = VariableAddress[pb] : +# 813| mu0_88(Base *) = Store : &:r0_87, r0_86 +# 814| r0_89(glval) = VariableAddress[pm] : +# 814| r0_90(Middle *) = Load : &:r0_89, ~mu0_2 +# 814| r0_91(Base *) = Convert : r0_90 +# 814| r0_92(glval) = VariableAddress[pb] : +# 814| mu0_93(Base *) = Store : &:r0_92, r0_91 +# 816| r0_94(glval) = VariableAddress[m] : +# 816| r0_95(glval) = FunctionAddress[operator=] : +# 816| r0_96(glval) = VariableAddress[b] : +# 816| r0_97(glval) = ConvertToDerived[Middle : Base] : r0_96 +# 816| r0_98(glval) = Convert : r0_97 +# 816| r0_99(Middle &) = Call : func:r0_95, this:r0_94, 0:r0_98 +# 816| mu0_100(unknown) = ^CallSideEffect : ~mu0_2 +# 816| v0_101(void) = ^IndirectReadSideEffect[-1] : &:r0_94, ~mu0_2 +# 816| v0_102(void) = ^IndirectReadSideEffect[0] : &:r0_98, ~mu0_2 +# 816| mu0_103(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_94 +# 816| mu0_104(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_98 +# 817| r0_105(glval) = VariableAddress[m] : +# 817| r0_106(glval) = FunctionAddress[operator=] : +# 817| r0_107(glval) = VariableAddress[b] : +# 817| r0_108(glval) = ConvertToDerived[Middle : Base] : r0_107 +# 817| r0_109(glval) = Convert : r0_108 +# 817| r0_110(Middle &) = Call : func:r0_106, this:r0_105, 0:r0_109 +# 817| mu0_111(unknown) = ^CallSideEffect : ~mu0_2 +# 817| v0_112(void) = ^IndirectReadSideEffect[-1] : &:r0_105, ~mu0_2 +# 817| v0_113(void) = ^IndirectReadSideEffect[0] : &:r0_109, ~mu0_2 +# 817| mu0_114(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_105 +# 817| mu0_115(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_109 +# 818| r0_116(glval) = VariableAddress[pb] : +# 818| r0_117(Base *) = Load : &:r0_116, ~mu0_2 +# 818| r0_118(Middle *) = ConvertToDerived[Middle : Base] : r0_117 +# 818| r0_119(glval) = VariableAddress[pm] : +# 818| mu0_120(Middle *) = Store : &:r0_119, r0_118 +# 819| r0_121(glval) = VariableAddress[pb] : +# 819| r0_122(Base *) = Load : &:r0_121, ~mu0_2 +# 819| r0_123(Middle *) = ConvertToDerived[Middle : Base] : r0_122 +# 819| r0_124(glval) = VariableAddress[pm] : +# 819| mu0_125(Middle *) = Store : &:r0_124, r0_123 +# 820| r0_126(glval) = VariableAddress[pb] : +# 820| r0_127(Base *) = Load : &:r0_126, ~mu0_2 +# 820| r0_128(Middle *) = Convert : r0_127 +# 820| r0_129(glval) = VariableAddress[pm] : +# 820| mu0_130(Middle *) = Store : &:r0_129, r0_128 +# 822| r0_131(glval) = VariableAddress[b] : +# 822| r0_132(glval) = FunctionAddress[operator=] : +# 822| r0_133(glval) = VariableAddress[d] : +# 822| r0_134(glval) = ConvertToBase[Derived : Middle] : r0_133 +# 822| r0_135(glval) = ConvertToBase[Middle : Base] : r0_134 +# 822| r0_136(Base &) = Call : func:r0_132, this:r0_131, 0:r0_135 +# 822| mu0_137(unknown) = ^CallSideEffect : ~mu0_2 +# 822| v0_138(void) = ^IndirectReadSideEffect[-1] : &:r0_131, ~mu0_2 +# 822| v0_139(void) = ^IndirectReadSideEffect[0] : &:r0_135, ~mu0_2 +# 822| mu0_140(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_131 +# 822| mu0_141(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_135 +# 823| r0_142(glval) = VariableAddress[b] : +# 823| r0_143(glval) = FunctionAddress[operator=] : +# 823| r0_144(glval) = FunctionAddress[Base] : +# 823| r0_145(glval) = VariableAddress[d] : +# 823| r0_146(glval) = ConvertToBase[Derived : Middle] : r0_145 +# 823| r0_147(glval) = ConvertToBase[Middle : Base] : r0_146 +# 823| v0_148(void) = Call : func:r0_144, 0:r0_147 +# 823| mu0_149(unknown) = ^CallSideEffect : ~mu0_2 +# 823| mu0_150(Base) = ^IndirectMayWriteSideEffect[-1] : +# 823| v0_151(void) = ^IndirectReadSideEffect[0] : &:r0_147, ~mu0_2 +# 823| mu0_152(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_147 +# 823| r0_153(glval) = Convert : v0_148 +# 823| r0_154(Base &) = Call : func:r0_143, this:r0_142, 0:r0_153 +# 823| mu0_155(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_156(void) = ^IndirectReadSideEffect[-1] : &:r0_142, ~mu0_2 +# 823| v0_157(void) = ^IndirectReadSideEffect[0] : &:r0_153, ~mu0_2 +# 823| mu0_158(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_142 +# 823| mu0_159(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_153 +# 824| r0_160(glval) = VariableAddress[b] : +# 824| r0_161(glval) = FunctionAddress[operator=] : +# 824| r0_162(glval) = FunctionAddress[Base] : +# 824| r0_163(glval) = VariableAddress[d] : +# 824| r0_164(glval) = ConvertToBase[Derived : Middle] : r0_163 +# 824| r0_165(glval) = ConvertToBase[Middle : Base] : r0_164 +# 824| v0_166(void) = Call : func:r0_162, 0:r0_165 +# 824| mu0_167(unknown) = ^CallSideEffect : ~mu0_2 +# 824| mu0_168(Base) = ^IndirectMayWriteSideEffect[-1] : +# 824| v0_169(void) = ^IndirectReadSideEffect[0] : &:r0_165, ~mu0_2 +# 824| mu0_170(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_165 +# 824| r0_171(glval) = Convert : v0_166 +# 824| r0_172(Base &) = Call : func:r0_161, this:r0_160, 0:r0_171 +# 824| mu0_173(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_174(void) = ^IndirectReadSideEffect[-1] : &:r0_160, ~mu0_2 +# 824| v0_175(void) = ^IndirectReadSideEffect[0] : &:r0_171, ~mu0_2 +# 824| mu0_176(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_160 +# 824| mu0_177(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_171 +# 825| r0_178(glval) = VariableAddress[pd] : +# 825| r0_179(Derived *) = Load : &:r0_178, ~mu0_2 +# 825| r0_180(Middle *) = ConvertToBase[Derived : Middle] : r0_179 +# 825| r0_181(Base *) = ConvertToBase[Middle : Base] : r0_180 +# 825| r0_182(glval) = VariableAddress[pb] : +# 825| mu0_183(Base *) = Store : &:r0_182, r0_181 +# 826| r0_184(glval) = VariableAddress[pd] : +# 826| r0_185(Derived *) = Load : &:r0_184, ~mu0_2 +# 826| r0_186(Middle *) = ConvertToBase[Derived : Middle] : r0_185 +# 826| r0_187(Base *) = ConvertToBase[Middle : Base] : r0_186 +# 826| r0_188(glval) = VariableAddress[pb] : +# 826| mu0_189(Base *) = Store : &:r0_188, r0_187 +# 827| r0_190(glval) = VariableAddress[pd] : +# 827| r0_191(Derived *) = Load : &:r0_190, ~mu0_2 +# 827| r0_192(Middle *) = ConvertToBase[Derived : Middle] : r0_191 +# 827| r0_193(Base *) = ConvertToBase[Middle : Base] : r0_192 +# 827| r0_194(glval) = VariableAddress[pb] : +# 827| mu0_195(Base *) = Store : &:r0_194, r0_193 +# 828| r0_196(glval) = VariableAddress[pd] : +# 828| r0_197(Derived *) = Load : &:r0_196, ~mu0_2 +# 828| r0_198(Base *) = Convert : r0_197 +# 828| r0_199(glval) = VariableAddress[pb] : +# 828| mu0_200(Base *) = Store : &:r0_199, r0_198 +# 830| r0_201(glval) = VariableAddress[d] : +# 830| r0_202(glval) = FunctionAddress[operator=] : +# 830| r0_203(glval) = VariableAddress[b] : +# 830| r0_204(glval) = ConvertToDerived[Middle : Base] : r0_203 +# 830| r0_205(glval) = ConvertToDerived[Derived : Middle] : r0_204 +# 830| r0_206(glval) = Convert : r0_205 +# 830| r0_207(Derived &) = Call : func:r0_202, this:r0_201, 0:r0_206 +# 830| mu0_208(unknown) = ^CallSideEffect : ~mu0_2 +# 830| v0_209(void) = ^IndirectReadSideEffect[-1] : &:r0_201, ~mu0_2 +# 830| v0_210(void) = ^IndirectReadSideEffect[0] : &:r0_206, ~mu0_2 +# 830| mu0_211(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_201 +# 830| mu0_212(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_206 +# 831| r0_213(glval) = VariableAddress[d] : +# 831| r0_214(glval) = FunctionAddress[operator=] : +# 831| r0_215(glval) = VariableAddress[b] : +# 831| r0_216(glval) = ConvertToDerived[Middle : Base] : r0_215 +# 831| r0_217(glval) = ConvertToDerived[Derived : Middle] : r0_216 +# 831| r0_218(glval) = Convert : r0_217 +# 831| r0_219(Derived &) = Call : func:r0_214, this:r0_213, 0:r0_218 +# 831| mu0_220(unknown) = ^CallSideEffect : ~mu0_2 +# 831| v0_221(void) = ^IndirectReadSideEffect[-1] : &:r0_213, ~mu0_2 +# 831| v0_222(void) = ^IndirectReadSideEffect[0] : &:r0_218, ~mu0_2 +# 831| mu0_223(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_213 +# 831| mu0_224(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_218 +# 832| r0_225(glval) = VariableAddress[pb] : +# 832| r0_226(Base *) = Load : &:r0_225, ~mu0_2 +# 832| r0_227(Middle *) = ConvertToDerived[Middle : Base] : r0_226 +# 832| r0_228(Derived *) = ConvertToDerived[Derived : Middle] : r0_227 +# 832| r0_229(glval) = VariableAddress[pd] : +# 832| mu0_230(Derived *) = Store : &:r0_229, r0_228 +# 833| r0_231(glval) = VariableAddress[pb] : +# 833| r0_232(Base *) = Load : &:r0_231, ~mu0_2 +# 833| r0_233(Middle *) = ConvertToDerived[Middle : Base] : r0_232 +# 833| r0_234(Derived *) = ConvertToDerived[Derived : Middle] : r0_233 +# 833| r0_235(glval) = VariableAddress[pd] : +# 833| mu0_236(Derived *) = Store : &:r0_235, r0_234 +# 834| r0_237(glval) = VariableAddress[pb] : +# 834| r0_238(Base *) = Load : &:r0_237, ~mu0_2 +# 834| r0_239(Derived *) = Convert : r0_238 +# 834| r0_240(glval) = VariableAddress[pd] : +# 834| mu0_241(Derived *) = Store : &:r0_240, r0_239 +# 836| r0_242(glval) = VariableAddress[pmv] : +# 836| r0_243(MiddleVB1 *) = Constant[0] : +# 836| mu0_244(MiddleVB1 *) = Store : &:r0_242, r0_243 +# 837| r0_245(glval) = VariableAddress[pdv] : +# 837| r0_246(DerivedVB *) = Constant[0] : +# 837| mu0_247(DerivedVB *) = Store : &:r0_245, r0_246 +# 838| r0_248(glval) = VariableAddress[pmv] : +# 838| r0_249(MiddleVB1 *) = Load : &:r0_248, ~mu0_2 +# 838| r0_250(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_249 +# 838| r0_251(glval) = VariableAddress[pb] : +# 838| mu0_252(Base *) = Store : &:r0_251, r0_250 +# 839| r0_253(glval) = VariableAddress[pdv] : +# 839| r0_254(DerivedVB *) = Load : &:r0_253, ~mu0_2 +# 839| r0_255(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_254 +# 839| r0_256(glval) = VariableAddress[pb] : +# 839| mu0_257(Base *) = Store : &:r0_256, r0_255 +# 840| v0_258(void) = NoOp : +# 799| v0_259(void) = ReturnVoid : +# 799| v0_260(void) = UnmodeledUse : mu* +# 799| v0_261(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -3944,53 +3950,55 @@ ir.cpp: # 849| mu0_1(unknown) = AliasedDefinition : # 849| mu0_2(unknown) = UnmodeledDefinition : # 850| r0_3(glval) = VariableAddress[b] : -#-----| r0_4(glval) = FunctionAddress[PolymorphicBase] : -#-----| v0_5(void) = Call : func:r0_4, this:r0_3 -#-----| mu0_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_7(PolymorphicBase) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 851| r0_8(glval) = VariableAddress[d] : -# 851| r0_9(glval) = FunctionAddress[PolymorphicDerived] : -# 851| v0_10(void) = Call : func:r0_9, this:r0_8 -# 851| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 -# 851| mu0_12(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r0_8 -# 853| r0_13(glval) = VariableAddress[pb] : -# 853| r0_14(glval) = VariableAddress[b] : -# 853| mu0_15(PolymorphicBase *) = Store : &:r0_13, r0_14 -# 854| r0_16(glval) = VariableAddress[pd] : -# 854| r0_17(glval) = VariableAddress[d] : -# 854| mu0_18(PolymorphicDerived *) = Store : &:r0_16, r0_17 -# 857| r0_19(glval) = VariableAddress[pd] : -# 857| r0_20(PolymorphicDerived *) = Load : &:r0_19, ~mu0_2 -# 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 -# 857| r0_22(glval) = VariableAddress[pb] : -# 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 -# 858| r0_24(glval) = VariableAddress[rb] : -# 858| r0_25(glval) = VariableAddress[d] : -# 858| r0_26(glval) = CheckedConvertOrThrow : r0_25 -# 858| mu0_27(PolymorphicBase &) = Store : &:r0_24, r0_26 -# 860| r0_28(glval) = VariableAddress[pb] : -# 860| r0_29(PolymorphicBase *) = Load : &:r0_28, ~mu0_2 -# 860| r0_30(PolymorphicDerived *) = CheckedConvertOrNull : r0_29 -# 860| r0_31(glval) = VariableAddress[pd] : -# 860| mu0_32(PolymorphicDerived *) = Store : &:r0_31, r0_30 -# 861| r0_33(glval) = VariableAddress[rd] : -# 861| r0_34(glval) = VariableAddress[b] : -# 861| r0_35(glval) = CheckedConvertOrThrow : r0_34 -# 861| mu0_36(PolymorphicDerived &) = Store : &:r0_33, r0_35 -# 863| r0_37(glval) = VariableAddress[pv] : -# 863| r0_38(glval) = VariableAddress[pb] : -# 863| r0_39(PolymorphicBase *) = Load : &:r0_38, ~mu0_2 -# 863| r0_40(void *) = DynamicCastToVoid : r0_39 -# 863| mu0_41(void *) = Store : &:r0_37, r0_40 -# 864| r0_42(glval) = VariableAddress[pcv] : -# 864| r0_43(glval) = VariableAddress[pd] : -# 864| r0_44(PolymorphicDerived *) = Load : &:r0_43, ~mu0_2 -# 864| r0_45(void *) = DynamicCastToVoid : r0_44 -# 864| mu0_46(void *) = Store : &:r0_42, r0_45 -# 865| v0_47(void) = NoOp : -# 849| v0_48(void) = ReturnVoid : -# 849| v0_49(void) = UnmodeledUse : mu* -# 849| v0_50(void) = ExitFunction : +# 850| mu0_4(PolymorphicBase) = Uninitialized[b] : &:r0_3 +#-----| r0_5(glval) = FunctionAddress[PolymorphicBase] : +#-----| v0_6(void) = Call : func:r0_5, this:r0_3 +#-----| mu0_7(unknown) = ^CallSideEffect : ~mu0_2 +#-----| mu0_8(PolymorphicBase) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 851| r0_9(glval) = VariableAddress[d] : +# 851| mu0_10(PolymorphicDerived) = Uninitialized[d] : &:r0_9 +# 851| r0_11(glval) = FunctionAddress[PolymorphicDerived] : +# 851| v0_12(void) = Call : func:r0_11, this:r0_9 +# 851| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 +# 851| mu0_14(PolymorphicDerived) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +# 853| r0_15(glval) = VariableAddress[pb] : +# 853| r0_16(glval) = VariableAddress[b] : +# 853| mu0_17(PolymorphicBase *) = Store : &:r0_15, r0_16 +# 854| r0_18(glval) = VariableAddress[pd] : +# 854| r0_19(glval) = VariableAddress[d] : +# 854| mu0_20(PolymorphicDerived *) = Store : &:r0_18, r0_19 +# 857| r0_21(glval) = VariableAddress[pd] : +# 857| r0_22(PolymorphicDerived *) = Load : &:r0_21, ~mu0_2 +# 857| r0_23(PolymorphicBase *) = CheckedConvertOrNull : r0_22 +# 857| r0_24(glval) = VariableAddress[pb] : +# 857| mu0_25(PolymorphicBase *) = Store : &:r0_24, r0_23 +# 858| r0_26(glval) = VariableAddress[rb] : +# 858| r0_27(glval) = VariableAddress[d] : +# 858| r0_28(glval) = CheckedConvertOrThrow : r0_27 +# 858| mu0_29(PolymorphicBase &) = Store : &:r0_26, r0_28 +# 860| r0_30(glval) = VariableAddress[pb] : +# 860| r0_31(PolymorphicBase *) = Load : &:r0_30, ~mu0_2 +# 860| r0_32(PolymorphicDerived *) = CheckedConvertOrNull : r0_31 +# 860| r0_33(glval) = VariableAddress[pd] : +# 860| mu0_34(PolymorphicDerived *) = Store : &:r0_33, r0_32 +# 861| r0_35(glval) = VariableAddress[rd] : +# 861| r0_36(glval) = VariableAddress[b] : +# 861| r0_37(glval) = CheckedConvertOrThrow : r0_36 +# 861| mu0_38(PolymorphicDerived &) = Store : &:r0_35, r0_37 +# 863| r0_39(glval) = VariableAddress[pv] : +# 863| r0_40(glval) = VariableAddress[pb] : +# 863| r0_41(PolymorphicBase *) = Load : &:r0_40, ~mu0_2 +# 863| r0_42(void *) = DynamicCastToVoid : r0_41 +# 863| mu0_43(void *) = Store : &:r0_39, r0_42 +# 864| r0_44(glval) = VariableAddress[pcv] : +# 864| r0_45(glval) = VariableAddress[pd] : +# 864| r0_46(PolymorphicDerived *) = Load : &:r0_45, ~mu0_2 +# 864| r0_47(void *) = DynamicCastToVoid : r0_46 +# 864| mu0_48(void *) = Store : &:r0_44, r0_47 +# 865| v0_49(void) = NoOp : +# 849| v0_50(void) = ReturnVoid : +# 849| v0_51(void) = UnmodeledUse : mu* +# 849| v0_52(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -4714,133 +4722,135 @@ ir.cpp: # 1035| v0_31(void) = ^IndirectReadSideEffect[-1] : &:r0_26, ~mu0_2 # 1035| mu0_32(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_26 # 1036| r0_33(glval) = VariableAddress[lambda_val] : -# 1036| r0_34(glval) = FunctionAddress[(constructor)] : -# 1036| r0_35(glval) = VariableAddress[#temp1036:21] : -# 1036| mu0_36(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_35 -# 1036| r0_37(glval) = FieldAddress[s] : r0_35 -#-----| r0_38(glval) = FunctionAddress[String] : -#-----| v0_39(void) = Call : func:r0_38, this:r0_37 -#-----| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_41(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_37 -# 1036| r0_42(glval) = FieldAddress[x] : r0_35 -#-----| r0_43(glval) = VariableAddress[x] : -#-----| r0_44(int) = Load : &:r0_43, ~mu0_2 -#-----| mu0_45(int) = Store : &:r0_42, r0_44 -# 1036| r0_46(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 -# 1036| v0_47(void) = Call : func:r0_34, this:r0_33, 0:r0_46 -# 1036| mu0_48(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| mu0_49(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_33 -# 1036| v0_50(void) = ^IndirectReadSideEffect[0] : &:r0_46, ~mu0_2 -# 1036| mu0_51(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_46 -# 1037| r0_52(glval) = VariableAddress[lambda_val] : -# 1037| r0_53(glval) = Convert : r0_52 -# 1037| r0_54(glval) = FunctionAddress[operator()] : -# 1037| r0_55(float) = Constant[2.0] : -# 1037| r0_56(char) = Call : func:r0_54, this:r0_53, 0:r0_55 -# 1037| mu0_57(unknown) = ^CallSideEffect : ~mu0_2 -# 1037| v0_58(void) = ^IndirectReadSideEffect[-1] : &:r0_53, ~mu0_2 -# 1037| mu0_59(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_53 -# 1038| r0_60(glval) = VariableAddress[lambda_ref_explicit] : -# 1038| r0_61(glval) = VariableAddress[#temp1038:30] : -# 1038| mu0_62(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_61 -# 1038| r0_63(glval) = FieldAddress[s] : r0_61 -# 1038| r0_64(glval) = VariableAddress[s] : -# 1038| r0_65(String &) = Load : &:r0_64, ~mu0_2 -# 1038| mu0_66(String &) = Store : &:r0_63, r0_65 -# 1038| r0_67(decltype([...](...){...})) = Load : &:r0_61, ~mu0_2 -# 1038| mu0_68(decltype([...](...){...})) = Store : &:r0_60, r0_67 -# 1039| r0_69(glval) = VariableAddress[lambda_ref_explicit] : -# 1039| r0_70(glval) = Convert : r0_69 -# 1039| r0_71(glval) = FunctionAddress[operator()] : -# 1039| r0_72(float) = Constant[3.0] : -# 1039| r0_73(char) = Call : func:r0_71, this:r0_70, 0:r0_72 -# 1039| mu0_74(unknown) = ^CallSideEffect : ~mu0_2 -# 1039| v0_75(void) = ^IndirectReadSideEffect[-1] : &:r0_70, ~mu0_2 -# 1039| mu0_76(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_70 -# 1040| r0_77(glval) = VariableAddress[lambda_val_explicit] : -# 1040| r0_78(glval) = FunctionAddress[(constructor)] : -# 1040| r0_79(glval) = VariableAddress[#temp1040:30] : -# 1040| mu0_80(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_79 -# 1040| r0_81(glval) = FieldAddress[s] : r0_79 -#-----| r0_82(glval) = FunctionAddress[String] : -#-----| v0_83(void) = Call : func:r0_82, this:r0_81 -#-----| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 -#-----| mu0_85(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_81 -# 1040| r0_86(decltype([...](...){...})) = Load : &:r0_79, ~mu0_2 -# 1040| v0_87(void) = Call : func:r0_78, this:r0_77, 0:r0_86 -# 1040| mu0_88(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| mu0_89(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_77 -# 1040| v0_90(void) = ^IndirectReadSideEffect[0] : &:r0_86, ~mu0_2 -# 1040| mu0_91(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_86 -# 1041| r0_92(glval) = VariableAddress[lambda_val_explicit] : -# 1041| r0_93(glval) = Convert : r0_92 -# 1041| r0_94(glval) = FunctionAddress[operator()] : -# 1041| r0_95(float) = Constant[4.0] : -# 1041| r0_96(char) = Call : func:r0_94, this:r0_93, 0:r0_95 -# 1041| mu0_97(unknown) = ^CallSideEffect : ~mu0_2 -# 1041| v0_98(void) = ^IndirectReadSideEffect[-1] : &:r0_93, ~mu0_2 -# 1041| mu0_99(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_93 -# 1042| r0_100(glval) = VariableAddress[lambda_mixed_explicit] : -# 1042| r0_101(glval) = VariableAddress[#temp1042:32] : -# 1042| mu0_102(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_101 -# 1042| r0_103(glval) = FieldAddress[s] : r0_101 -# 1042| r0_104(glval) = VariableAddress[s] : -# 1042| r0_105(String &) = Load : &:r0_104, ~mu0_2 -# 1042| mu0_106(String &) = Store : &:r0_103, r0_105 -# 1042| r0_107(glval) = FieldAddress[x] : r0_101 -# 1042| r0_108(glval) = VariableAddress[x] : -# 1042| r0_109(int) = Load : &:r0_108, ~mu0_2 -# 1042| mu0_110(int) = Store : &:r0_107, r0_109 -# 1042| r0_111(decltype([...](...){...})) = Load : &:r0_101, ~mu0_2 -# 1042| mu0_112(decltype([...](...){...})) = Store : &:r0_100, r0_111 -# 1043| r0_113(glval) = VariableAddress[lambda_mixed_explicit] : -# 1043| r0_114(glval) = Convert : r0_113 -# 1043| r0_115(glval) = FunctionAddress[operator()] : -# 1043| r0_116(float) = Constant[5.0] : -# 1043| r0_117(char) = Call : func:r0_115, this:r0_114, 0:r0_116 -# 1043| mu0_118(unknown) = ^CallSideEffect : ~mu0_2 -# 1043| v0_119(void) = ^IndirectReadSideEffect[-1] : &:r0_114, ~mu0_2 -# 1043| mu0_120(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_114 -# 1044| r0_121(glval) = VariableAddress[r] : -# 1044| r0_122(glval) = VariableAddress[x] : -# 1044| r0_123(int) = Load : &:r0_122, ~mu0_2 -# 1044| r0_124(int) = Constant[1] : -# 1044| r0_125(int) = Sub : r0_123, r0_124 -# 1044| mu0_126(int) = Store : &:r0_121, r0_125 -# 1045| r0_127(glval) = VariableAddress[lambda_inits] : -# 1045| r0_128(glval) = VariableAddress[#temp1045:23] : -# 1045| mu0_129(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_128 -# 1045| r0_130(glval) = FieldAddress[s] : r0_128 -# 1045| r0_131(glval) = VariableAddress[s] : -# 1045| r0_132(String &) = Load : &:r0_131, ~mu0_2 -# 1045| mu0_133(String &) = Store : &:r0_130, r0_132 -# 1045| r0_134(glval) = FieldAddress[x] : r0_128 -# 1045| r0_135(glval) = VariableAddress[x] : -# 1045| r0_136(int) = Load : &:r0_135, ~mu0_2 -# 1045| mu0_137(int) = Store : &:r0_134, r0_136 -# 1045| r0_138(glval) = FieldAddress[i] : r0_128 -# 1045| r0_139(glval) = VariableAddress[x] : -# 1045| r0_140(int) = Load : &:r0_139, ~mu0_2 -# 1045| r0_141(int) = Constant[1] : -# 1045| r0_142(int) = Add : r0_140, r0_141 -# 1045| mu0_143(int) = Store : &:r0_138, r0_142 -# 1045| r0_144(glval) = FieldAddress[j] : r0_128 -# 1045| r0_145(glval) = VariableAddress[r] : -# 1045| mu0_146(int &) = Store : &:r0_144, r0_145 -# 1045| r0_147(decltype([...](...){...})) = Load : &:r0_128, ~mu0_2 -# 1045| mu0_148(decltype([...](...){...})) = Store : &:r0_127, r0_147 -# 1046| r0_149(glval) = VariableAddress[lambda_inits] : -# 1046| r0_150(glval) = Convert : r0_149 -# 1046| r0_151(glval) = FunctionAddress[operator()] : -# 1046| r0_152(float) = Constant[6.0] : -# 1046| r0_153(char) = Call : func:r0_151, this:r0_150, 0:r0_152 -# 1046| mu0_154(unknown) = ^CallSideEffect : ~mu0_2 -# 1046| v0_155(void) = ^IndirectReadSideEffect[-1] : &:r0_150, ~mu0_2 -# 1046| mu0_156(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_150 -# 1047| v0_157(void) = NoOp : -# 1031| v0_158(void) = ReturnVoid : -# 1031| v0_159(void) = UnmodeledUse : mu* -# 1031| v0_160(void) = ExitFunction : +# 1036| mu0_34(decltype([...](...){...})) = Uninitialized[lambda_val] : &:r0_33 +# 1036| r0_35(glval) = FunctionAddress[(constructor)] : +# 1036| r0_36(glval) = VariableAddress[#temp1036:21] : +# 1036| mu0_37(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_36 +# 1036| r0_38(glval) = FieldAddress[s] : r0_36 +#-----| r0_39(glval) = FunctionAddress[String] : +#-----| v0_40(void) = Call : func:r0_39, this:r0_38 +#-----| mu0_41(unknown) = ^CallSideEffect : ~mu0_2 +#-----| mu0_42(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_38 +# 1036| r0_43(glval) = FieldAddress[x] : r0_36 +#-----| r0_44(glval) = VariableAddress[x] : +#-----| r0_45(int) = Load : &:r0_44, ~mu0_2 +#-----| mu0_46(int) = Store : &:r0_43, r0_45 +# 1036| r0_47(decltype([...](...){...})) = Load : &:r0_36, ~mu0_2 +# 1036| v0_48(void) = Call : func:r0_35, this:r0_33, 0:r0_47 +# 1036| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| mu0_50(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_33 +# 1036| v0_51(void) = ^IndirectReadSideEffect[0] : &:r0_47, ~mu0_2 +# 1036| mu0_52(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_47 +# 1037| r0_53(glval) = VariableAddress[lambda_val] : +# 1037| r0_54(glval) = Convert : r0_53 +# 1037| r0_55(glval) = FunctionAddress[operator()] : +# 1037| r0_56(float) = Constant[2.0] : +# 1037| r0_57(char) = Call : func:r0_55, this:r0_54, 0:r0_56 +# 1037| mu0_58(unknown) = ^CallSideEffect : ~mu0_2 +# 1037| v0_59(void) = ^IndirectReadSideEffect[-1] : &:r0_54, ~mu0_2 +# 1037| mu0_60(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_54 +# 1038| r0_61(glval) = VariableAddress[lambda_ref_explicit] : +# 1038| r0_62(glval) = VariableAddress[#temp1038:30] : +# 1038| mu0_63(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_62 +# 1038| r0_64(glval) = FieldAddress[s] : r0_62 +# 1038| r0_65(glval) = VariableAddress[s] : +# 1038| r0_66(String &) = Load : &:r0_65, ~mu0_2 +# 1038| mu0_67(String &) = Store : &:r0_64, r0_66 +# 1038| r0_68(decltype([...](...){...})) = Load : &:r0_62, ~mu0_2 +# 1038| mu0_69(decltype([...](...){...})) = Store : &:r0_61, r0_68 +# 1039| r0_70(glval) = VariableAddress[lambda_ref_explicit] : +# 1039| r0_71(glval) = Convert : r0_70 +# 1039| r0_72(glval) = FunctionAddress[operator()] : +# 1039| r0_73(float) = Constant[3.0] : +# 1039| r0_74(char) = Call : func:r0_72, this:r0_71, 0:r0_73 +# 1039| mu0_75(unknown) = ^CallSideEffect : ~mu0_2 +# 1039| v0_76(void) = ^IndirectReadSideEffect[-1] : &:r0_71, ~mu0_2 +# 1039| mu0_77(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_71 +# 1040| r0_78(glval) = VariableAddress[lambda_val_explicit] : +# 1040| mu0_79(decltype([...](...){...})) = Uninitialized[lambda_val_explicit] : &:r0_78 +# 1040| r0_80(glval) = FunctionAddress[(constructor)] : +# 1040| r0_81(glval) = VariableAddress[#temp1040:30] : +# 1040| mu0_82(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_81 +# 1040| r0_83(glval) = FieldAddress[s] : r0_81 +#-----| r0_84(glval) = FunctionAddress[String] : +#-----| v0_85(void) = Call : func:r0_84, this:r0_83 +#-----| mu0_86(unknown) = ^CallSideEffect : ~mu0_2 +#-----| mu0_87(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_83 +# 1040| r0_88(decltype([...](...){...})) = Load : &:r0_81, ~mu0_2 +# 1040| v0_89(void) = Call : func:r0_80, this:r0_78, 0:r0_88 +# 1040| mu0_90(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| mu0_91(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_78 +# 1040| v0_92(void) = ^IndirectReadSideEffect[0] : &:r0_88, ~mu0_2 +# 1040| mu0_93(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_88 +# 1041| r0_94(glval) = VariableAddress[lambda_val_explicit] : +# 1041| r0_95(glval) = Convert : r0_94 +# 1041| r0_96(glval) = FunctionAddress[operator()] : +# 1041| r0_97(float) = Constant[4.0] : +# 1041| r0_98(char) = Call : func:r0_96, this:r0_95, 0:r0_97 +# 1041| mu0_99(unknown) = ^CallSideEffect : ~mu0_2 +# 1041| v0_100(void) = ^IndirectReadSideEffect[-1] : &:r0_95, ~mu0_2 +# 1041| mu0_101(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_95 +# 1042| r0_102(glval) = VariableAddress[lambda_mixed_explicit] : +# 1042| r0_103(glval) = VariableAddress[#temp1042:32] : +# 1042| mu0_104(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_103 +# 1042| r0_105(glval) = FieldAddress[s] : r0_103 +# 1042| r0_106(glval) = VariableAddress[s] : +# 1042| r0_107(String &) = Load : &:r0_106, ~mu0_2 +# 1042| mu0_108(String &) = Store : &:r0_105, r0_107 +# 1042| r0_109(glval) = FieldAddress[x] : r0_103 +# 1042| r0_110(glval) = VariableAddress[x] : +# 1042| r0_111(int) = Load : &:r0_110, ~mu0_2 +# 1042| mu0_112(int) = Store : &:r0_109, r0_111 +# 1042| r0_113(decltype([...](...){...})) = Load : &:r0_103, ~mu0_2 +# 1042| mu0_114(decltype([...](...){...})) = Store : &:r0_102, r0_113 +# 1043| r0_115(glval) = VariableAddress[lambda_mixed_explicit] : +# 1043| r0_116(glval) = Convert : r0_115 +# 1043| r0_117(glval) = FunctionAddress[operator()] : +# 1043| r0_118(float) = Constant[5.0] : +# 1043| r0_119(char) = Call : func:r0_117, this:r0_116, 0:r0_118 +# 1043| mu0_120(unknown) = ^CallSideEffect : ~mu0_2 +# 1043| v0_121(void) = ^IndirectReadSideEffect[-1] : &:r0_116, ~mu0_2 +# 1043| mu0_122(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_116 +# 1044| r0_123(glval) = VariableAddress[r] : +# 1044| r0_124(glval) = VariableAddress[x] : +# 1044| r0_125(int) = Load : &:r0_124, ~mu0_2 +# 1044| r0_126(int) = Constant[1] : +# 1044| r0_127(int) = Sub : r0_125, r0_126 +# 1044| mu0_128(int) = Store : &:r0_123, r0_127 +# 1045| r0_129(glval) = VariableAddress[lambda_inits] : +# 1045| r0_130(glval) = VariableAddress[#temp1045:23] : +# 1045| mu0_131(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_130 +# 1045| r0_132(glval) = FieldAddress[s] : r0_130 +# 1045| r0_133(glval) = VariableAddress[s] : +# 1045| r0_134(String &) = Load : &:r0_133, ~mu0_2 +# 1045| mu0_135(String &) = Store : &:r0_132, r0_134 +# 1045| r0_136(glval) = FieldAddress[x] : r0_130 +# 1045| r0_137(glval) = VariableAddress[x] : +# 1045| r0_138(int) = Load : &:r0_137, ~mu0_2 +# 1045| mu0_139(int) = Store : &:r0_136, r0_138 +# 1045| r0_140(glval) = FieldAddress[i] : r0_130 +# 1045| r0_141(glval) = VariableAddress[x] : +# 1045| r0_142(int) = Load : &:r0_141, ~mu0_2 +# 1045| r0_143(int) = Constant[1] : +# 1045| r0_144(int) = Add : r0_142, r0_143 +# 1045| mu0_145(int) = Store : &:r0_140, r0_144 +# 1045| r0_146(glval) = FieldAddress[j] : r0_130 +# 1045| r0_147(glval) = VariableAddress[r] : +# 1045| mu0_148(int &) = Store : &:r0_146, r0_147 +# 1045| r0_149(decltype([...](...){...})) = Load : &:r0_130, ~mu0_2 +# 1045| mu0_150(decltype([...](...){...})) = Store : &:r0_129, r0_149 +# 1046| r0_151(glval) = VariableAddress[lambda_inits] : +# 1046| r0_152(glval) = Convert : r0_151 +# 1046| r0_153(glval) = FunctionAddress[operator()] : +# 1046| r0_154(float) = Constant[6.0] : +# 1046| r0_155(char) = Call : func:r0_153, this:r0_152, 0:r0_154 +# 1046| mu0_156(unknown) = ^CallSideEffect : ~mu0_2 +# 1046| v0_157(void) = ^IndirectReadSideEffect[-1] : &:r0_152, ~mu0_2 +# 1046| mu0_158(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_152 +# 1047| v0_159(void) = NoOp : +# 1031| v0_160(void) = ReturnVoid : +# 1031| v0_161(void) = UnmodeledUse : mu* +# 1031| v0_162(void) = ExitFunction : # 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&) # 1032| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 813d7a9bdcde..84dca0766911 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -884,36 +884,41 @@ ssa.cpp: # 220| m0_8(unknown) = ^CallSideEffect : ~m0_1 # 220| m0_9(unknown) = Chi : total:m0_1, partial:m0_8 # 220| m0_10(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 221| r0_11(glval) = VariableAddress[c] : -# 221| r0_12(glval) = FunctionAddress[g] : -# 221| v0_13(void) = Call : func:r0_12, this:r0_11 -# 221| m0_14(unknown) = ^CallSideEffect : ~m0_9 -# 221| m0_15(unknown) = Chi : total:m0_9, partial:m0_14 -# 221| v0_16(void) = ^IndirectReadSideEffect[-1] : &:r0_11, m0_10 -# 221| m0_17(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 -# 222| r0_18(glval) = VariableAddress[c] : -# 222| r0_19(glval) = FunctionAddress[g] : -# 222| v0_20(void) = Call : func:r0_19, this:r0_18 -# 222| m0_21(unknown) = ^CallSideEffect : ~m0_15 -# 222| m0_22(unknown) = Chi : total:m0_15, partial:m0_21 -# 222| v0_23(void) = ^IndirectReadSideEffect[-1] : &:r0_18, m0_17 -# 222| m0_24(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_18 -# 223| r0_25(glval) = VariableAddress[c2] : -# 223| m0_26(Constructible) = Uninitialized[c2] : &:r0_25 -# 223| r0_27(glval) = FunctionAddress[Constructible] : -# 223| r0_28(int) = Constant[2] : -# 223| v0_29(void) = Call : func:r0_27, this:r0_25, 0:r0_28 -# 223| m0_30(unknown) = ^CallSideEffect : ~m0_22 -# 223| m0_31(unknown) = Chi : total:m0_22, partial:m0_30 -# 223| m0_32(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_25 -# 224| r0_33(glval) = VariableAddress[c2] : -# 224| r0_34(glval) = FunctionAddress[g] : -# 224| v0_35(void) = Call : func:r0_34, this:r0_33 -# 224| m0_36(unknown) = ^CallSideEffect : ~m0_31 -# 224| m0_37(unknown) = Chi : total:m0_31, partial:m0_36 -# 224| v0_38(void) = ^IndirectReadSideEffect[-1] : &:r0_33, m0_32 -# 224| m0_39(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_33 -# 225| v0_40(void) = NoOp : -# 219| v0_41(void) = ReturnVoid : -# 219| v0_42(void) = UnmodeledUse : mu* -# 219| v0_43(void) = ExitFunction : +# 220| m0_11(Constructible) = Chi : total:m0_10, partial:m0_10 +# 221| r0_12(glval) = VariableAddress[c] : +# 221| r0_13(glval) = FunctionAddress[g] : +# 221| v0_14(void) = Call : func:r0_13, this:r0_12 +# 221| m0_15(unknown) = ^CallSideEffect : ~m0_9 +# 221| m0_16(unknown) = Chi : total:m0_9, partial:m0_15 +# 221| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_12, m0_10 +# 221| m0_18(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_12 +# 221| m0_19(Constructible) = Chi : total:m0_18, partial:m0_18 +# 222| r0_20(glval) = VariableAddress[c] : +# 222| r0_21(glval) = FunctionAddress[g] : +# 222| v0_22(void) = Call : func:r0_21, this:r0_20 +# 222| m0_23(unknown) = ^CallSideEffect : ~m0_16 +# 222| m0_24(unknown) = Chi : total:m0_16, partial:m0_23 +# 222| v0_25(void) = ^IndirectReadSideEffect[-1] : &:r0_20, m0_18 +# 222| m0_26(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_20 +# 222| m0_27(Constructible) = Chi : total:m0_26, partial:m0_26 +# 223| r0_28(glval) = VariableAddress[c2] : +# 223| m0_29(Constructible) = Uninitialized[c2] : &:r0_28 +# 223| r0_30(glval) = FunctionAddress[Constructible] : +# 223| r0_31(int) = Constant[2] : +# 223| v0_32(void) = Call : func:r0_30, this:r0_28, 0:r0_31 +# 223| m0_33(unknown) = ^CallSideEffect : ~m0_24 +# 223| m0_34(unknown) = Chi : total:m0_24, partial:m0_33 +# 223| m0_35(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_28 +# 223| m0_36(Constructible) = Chi : total:m0_35, partial:m0_35 +# 224| r0_37(glval) = VariableAddress[c2] : +# 224| r0_38(glval) = FunctionAddress[g] : +# 224| v0_39(void) = Call : func:r0_38, this:r0_37 +# 224| m0_40(unknown) = ^CallSideEffect : ~m0_34 +# 224| m0_41(unknown) = Chi : total:m0_34, partial:m0_40 +# 224| v0_42(void) = ^IndirectReadSideEffect[-1] : &:r0_37, m0_35 +# 224| m0_43(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_37 +# 224| m0_44(Constructible) = Chi : total:m0_43, partial:m0_43 +# 225| v0_45(void) = NoOp : +# 219| v0_46(void) = ReturnVoid : +# 219| v0_47(void) = UnmodeledUse : mu* +# 219| v0_48(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 029c552f5d5b..a94e99610b1a 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -837,37 +837,37 @@ ssa.cpp: # 219| mu0_1(unknown) = AliasedDefinition : # 219| mu0_2(unknown) = UnmodeledDefinition : # 220| r0_3(glval) = VariableAddress[c] : -# 220| m0_4(Constructible) = Uninitialized[c] : &:r0_3 +# 220| mu0_4(Constructible) = Uninitialized[c] : &:r0_3 # 220| r0_5(glval) = FunctionAddress[Constructible] : # 220| r0_6(int) = Constant[1] : # 220| v0_7(void) = Call : func:r0_5, this:r0_3, 0:r0_6 # 220| mu0_8(unknown) = ^CallSideEffect : ~mu0_2 -# 220| m0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 +# 220| mu0_9(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 # 221| r0_10(glval) = VariableAddress[c] : # 221| r0_11(glval) = FunctionAddress[g] : # 221| v0_12(void) = Call : func:r0_11, this:r0_10 # 221| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -# 221| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_10, m0_9 -# 221| m0_15(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 +# 221| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_10, ~mu0_2 +# 221| mu0_15(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_10 # 222| r0_16(glval) = VariableAddress[c] : # 222| r0_17(glval) = FunctionAddress[g] : # 222| v0_18(void) = Call : func:r0_17, this:r0_16 # 222| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 -# 222| v0_20(void) = ^IndirectReadSideEffect[-1] : &:r0_16, m0_15 -# 222| m0_21(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_16 +# 222| v0_20(void) = ^IndirectReadSideEffect[-1] : &:r0_16, ~mu0_2 +# 222| mu0_21(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_16 # 223| r0_22(glval) = VariableAddress[c2] : -# 223| m0_23(Constructible) = Uninitialized[c2] : &:r0_22 +# 223| mu0_23(Constructible) = Uninitialized[c2] : &:r0_22 # 223| r0_24(glval) = FunctionAddress[Constructible] : # 223| r0_25(int) = Constant[2] : # 223| v0_26(void) = Call : func:r0_24, this:r0_22, 0:r0_25 # 223| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 -# 223| m0_28(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 +# 223| mu0_28(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 # 224| r0_29(glval) = VariableAddress[c2] : # 224| r0_30(glval) = FunctionAddress[g] : # 224| v0_31(void) = Call : func:r0_30, this:r0_29 # 224| mu0_32(unknown) = ^CallSideEffect : ~mu0_2 -# 224| v0_33(void) = ^IndirectReadSideEffect[-1] : &:r0_29, m0_28 -# 224| m0_34(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_29 +# 224| v0_33(void) = ^IndirectReadSideEffect[-1] : &:r0_29, ~mu0_2 +# 224| mu0_34(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_29 # 225| v0_35(void) = NoOp : # 219| v0_36(void) = ReturnVoid : # 219| v0_37(void) = UnmodeledUse : mu* From 17e14348d5d51978903f4f3688363756df7e60b7 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 4 Oct 2019 11:37:56 -0700 Subject: [PATCH 0028/2538] C++: sanity test for identical Chi node operands --- .../code/cpp/ir/implementation/aliased_ssa/Instruction.qll | 4 ++++ .../semmle/code/cpp/ir/implementation/raw/Instruction.qll | 4 ++++ .../cpp/ir/implementation/unaliased_ssa/Instruction.qll | 4 ++++ cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected | 5 +++++ cpp/ql/test/library-tests/ir/ir/raw_sanity.expected | 1 + .../test/library-tests/ir/ir/unaliased_ssa_sanity.expected | 1 + .../test/library-tests/ir/ssa/aliased_ssa_sanity.expected | 6 ++++++ .../test/library-tests/ir/ssa/unaliased_ssa_sanity.expected | 1 + .../code/csharp/ir/implementation/raw/Instruction.qll | 4 ++++ .../csharp/ir/implementation/unaliased_ssa/Instruction.qll | 4 ++++ 10 files changed, 34 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index efc873b8f441..acaf7569439f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -120,6 +120,10 @@ module InstructionSanity { ) } + query predicate duplicateChiOperand(ChiInstruction chi) { + chi.getTotal() = chi.getPartial() + } + /** * Holds if an instruction, other than `ExitFunction`, has no successors. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index efc873b8f441..acaf7569439f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -120,6 +120,10 @@ module InstructionSanity { ) } + query predicate duplicateChiOperand(ChiInstruction chi) { + chi.getTotal() = chi.getPartial() + } + /** * Holds if an instruction, other than `ExitFunction`, has no successors. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index efc873b8f441..acaf7569439f 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -120,6 +120,10 @@ module InstructionSanity { ) } + query predicate duplicateChiOperand(ChiInstruction chi) { + chi.getTotal() = chi.getPartial() + } + /** * Holds if an instruction, other than `ExitFunction`, has no successors. */ diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index d86f9a053346..5fece7284c9e 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -7,6 +7,11 @@ unexpectedOperand duplicateOperand missingPhiOperand missingOperandType +duplicateChiOperand +| ir.cpp:1035:3:1035:12 | Chi: (const lambda [] type at line 1034, col. 21)... | +| ir.cpp:1039:3:1039:21 | Chi: (const lambda [] type at line 1038, col. 30)... | +| ir.cpp:1043:3:1043:23 | Chi: (const lambda [] type at line 1042, col. 32)... | +| ir.cpp:1046:3:1046:14 | Chi: (const lambda [] type at line 1045, col. 23)... | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected index d86f9a053346..ff4f9c7af572 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected @@ -7,6 +7,7 @@ unexpectedOperand duplicateOperand missingPhiOperand missingOperandType +duplicateChiOperand instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index d86f9a053346..ff4f9c7af572 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -7,6 +7,7 @@ unexpectedOperand duplicateOperand missingPhiOperand missingOperandType +duplicateChiOperand instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected index ae680785ce64..7cd6618fc2bd 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected @@ -3,6 +3,12 @@ unexpectedOperand duplicateOperand missingPhiOperand missingOperandType +duplicateChiOperand +| ssa.cpp:220:19:220:20 | Chi: call to Constructible | +| ssa.cpp:221:3:221:3 | Chi: c | +| ssa.cpp:222:3:222:3 | Chi: c | +| ssa.cpp:223:21:223:37 | Chi: call to Constructible | +| ssa.cpp:224:3:224:4 | Chi: c2 | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected index ae680785ce64..47daae9bc6f0 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected @@ -3,6 +3,7 @@ unexpectedOperand duplicateOperand missingPhiOperand missingOperandType +duplicateChiOperand instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index efc873b8f441..acaf7569439f 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -120,6 +120,10 @@ module InstructionSanity { ) } + query predicate duplicateChiOperand(ChiInstruction chi) { + chi.getTotal() = chi.getPartial() + } + /** * Holds if an instruction, other than `ExitFunction`, has no successors. */ diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index efc873b8f441..acaf7569439f 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -120,6 +120,10 @@ module InstructionSanity { ) } + query predicate duplicateChiOperand(ChiInstruction chi) { + chi.getTotal() = chi.getPartial() + } + /** * Holds if an instruction, other than `ExitFunction`, has no successors. */ From 057c634fe425d8371a2c75b30f0a09e215de5ba1 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 4 Oct 2019 13:05:47 -0700 Subject: [PATCH 0029/2538] C++: fix identical chi node operands --- .../aliased_ssa/internal/SSAConstruction.qll | 4 +++- .../unaliased_ssa/internal/SSAConstruction.qll | 4 +++- .../ir/ir/aliased_ssa_sanity.expected | 4 ---- .../library-tests/ir/ssa/aliased_ssa_ir.expected | 16 ++++++++-------- .../ir/ssa/aliased_ssa_sanity.expected | 5 ----- 5 files changed, 14 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 753cca6b955c..df82ed10f3a4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -740,7 +740,9 @@ module DefUse { block.getInstruction(index) = def and overlap = Alias::getOverlap(defLocation, useLocation) and if - overlap instanceof MayPartiallyOverlap + overlap instanceof MayPartiallyOverlap or + def.getResultMemoryAccess() instanceof IndirectMayMemoryAccess or + def.getResultMemoryAccess() instanceof BufferMayMemoryAccess then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction. else offset = index * 2 // The use will be connected to the definition on the original instruction. ) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 753cca6b955c..df82ed10f3a4 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -740,7 +740,9 @@ module DefUse { block.getInstruction(index) = def and overlap = Alias::getOverlap(defLocation, useLocation) and if - overlap instanceof MayPartiallyOverlap + overlap instanceof MayPartiallyOverlap or + def.getResultMemoryAccess() instanceof IndirectMayMemoryAccess or + def.getResultMemoryAccess() instanceof BufferMayMemoryAccess then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction. else offset = index * 2 // The use will be connected to the definition on the original instruction. ) diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index 5fece7284c9e..ff4f9c7af572 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -8,10 +8,6 @@ duplicateOperand missingPhiOperand missingOperandType duplicateChiOperand -| ir.cpp:1035:3:1035:12 | Chi: (const lambda [] type at line 1034, col. 21)... | -| ir.cpp:1039:3:1039:21 | Chi: (const lambda [] type at line 1038, col. 30)... | -| ir.cpp:1043:3:1043:23 | Chi: (const lambda [] type at line 1042, col. 32)... | -| ir.cpp:1046:3:1046:14 | Chi: (const lambda [] type at line 1045, col. 23)... | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 84dca0766911..c11dd129637b 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -884,23 +884,23 @@ ssa.cpp: # 220| m0_8(unknown) = ^CallSideEffect : ~m0_1 # 220| m0_9(unknown) = Chi : total:m0_1, partial:m0_8 # 220| m0_10(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_3 -# 220| m0_11(Constructible) = Chi : total:m0_10, partial:m0_10 +# 220| m0_11(Constructible) = Chi : total:m0_4, partial:m0_10 # 221| r0_12(glval) = VariableAddress[c] : # 221| r0_13(glval) = FunctionAddress[g] : # 221| v0_14(void) = Call : func:r0_13, this:r0_12 # 221| m0_15(unknown) = ^CallSideEffect : ~m0_9 # 221| m0_16(unknown) = Chi : total:m0_9, partial:m0_15 -# 221| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_12, m0_10 +# 221| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_12, m0_11 # 221| m0_18(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_12 -# 221| m0_19(Constructible) = Chi : total:m0_18, partial:m0_18 +# 221| m0_19(Constructible) = Chi : total:m0_11, partial:m0_18 # 222| r0_20(glval) = VariableAddress[c] : # 222| r0_21(glval) = FunctionAddress[g] : # 222| v0_22(void) = Call : func:r0_21, this:r0_20 # 222| m0_23(unknown) = ^CallSideEffect : ~m0_16 # 222| m0_24(unknown) = Chi : total:m0_16, partial:m0_23 -# 222| v0_25(void) = ^IndirectReadSideEffect[-1] : &:r0_20, m0_18 +# 222| v0_25(void) = ^IndirectReadSideEffect[-1] : &:r0_20, m0_19 # 222| m0_26(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_20 -# 222| m0_27(Constructible) = Chi : total:m0_26, partial:m0_26 +# 222| m0_27(Constructible) = Chi : total:m0_19, partial:m0_26 # 223| r0_28(glval) = VariableAddress[c2] : # 223| m0_29(Constructible) = Uninitialized[c2] : &:r0_28 # 223| r0_30(glval) = FunctionAddress[Constructible] : @@ -909,15 +909,15 @@ ssa.cpp: # 223| m0_33(unknown) = ^CallSideEffect : ~m0_24 # 223| m0_34(unknown) = Chi : total:m0_24, partial:m0_33 # 223| m0_35(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_28 -# 223| m0_36(Constructible) = Chi : total:m0_35, partial:m0_35 +# 223| m0_36(Constructible) = Chi : total:m0_29, partial:m0_35 # 224| r0_37(glval) = VariableAddress[c2] : # 224| r0_38(glval) = FunctionAddress[g] : # 224| v0_39(void) = Call : func:r0_38, this:r0_37 # 224| m0_40(unknown) = ^CallSideEffect : ~m0_34 # 224| m0_41(unknown) = Chi : total:m0_34, partial:m0_40 -# 224| v0_42(void) = ^IndirectReadSideEffect[-1] : &:r0_37, m0_35 +# 224| v0_42(void) = ^IndirectReadSideEffect[-1] : &:r0_37, m0_36 # 224| m0_43(Constructible) = ^IndirectMayWriteSideEffect[-1] : &:r0_37 -# 224| m0_44(Constructible) = Chi : total:m0_43, partial:m0_43 +# 224| m0_44(Constructible) = Chi : total:m0_36, partial:m0_43 # 225| v0_45(void) = NoOp : # 219| v0_46(void) = ReturnVoid : # 219| v0_47(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected index 7cd6618fc2bd..47daae9bc6f0 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected @@ -4,11 +4,6 @@ duplicateOperand missingPhiOperand missingOperandType duplicateChiOperand -| ssa.cpp:220:19:220:20 | Chi: call to Constructible | -| ssa.cpp:221:3:221:3 | Chi: c | -| ssa.cpp:222:3:222:3 | Chi: c | -| ssa.cpp:223:21:223:37 | Chi: call to Constructible | -| ssa.cpp:224:3:224:4 | Chi: c2 | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop From b60e7c204d9e44ee5ea6918210be5d10a6adff16 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 7 Oct 2019 14:07:25 -0700 Subject: [PATCH 0030/2538] C++: autoformat and accept test output --- .../cpp/ir/implementation/aliased_ssa/Instruction.qll | 4 +--- .../code/cpp/ir/implementation/raw/Instruction.qll | 4 +--- .../ir/implementation/unaliased_ssa/Instruction.qll | 4 +--- .../syntax-zoo/aliased_ssa_sanity.expected | 10 ++++++---- .../test/library-tests/syntax-zoo/raw_sanity.expected | 1 + .../syntax-zoo/unaliased_ssa_sanity.expected | 1 + .../code/csharp/ir/implementation/raw/Instruction.qll | 4 +--- .../ir/implementation/unaliased_ssa/Instruction.qll | 4 +--- 8 files changed, 13 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index acaf7569439f..7b4dc602519d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -120,9 +120,7 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { - chi.getTotal() = chi.getPartial() - } + query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index acaf7569439f..7b4dc602519d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -120,9 +120,7 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { - chi.getTotal() = chi.getPartial() - } + query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index acaf7569439f..7b4dc602519d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -120,9 +120,7 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { - chi.getTotal() = chi.getPartial() - } + query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 552c0693ad4c..ec35510d5e20 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -28,18 +28,20 @@ missingOperand | ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Instruction 'IndirectMayWriteSideEffect' is missing an expected operand with tag 'Address' in function '$@'. | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | +| try_catch.cpp:13:5:13:16 | Chi: call to exn1 | Instruction 'Chi' is missing an expected operand with tag 'ChiTotal' in function '$@'. | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() | unexpectedOperand duplicateOperand missingPhiOperand | cpp11.cpp:141:7:141:7 | Phi: g | cpp11.cpp:161:16:161:16 | NoOp: label ...: | missingOperandType +duplicateChiOperand instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | assume0.cpp:7:2:7:2 | Chi: call to f | -| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | -| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | +| condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt | +| condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt | +| condition_decls.cpp:41:22:41:23 | Chi: call to BoxedInt | +| condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | | misc.c:219:47:219:48 | InitializeParameter: sp | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 2b3d6b07fc1b..6912a5028b95 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -48,6 +48,7 @@ unexpectedOperand duplicateOperand missingPhiOperand missingOperandType +duplicateChiOperand instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index e984a30e3c5a..eef63fe23f39 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -42,6 +42,7 @@ missingPhiOperand | range_analysis.c:389:3:389:32 | Phi: return ... | range_analysis.c:387:38:387:38 | Constant: 5 | | range_analysis.c:389:3:389:32 | Phi: return ... | range_analysis.c:387:38:387:38 | Constant: 5 | missingOperandType +duplicateChiOperand instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index acaf7569439f..7b4dc602519d 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -120,9 +120,7 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { - chi.getTotal() = chi.getPartial() - } + query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index acaf7569439f..7b4dc602519d 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -120,9 +120,7 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { - chi.getTotal() = chi.getPartial() - } + query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } /** * Holds if an instruction, other than `ExitFunction`, has no successors. From 5c084f8b39c9503c1326ef68befeb325e435a023 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 7 Oct 2019 14:16:21 -0700 Subject: [PATCH 0031/2538] C++: respond to more PR comments --- cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql | 4 ++-- cpp/ql/src/semmle/code/cpp/Declaration.qll | 8 +------- cpp/ql/src/semmle/code/cpp/commons/File.qll | 2 +- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 5d02533124a0..42a29b96268b 100644 --- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -34,10 +34,10 @@ class FileFunction extends FunctionWithWrappers { nme.matches("CreateFile%") ) or - this.hasStdName("fopen") + this.hasQualifiedName("std", "fopen") or // on any of the fstream classes, or filebuf - exists(string nme | this.getDeclaringType().hasStdName(nme) | + exists(string nme | this.getDeclaringType().hasQualifiedName("std", nme) | nme = "basic_fstream" or nme = "basic_ifstream" or nme = "basic_ofstream" or diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 7c38acc564ee..88ee21da5580 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -119,17 +119,11 @@ abstract class Declaration extends Locatable, @declaration { /** Holds if this declaration has the given name in the global namespace. */ predicate hasGlobalName(string name) { this.hasQualifiedName("", "", name) } - - /** Holds if this declaration has the given name in the `std` namespace. */ - predicate hasStdName(string name) { - this.hasQualifiedName("std", "", name) - } - /** Holds if this declaration has the given name in the global namespace or the `std` namespace. */ predicate hasGlobalOrStdName(string name) { this.hasGlobalName(name) or - this.hasStdName(name) + this.hasQualifiedName("std", "", name) } /** Gets a specifier of this declaration. */ diff --git a/cpp/ql/src/semmle/code/cpp/commons/File.qll b/cpp/ql/src/semmle/code/cpp/commons/File.qll index ea8f8b9dc654..5808d704e385 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/File.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/File.qll @@ -6,7 +6,7 @@ import cpp predicate fopenCall(FunctionCall fc) { exists(Function f | f = fc.getTarget() | f.hasGlobalOrStdName("fopen") or - f.hasGlobalOrStdName("open") or + f.hasGlobalName("open") or f.hasGlobalName("_open") or f.hasGlobalName("_wopen") or f.hasGlobalName("CreateFile") or From 7fa367d6cf9342b1065eb1250e83c3e454232bbb Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 7 Oct 2019 16:37:35 -0700 Subject: [PATCH 0032/2538] C++: autoformat --- cpp/ql/src/semmle/code/cpp/commons/Alloc.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll index 618afd624c47..8462cb13b1d3 100644 --- a/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll +++ b/cpp/ql/src/semmle/code/cpp/commons/Alloc.qll @@ -195,4 +195,3 @@ predicate isDeallocationExpr(Expr e) { e instanceof DeleteExpr or e instanceof DeleteArrayExpr } - From 55c26a8880bca000c2253349b08cb298a9fadb49 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 1 Oct 2019 15:11:18 -0700 Subject: [PATCH 0033/2538] [CPP-434] Initial version of query + test cases. --- .../Arithmetic/SignedComparisons.ql | 33 ++++++++++++++++ .../SignedComparisons/SignedComparisons.cpp | 38 +++++++++++++++++++ .../SignedComparisons/SignedComparisons.qlref | 1 + 3 files changed, 72 insertions(+) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql new file mode 100644 index 000000000000..b6dd8fb1d42d --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql @@ -0,0 +1,33 @@ +/** + * @name Undefined result of signed test for overflow + * @description Testing for signed integer overflow by adding a value to + * a variable (or subtracting a value from a variable) and + * then comparing the result to said variable is not defined + * by the C or C++ standards. The comparison may produce an + * unintended result, or may be deleted by the compiler + * entirely. + * @kind problem + * @problem.severity warning + * @precision medium + * @id cpp/signed-overflow-check + * @tags reliability + * security + */ + +import cpp + +from RelationalOperation ro, BinaryArithmeticOperation bao, VariableAccess va1, VariableAccess va2 +where + ro.getAnOperand() = bao and + (bao instanceof AddExpr or bao instanceof SubExpr) and + bao.getAnOperand() = va1 and + ro.getAnOperand() = va2 and + va1.getTarget() = va2.getTarget() and + /* + * if the addition/subtraction (`bao`) has been promoted to a signed type, + * then the other operand (`va2`) must also be signed and we have a signed + * comparison + */ + + bao.getFullyConverted().getType().(IntegralType).isSigned() +select ro, "Testing for signed overflow/underflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp new file mode 100644 index 000000000000..32d3bab19c74 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp @@ -0,0 +1,38 @@ +// Signed-comparison tests + +/* 1. Signed-signed comparison. The semantics are undefined. */ +bool cannotHoldAnother8(int n1) { + // clang 8.0.0 -O2: deleted (silently) + // gcc 9.2 -O2: deleted (silently) + // msvc 19.22 /O2: not deleted + return n1 + 8 < n1; // BAD +} +bool canHoldPreceding16(int n1) { + return n1 - 16 < n1; +} + +/* 2. Signed comparison with a narrower unsigned type. The narrower + type gets promoted to the (signed) larger type, and so the + semantics are undefined. */ +bool cannotHoldAnotherUShort(int n1, unsigned short delta) { + // clang 8.0.0 -O2: deleted (silently) + // gcc 9.2 -O2: deleted (silently) + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // BAD +} +bool canHoldPrecedingUShort(int n1, unsigned short delta) { + return n1 - delta < n1; +} + +/* 3. Signed comparison with a non-narrower unsigned type. The + signed type gets promoted to (a possibly wider) unsigned type, + and the resulting comparison is unsigned. */ +bool cannotHoldAnotherUInt(int n1, unsigned int delta) { + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // GOOD +} +bool canHoldPrecedingUInt(int n1, unsigned int delta) { + return n1 - delta < n1; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref new file mode 100644 index 000000000000..f645e2e24082 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref @@ -0,0 +1 @@ +Likely Bugs/Arithmetic/SignedComparisons.ql From c9a9aff221ce2ecb60d7aef8bfceb6ece52c47df Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 1 Oct 2019 15:13:08 -0700 Subject: [PATCH 0034/2538] [CPP-434] Expected result. --- .../Arithmetic/SignedComparisons/SignedComparisons.expected | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected new file mode 100644 index 000000000000..bceb4fd08027 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected @@ -0,0 +1,4 @@ +| SignedComparisons.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedComparisons.cpp:11:9:11:20 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedComparisons.cpp:21:12:21:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedComparisons.cpp:24:9:24:23 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | From 8c6caf2b4e79ffe785f79c067619e8e8ae1a87e8 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 12:27:16 -0700 Subject: [PATCH 0035/2538] [CPP-434] Rename everything to SignedOverflowCheck. Add .qlhelp. Deal with addition only, not subtraction. --- .../Arithmetic/SignedOverflowCheck-bad.cpp | 3 ++ .../Arithmetic/SignedOverflowCheck-good.cpp | 3 ++ .../Arithmetic/SignedOverflowCheck.qhelp | 42 +++++++++++++++++++ ...dComparisons.ql => SignedOverflowCheck.ql} | 15 +++---- .../SignedComparisons.expected | 4 -- .../SignedComparisons/SignedComparisons.qlref | 1 - .../SignedOverflowCheck.cpp} | 9 ---- .../SignedOverflowCheck.expected | 2 + .../SignedOverflowCheck.qlref | 1 + 9 files changed, 57 insertions(+), 23 deletions(-) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp rename cpp/ql/src/Likely Bugs/Arithmetic/{SignedComparisons.ql => SignedOverflowCheck.ql} (55%) delete mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected delete mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedComparisons/SignedComparisons.cpp => SignedOverflowCheck/SignedOverflowCheck.cpp} (82%) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp new file mode 100644 index 000000000000..e50273aacded --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp @@ -0,0 +1,3 @@ +bool foo(int n1, unsigned short delta) { + return n1 + delta < n1; // BAD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp new file mode 100644 index 000000000000..2554e0d93711 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp @@ -0,0 +1,3 @@ +bool bar(int n1, unsigned int delta) { + return n1 + delta < n1; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp new file mode 100644 index 000000000000..253950c3bf44 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -0,0 +1,42 @@ + + + +

+Testing for signed integer overflow by adding a +value to a variable and then comparing the result to said variable +is not defined by the C or C++ standards. The comparison may +produce an unintended result, or may be deleted by the compiler +entirely. +

+
+ +

+Make sure that the comparison in question uses unsigned values. +

+
+ +

+In the following example, even though delta has been declared +unsigned short, C/C++ type promotion rules require that its +type is promoted to the larger type used in the addition and comparison, +namely a signed int. As a result, the entire expression is +evaluated using signed values and its value is therefore undefined. +

+ +

+In the next example, a value of type signed int is +getting added to a value ot type unsigned int. Because +the types are of the same size, C/C++ promotion rules dictate that +unsigned int is chosen as the overall type of the addition +operation. The entire expression is evaluated using unsigned +values, which is allowed and defined behavior per the C/C++ standard. +

+ +
+ +
  • Preserving Rules
  • +
  • Understand integer conversion rules
  • +
    +
    diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql similarity index 55% rename from cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql rename to cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index b6dd8fb1d42d..9414ee773d72 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedComparisons.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -1,11 +1,8 @@ /** * @name Undefined result of signed test for overflow - * @description Testing for signed integer overflow by adding a value to - * a variable (or subtracting a value from a variable) and - * then comparing the result to said variable is not defined - * by the C or C++ standards. The comparison may produce an - * unintended result, or may be deleted by the compiler - * entirely. + * @description Testing for oveflow by adding a value to a variable + * to see if it "wraps around" works only for + * `unsigned` integer values. * @kind problem * @problem.severity warning * @precision medium @@ -19,14 +16,14 @@ import cpp from RelationalOperation ro, BinaryArithmeticOperation bao, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = bao and - (bao instanceof AddExpr or bao instanceof SubExpr) and + bao instanceof AddExpr and bao.getAnOperand() = va1 and ro.getAnOperand() = va2 and va1.getTarget() = va2.getTarget() and /* * if the addition/subtraction (`bao`) has been promoted to a signed type, - * then the other operand (`va2`) must also be signed and we have a signed - * comparison + * then the other operand (`va2`) must have been likewise promoted and so + * have a signed comparison */ bao.getFullyConverted().getType().(IntegralType).isSigned() diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected deleted file mode 100644 index bceb4fd08027..000000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.expected +++ /dev/null @@ -1,4 +0,0 @@ -| SignedComparisons.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedComparisons.cpp:11:9:11:20 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedComparisons.cpp:21:12:21:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedComparisons.cpp:24:9:24:23 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref deleted file mode 100644 index f645e2e24082..000000000000 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.qlref +++ /dev/null @@ -1 +0,0 @@ -Likely Bugs/Arithmetic/SignedComparisons.ql diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp similarity index 82% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 32d3bab19c74..4f5ea296d7ca 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedComparisons/SignedComparisons.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -7,9 +7,6 @@ bool cannotHoldAnother8(int n1) { // msvc 19.22 /O2: not deleted return n1 + 8 < n1; // BAD } -bool canHoldPreceding16(int n1) { - return n1 - 16 < n1; -} /* 2. Signed comparison with a narrower unsigned type. The narrower type gets promoted to the (signed) larger type, and so the @@ -20,9 +17,6 @@ bool cannotHoldAnotherUShort(int n1, unsigned short delta) { // msvc 19.22 /O2: not deleted return n1 + delta < n1; // BAD } -bool canHoldPrecedingUShort(int n1, unsigned short delta) { - return n1 - delta < n1; -} /* 3. Signed comparison with a non-narrower unsigned type. The signed type gets promoted to (a possibly wider) unsigned type, @@ -33,6 +27,3 @@ bool cannotHoldAnotherUInt(int n1, unsigned int delta) { // msvc 19.22 /O2: not deleted return n1 + delta < n1; // GOOD } -bool canHoldPrecedingUInt(int n1, unsigned int delta) { - return n1 - delta < n1; -} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected new file mode 100644 index 000000000000..5963f1b340f6 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -0,0 +1,2 @@ +| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref new file mode 100644 index 000000000000..dde648402029 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref @@ -0,0 +1 @@ +Likely Bugs/Arithmetic/SignedOverflowCheck.ql From 16411d1b6e0bd9f57299a9934913d170b2cfd4ee Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 12:32:11 -0700 Subject: [PATCH 0036/2538] [CPP-434] Remove references to underflow and subtraction. --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 9414ee773d72..18c54c01629e 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -21,10 +21,10 @@ where ro.getAnOperand() = va2 and va1.getTarget() = va2.getTarget() and /* - * if the addition/subtraction (`bao`) has been promoted to a signed type, + * if the addition (`bao`) has been promoted to a signed type, * then the other operand (`va2`) must have been likewise promoted and so * have a signed comparison */ bao.getFullyConverted().getType().(IntegralType).isSigned() -select ro, "Testing for signed overflow/underflow may produce undefined results." +select ro, "Testing for signed overflow may produce undefined results." From 341dc12fc86713880ba56efd389ce2e74d9ad223 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 15:02:44 -0700 Subject: [PATCH 0037/2538] [CPP-434] Adjust expected output. --- .../SignedOverflowCheck/SignedOverflowCheck.expected | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index 5963f1b340f6..4fc4cce41a21 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,2 +1,2 @@ -| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | -| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow/underflow may produce undefined results. | +| SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | From 872054a89a8ed4d8687402ca6d4f41344e036d94 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 2 Oct 2019 17:59:19 -0700 Subject: [PATCH 0038/2538] [CPP-434] Narrow down query. --- .../Arithmetic/SignedOverflowCheck.ql | 14 ++--- .../SignedOverflowCheck.cpp | 52 +++++++++++++++++++ .../SignedOverflowCheck.expected | 1 + 3 files changed, 60 insertions(+), 7 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 18c54c01629e..490b1a53a17e 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -1,6 +1,6 @@ /** * @name Undefined result of signed test for overflow - * @description Testing for oveflow by adding a value to a variable + * @description Testing for overflow by adding a value to a variable * to see if it "wraps around" works only for * `unsigned` integer values. * @kind problem @@ -13,18 +13,18 @@ import cpp -from RelationalOperation ro, BinaryArithmeticOperation bao, VariableAccess va1, VariableAccess va2 +from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where - ro.getAnOperand() = bao and - bao instanceof AddExpr and - bao.getAnOperand() = va1 and + ro.getAnOperand() = add and + add.getAnOperand() = va1 and ro.getAnOperand() = va2 and va1.getTarget() = va2.getTarget() and + (not exists(va1.getQualifier()) or va1.getQualifier() = va2.getQualifier()) and /* - * if the addition (`bao`) has been promoted to a signed type, + * if the addition (`add`) has been promoted to a signed type, * then the other operand (`va2`) must have been likewise promoted and so * have a signed comparison */ - bao.getFullyConverted().getType().(IntegralType).isSigned() + add.getExplicitlyConverted().getType().(IntegralType).isSigned() select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 4f5ea296d7ca..92edcf1daf21 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -27,3 +27,55 @@ bool cannotHoldAnotherUInt(int n1, unsigned int delta) { // msvc 19.22 /O2: not deleted return n1 + delta < n1; // GOOD } + +bool shortShort1(unsigned short n1, unsigned short delta) { + // clang 8.0.0 -O2: deleted + // gcc 9.2 -O2: deleted + // msvc 19.22 /O2: not deleted + return n1 + delta < n1; // BAD +} + +bool shortShort2(unsigned short n1, unsigned short delta) { + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return (unsigned short)(n1 + delta) < n1; // GOOD +} + +/* Distinguish `varname` from `ptr->varname` and `obj.varname` */ +struct N { + unsigned short n1; +} n, *np; + +bool shortStruct1(unsigned short n1, unsigned short delta) { + return np->n1 + delta < n1; // GOOD +} + +bool shortStruct1a(unsigned short n1, unsigned short delta) { + return n1 + delta < n.n1; // GOOD +} + +bool shortStruct2(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n.n1; // GOOD +} + +struct se { + short xPos; + short yPos; + short xSize; + short ySize; +}; + +extern se *getSo(void); + +bool func1(se *so) { + se *o = getSo(); + if (so->xPos + so->xSize < o->xPos // GOOD + || so->xPos > o->xPos + o->xSize) { // GOOD + // clang 8.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return false; + } + return true; +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index 4fc4cce41a21..c1867e71c183 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,2 +1,3 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | From afa34b5054a13843c0425cd4613fd29694fecf27 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 8 Oct 2019 14:07:20 -0700 Subject: [PATCH 0039/2538] [CPP-434] Improvements to Qhelp; hashCons-ify query. --- .../Arithmetic/SignedOverflowCheck.qhelp | 8 ++++---- .../Arithmetic/SignedOverflowCheck.ql | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 253950c3bf44..0fe578915341 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -5,7 +5,7 @@

    Testing for signed integer overflow by adding a -value to a variable and then comparing the result to said variable +value to a variable and then comparing the result to that variable is not defined by the C or C++ standards. The comparison may produce an unintended result, or may be deleted by the compiler entirely. @@ -27,7 +27,7 @@ evaluated using signed values and its value is therefore undefined.

    In the next example, a value of type signed int is -getting added to a value ot type unsigned int. Because +added to a value of type unsigned int. Because the types are of the same size, C/C++ promotion rules dictate that unsigned int is chosen as the overall type of the addition operation. The entire expression is evaluated using unsigned @@ -36,7 +36,7 @@ values, which is allowed and defined behavior per the C/C++ standard. -

  • Preserving Rules
  • -
  • Understand integer conversion rules
  • +
  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • +
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 490b1a53a17e..f01ee5dd6076 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -12,19 +12,19 @@ */ import cpp +import semmle.code.cpp.valuenumbering.HashCons + +private predicate sameAccess(VariableAccess va1, VariableAccess va2) { + hashCons(va1) = hashCons(va2) +} from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = add and add.getAnOperand() = va1 and ro.getAnOperand() = va2 and - va1.getTarget() = va2.getTarget() and - (not exists(va1.getQualifier()) or va1.getQualifier() = va2.getQualifier()) and - /* - * if the addition (`add`) has been promoted to a signed type, - * then the other operand (`va2`) must have been likewise promoted and so - * have a signed comparison - */ - - add.getExplicitlyConverted().getType().(IntegralType).isSigned() -select ro, "Testing for signed overflow may produce undefined results." + sameAccess(va1, va2) and + add.getExplicitlyConverted().getType().(IntegralType).isSigned() and + va2.getExplicitlyConverted().getType().(IntegralType).isSigned() +select va1, va1.getQualifier().getAQlClass(), va2, va2.getQualifier().getAQlClass(), ro, + "Testing for signed overflow may produce undefined results." From bd87d7bc76134f44b3884adc1220e00ead70a92b Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 8 Oct 2019 16:33:05 -0700 Subject: [PATCH 0040/2538] [CPP-434] Switch to global value numbering (GVN). Improve qlhelp doc. --- .../Arithmetic/SignedOverflowCheck-bad2.cpp | 3 +++ .../Arithmetic/SignedOverflowCheck-good.cpp | 2 +- .../Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 11 ++++++++++- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 9 ++++----- 4 files changed, 18 insertions(+), 7 deletions(-) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp new file mode 100644 index 000000000000..293a8c6e49e2 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -0,0 +1,3 @@ +bool bar(unsigned short n1, unsigned short delta) { + return n1 + delta < n1; // BAD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp index 2554e0d93711..2670a4371f6c 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp @@ -1,3 +1,3 @@ -bool bar(int n1, unsigned int delta) { +bool baz(int n1, unsigned int delta) { return n1 + delta < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 0fe578915341..c3147d23284b 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,10 +22,19 @@ In the following example, even though delta has been declared unsigned short, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely a signed int. As a result, the entire expression is -evaluated using signed values and its value is therefore undefined. +evaluated using signed values and its value is therefore undefined.

    +In the following example, even though both n and delta +have been declared unsigned short, C/C++ type promotion rules +require that both parameters be promoted to the next bigger signed +integer type (in this case signed int) before being added together + so as to avoid overflows or underflows. As a result, the entire expression is +evaluated using signed values and its value is therefore undefined. +

    + +

    In the next example, a value of type signed int is added to a value of type unsigned int. Because the types are of the same size, C/C++ promotion rules dictate that diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index f01ee5dd6076..21e602e2eb41 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -5,17 +5,17 @@ * `unsigned` integer values. * @kind problem * @problem.severity warning - * @precision medium + * @precision high * @id cpp/signed-overflow-check * @tags reliability * security */ import cpp -import semmle.code.cpp.valuenumbering.HashCons +import semmle.code.cpp.valuenumbering.GlobalValueNumbering private predicate sameAccess(VariableAccess va1, VariableAccess va2) { - hashCons(va1) = hashCons(va2) + globalValueNumber(va1) = globalValueNumber(va2) } from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 @@ -26,5 +26,4 @@ where sameAccess(va1, va2) and add.getExplicitlyConverted().getType().(IntegralType).isSigned() and va2.getExplicitlyConverted().getType().(IntegralType).isSigned() -select va1, va1.getQualifier().getAQlClass(), va2, va2.getQualifier().getAQlClass(), ro, - "Testing for signed overflow may produce undefined results." +select ro, "Testing for signed overflow may produce undefined results." From e617a05a1f12ccb3588524132f8856151ce7cf5d Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 8 Oct 2019 17:20:25 -0700 Subject: [PATCH 0041/2538] [CPP-434] One bad usage is undetected; adjust test accordingly. --- .../Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp | 2 +- .../Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 92edcf1daf21..78d228890f0f 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD + return n1 + delta < n1; // BAD [NOT DETECTED] } bool shortShort2(unsigned short n1, unsigned short delta) { diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index c1867e71c183..4fc4cce41a21 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,3 +1,2 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | From 0ccc0057f95314fa179a80216558bb6704eb1a94 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 8 Oct 2019 15:04:11 +0200 Subject: [PATCH 0042/2538] add Deferred model to Promises.qll --- change-notes/1.23/analysis-javascript.md | 1 + .../ql/src/semmle/javascript/Promises.qll | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 04b5e6cb5418..87b12c192303 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -38,3 +38,4 @@ ## Changes to QL libraries * `Expr.getDocumentation()` now handles chain assignments. +* Added `Deferred` as a promise library in Promises.qll diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 858064e85a0d..794a866aee29 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -32,6 +32,39 @@ module Bluebird { } } +/** + * Provides classes for working with various Deferred implementations + */ +module Deferred { + private DataFlow::SourceNode deferred() { + exists(VarAccess var, DataFlow::NewNode instantiation | + var.getName() = "Deferred" and + result = DataFlow::exprNode(var).getALocalSource() and + // Sanity check that result really is a Deferred implementation + instantiation = result.getAnInstantiation() and + exists(instantiation.getAMemberCall("resolve")) + ) + } + + /** + * A promise object created by a Deferred constructor + */ + private class DeferredPromiseDefinition extends PromiseDefinition, DataFlow::NewNode { + DeferredPromiseDefinition() { this = deferred().getAnInstantiation() } + + override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } + } + + /** + * A resolved promise created by a `new Deferred().resolve()` call. + */ + class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { + ResolvedDeferredPromiseDefinition() { this = any(DeferredPromiseDefinition def).getAMemberCall("resolve") } + + override DataFlow::Node getValue() { result = getArgument(0) } + } +} + /** * Provides classes for working with the `q` library (https://github.com/kriskowal/q). */ From 411ed702fb1eabc9f308a34abe6105b688d12c36 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Oct 2019 13:50:12 +0200 Subject: [PATCH 0043/2538] change change-notes --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 87b12c192303..70d903cb9448 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -9,6 +9,7 @@ - [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible) * The call graph has been improved to resolve method calls in more cases. This may produce more security alerts. +* Promises derived from a Deferred object are now recognized. ## New queries @@ -38,4 +39,3 @@ ## Changes to QL libraries * `Expr.getDocumentation()` now handles chain assignments. -* Added `Deferred` as a promise library in Promises.qll From c7eb0f17a9e35a0d9e0be951373df7bcad9c4f87 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Oct 2019 13:59:00 +0200 Subject: [PATCH 0044/2538] add TaintTracking test for new Deferred model --- .../TaintTracking/BasicTaintTracking.expected | 1 + .../ql/test/library-tests/TaintTracking/promise.js | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 2722f67d6fdf..77592a2e855c 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,6 +69,7 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | +| promise.js:22:23:22:30 | source() | promise.js:22:7:22:31 | promise ... urce()) | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index cd5351720ba2..87e89451d99c 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -12,3 +12,12 @@ function closure() { resolver.resolve(source()); sink(resolver.promise); // NOT OK } + +class Deferred { + +} + +function deferred() { + var promise = new Deferred(); + sink(promise.resolve(source())); // NOT OK +} \ No newline at end of file From 4ec825b5b6f3dbb1ba8c5e20bf70963772c9bda0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 9 Oct 2019 16:18:04 +0200 Subject: [PATCH 0045/2538] made model of Deferred more precise --- .../ql/src/semmle/javascript/Promises.qll | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 794a866aee29..362bb2f5063a 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -37,10 +37,23 @@ module Bluebird { */ module Deferred { private DataFlow::SourceNode deferred() { - exists(VarAccess var, DataFlow::NewNode instantiation | - var.getName() = "Deferred" and - result = DataFlow::exprNode(var).getALocalSource() and - // Sanity check that result really is a Deferred implementation + ( + exists(Variable var | + var.getName() = "Deferred" and + (var.getADeclaration() instanceof LocalNamespaceDecl or var.getScope() instanceof GlobalScope) and + result = DataFlow::valueNode(var.getADefinition()) + ) + or + result.(DataFlow::ParameterNode).getName() = "Deferred" + or + exists(Function f | + f.getName() = "Deferred" and + result = DataFlow::valueNode(f) + ) + ) + and + // Sanity check that it is a Deferred implementation + exists(DataFlow::NewNode instantiation | instantiation = result.getAnInstantiation() and exists(instantiation.getAMemberCall("resolve")) ) From 7fc47d496a6cc817761fcfe06acb320dd0931a50 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 9 Oct 2019 16:40:19 -0700 Subject: [PATCH 0046/2538] [CPP-434] Much improved query (producing only true positives on a run of 75 projects). --- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 10 +++------- .../SignedOverflowCheck/SignedOverflowCheck.cpp | 2 +- .../SignedOverflowCheck/SignedOverflowCheck.expected | 1 + 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 21e602e2eb41..96de06c48b47 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -14,16 +14,12 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering -private predicate sameAccess(VariableAccess va1, VariableAccess va2) { - globalValueNumber(va1) = globalValueNumber(va2) -} - from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = add and add.getAnOperand() = va1 and ro.getAnOperand() = va2 and - sameAccess(va1, va2) and - add.getExplicitlyConverted().getType().(IntegralType).isSigned() and - va2.getExplicitlyConverted().getType().(IntegralType).isSigned() + globalValueNumber(va1) = globalValueNumber(va2) and + add.getFullyConverted().getType().getUnspecifiedType().(IntegralType).isSigned() and + not add.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 78d228890f0f..92edcf1daf21 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD [NOT DETECTED] + return n1 + delta < n1; // BAD } bool shortShort2(unsigned short n1, unsigned short delta) { diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index 4fc4cce41a21..c1867e71c183 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,2 +1,3 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | From 1ab965761b13be373375ce694d2bb887ed6d4351 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 9 Oct 2019 17:30:30 -0700 Subject: [PATCH 0047/2538] [CPP-434] Incorporate test from BadAdditionOverflowCheck. --- .../Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index 92edcf1daf21..e04a6d25f55c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -79,3 +79,7 @@ bool func1(se *so) { } return true; } + +bool checkOverflow3(unsigned int a, unsigned short b) { + return (a + b < a); // GOOD +} From 0a6b343820e43fd47efa61cf8acec0deab53c458 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 10 Oct 2019 11:50:34 +0200 Subject: [PATCH 0048/2538] add "class Deferred{...}" as potential Deferred implementation to fix the tests --- javascript/ql/src/semmle/javascript/Promises.qll | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 362bb2f5063a..488adebab6e2 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -46,10 +46,15 @@ module Deferred { or result.(DataFlow::ParameterNode).getName() = "Deferred" or - exists(Function f | + exists(Function f | f.getName() = "Deferred" and result = DataFlow::valueNode(f) ) + or + exists(ClassDefinition c | + c.getName() = "Deferred" and + result = DataFlow::valueNode(c) + ) ) and // Sanity check that it is a Deferred implementation From 33cd6de7294705a865fd901190b174ec0e268791 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 10 Oct 2019 18:11:35 -0700 Subject: [PATCH 0049/2538] [CPP-434] Improved query and test suite. --- .../Arithmetic/SignedOverflowCheck.ql | 9 +++++++-- .../SignedOverflowCheck.cpp | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 96de06c48b47..2dd4ae40152c 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -14,12 +14,17 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering +private predicate isSignedWithoutUnsignedCast(Expr e) { + e.getType().getUnspecifiedType().(IntegralType).isSigned() and + not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() +} + from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where ro.getAnOperand() = add and add.getAnOperand() = va1 and ro.getAnOperand() = va2 and globalValueNumber(va1) = globalValueNumber(va2) and - add.getFullyConverted().getType().getUnspecifiedType().(IntegralType).isSigned() and - not add.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() + isSignedWithoutUnsignedCast(add) and + isSignedWithoutUnsignedCast(va2) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index e04a6d25f55c..be8dd05f4f04 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -83,3 +83,22 @@ bool func1(se *so) { bool checkOverflow3(unsigned int a, unsigned short b) { return (a + b < a); // GOOD } + +struct C { + unsigned int length; +}; + +int checkOverflow4(unsigned int ioff, C c) { + // not deleted by gcc or clang + if ((int)(ioff + c.length) < (int)ioff) return 0; // GOOD + return 1; +} + +#define AV_INPUT_BUFFER_PADDING_SIZE 64 + +int overflow12(int codecdata_length) { + if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length) { // GOOD + return -1; + } + return 1; +} From 31009d979d323eb496530ae99c9f719ebed67272 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 11 Oct 2019 12:04:34 +0200 Subject: [PATCH 0050/2538] add type tracking to detect instances --- .../ql/src/semmle/javascript/Promises.qll | 71 ++++++++++++------- .../library-tests/TaintTracking/promise.js | 2 + 2 files changed, 49 insertions(+), 24 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 488adebab6e2..13eb1e8114e9 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -36,39 +36,60 @@ module Bluebird { * Provides classes for working with various Deferred implementations */ module Deferred { - private DataFlow::SourceNode deferred() { - ( - exists(Variable var | + class DeferredClass extends DataFlow::SourceNode { + DeferredClass() { + exists(Variable var | var.getName() = "Deferred" and - (var.getADeclaration() instanceof LocalNamespaceDecl or var.getScope() instanceof GlobalScope) and - result = DataFlow::valueNode(var.getADefinition()) - ) - or - result.(DataFlow::ParameterNode).getName() = "Deferred" - or + ( + var.getADeclaration() instanceof LocalNamespaceDecl or + var.getScope() instanceof GlobalScope + ) and + this = DataFlow::valueNode(var.getADefinition()) + ) + or + this.(DataFlow::ParameterNode).getName() = "Deferred" + or exists(Function f | - f.getName() = "Deferred" and - result = DataFlow::valueNode(f) + f.getName() = "Deferred" and + this = DataFlow::valueNode(f) ) or - exists(ClassDefinition c | - c.getName() = "Deferred" and - result = DataFlow::valueNode(c) + exists(ClassDefinition c | + c.getName() = "Deferred" and + this = DataFlow::valueNode(c) ) - ) - and - // Sanity check that it is a Deferred implementation - exists(DataFlow::NewNode instantiation | - instantiation = result.getAnInstantiation() and - exists(instantiation.getAMemberCall("resolve")) - ) + } + } + + class DeferredInstance extends DataFlow::NewNode { + DeferredClass deferredClass; + + DeferredInstance() { this = deferredClass.getAnInstantiation() } + + private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { + t.start() and + result = this + or + exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + } + + DeferredClass getDeferredClass() { result = deferredClass } + + DataFlow::CallNode getPromiseMemberCall(string methodName) { + result = ref(DataFlow::TypeTracker::end()).getAMemberCall(methodName) + } } /** * A promise object created by a Deferred constructor */ - private class DeferredPromiseDefinition extends PromiseDefinition, DataFlow::NewNode { - DeferredPromiseDefinition() { this = deferred().getAnInstantiation() } + private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { + DeferredPromiseDefinition() { + this = any(DeferredClass c | + exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("resolve")) and + exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("reject")) + ).getAnInstantiation() + } override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } } @@ -77,7 +98,9 @@ module Deferred { * A resolved promise created by a `new Deferred().resolve()` call. */ class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { - ResolvedDeferredPromiseDefinition() { this = any(DeferredPromiseDefinition def).getAMemberCall("resolve") } + ResolvedDeferredPromiseDefinition() { + this = any(DeferredPromiseDefinition def).getPromiseMemberCall("resolve") + } override DataFlow::Node getValue() { result = getArgument(0) } } diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index 87e89451d99c..d16e57241e8d 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -20,4 +20,6 @@ class Deferred { function deferred() { var promise = new Deferred(); sink(promise.resolve(source())); // NOT OK + + new Deferred().reject("foo") // <- a reject has to exist. } \ No newline at end of file From 592cb18bf486ba6f8b37abf291516e365d4f8e25 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 4 Oct 2019 16:28:38 +0200 Subject: [PATCH 0051/2538] add array callbacks to useOfReturnlessFunction query --- .../ql/src/Expressions/ExprHasNoEffect.ql | 115 +---------------- .../ql/src/Expressions/ExprHasNoEffect.qll | 121 ++++++++++++++++++ .../src/Statements/UseOfReturnlessFunction.ql | 63 ++++++++- 3 files changed, 178 insertions(+), 121 deletions(-) diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.ql b/javascript/ql/src/Expressions/ExprHasNoEffect.ql index 14024ec8f381..929e84616f07 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.ql +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.ql @@ -13,122 +13,9 @@ */ import javascript -import DOMProperties -import semmle.javascript.frameworks.xUnit -import semmle.javascript.RestrictedLocations import ExprHasNoEffect -/** - * Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag. - * In that case, it is probably meant as a declaration and shouldn't be flagged by this query. - * - * This will still flag cases where the JSDoc comment contains no tag at all (and hence carries - * no semantic information), and expression statements with an ordinary (non-JSDoc) comment - * attached to them. - */ -predicate isDeclaration(Expr e) { - (e instanceof VarAccess or e instanceof PropAccess) and - exists(e.getParent().(ExprStmt).getDocumentation().getATag()) -} - -/** - * Holds if there exists a getter for a property called `name` anywhere in the program. - */ -predicate isGetterProperty(string name) { - // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... - exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | - // ... where `descriptor` defines a getter - defProp.hasPropertyAttributeWrite("get", _) - or - // ... where `descriptor` may define a getter - exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) | - descriptor.isIncomplete(_) - or - // minimal escape analysis for the descriptor - exists(DataFlow::InvokeNode invk | - not invk = defProp and - descriptor.flowsTo(invk.getAnArgument()) - ) - ) - ) - or - // there is an object expression with a getter property `name` - exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter) -} - -/** - * A property access that may invoke a getter. - */ -class GetterPropertyAccess extends PropAccess { - override predicate isImpure() { isGetterProperty(getPropertyName()) } -} - -/** - * Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where - * `dummy` is some expression whose value is discarded, and which simply - * exists to prevent the call from being interpreted as a direct eval. - */ -predicate isIndirectEval(CallExpr c, Expr dummy) { - exists(SeqExpr seq | seq = c.getCallee().stripParens() | - dummy = seq.getOperand(0) and - seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and - seq.getNumOperands() = 2 - ) -} - -/** - * Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is - * some expression whose value is discarded, and which simply exists - * to prevent the call from being interpreted as a method call. - */ -predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { - exists(SeqExpr seq | seq = c.getCallee().stripParens() | - dummy = seq.getOperand(0) and - seq.getOperand(1) = callee and - seq.getNumOperands() = 2 - ) -} - -/** - * Holds if evaluating `e` has no side effects (except potentially allocating - * and initializing a new object). - * - * For calls, we do not check whether their arguments have any side effects: - * even if they do, the call itself is useless and should be flagged by this - * query. - */ -predicate noSideEffects(Expr e) { - e.isPure() - or - // `new Error(...)`, `new SyntaxError(...)`, etc. - forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() | - f.(ExternalType).getASupertype*().getName() = "Error" - ) -} from Expr e -where - noSideEffects(e) and - inVoidContext(e) and - // disregard pure expressions wrapped in a void(...) - not e instanceof VoidExpr and - // filter out directives (unknown directives are handled by UnknownDirective.ql) - not exists(Directive d | e = d.getExpr()) and - // or about externs - not e.inExternsFile() and - // don't complain about declarations - not isDeclaration(e) and - // exclude DOM properties, which sometimes have magical auto-update properties - not isDOMProperty(e.(PropAccess).getPropertyName()) and - // exclude xUnit.js annotations - not e instanceof XUnitAnnotation and - // exclude common patterns that are most likely intentional - not isIndirectEval(_, e) and - not isReceiverSuppressingCall(_, e, _) and - // exclude anonymous function expressions as statements; these can only arise - // from a syntax error we already flag - not exists(FunctionExpr fe, ExprStmt es | fe = e | - fe = es.getExpr() and - not exists(fe.getName()) - ) +where hasNoEffect(e) select e.(FirstLineOf), "This expression has no effect." diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/src/Expressions/ExprHasNoEffect.qll index 858f719ba0a0..822bcbb26fae 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.qll @@ -3,6 +3,9 @@ */ import javascript +import DOMProperties +import semmle.javascript.frameworks.xUnit +import semmle.javascript.RestrictedLocations /** * Holds if `e` appears in a syntactic context where its value is discarded. @@ -37,3 +40,121 @@ predicate inVoidContext(Expr e) { or exists(LogicalBinaryExpr logical | e = logical.getRightOperand() and inVoidContext(logical)) } + + +/** + * Holds if `e` is of the form `x;` or `e.p;` and has a JSDoc comment containing a tag. + * In that case, it is probably meant as a declaration and shouldn't be flagged by this query. + * + * This will still flag cases where the JSDoc comment contains no tag at all (and hence carries + * no semantic information), and expression statements with an ordinary (non-JSDoc) comment + * attached to them. + */ +predicate isDeclaration(Expr e) { + (e instanceof VarAccess or e instanceof PropAccess) and + exists(e.getParent().(ExprStmt).getDocumentation().getATag()) +} + +/** + * Holds if there exists a getter for a property called `name` anywhere in the program. + */ +predicate isGetterProperty(string name) { + // there is a call of the form `Object.defineProperty(..., name, descriptor)` ... + exists(CallToObjectDefineProperty defProp | name = defProp.getPropertyName() | + // ... where `descriptor` defines a getter + defProp.hasPropertyAttributeWrite("get", _) + or + // ... where `descriptor` may define a getter + exists(DataFlow::SourceNode descriptor | descriptor.flowsTo(defProp.getPropertyDescriptor()) | + descriptor.isIncomplete(_) + or + // minimal escape analysis for the descriptor + exists(DataFlow::InvokeNode invk | + not invk = defProp and + descriptor.flowsTo(invk.getAnArgument()) + ) + ) + ) + or + // there is an object expression with a getter property `name` + exists(ObjectExpr obj | obj.getPropertyByName(name) instanceof PropertyGetter) +} + +/** + * A property access that may invoke a getter. + */ +class GetterPropertyAccess extends PropAccess { + override predicate isImpure() { isGetterProperty(getPropertyName()) } +} + +/** + * Holds if `c` is an indirect eval call of the form `(dummy, eval)(...)`, where + * `dummy` is some expression whose value is discarded, and which simply + * exists to prevent the call from being interpreted as a direct eval. + */ +predicate isIndirectEval(CallExpr c, Expr dummy) { + exists(SeqExpr seq | seq = c.getCallee().stripParens() | + dummy = seq.getOperand(0) and + seq.getOperand(1).(GlobalVarAccess).getName() = "eval" and + seq.getNumOperands() = 2 + ) +} + +/** + * Holds if `c` is a call of the form `(dummy, e[p])(...)`, where `dummy` is + * some expression whose value is discarded, and which simply exists + * to prevent the call from being interpreted as a method call. + */ +predicate isReceiverSuppressingCall(CallExpr c, Expr dummy, PropAccess callee) { + exists(SeqExpr seq | seq = c.getCallee().stripParens() | + dummy = seq.getOperand(0) and + seq.getOperand(1) = callee and + seq.getNumOperands() = 2 + ) +} + +/** + * Holds if evaluating `e` has no side effects (except potentially allocating + * and initializing a new object). + * + * For calls, we do not check whether their arguments have any side effects: + * even if they do, the call itself is useless and should be flagged by this + * query. + */ +predicate noSideEffects(Expr e) { + e.isPure() + or + // `new Error(...)`, `new SyntaxError(...)`, etc. + forex(Function f | f = e.flow().(DataFlow::NewNode).getACallee() | + f.(ExternalType).getASupertype*().getName() = "Error" + ) +} + +/** + * Holds if the expression `e` should be reported as having no effect. + */ +predicate hasNoEffect(Expr e) { + noSideEffects(e) and + inVoidContext(e) and + // disregard pure expressions wrapped in a void(...) + not e instanceof VoidExpr and + // filter out directives (unknown directives are handled by UnknownDirective.ql) + not exists(Directive d | e = d.getExpr()) and + // or about externs + not e.inExternsFile() and + // don't complain about declarations + not isDeclaration(e) and + // exclude DOM properties, which sometimes have magical auto-update properties + not isDOMProperty(e.(PropAccess).getPropertyName()) and + // exclude xUnit.js annotations + not e instanceof XUnitAnnotation and + // exclude common patterns that are most likely intentional + not isIndirectEval(_, e) and + not isReceiverSuppressingCall(_, e, _) and + // exclude anonymous function expressions as statements; these can only arise + // from a syntax error we already flag + not exists(FunctionExpr fe, ExprStmt es | fe = e | + fe = es.getExpr() and + not exists(fe.getName()) + ) +} \ No newline at end of file diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index c63127b83a37..61a485313e4d 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -82,17 +82,66 @@ predicate alwaysThrows(Function f) { ) } -from DataFlow::CallNode call -where +predicate callToVoidFunction(DataFlow::CallNode call, Function func) { not call.isIndefinite(_) and - forex(Function f | f = call.getACallee() | + func = call.getACallee() and + forall(Function f | f = call.getACallee() | returnsVoid(f) and not isStub(f) and not alwaysThrows(f) + ) +} + +predicate hasNonVoidCallbackMethod(string name) { + name = "every" or + name = "filter" or + name = "find" or + name = "findIndex" or + name = "flatMap" or + name = "map" or + name = "reduce" or + name = "reduceRight" or + name = "some" or + name = "sort" +} + +DataFlow::SourceNode array(DataFlow::TypeTracker t) { + t.start() and result instanceof DataFlow::ArrayCreationNode + or + exists (DataFlow::TypeTracker t2 | + result = array(t2).track(t2, t) + ) +} + +DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } + +predicate voidArrayCallback(DataFlow::MethodCallNode call, Function func) { + hasNonVoidCallbackMethod(call.getMethodName()) and + func = call.getAnArgument().getALocalSource().asExpr() and + 1 = count(DataFlow::Node arg | arg = call.getAnArgument() and arg.getALocalSource().asExpr() instanceof Function) and + returnsVoid(func) and + not isStub(func) and + not alwaysThrows(func) and + ( + call.getReceiver().getALocalSource() = array() + or + call.getCalleeNode() instanceof LodashUnderscore::Member + ) +} + +from DataFlow::CallNode call, Function func, string name, string msg +where + ( + callToVoidFunction(call, func) and + msg = "the $@ does not return anything, yet the return value is used." and + name = "function " + call.getCalleeName() + or + voidArrayCallback(call, func) and + msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + "() is used." and + name = "callback function" ) and - not benignContext(call.asExpr()) and - + // Avoid double reporting from js/useless-expression + not hasNoEffect(func.getBodyStmt(func.getNumBodyStmt() - 1).(ExprStmt).getExpr()) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select - call, "the function $@ does not return anything, yet the return value is used.", call.getACallee(), call.getCalleeName() - + call, msg, func, name From a7c1c34e1e48a311057ae223d545ed59a54439ee Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 11 Oct 2019 17:14:58 +0200 Subject: [PATCH 0052/2538] fix test output, and add new test for array callbacks --- .../UseOfReturnlessFunction.expected | 11 ++++++----- .../Statements/UseOfReturnlessFunction/tst.js | 7 +++++++ 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 500d900ff9e3..0dc283d5edc6 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,5 +1,6 @@ -| tst.js:20:17:20:33 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:24:13:24:29 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:30:20:30:36 | onlySideEffects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | onlySideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the function $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | bothOnlyHaveSideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the function $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | bothOnlyHaveSideEffects | +| tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:30:20:30:36 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | +| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 8bb49f7e7615..1306c6e7f65a 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -68,4 +68,11 @@ var h = returnsValue() || alwaysThrows(); // OK! console.log(h); + + function equals(x, y) { + return x === y; + } + + var foo = [1,2,3].filter(n => {equals(n, 3)}) // NOT OK! + console.log(foo); })(); \ No newline at end of file From 5558922b31f4ad6290109d593f49d228177f27fa Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 11 Oct 2019 17:01:16 -0700 Subject: [PATCH 0053/2538] [CPP-434] Drop the requirement that RHS not be cast to unsigned, since overflow occurs on LHS. Adjust test case. --- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 3 +-- .../SignedOverflowCheck/SignedOverflowCheck.cpp | 10 +++------- .../SignedOverflowCheck/SignedOverflowCheck.expected | 1 + 3 files changed, 5 insertions(+), 9 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 2dd4ae40152c..076e47df7014 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -25,6 +25,5 @@ where add.getAnOperand() = va1 and ro.getAnOperand() = va2 and globalValueNumber(va1) = globalValueNumber(va2) and - isSignedWithoutUnsignedCast(add) and - isSignedWithoutUnsignedCast(va2) + isSignedWithoutUnsignedCast(add) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp index be8dd05f4f04..4396d8578848 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp @@ -94,11 +94,7 @@ int checkOverflow4(unsigned int ioff, C c) { return 1; } -#define AV_INPUT_BUFFER_PADDING_SIZE 64 - -int overflow12(int codecdata_length) { - if(codecdata_length + AV_INPUT_BUFFER_PADDING_SIZE <= (unsigned)codecdata_length) { // GOOD - return -1; - } - return 1; +int overflow12(int n) { + // not deleted by gcc or clang + return (n + 32 <= (unsigned)n? -1: 1); // BAD } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected index c1867e71c183..bc7b98fd3e27 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected @@ -1,3 +1,4 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | From 28056791a57d53a265cf6348d71e93a4aa60a4f8 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 14 Oct 2019 14:14:26 +0200 Subject: [PATCH 0054/2538] add .getALocalSource() when testing for lodash-members --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 6 +++--- .../UseOfReturnlessFunction.expected | 1 + .../query-tests/Statements/UseOfReturnlessFunction/tst.js | 4 ++++ 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 61a485313e4d..2d70cecb0d3a 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -113,8 +113,8 @@ DataFlow::SourceNode array(DataFlow::TypeTracker t) { DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } -predicate voidArrayCallback(DataFlow::MethodCallNode call, Function func) { - hasNonVoidCallbackMethod(call.getMethodName()) and +predicate voidArrayCallback(DataFlow::CallNode call, Function func) { + hasNonVoidCallbackMethod(call.getCalleeName()) and func = call.getAnArgument().getALocalSource().asExpr() and 1 = count(DataFlow::Node arg | arg = call.getAnArgument() and arg.getALocalSource().asExpr() instanceof Function) and returnsVoid(func) and @@ -123,7 +123,7 @@ predicate voidArrayCallback(DataFlow::MethodCallNode call, Function func) { ( call.getReceiver().getALocalSource() = array() or - call.getCalleeNode() instanceof LodashUnderscore::Member + call.getCalleeNode().getALocalSource() instanceof LodashUnderscore::Member ) } diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 0dc283d5edc6..98ae4e3696c7 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -4,3 +4,4 @@ | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | | tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | | tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | +| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 1306c6e7f65a..2b523223e91f 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -75,4 +75,8 @@ var foo = [1,2,3].filter(n => {equals(n, 3)}) // NOT OK! console.log(foo); + + import { filter } from 'lodash' + var bar = filter([1,2,4], x => { equals(x, 3) } ) // NOT OK! + console.log(bar); })(); \ No newline at end of file From f40c21bf6ea0f9e4bc25e8bfa4897eb6b1950333 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 14 Oct 2019 08:06:02 -0700 Subject: [PATCH 0055/2538] [CPP-434] Add release note. --- change-notes/1.23/analysis-cpp.md | 1 + 1 file changed, 1 insertion(+) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 5a97e1347bb3..24fa06e9bbfe 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,6 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | This query checks for when two signed values are added together to test for overflow (`a + b < a`), which is undefined behavior. | ## Changes to existing queries From fb625c12ef7d5d00f33bb88437c3575515301a6b Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Wed, 16 Oct 2019 14:31:11 -0700 Subject: [PATCH 0056/2538] [CPP-434] Move SignedOverflowCheck test to BadAdditionOverflowCheck directory; add additional tests. --- .../BadAdditionOverflowCheck.expected | 2 ++ .../SignedOverflowCheck.cpp | 14 ++++++++++++++ .../SignedOverflowCheck.expected | 3 +++ .../SignedOverflowCheck.qlref | 0 4 files changed, 19 insertions(+) rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedOverflowCheck => BadAdditionOverflowCheck}/SignedOverflowCheck.cpp (86%) rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedOverflowCheck => BadAdditionOverflowCheck}/SignedOverflowCheck.expected (57%) rename cpp/ql/test/query-tests/Likely Bugs/Arithmetic/{SignedOverflowCheck => BadAdditionOverflowCheck}/SignedOverflowCheck.qlref (100%) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected index 9cb1aaa02aff..920a1f820f86 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/BadAdditionOverflowCheck.expected @@ -1 +1,3 @@ +| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Bad overflow check. | +| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Bad overflow check. | | test.cpp:3:11:3:19 | ... < ... | Bad overflow check. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp similarity index 86% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 4396d8578848..4ef9d83b63d4 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -98,3 +98,17 @@ int overflow12(int n) { // not deleted by gcc or clang return (n + 32 <= (unsigned)n? -1: 1); // BAD } + +bool multipleCasts(char x) { + // clang 9.0.0 -O2: deleted + // gcc 9.2 -O2: deleted + // msvc 19.22 /O2: deleted + return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // BAD +} + +bool multipleCasts2(char x) { + // clang 9.0.0 -O2: not deleted + // gcc 9.2 -O2: not deleted + // msvc 19.22 /O2: not deleted + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD [FALSE POSITIVE] +} diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected similarity index 57% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index bc7b98fd3e27..d4fd6334eaaa 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -2,3 +2,6 @@ | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. | +| test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref similarity index 100% rename from cpp/ql/test/query-tests/Likely Bugs/Arithmetic/SignedOverflowCheck/SignedOverflowCheck.qlref rename to cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.qlref From 6cef93604679962e08d9e47acebca4a13e7d84c0 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 16 Oct 2019 15:59:00 -0700 Subject: [PATCH 0057/2538] C++: add function info to duplicateChiOperand --- .../cpp/ir/implementation/aliased_ssa/Instruction.qll | 10 +++++++++- .../code/cpp/ir/implementation/raw/Instruction.qll | 10 +++++++++- .../ir/implementation/unaliased_ssa/Instruction.qll | 10 +++++++++- .../code/csharp/ir/implementation/raw/Instruction.qll | 10 +++++++++- .../ir/implementation/unaliased_ssa/Instruction.qll | 10 +++++++++- 5 files changed, 45 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 7b4dc602519d..285a96b39dec 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -120,7 +120,15 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } + query predicate duplicateChiOperand( + ChiInstruction chi, string message, IRFunction func, string funcText + ) { + chi.getTotal() = chi.getPartial() and + message = "Chi instruction for " + chi.getPartial().toString() + + " has duplicate operands in function $@" and + func = chi.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 7b4dc602519d..285a96b39dec 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -120,7 +120,15 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } + query predicate duplicateChiOperand( + ChiInstruction chi, string message, IRFunction func, string funcText + ) { + chi.getTotal() = chi.getPartial() and + message = "Chi instruction for " + chi.getPartial().toString() + + " has duplicate operands in function $@" and + func = chi.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 7b4dc602519d..285a96b39dec 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -120,7 +120,15 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } + query predicate duplicateChiOperand( + ChiInstruction chi, string message, IRFunction func, string funcText + ) { + chi.getTotal() = chi.getPartial() and + message = "Chi instruction for " + chi.getPartial().toString() + + " has duplicate operands in function $@" and + func = chi.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 7b4dc602519d..285a96b39dec 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -120,7 +120,15 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } + query predicate duplicateChiOperand( + ChiInstruction chi, string message, IRFunction func, string funcText + ) { + chi.getTotal() = chi.getPartial() and + message = "Chi instruction for " + chi.getPartial().toString() + + " has duplicate operands in function $@" and + func = chi.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + } /** * Holds if an instruction, other than `ExitFunction`, has no successors. diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 7b4dc602519d..285a96b39dec 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -120,7 +120,15 @@ module InstructionSanity { ) } - query predicate duplicateChiOperand(ChiInstruction chi) { chi.getTotal() = chi.getPartial() } + query predicate duplicateChiOperand( + ChiInstruction chi, string message, IRFunction func, string funcText + ) { + chi.getTotal() = chi.getPartial() and + message = "Chi instruction for " + chi.getPartial().toString() + + " has duplicate operands in function $@" and + func = chi.getEnclosingIRFunction() and + funcText = Language::getIdentityString(func.getFunction()) + } /** * Holds if an instruction, other than `ExitFunction`, has no successors. From 70441edacf71f7c7a57a367ebb4448b031dfbf35 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 17 Oct 2019 16:41:17 -0700 Subject: [PATCH 0058/2538] [CPP-434] Additional test case; improve QHelp by including themes from the BadAdditionOverflowCheck QHelp. --- ...k-bad.cpp => SignedOverflowCheck-bad1.cpp} | 0 .../Arithmetic/SignedOverflowCheck-good1.cpp | 3 +++ ...good.cpp => SignedOverflowCheck-good2.cpp} | 0 .../Arithmetic/SignedOverflowCheck.qhelp | 21 ++++++++++++++----- .../SignedOverflowCheck.cpp | 4 ++++ 5 files changed, 23 insertions(+), 5 deletions(-) rename cpp/ql/src/Likely Bugs/Arithmetic/{SignedOverflowCheck-bad.cpp => SignedOverflowCheck-bad1.cpp} (100%) create mode 100644 cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp rename cpp/ql/src/Likely Bugs/Arithmetic/{SignedOverflowCheck-good.cpp => SignedOverflowCheck-good2.cpp} (100%) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp similarity index 100% rename from cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad.cpp rename to cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad1.cpp diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp new file mode 100644 index 000000000000..d79d3ccbe93a --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -0,0 +1,3 @@ +bool baf(unsigned short n1, unsigned short delta) { + return n1 + (unsigned)delta < n1; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp similarity index 100% rename from cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good.cpp rename to cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index c3147d23284b..49fc8afb7577 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -24,17 +24,28 @@ type is promoted to the larger type used in the addition and comparison, namely a signed int. As a result, the entire expression is evaluated using signed values and its value is therefore undefined.

    - +

    In the following example, even though both n and delta have been declared unsigned short, C/C++ type promotion rules require that both parameters be promoted to the next bigger signed -integer type (in this case signed int) before being added together - so as to avoid overflows or underflows. As a result, the entire expression is -evaluated using signed values and its value is therefore undefined. +integer type (in this case signed int) before being added together. +As a result, the entire expression is evaluated using signed values +and its value is therefore undefined. (Note, however, that the addition cannot +overflow since we are adding two "small" unsigned short values.)

    +The following example builds upon the previous one. Again, we have two +unsigned short values getting promoted to a wider type. However, +since delta is explicitly cast to an unsigned type, +n1 (on both sides of the comparison) is promoted to +unsigned as well. Since we are now operating on +unsigned values, the overflow check is defined and supported by +standard C/C++. +

    + +

    In the next example, a value of type signed int is added to a value of type unsigned int. Because the types are of the same size, C/C++ promotion rules dictate that @@ -42,7 +53,7 @@ the types are of the same size, C/C++ promotion rules dictate that operation. The entire expression is evaluated using unsigned values, which is allowed and defined behavior per the C/C++ standard.

    - +
  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 4ef9d83b63d4..febb45e8ecc5 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -112,3 +112,7 @@ bool multipleCasts2(char x) { // msvc 19.22 /O2: not deleted return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD [FALSE POSITIVE] } + +int does_it_overflow(int n1, unsigned short delta) { + return n1 + (unsigned)delta < n1; // GOOD +} From 6772fa1352ca82568d384566df0d80033176c6f5 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 17 Oct 2019 17:21:14 -0700 Subject: [PATCH 0059/2538] [CPP-434] Reformat QHelp. --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 49fc8afb7577..741dda54a820 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -26,10 +26,10 @@ evaluated using signed values and its value is therefore undefined.

    -In the following example, even though both n and delta -have been declared unsigned short, C/C++ type promotion rules +In the following example, even though both n and delta +have been declared unsigned short, C/C++ type promotion rules require that both parameters be promoted to the next bigger signed -integer type (in this case signed int) before being added together. +integer type (in this case signed int) before being added together. As a result, the entire expression is evaluated using signed values and its value is therefore undefined. (Note, however, that the addition cannot overflow since we are adding two "small" unsigned short values.) From 8905159de7ce5e9f6d902154ec30bd02ccb4441c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 18 Oct 2019 11:06:09 -0700 Subject: [PATCH 0060/2538] C++: add InitializeIndirection for pointer params --- .../code/cpp/ir/implementation/Opcode.qll | 6 + .../aliased_ssa/Instruction.qll | 8 + .../cpp/ir/implementation/raw/Instruction.qll | 8 + .../raw/internal/InstructionTag.qll | 6 + .../raw/internal/TranslatedFunction.qll | 45 +- .../unaliased_ssa/Instruction.qll | 8 + .../test/library-tests/ir/ir/raw_ir.expected | 1474 +++++++++-------- .../ir/ssa/aliased_ssa_ir.expected | 241 +-- .../ir/ssa/unaliased_ssa_ir.expected | 200 ++- .../syntax-zoo/aliased_ssa_sanity.expected | 4 +- .../syntax-zoo/raw_sanity.expected | 4 +- .../syntax-zoo/unaliased_ssa_sanity.expected | 4 +- .../code/csharp/ir/implementation/Opcode.qll | 6 + .../ir/implementation/raw/Instruction.qll | 8 + .../unaliased_ssa/Instruction.qll | 8 + 15 files changed, 1118 insertions(+), 912 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index 0c1009b4fac4..b0b51b5eca73 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -3,6 +3,7 @@ private newtype TOpcode = TUninitialized() or TError() or TInitializeParameter() or + TInitializeIndirection() or TInitializeThis() or TEnterFunction() or TExitFunction() or @@ -177,6 +178,11 @@ module Opcode { final override string toString() { result = "InitializeParameter" } } + class InitializeIndirection extends MemoryAccessOpcode, TInitializeIndirection { + final override string toString() { result = "InitializeIndirection" } + } + + class InitializeThis extends Opcode, TInitializeThis { final override string toString() { result = "InitializeThis" } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 3244afeb1447..f0a9c0e698ae 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -675,6 +675,14 @@ class InitializeParameterInstruction extends VariableInstruction { final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } } +class InitializeIndirectionInstruction extends VariableInstruction { + InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } + + final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } +} + /** * An instruction that initializes the `this` pointer parameter of the enclosing function. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 3244afeb1447..f0a9c0e698ae 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -675,6 +675,14 @@ class InitializeParameterInstruction extends VariableInstruction { final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } } +class InitializeIndirectionInstruction extends VariableInstruction { + InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } + + final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } +} + /** * An instruction that initializes the `this` pointer parameter of the enclosing function. */ diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll index ddac5692cdfb..228ceec4822b 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/InstructionTag.qll @@ -6,6 +6,8 @@ newtype TInstructionTag = InitializerVariableAddressTag() or InitializerLoadStringTag() or InitializerStoreTag() or + InitializerIndirectAddressTag() or + InitializerIndirectStoreTag() or ZeroPadStringConstantTag() or ZeroPadStringElementIndexTag() or ZeroPadStringElementAddressTag() or @@ -78,6 +80,10 @@ string getInstructionTagId(TInstructionTag tag) { or tag = InitializerUninitializedTag() and result = "InitUninit" or + tag = InitializerIndirectAddressTag() and result = "InitIndirectAddr" + or + tag = InitializerIndirectStoreTag() and result = "InitIndirectStore" + or tag = ZeroPadStringConstantTag() and result = "ZeroPadConst" or tag = ZeroPadStringElementIndexTag() and result = "ZeroPadElemIndex" diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index a035f8b9b314..c4e4f5c02d22 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -329,6 +329,14 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter { result = getInstruction(InitializerStoreTag()) or tag = InitializerStoreTag() and + if hasIndirection() + then result = getInstruction(InitializerIndirectAddressTag()) + else result = getParent().getChildSuccessor(this) + or + tag = InitializerIndirectAddressTag() and + result = getInstruction(InitializerIndirectStoreTag()) + or + tag = InitializerIndirectStoreTag() and result = getParent().getChildSuccessor(this) ) } @@ -347,12 +355,25 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter { opcode instanceof Opcode::InitializeParameter and resultType = getVariableType(param) and isGLValue = false + or + hasIndirection() and + tag = InitializerIndirectAddressTag() and + opcode instanceof Opcode::Load and + resultType = getVariableType(param) and // should this strip a layer of indirection? if so, should isGLValue be true? + isGLValue = false + or + hasIndirection() and + tag = InitializerIndirectStoreTag() and + opcode instanceof Opcode::InitializeIndirection and + resultType instanceof UnknownType and // TODO: differentiate single-element and multi-element pointers + isGLValue = false } final override IRVariable getInstructionVariable(InstructionTag tag) { ( tag = InitializerStoreTag() or - tag = InitializerVariableAddressTag() + tag = InitializerVariableAddressTag() or + tag = InitializerIndirectStoreTag() ) and result = getIRUserVariable(getFunction(), param) } @@ -363,6 +384,28 @@ class TranslatedParameter extends TranslatedElement, TTranslatedParameter { operandTag instanceof AddressOperandTag and result = getInstruction(InitializerVariableAddressTag()) ) + or + // this feels a little strange, but I think it's the best we can do + tag = InitializerIndirectAddressTag() and + ( + operandTag instanceof AddressOperandTag and + result = getInstruction(InitializerVariableAddressTag()) + or + operandTag instanceof LoadOperandTag and + result = getInstruction(InitializerStoreTag()) + ) + or + tag = InitializerIndirectStoreTag() and + operandTag instanceof AddressOperandTag and + result = getInstruction(InitializerIndirectAddressTag()) + } + + predicate hasIndirection() { + exists(Type t | t = param.getUnspecifiedType() | + t instanceof ArrayType or + t instanceof PointerType or + t instanceof ReferenceType + ) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 3244afeb1447..f0a9c0e698ae 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -675,6 +675,14 @@ class InitializeParameterInstruction extends VariableInstruction { final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } } +class InitializeIndirectionInstruction extends VariableInstruction { + InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } + + final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } +} + /** * An instruction that initializes the `this` pointer parameter of the enclosing function. */ diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 3bff2bff6907..4cc0d7bb8a89 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -34,21 +34,23 @@ bad_asts.cpp: # 26| void Bad::CallCopyConstructor(Bad::Point const&) # 26| Block 0 -# 26| v0_0(void) = EnterFunction : -# 26| mu0_1(unknown) = AliasedDefinition : -# 26| mu0_2(unknown) = UnmodeledDefinition : -# 26| r0_3(glval) = VariableAddress[a] : -# 26| mu0_4(Point &) = InitializeParameter[a] : &:r0_3 -# 27| r0_5(glval) = VariableAddress[b] : -# 27| r0_6(glval) = VariableAddress[a] : -# 27| r0_7(Point &) = Load : &:r0_6, ~mu0_2 -# 27| r0_8(glval) = Convert : r0_7 -# 27| r0_9(Point) = Load : &:r0_8, ~mu0_2 -# 27| mu0_10(Point) = Store : &:r0_5, r0_9 -# 28| v0_11(void) = NoOp : -# 26| v0_12(void) = ReturnVoid : -# 26| v0_13(void) = UnmodeledUse : mu* -# 26| v0_14(void) = ExitFunction : +# 26| v0_0(void) = EnterFunction : +# 26| mu0_1(unknown) = AliasedDefinition : +# 26| mu0_2(unknown) = UnmodeledDefinition : +# 26| r0_3(glval) = VariableAddress[a] : +# 26| mu0_4(Point &) = InitializeParameter[a] : &:r0_3 +# 26| r0_5(Point &) = Load : &:r0_3, ~mu0_4 +# 26| mu0_6(unknown) = InitializeIndirection[a] : &:r0_5 +# 27| r0_7(glval) = VariableAddress[b] : +# 27| r0_8(glval) = VariableAddress[a] : +# 27| r0_9(Point &) = Load : &:r0_8, ~mu0_2 +# 27| r0_10(glval) = Convert : r0_9 +# 27| r0_11(Point) = Load : &:r0_10, ~mu0_2 +# 27| mu0_12(Point) = Store : &:r0_7, r0_11 +# 28| v0_13(void) = NoOp : +# 26| v0_14(void) = ReturnVoid : +# 26| v0_15(void) = UnmodeledUse : mu* +# 26| v0_16(void) = ExitFunction : # 30| void Bad::errorExpr() # 30| Block 0 @@ -697,161 +699,165 @@ ir.cpp: # 153| void PointerOps(int*, int) # 153| Block 0 -# 153| v0_0(void) = EnterFunction : -# 153| mu0_1(unknown) = AliasedDefinition : -# 153| mu0_2(unknown) = UnmodeledDefinition : -# 153| r0_3(glval) = VariableAddress[p] : -# 153| mu0_4(int *) = InitializeParameter[p] : &:r0_3 -# 153| r0_5(glval) = VariableAddress[i] : -# 153| mu0_6(int) = InitializeParameter[i] : &:r0_5 -# 154| r0_7(glval) = VariableAddress[q] : -# 154| mu0_8(int *) = Uninitialized[q] : &:r0_7 -# 155| r0_9(glval) = VariableAddress[b] : -# 155| mu0_10(bool) = Uninitialized[b] : &:r0_9 -# 157| r0_11(glval) = VariableAddress[p] : -# 157| r0_12(int *) = Load : &:r0_11, ~mu0_2 -# 157| r0_13(glval) = VariableAddress[i] : -# 157| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 157| r0_15(int *) = PointerAdd[4] : r0_12, r0_14 -# 157| r0_16(glval) = VariableAddress[q] : -# 157| mu0_17(int *) = Store : &:r0_16, r0_15 -# 158| r0_18(glval) = VariableAddress[i] : -# 158| r0_19(int) = Load : &:r0_18, ~mu0_2 -# 158| r0_20(glval) = VariableAddress[p] : -# 158| r0_21(int *) = Load : &:r0_20, ~mu0_2 -# 158| r0_22(int *) = PointerAdd[4] : r0_21, r0_19 -# 158| r0_23(glval) = VariableAddress[q] : -# 158| mu0_24(int *) = Store : &:r0_23, r0_22 -# 159| r0_25(glval) = VariableAddress[p] : -# 159| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 159| r0_27(glval) = VariableAddress[i] : -# 159| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 159| r0_29(int *) = PointerSub[4] : r0_26, r0_28 -# 159| r0_30(glval) = VariableAddress[q] : -# 159| mu0_31(int *) = Store : &:r0_30, r0_29 -# 160| r0_32(glval) = VariableAddress[p] : -# 160| r0_33(int *) = Load : &:r0_32, ~mu0_2 -# 160| r0_34(glval) = VariableAddress[q] : -# 160| r0_35(int *) = Load : &:r0_34, ~mu0_2 -# 160| r0_36(long) = PointerDiff[4] : r0_33, r0_35 -# 160| r0_37(int) = Convert : r0_36 -# 160| r0_38(glval) = VariableAddress[i] : -# 160| mu0_39(int) = Store : &:r0_38, r0_37 -# 162| r0_40(glval) = VariableAddress[p] : -# 162| r0_41(int *) = Load : &:r0_40, ~mu0_2 -# 162| r0_42(glval) = VariableAddress[q] : -# 162| mu0_43(int *) = Store : &:r0_42, r0_41 -# 164| r0_44(glval) = VariableAddress[i] : -# 164| r0_45(int) = Load : &:r0_44, ~mu0_2 -# 164| r0_46(glval) = VariableAddress[q] : -# 164| r0_47(int *) = Load : &:r0_46, ~mu0_2 -# 164| r0_48(int *) = PointerAdd[4] : r0_47, r0_45 -# 164| mu0_49(int *) = Store : &:r0_46, r0_48 -# 165| r0_50(glval) = VariableAddress[i] : -# 165| r0_51(int) = Load : &:r0_50, ~mu0_2 -# 165| r0_52(glval) = VariableAddress[q] : -# 165| r0_53(int *) = Load : &:r0_52, ~mu0_2 -# 165| r0_54(int *) = PointerSub[4] : r0_53, r0_51 -# 165| mu0_55(int *) = Store : &:r0_52, r0_54 -# 167| r0_56(glval) = VariableAddress[p] : -# 167| r0_57(int *) = Load : &:r0_56, ~mu0_2 -# 167| r0_58(int *) = Constant[0] : -# 167| r0_59(bool) = CompareNE : r0_57, r0_58 -# 167| r0_60(glval) = VariableAddress[b] : -# 167| mu0_61(bool) = Store : &:r0_60, r0_59 -# 168| r0_62(glval) = VariableAddress[p] : -# 168| r0_63(int *) = Load : &:r0_62, ~mu0_2 -# 168| r0_64(int *) = Constant[0] : -# 168| r0_65(bool) = CompareNE : r0_63, r0_64 -# 168| r0_66(bool) = LogicalNot : r0_65 -# 168| r0_67(glval) = VariableAddress[b] : -# 168| mu0_68(bool) = Store : &:r0_67, r0_66 -# 169| v0_69(void) = NoOp : -# 153| v0_70(void) = ReturnVoid : -# 153| v0_71(void) = UnmodeledUse : mu* -# 153| v0_72(void) = ExitFunction : +# 153| v0_0(void) = EnterFunction : +# 153| mu0_1(unknown) = AliasedDefinition : +# 153| mu0_2(unknown) = UnmodeledDefinition : +# 153| r0_3(glval) = VariableAddress[p] : +# 153| mu0_4(int *) = InitializeParameter[p] : &:r0_3 +# 153| r0_5(int *) = Load : &:r0_3, ~mu0_4 +# 153| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 153| r0_7(glval) = VariableAddress[i] : +# 153| mu0_8(int) = InitializeParameter[i] : &:r0_7 +# 154| r0_9(glval) = VariableAddress[q] : +# 154| mu0_10(int *) = Uninitialized[q] : &:r0_9 +# 155| r0_11(glval) = VariableAddress[b] : +# 155| mu0_12(bool) = Uninitialized[b] : &:r0_11 +# 157| r0_13(glval) = VariableAddress[p] : +# 157| r0_14(int *) = Load : &:r0_13, ~mu0_2 +# 157| r0_15(glval) = VariableAddress[i] : +# 157| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 157| r0_17(int *) = PointerAdd[4] : r0_14, r0_16 +# 157| r0_18(glval) = VariableAddress[q] : +# 157| mu0_19(int *) = Store : &:r0_18, r0_17 +# 158| r0_20(glval) = VariableAddress[i] : +# 158| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 158| r0_22(glval) = VariableAddress[p] : +# 158| r0_23(int *) = Load : &:r0_22, ~mu0_2 +# 158| r0_24(int *) = PointerAdd[4] : r0_23, r0_21 +# 158| r0_25(glval) = VariableAddress[q] : +# 158| mu0_26(int *) = Store : &:r0_25, r0_24 +# 159| r0_27(glval) = VariableAddress[p] : +# 159| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 159| r0_29(glval) = VariableAddress[i] : +# 159| r0_30(int) = Load : &:r0_29, ~mu0_2 +# 159| r0_31(int *) = PointerSub[4] : r0_28, r0_30 +# 159| r0_32(glval) = VariableAddress[q] : +# 159| mu0_33(int *) = Store : &:r0_32, r0_31 +# 160| r0_34(glval) = VariableAddress[p] : +# 160| r0_35(int *) = Load : &:r0_34, ~mu0_2 +# 160| r0_36(glval) = VariableAddress[q] : +# 160| r0_37(int *) = Load : &:r0_36, ~mu0_2 +# 160| r0_38(long) = PointerDiff[4] : r0_35, r0_37 +# 160| r0_39(int) = Convert : r0_38 +# 160| r0_40(glval) = VariableAddress[i] : +# 160| mu0_41(int) = Store : &:r0_40, r0_39 +# 162| r0_42(glval) = VariableAddress[p] : +# 162| r0_43(int *) = Load : &:r0_42, ~mu0_2 +# 162| r0_44(glval) = VariableAddress[q] : +# 162| mu0_45(int *) = Store : &:r0_44, r0_43 +# 164| r0_46(glval) = VariableAddress[i] : +# 164| r0_47(int) = Load : &:r0_46, ~mu0_2 +# 164| r0_48(glval) = VariableAddress[q] : +# 164| r0_49(int *) = Load : &:r0_48, ~mu0_2 +# 164| r0_50(int *) = PointerAdd[4] : r0_49, r0_47 +# 164| mu0_51(int *) = Store : &:r0_48, r0_50 +# 165| r0_52(glval) = VariableAddress[i] : +# 165| r0_53(int) = Load : &:r0_52, ~mu0_2 +# 165| r0_54(glval) = VariableAddress[q] : +# 165| r0_55(int *) = Load : &:r0_54, ~mu0_2 +# 165| r0_56(int *) = PointerSub[4] : r0_55, r0_53 +# 165| mu0_57(int *) = Store : &:r0_54, r0_56 +# 167| r0_58(glval) = VariableAddress[p] : +# 167| r0_59(int *) = Load : &:r0_58, ~mu0_2 +# 167| r0_60(int *) = Constant[0] : +# 167| r0_61(bool) = CompareNE : r0_59, r0_60 +# 167| r0_62(glval) = VariableAddress[b] : +# 167| mu0_63(bool) = Store : &:r0_62, r0_61 +# 168| r0_64(glval) = VariableAddress[p] : +# 168| r0_65(int *) = Load : &:r0_64, ~mu0_2 +# 168| r0_66(int *) = Constant[0] : +# 168| r0_67(bool) = CompareNE : r0_65, r0_66 +# 168| r0_68(bool) = LogicalNot : r0_67 +# 168| r0_69(glval) = VariableAddress[b] : +# 168| mu0_70(bool) = Store : &:r0_69, r0_68 +# 169| v0_71(void) = NoOp : +# 153| v0_72(void) = ReturnVoid : +# 153| v0_73(void) = UnmodeledUse : mu* +# 153| v0_74(void) = ExitFunction : # 171| void ArrayAccess(int*, int) # 171| Block 0 -# 171| v0_0(void) = EnterFunction : -# 171| mu0_1(unknown) = AliasedDefinition : -# 171| mu0_2(unknown) = UnmodeledDefinition : -# 171| r0_3(glval) = VariableAddress[p] : -# 171| mu0_4(int *) = InitializeParameter[p] : &:r0_3 -# 171| r0_5(glval) = VariableAddress[i] : -# 171| mu0_6(int) = InitializeParameter[i] : &:r0_5 -# 172| r0_7(glval) = VariableAddress[x] : -# 172| mu0_8(int) = Uninitialized[x] : &:r0_7 -# 174| r0_9(glval) = VariableAddress[p] : -# 174| r0_10(int *) = Load : &:r0_9, ~mu0_2 -# 174| r0_11(glval) = VariableAddress[i] : -# 174| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 174| r0_13(glval) = PointerAdd[4] : r0_10, r0_12 -# 174| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 174| r0_15(glval) = VariableAddress[x] : -# 174| mu0_16(int) = Store : &:r0_15, r0_14 -# 175| r0_17(glval) = VariableAddress[p] : -# 175| r0_18(int *) = Load : &:r0_17, ~mu0_2 -# 175| r0_19(glval) = VariableAddress[i] : -# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 175| r0_21(glval) = PointerAdd[4] : r0_18, r0_20 -# 175| r0_22(int) = Load : &:r0_21, ~mu0_2 -# 175| r0_23(glval) = VariableAddress[x] : -# 175| mu0_24(int) = Store : &:r0_23, r0_22 -# 177| r0_25(glval) = VariableAddress[x] : -# 177| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 177| r0_27(glval) = VariableAddress[p] : -# 177| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 177| r0_29(glval) = VariableAddress[i] : -# 177| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 177| r0_31(glval) = PointerAdd[4] : r0_28, r0_30 -# 177| mu0_32(int) = Store : &:r0_31, r0_26 -# 178| r0_33(glval) = VariableAddress[x] : -# 178| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 178| r0_35(glval) = VariableAddress[p] : -# 178| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 178| r0_37(glval) = VariableAddress[i] : -# 178| r0_38(int) = Load : &:r0_37, ~mu0_2 -# 178| r0_39(glval) = PointerAdd[4] : r0_36, r0_38 -# 178| mu0_40(int) = Store : &:r0_39, r0_34 -# 180| r0_41(glval) = VariableAddress[a] : -# 180| mu0_42(int[10]) = Uninitialized[a] : &:r0_41 -# 181| r0_43(glval) = VariableAddress[a] : -# 181| r0_44(int *) = Convert : r0_43 -# 181| r0_45(glval) = VariableAddress[i] : -# 181| r0_46(int) = Load : &:r0_45, ~mu0_2 -# 181| r0_47(glval) = PointerAdd[4] : r0_44, r0_46 -# 181| r0_48(int) = Load : &:r0_47, ~mu0_2 -# 181| r0_49(glval) = VariableAddress[x] : -# 181| mu0_50(int) = Store : &:r0_49, r0_48 -# 182| r0_51(glval) = VariableAddress[a] : -# 182| r0_52(int *) = Convert : r0_51 -# 182| r0_53(glval) = VariableAddress[i] : -# 182| r0_54(int) = Load : &:r0_53, ~mu0_2 -# 182| r0_55(glval) = PointerAdd[4] : r0_52, r0_54 -# 182| r0_56(int) = Load : &:r0_55, ~mu0_2 -# 182| r0_57(glval) = VariableAddress[x] : -# 182| mu0_58(int) = Store : &:r0_57, r0_56 -# 183| r0_59(glval) = VariableAddress[x] : -# 183| r0_60(int) = Load : &:r0_59, ~mu0_2 -# 183| r0_61(glval) = VariableAddress[a] : -# 183| r0_62(int *) = Convert : r0_61 -# 183| r0_63(glval) = VariableAddress[i] : -# 183| r0_64(int) = Load : &:r0_63, ~mu0_2 -# 183| r0_65(glval) = PointerAdd[4] : r0_62, r0_64 -# 183| mu0_66(int) = Store : &:r0_65, r0_60 -# 184| r0_67(glval) = VariableAddress[x] : -# 184| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 184| r0_69(glval) = VariableAddress[a] : -# 184| r0_70(int *) = Convert : r0_69 -# 184| r0_71(glval) = VariableAddress[i] : -# 184| r0_72(int) = Load : &:r0_71, ~mu0_2 -# 184| r0_73(glval) = PointerAdd[4] : r0_70, r0_72 -# 184| mu0_74(int) = Store : &:r0_73, r0_68 -# 185| v0_75(void) = NoOp : -# 171| v0_76(void) = ReturnVoid : -# 171| v0_77(void) = UnmodeledUse : mu* -# 171| v0_78(void) = ExitFunction : +# 171| v0_0(void) = EnterFunction : +# 171| mu0_1(unknown) = AliasedDefinition : +# 171| mu0_2(unknown) = UnmodeledDefinition : +# 171| r0_3(glval) = VariableAddress[p] : +# 171| mu0_4(int *) = InitializeParameter[p] : &:r0_3 +# 171| r0_5(int *) = Load : &:r0_3, ~mu0_4 +# 171| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 171| r0_7(glval) = VariableAddress[i] : +# 171| mu0_8(int) = InitializeParameter[i] : &:r0_7 +# 172| r0_9(glval) = VariableAddress[x] : +# 172| mu0_10(int) = Uninitialized[x] : &:r0_9 +# 174| r0_11(glval) = VariableAddress[p] : +# 174| r0_12(int *) = Load : &:r0_11, ~mu0_2 +# 174| r0_13(glval) = VariableAddress[i] : +# 174| r0_14(int) = Load : &:r0_13, ~mu0_2 +# 174| r0_15(glval) = PointerAdd[4] : r0_12, r0_14 +# 174| r0_16(int) = Load : &:r0_15, ~mu0_2 +# 174| r0_17(glval) = VariableAddress[x] : +# 174| mu0_18(int) = Store : &:r0_17, r0_16 +# 175| r0_19(glval) = VariableAddress[p] : +# 175| r0_20(int *) = Load : &:r0_19, ~mu0_2 +# 175| r0_21(glval) = VariableAddress[i] : +# 175| r0_22(int) = Load : &:r0_21, ~mu0_2 +# 175| r0_23(glval) = PointerAdd[4] : r0_20, r0_22 +# 175| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 175| r0_25(glval) = VariableAddress[x] : +# 175| mu0_26(int) = Store : &:r0_25, r0_24 +# 177| r0_27(glval) = VariableAddress[x] : +# 177| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 177| r0_29(glval) = VariableAddress[p] : +# 177| r0_30(int *) = Load : &:r0_29, ~mu0_2 +# 177| r0_31(glval) = VariableAddress[i] : +# 177| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 177| r0_33(glval) = PointerAdd[4] : r0_30, r0_32 +# 177| mu0_34(int) = Store : &:r0_33, r0_28 +# 178| r0_35(glval) = VariableAddress[x] : +# 178| r0_36(int) = Load : &:r0_35, ~mu0_2 +# 178| r0_37(glval) = VariableAddress[p] : +# 178| r0_38(int *) = Load : &:r0_37, ~mu0_2 +# 178| r0_39(glval) = VariableAddress[i] : +# 178| r0_40(int) = Load : &:r0_39, ~mu0_2 +# 178| r0_41(glval) = PointerAdd[4] : r0_38, r0_40 +# 178| mu0_42(int) = Store : &:r0_41, r0_36 +# 180| r0_43(glval) = VariableAddress[a] : +# 180| mu0_44(int[10]) = Uninitialized[a] : &:r0_43 +# 181| r0_45(glval) = VariableAddress[a] : +# 181| r0_46(int *) = Convert : r0_45 +# 181| r0_47(glval) = VariableAddress[i] : +# 181| r0_48(int) = Load : &:r0_47, ~mu0_2 +# 181| r0_49(glval) = PointerAdd[4] : r0_46, r0_48 +# 181| r0_50(int) = Load : &:r0_49, ~mu0_2 +# 181| r0_51(glval) = VariableAddress[x] : +# 181| mu0_52(int) = Store : &:r0_51, r0_50 +# 182| r0_53(glval) = VariableAddress[a] : +# 182| r0_54(int *) = Convert : r0_53 +# 182| r0_55(glval) = VariableAddress[i] : +# 182| r0_56(int) = Load : &:r0_55, ~mu0_2 +# 182| r0_57(glval) = PointerAdd[4] : r0_54, r0_56 +# 182| r0_58(int) = Load : &:r0_57, ~mu0_2 +# 182| r0_59(glval) = VariableAddress[x] : +# 182| mu0_60(int) = Store : &:r0_59, r0_58 +# 183| r0_61(glval) = VariableAddress[x] : +# 183| r0_62(int) = Load : &:r0_61, ~mu0_2 +# 183| r0_63(glval) = VariableAddress[a] : +# 183| r0_64(int *) = Convert : r0_63 +# 183| r0_65(glval) = VariableAddress[i] : +# 183| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 183| r0_67(glval) = PointerAdd[4] : r0_64, r0_66 +# 183| mu0_68(int) = Store : &:r0_67, r0_62 +# 184| r0_69(glval) = VariableAddress[x] : +# 184| r0_70(int) = Load : &:r0_69, ~mu0_2 +# 184| r0_71(glval) = VariableAddress[a] : +# 184| r0_72(int *) = Convert : r0_71 +# 184| r0_73(glval) = VariableAddress[i] : +# 184| r0_74(int) = Load : &:r0_73, ~mu0_2 +# 184| r0_75(glval) = PointerAdd[4] : r0_72, r0_74 +# 184| mu0_76(int) = Store : &:r0_75, r0_70 +# 185| v0_77(void) = NoOp : +# 171| v0_78(void) = ReturnVoid : +# 171| v0_79(void) = UnmodeledUse : mu* +# 171| v0_80(void) = ExitFunction : # 187| void StringLiteral(int) # 187| Block 0 @@ -888,103 +894,109 @@ ir.cpp: # 193| void PointerCompare(int*, int*) # 193| Block 0 -# 193| v0_0(void) = EnterFunction : -# 193| mu0_1(unknown) = AliasedDefinition : -# 193| mu0_2(unknown) = UnmodeledDefinition : -# 193| r0_3(glval) = VariableAddress[p] : -# 193| mu0_4(int *) = InitializeParameter[p] : &:r0_3 -# 193| r0_5(glval) = VariableAddress[q] : -# 193| mu0_6(int *) = InitializeParameter[q] : &:r0_5 -# 194| r0_7(glval) = VariableAddress[b] : -# 194| mu0_8(bool) = Uninitialized[b] : &:r0_7 -# 196| r0_9(glval) = VariableAddress[p] : -# 196| r0_10(int *) = Load : &:r0_9, ~mu0_2 -# 196| r0_11(glval) = VariableAddress[q] : -# 196| r0_12(int *) = Load : &:r0_11, ~mu0_2 -# 196| r0_13(bool) = CompareEQ : r0_10, r0_12 -# 196| r0_14(glval) = VariableAddress[b] : -# 196| mu0_15(bool) = Store : &:r0_14, r0_13 -# 197| r0_16(glval) = VariableAddress[p] : -# 197| r0_17(int *) = Load : &:r0_16, ~mu0_2 -# 197| r0_18(glval) = VariableAddress[q] : -# 197| r0_19(int *) = Load : &:r0_18, ~mu0_2 -# 197| r0_20(bool) = CompareNE : r0_17, r0_19 -# 197| r0_21(glval) = VariableAddress[b] : -# 197| mu0_22(bool) = Store : &:r0_21, r0_20 -# 198| r0_23(glval) = VariableAddress[p] : -# 198| r0_24(int *) = Load : &:r0_23, ~mu0_2 -# 198| r0_25(glval) = VariableAddress[q] : -# 198| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 198| r0_27(bool) = CompareLT : r0_24, r0_26 -# 198| r0_28(glval) = VariableAddress[b] : -# 198| mu0_29(bool) = Store : &:r0_28, r0_27 -# 199| r0_30(glval) = VariableAddress[p] : -# 199| r0_31(int *) = Load : &:r0_30, ~mu0_2 -# 199| r0_32(glval) = VariableAddress[q] : -# 199| r0_33(int *) = Load : &:r0_32, ~mu0_2 -# 199| r0_34(bool) = CompareGT : r0_31, r0_33 -# 199| r0_35(glval) = VariableAddress[b] : -# 199| mu0_36(bool) = Store : &:r0_35, r0_34 -# 200| r0_37(glval) = VariableAddress[p] : -# 200| r0_38(int *) = Load : &:r0_37, ~mu0_2 -# 200| r0_39(glval) = VariableAddress[q] : -# 200| r0_40(int *) = Load : &:r0_39, ~mu0_2 -# 200| r0_41(bool) = CompareLE : r0_38, r0_40 -# 200| r0_42(glval) = VariableAddress[b] : -# 200| mu0_43(bool) = Store : &:r0_42, r0_41 -# 201| r0_44(glval) = VariableAddress[p] : -# 201| r0_45(int *) = Load : &:r0_44, ~mu0_2 -# 201| r0_46(glval) = VariableAddress[q] : -# 201| r0_47(int *) = Load : &:r0_46, ~mu0_2 -# 201| r0_48(bool) = CompareGE : r0_45, r0_47 -# 201| r0_49(glval) = VariableAddress[b] : -# 201| mu0_50(bool) = Store : &:r0_49, r0_48 -# 202| v0_51(void) = NoOp : -# 193| v0_52(void) = ReturnVoid : -# 193| v0_53(void) = UnmodeledUse : mu* -# 193| v0_54(void) = ExitFunction : +# 193| v0_0(void) = EnterFunction : +# 193| mu0_1(unknown) = AliasedDefinition : +# 193| mu0_2(unknown) = UnmodeledDefinition : +# 193| r0_3(glval) = VariableAddress[p] : +# 193| mu0_4(int *) = InitializeParameter[p] : &:r0_3 +# 193| r0_5(int *) = Load : &:r0_3, ~mu0_4 +# 193| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 193| r0_7(glval) = VariableAddress[q] : +# 193| mu0_8(int *) = InitializeParameter[q] : &:r0_7 +# 193| r0_9(int *) = Load : &:r0_7, ~mu0_8 +# 193| mu0_10(unknown) = InitializeIndirection[q] : &:r0_9 +# 194| r0_11(glval) = VariableAddress[b] : +# 194| mu0_12(bool) = Uninitialized[b] : &:r0_11 +# 196| r0_13(glval) = VariableAddress[p] : +# 196| r0_14(int *) = Load : &:r0_13, ~mu0_2 +# 196| r0_15(glval) = VariableAddress[q] : +# 196| r0_16(int *) = Load : &:r0_15, ~mu0_2 +# 196| r0_17(bool) = CompareEQ : r0_14, r0_16 +# 196| r0_18(glval) = VariableAddress[b] : +# 196| mu0_19(bool) = Store : &:r0_18, r0_17 +# 197| r0_20(glval) = VariableAddress[p] : +# 197| r0_21(int *) = Load : &:r0_20, ~mu0_2 +# 197| r0_22(glval) = VariableAddress[q] : +# 197| r0_23(int *) = Load : &:r0_22, ~mu0_2 +# 197| r0_24(bool) = CompareNE : r0_21, r0_23 +# 197| r0_25(glval) = VariableAddress[b] : +# 197| mu0_26(bool) = Store : &:r0_25, r0_24 +# 198| r0_27(glval) = VariableAddress[p] : +# 198| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 198| r0_29(glval) = VariableAddress[q] : +# 198| r0_30(int *) = Load : &:r0_29, ~mu0_2 +# 198| r0_31(bool) = CompareLT : r0_28, r0_30 +# 198| r0_32(glval) = VariableAddress[b] : +# 198| mu0_33(bool) = Store : &:r0_32, r0_31 +# 199| r0_34(glval) = VariableAddress[p] : +# 199| r0_35(int *) = Load : &:r0_34, ~mu0_2 +# 199| r0_36(glval) = VariableAddress[q] : +# 199| r0_37(int *) = Load : &:r0_36, ~mu0_2 +# 199| r0_38(bool) = CompareGT : r0_35, r0_37 +# 199| r0_39(glval) = VariableAddress[b] : +# 199| mu0_40(bool) = Store : &:r0_39, r0_38 +# 200| r0_41(glval) = VariableAddress[p] : +# 200| r0_42(int *) = Load : &:r0_41, ~mu0_2 +# 200| r0_43(glval) = VariableAddress[q] : +# 200| r0_44(int *) = Load : &:r0_43, ~mu0_2 +# 200| r0_45(bool) = CompareLE : r0_42, r0_44 +# 200| r0_46(glval) = VariableAddress[b] : +# 200| mu0_47(bool) = Store : &:r0_46, r0_45 +# 201| r0_48(glval) = VariableAddress[p] : +# 201| r0_49(int *) = Load : &:r0_48, ~mu0_2 +# 201| r0_50(glval) = VariableAddress[q] : +# 201| r0_51(int *) = Load : &:r0_50, ~mu0_2 +# 201| r0_52(bool) = CompareGE : r0_49, r0_51 +# 201| r0_53(glval) = VariableAddress[b] : +# 201| mu0_54(bool) = Store : &:r0_53, r0_52 +# 202| v0_55(void) = NoOp : +# 193| v0_56(void) = ReturnVoid : +# 193| v0_57(void) = UnmodeledUse : mu* +# 193| v0_58(void) = ExitFunction : # 204| void PointerCrement(int*) # 204| Block 0 -# 204| v0_0(void) = EnterFunction : -# 204| mu0_1(unknown) = AliasedDefinition : -# 204| mu0_2(unknown) = UnmodeledDefinition : -# 204| r0_3(glval) = VariableAddress[p] : -# 204| mu0_4(int *) = InitializeParameter[p] : &:r0_3 -# 205| r0_5(glval) = VariableAddress[q] : -# 205| mu0_6(int *) = Uninitialized[q] : &:r0_5 -# 207| r0_7(glval) = VariableAddress[p] : -# 207| r0_8(int *) = Load : &:r0_7, ~mu0_2 -# 207| r0_9(int) = Constant[1] : -# 207| r0_10(int *) = PointerAdd[4] : r0_8, r0_9 -# 207| mu0_11(int *) = Store : &:r0_7, r0_10 -# 207| r0_12(glval) = VariableAddress[q] : -# 207| mu0_13(int *) = Store : &:r0_12, r0_10 -# 208| r0_14(glval) = VariableAddress[p] : -# 208| r0_15(int *) = Load : &:r0_14, ~mu0_2 -# 208| r0_16(int) = Constant[1] : -# 208| r0_17(int *) = PointerSub[4] : r0_15, r0_16 -# 208| mu0_18(int *) = Store : &:r0_14, r0_17 -# 208| r0_19(glval) = VariableAddress[q] : -# 208| mu0_20(int *) = Store : &:r0_19, r0_17 -# 209| r0_21(glval) = VariableAddress[p] : -# 209| r0_22(int *) = Load : &:r0_21, ~mu0_2 -# 209| r0_23(int) = Constant[1] : -# 209| r0_24(int *) = PointerAdd[4] : r0_22, r0_23 -# 209| mu0_25(int *) = Store : &:r0_21, r0_24 -# 209| r0_26(glval) = VariableAddress[q] : -# 209| mu0_27(int *) = Store : &:r0_26, r0_22 -# 210| r0_28(glval) = VariableAddress[p] : -# 210| r0_29(int *) = Load : &:r0_28, ~mu0_2 -# 210| r0_30(int) = Constant[1] : -# 210| r0_31(int *) = PointerSub[4] : r0_29, r0_30 -# 210| mu0_32(int *) = Store : &:r0_28, r0_31 -# 210| r0_33(glval) = VariableAddress[q] : -# 210| mu0_34(int *) = Store : &:r0_33, r0_29 -# 211| v0_35(void) = NoOp : -# 204| v0_36(void) = ReturnVoid : -# 204| v0_37(void) = UnmodeledUse : mu* -# 204| v0_38(void) = ExitFunction : +# 204| v0_0(void) = EnterFunction : +# 204| mu0_1(unknown) = AliasedDefinition : +# 204| mu0_2(unknown) = UnmodeledDefinition : +# 204| r0_3(glval) = VariableAddress[p] : +# 204| mu0_4(int *) = InitializeParameter[p] : &:r0_3 +# 204| r0_5(int *) = Load : &:r0_3, ~mu0_4 +# 204| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 205| r0_7(glval) = VariableAddress[q] : +# 205| mu0_8(int *) = Uninitialized[q] : &:r0_7 +# 207| r0_9(glval) = VariableAddress[p] : +# 207| r0_10(int *) = Load : &:r0_9, ~mu0_2 +# 207| r0_11(int) = Constant[1] : +# 207| r0_12(int *) = PointerAdd[4] : r0_10, r0_11 +# 207| mu0_13(int *) = Store : &:r0_9, r0_12 +# 207| r0_14(glval) = VariableAddress[q] : +# 207| mu0_15(int *) = Store : &:r0_14, r0_12 +# 208| r0_16(glval) = VariableAddress[p] : +# 208| r0_17(int *) = Load : &:r0_16, ~mu0_2 +# 208| r0_18(int) = Constant[1] : +# 208| r0_19(int *) = PointerSub[4] : r0_17, r0_18 +# 208| mu0_20(int *) = Store : &:r0_16, r0_19 +# 208| r0_21(glval) = VariableAddress[q] : +# 208| mu0_22(int *) = Store : &:r0_21, r0_19 +# 209| r0_23(glval) = VariableAddress[p] : +# 209| r0_24(int *) = Load : &:r0_23, ~mu0_2 +# 209| r0_25(int) = Constant[1] : +# 209| r0_26(int *) = PointerAdd[4] : r0_24, r0_25 +# 209| mu0_27(int *) = Store : &:r0_23, r0_26 +# 209| r0_28(glval) = VariableAddress[q] : +# 209| mu0_29(int *) = Store : &:r0_28, r0_24 +# 210| r0_30(glval) = VariableAddress[p] : +# 210| r0_31(int *) = Load : &:r0_30, ~mu0_2 +# 210| r0_32(int) = Constant[1] : +# 210| r0_33(int *) = PointerSub[4] : r0_31, r0_32 +# 210| mu0_34(int *) = Store : &:r0_30, r0_33 +# 210| r0_35(glval) = VariableAddress[q] : +# 210| mu0_36(int *) = Store : &:r0_35, r0_31 +# 211| v0_37(void) = NoOp : +# 204| v0_38(void) = ReturnVoid : +# 204| v0_39(void) = UnmodeledUse : mu* +# 204| v0_40(void) = ExitFunction : # 213| void CompoundAssignment() # 213| Block 0 @@ -1544,19 +1556,21 @@ ir.cpp: # 341| mu0_2(unknown) = UnmodeledDefinition : # 341| r0_3(glval) = VariableAddress[p] : # 341| mu0_4(int *) = InitializeParameter[p] : &:r0_3 -# 342| r0_5(int) = Constant[1] : -# 342| r0_6(glval) = VariableAddress[p] : -# 342| r0_7(int *) = Load : &:r0_6, ~mu0_2 -# 342| mu0_8(int) = Store : &:r0_7, r0_5 -# 343| r0_9(glval) = VariableAddress[#return] : -# 343| r0_10(glval) = VariableAddress[p] : -# 343| r0_11(int *) = Load : &:r0_10, ~mu0_2 -# 343| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 343| mu0_13(int) = Store : &:r0_9, r0_12 -# 341| r0_14(glval) = VariableAddress[#return] : -# 341| v0_15(void) = ReturnValue : &:r0_14, ~mu0_2 -# 341| v0_16(void) = UnmodeledUse : mu* -# 341| v0_17(void) = ExitFunction : +# 341| r0_5(int *) = Load : &:r0_3, ~mu0_4 +# 341| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 342| r0_7(int) = Constant[1] : +# 342| r0_8(glval) = VariableAddress[p] : +# 342| r0_9(int *) = Load : &:r0_8, ~mu0_2 +# 342| mu0_10(int) = Store : &:r0_9, r0_7 +# 343| r0_11(glval) = VariableAddress[#return] : +# 343| r0_12(glval) = VariableAddress[p] : +# 343| r0_13(int *) = Load : &:r0_12, ~mu0_2 +# 343| r0_14(int) = Load : &:r0_13, ~mu0_2 +# 343| mu0_15(int) = Store : &:r0_11, r0_14 +# 341| r0_16(glval) = VariableAddress[#return] : +# 341| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 341| v0_18(void) = UnmodeledUse : mu* +# 341| v0_19(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -2748,37 +2762,41 @@ ir.cpp: # 622| mu0_2(unknown) = UnmodeledDefinition : # 622| r0_3(glval) = VariableAddress[r] : # 622| mu0_4(String &) = InitializeParameter[r] : &:r0_3 -# 622| r0_5(glval) = VariableAddress[p] : -# 622| mu0_6(String *) = InitializeParameter[p] : &:r0_5 -# 622| r0_7(glval) = VariableAddress[s] : -# 622| mu0_8(String) = InitializeParameter[s] : &:r0_7 -# 623| r0_9(glval) = VariableAddress[r] : -# 623| r0_10(String &) = Load : &:r0_9, ~mu0_2 -# 623| r0_11(glval) = Convert : r0_10 -# 623| r0_12(glval) = FunctionAddress[c_str] : -# 623| r0_13(char *) = Call : func:r0_12, this:r0_11 -# 623| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -# 623| v0_15(void) = ^IndirectReadSideEffect[-1] : &:r0_11, ~mu0_2 -# 623| mu0_16(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 -# 624| r0_17(glval) = VariableAddress[p] : -# 624| r0_18(String *) = Load : &:r0_17, ~mu0_2 -# 624| r0_19(String *) = Convert : r0_18 -# 624| r0_20(glval) = FunctionAddress[c_str] : -# 624| r0_21(char *) = Call : func:r0_20, this:r0_19 -# 624| mu0_22(unknown) = ^CallSideEffect : ~mu0_2 -# 624| v0_23(void) = ^IndirectReadSideEffect[-1] : &:r0_19, ~mu0_2 -# 624| mu0_24(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 -# 625| r0_25(glval) = VariableAddress[s] : -# 625| r0_26(glval) = Convert : r0_25 -# 625| r0_27(glval) = FunctionAddress[c_str] : -# 625| r0_28(char *) = Call : func:r0_27, this:r0_26 -# 625| mu0_29(unknown) = ^CallSideEffect : ~mu0_2 -# 625| v0_30(void) = ^IndirectReadSideEffect[-1] : &:r0_26, ~mu0_2 -# 625| mu0_31(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_26 -# 626| v0_32(void) = NoOp : -# 622| v0_33(void) = ReturnVoid : -# 622| v0_34(void) = UnmodeledUse : mu* -# 622| v0_35(void) = ExitFunction : +# 622| r0_5(String &) = Load : &:r0_3, ~mu0_4 +# 622| mu0_6(unknown) = InitializeIndirection[r] : &:r0_5 +# 622| r0_7(glval) = VariableAddress[p] : +# 622| mu0_8(String *) = InitializeParameter[p] : &:r0_7 +# 622| r0_9(String *) = Load : &:r0_7, ~mu0_8 +# 622| mu0_10(unknown) = InitializeIndirection[p] : &:r0_9 +# 622| r0_11(glval) = VariableAddress[s] : +# 622| mu0_12(String) = InitializeParameter[s] : &:r0_11 +# 623| r0_13(glval) = VariableAddress[r] : +# 623| r0_14(String &) = Load : &:r0_13, ~mu0_2 +# 623| r0_15(glval) = Convert : r0_14 +# 623| r0_16(glval) = FunctionAddress[c_str] : +# 623| r0_17(char *) = Call : func:r0_16, this:r0_15 +# 623| mu0_18(unknown) = ^CallSideEffect : ~mu0_2 +# 623| v0_19(void) = ^IndirectReadSideEffect[-1] : &:r0_15, ~mu0_2 +# 623| mu0_20(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_15 +# 624| r0_21(glval) = VariableAddress[p] : +# 624| r0_22(String *) = Load : &:r0_21, ~mu0_2 +# 624| r0_23(String *) = Convert : r0_22 +# 624| r0_24(glval) = FunctionAddress[c_str] : +# 624| r0_25(char *) = Call : func:r0_24, this:r0_23 +# 624| mu0_26(unknown) = ^CallSideEffect : ~mu0_2 +# 624| v0_27(void) = ^IndirectReadSideEffect[-1] : &:r0_23, ~mu0_2 +# 624| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_23 +# 625| r0_29(glval) = VariableAddress[s] : +# 625| r0_30(glval) = Convert : r0_29 +# 625| r0_31(glval) = FunctionAddress[c_str] : +# 625| r0_32(char *) = Call : func:r0_31, this:r0_30 +# 625| mu0_33(unknown) = ^CallSideEffect : ~mu0_2 +# 625| v0_34(void) = ^IndirectReadSideEffect[-1] : &:r0_30, ~mu0_2 +# 625| mu0_35(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_30 +# 626| v0_36(void) = NoOp : +# 622| v0_37(void) = ReturnVoid : +# 622| v0_38(void) = UnmodeledUse : mu* +# 622| v0_39(void) = ExitFunction : # 630| int C::StaticMemberFunction(int) # 630| Block 0 @@ -2941,15 +2959,17 @@ ir.cpp: # 675| mu0_2(unknown) = UnmodeledDefinition : # 675| r0_3(glval) = VariableAddress[r] : # 675| mu0_4(int &) = InitializeParameter[r] : &:r0_3 -# 676| r0_5(glval) = VariableAddress[#return] : -# 676| r0_6(glval) = VariableAddress[r] : -# 676| r0_7(int &) = Load : &:r0_6, ~mu0_2 -# 676| r0_8(int) = Load : &:r0_7, ~mu0_2 -# 676| mu0_9(int) = Store : &:r0_5, r0_8 -# 675| r0_10(glval) = VariableAddress[#return] : -# 675| v0_11(void) = ReturnValue : &:r0_10, ~mu0_2 -# 675| v0_12(void) = UnmodeledUse : mu* -# 675| v0_13(void) = ExitFunction : +# 675| r0_5(int &) = Load : &:r0_3, ~mu0_4 +# 675| mu0_6(unknown) = InitializeIndirection[r] : &:r0_5 +# 676| r0_7(glval) = VariableAddress[#return] : +# 676| r0_8(glval) = VariableAddress[r] : +# 676| r0_9(int &) = Load : &:r0_8, ~mu0_2 +# 676| r0_10(int) = Load : &:r0_9, ~mu0_2 +# 676| mu0_11(int) = Store : &:r0_7, r0_10 +# 675| r0_12(glval) = VariableAddress[#return] : +# 675| v0_13(void) = ReturnValue : &:r0_12, ~mu0_2 +# 675| v0_14(void) = UnmodeledUse : mu* +# 675| v0_15(void) = ExitFunction : # 679| int& TakeReference() # 679| Block 0 @@ -3106,15 +3126,17 @@ ir.cpp: # 715| mu0_2(unknown) = UnmodeledDefinition : # 715| r0_3(glval) = VariableAddress[x] : # 715| mu0_4(void *) = InitializeParameter[x] : &:r0_3 -# 715| r0_5(glval) = VariableAddress[y] : -# 715| mu0_6(char) = InitializeParameter[y] : &:r0_5 -# 716| r0_7(glval) = VariableAddress[#return] : -# 716| r0_8(long) = Constant[0] : -# 716| mu0_9(long) = Store : &:r0_7, r0_8 -# 715| r0_10(glval) = VariableAddress[#return] : -# 715| v0_11(void) = ReturnValue : &:r0_10, ~mu0_2 -# 715| v0_12(void) = UnmodeledUse : mu* -# 715| v0_13(void) = ExitFunction : +# 715| r0_5(void *) = Load : &:r0_3, ~mu0_4 +# 715| mu0_6(unknown) = InitializeIndirection[x] : &:r0_5 +# 715| r0_7(glval) = VariableAddress[y] : +# 715| mu0_8(char) = InitializeParameter[y] : &:r0_7 +# 716| r0_9(glval) = VariableAddress[#return] : +# 716| r0_10(long) = Constant[0] : +# 716| mu0_11(long) = Store : &:r0_9, r0_10 +# 715| r0_12(glval) = VariableAddress[#return] : +# 715| v0_13(void) = ReturnValue : &:r0_12, ~mu0_2 +# 715| v0_14(void) = UnmodeledUse : mu* +# 715| v0_15(void) = ExitFunction : # 720| double CallNestedTemplateFunc() # 720| Block 0 @@ -3220,15 +3242,17 @@ ir.cpp: # 735| Block 10 # 735| r10_0(glval) = VariableAddress[s] : # 735| mu10_1(char *) = InitializeParameter[s] : &:r10_0 -# 736| r10_2(glval) = VariableAddress[#throw736:5] : -# 736| r10_3(glval) = FunctionAddress[String] : -# 736| r10_4(glval) = VariableAddress[s] : -# 736| r10_5(char *) = Load : &:r10_4, ~mu0_2 -# 736| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 -# 736| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 736| v10_8(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 -# 736| mu10_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 -# 736| v10_10(void) = ThrowValue : &:r10_2, ~mu0_2 +# 735| r10_2(char *) = Load : &:r10_0, ~mu10_1 +# 735| mu10_3(unknown) = InitializeIndirection[s] : &:r10_2 +# 736| r10_4(glval) = VariableAddress[#throw736:5] : +# 736| r10_5(glval) = FunctionAddress[String] : +# 736| r10_6(glval) = VariableAddress[s] : +# 736| r10_7(char *) = Load : &:r10_6, ~mu0_2 +# 736| v10_8(void) = Call : func:r10_5, this:r10_4, 0:r10_7 +# 736| mu10_9(unknown) = ^CallSideEffect : ~mu0_2 +# 736| v10_10(void) = ^IndirectReadSideEffect[0] : &:r10_7, ~mu0_2 +# 736| mu10_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_7 +# 736| v10_12(void) = ThrowValue : &:r10_4, ~mu0_2 #-----| Exception -> Block 2 # 738| Block 11 @@ -3237,9 +3261,11 @@ ir.cpp: #-----| Goto -> Block 12 # 738| Block 12 -# 738| r12_0(glval) = VariableAddress[e] : -# 738| mu12_1(String &) = InitializeParameter[e] : &:r12_0 -# 738| v12_2(void) = NoOp : +# 738| r12_0(glval) = VariableAddress[e] : +# 738| mu12_1(String &) = InitializeParameter[e] : &:r12_0 +# 738| r12_2(String &) = Load : &:r12_0, ~mu12_1 +# 738| mu12_3(unknown) = InitializeIndirection[e] : &:r12_2 +# 738| v12_4(void) = NoOp : #-----| Goto -> Block 14 # 740| Block 13 @@ -3254,48 +3280,52 @@ ir.cpp: # 745| Base& Base::operator=(Base const&) # 745| Block 0 -# 745| v0_0(void) = EnterFunction : -# 745| mu0_1(unknown) = AliasedDefinition : -# 745| mu0_2(unknown) = UnmodeledDefinition : -# 745| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Base *) = CopyValue : r0_3 -#-----| r0_7(glval) = FieldAddress[base_s] : r0_6 -# 745| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Base &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(glval) = FieldAddress[base_s] : r0_10 -# 745| r0_12(String &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 745| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 -#-----| mu0_16(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -#-----| r0_18(glval) = VariableAddress[#return] : -#-----| r0_19(Base *) = CopyValue : r0_3 -#-----| mu0_20(Base &) = Store : &:r0_18, r0_19 -# 745| r0_21(glval) = VariableAddress[#return] : -# 745| v0_22(void) = ReturnValue : &:r0_21, ~mu0_2 -# 745| v0_23(void) = UnmodeledUse : mu* -# 745| v0_24(void) = ExitFunction : +# 745| v0_0(void) = EnterFunction : +# 745| mu0_1(unknown) = AliasedDefinition : +# 745| mu0_2(unknown) = UnmodeledDefinition : +# 745| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(Base &) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +#-----| r0_8(Base *) = CopyValue : r0_3 +#-----| r0_9(glval) = FieldAddress[base_s] : r0_8 +# 745| r0_10(glval) = FunctionAddress[operator=] : +#-----| r0_11(glval) = VariableAddress[p#0] : +#-----| r0_12(Base &) = Load : &:r0_11, ~mu0_2 +#-----| r0_13(glval) = FieldAddress[base_s] : r0_12 +# 745| r0_14(String &) = Call : func:r0_10, this:r0_9, 0:r0_13 +# 745| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_16(void) = ^IndirectReadSideEffect[-1] : &:r0_9, ~mu0_2 +#-----| v0_17(void) = ^IndirectReadSideEffect[0] : &:r0_13, ~mu0_2 +#-----| mu0_18(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +#-----| mu0_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_13 +#-----| r0_20(glval) = VariableAddress[#return] : +#-----| r0_21(Base *) = CopyValue : r0_3 +#-----| mu0_22(Base &) = Store : &:r0_20, r0_21 +# 745| r0_23(glval) = VariableAddress[#return] : +# 745| v0_24(void) = ReturnValue : &:r0_23, ~mu0_2 +# 745| v0_25(void) = UnmodeledUse : mu* +# 745| v0_26(void) = ExitFunction : # 745| void Base::Base(Base const&) # 745| Block 0 -# 745| v0_0(void) = EnterFunction : -# 745| mu0_1(unknown) = AliasedDefinition : -# 745| mu0_2(unknown) = UnmodeledDefinition : -# 745| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 -# 745| r0_6(glval) = FieldAddress[base_s] : r0_3 -# 745| r0_7(glval) = FunctionAddress[String] : -# 745| v0_8(void) = Call : func:r0_7, this:r0_6 -# 745| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 745| v0_10(void) = NoOp : -# 745| v0_11(void) = ReturnVoid : -# 745| v0_12(void) = UnmodeledUse : mu* -# 745| v0_13(void) = ExitFunction : +# 745| v0_0(void) = EnterFunction : +# 745| mu0_1(unknown) = AliasedDefinition : +# 745| mu0_2(unknown) = UnmodeledDefinition : +# 745| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(Base &) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(Base &) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +# 745| r0_8(glval) = FieldAddress[base_s] : r0_3 +# 745| r0_9(glval) = FunctionAddress[String] : +# 745| v0_10(void) = Call : func:r0_9, this:r0_8 +# 745| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 745| v0_12(void) = NoOp : +# 745| v0_13(void) = ReturnVoid : +# 745| v0_14(void) = UnmodeledUse : mu* +# 745| v0_15(void) = ExitFunction : # 748| void Base::Base() # 748| Block 0 @@ -3335,37 +3365,39 @@ ir.cpp: # 754| r0_3(glval) = InitializeThis : #-----| r0_4(glval) = VariableAddress[p#0] : #-----| mu0_5(Middle &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Middle *) = CopyValue : r0_3 -#-----| r0_7(Base *) = ConvertToBase[Middle : Base] : r0_6 -# 754| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Middle &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Base *) = ConvertToBase[Middle : Base] : r0_10 -# 754| r0_12(Base &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 754| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 -#-----| mu0_16(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -#-----| r0_18(Middle *) = CopyValue : r0_3 -#-----| r0_19(glval) = FieldAddress[middle_s] : r0_18 -# 754| r0_20(glval) = FunctionAddress[operator=] : -#-----| r0_21(glval) = VariableAddress[p#0] : -#-----| r0_22(Middle &) = Load : &:r0_21, ~mu0_2 -#-----| r0_23(glval) = FieldAddress[middle_s] : r0_22 -# 754| r0_24(String &) = Call : func:r0_20, this:r0_19, 0:r0_23 -# 754| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_26(void) = ^IndirectReadSideEffect[-1] : &:r0_19, ~mu0_2 -#-----| v0_27(void) = ^IndirectReadSideEffect[0] : &:r0_23, ~mu0_2 -#-----| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 -#-----| mu0_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_23 -#-----| r0_30(glval) = VariableAddress[#return] : -#-----| r0_31(Middle *) = CopyValue : r0_3 -#-----| mu0_32(Middle &) = Store : &:r0_30, r0_31 -# 754| r0_33(glval) = VariableAddress[#return] : -# 754| v0_34(void) = ReturnValue : &:r0_33, ~mu0_2 -# 754| v0_35(void) = UnmodeledUse : mu* -# 754| v0_36(void) = ExitFunction : +#-----| r0_6(Middle &) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +#-----| r0_8(Middle *) = CopyValue : r0_3 +#-----| r0_9(Base *) = ConvertToBase[Middle : Base] : r0_8 +# 754| r0_10(glval) = FunctionAddress[operator=] : +#-----| r0_11(glval) = VariableAddress[p#0] : +#-----| r0_12(Middle &) = Load : &:r0_11, ~mu0_2 +#-----| r0_13(Base *) = ConvertToBase[Middle : Base] : r0_12 +# 754| r0_14(Base &) = Call : func:r0_10, this:r0_9, 0:r0_13 +# 754| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_16(void) = ^IndirectReadSideEffect[-1] : &:r0_9, ~mu0_2 +#-----| v0_17(void) = ^IndirectReadSideEffect[0] : &:r0_13, ~mu0_2 +#-----| mu0_18(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +#-----| mu0_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_13 +#-----| r0_20(Middle *) = CopyValue : r0_3 +#-----| r0_21(glval) = FieldAddress[middle_s] : r0_20 +# 754| r0_22(glval) = FunctionAddress[operator=] : +#-----| r0_23(glval) = VariableAddress[p#0] : +#-----| r0_24(Middle &) = Load : &:r0_23, ~mu0_2 +#-----| r0_25(glval) = FieldAddress[middle_s] : r0_24 +# 754| r0_26(String &) = Call : func:r0_22, this:r0_21, 0:r0_25 +# 754| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_28(void) = ^IndirectReadSideEffect[-1] : &:r0_21, ~mu0_2 +#-----| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 +#-----| mu0_30(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_21 +#-----| mu0_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 +#-----| r0_32(glval) = VariableAddress[#return] : +#-----| r0_33(Middle *) = CopyValue : r0_3 +#-----| mu0_34(Middle &) = Store : &:r0_32, r0_33 +# 754| r0_35(glval) = VariableAddress[#return] : +# 754| v0_36(void) = ReturnValue : &:r0_35, ~mu0_2 +# 754| v0_37(void) = UnmodeledUse : mu* +# 754| v0_38(void) = ExitFunction : # 757| void Middle::Middle() # 757| Block 0 @@ -3413,37 +3445,39 @@ ir.cpp: # 763| r0_3(glval) = InitializeThis : #-----| r0_4(glval) = VariableAddress[p#0] : #-----| mu0_5(Derived &) = InitializeParameter[p#0] : &:r0_4 -#-----| r0_6(Derived *) = CopyValue : r0_3 -#-----| r0_7(Middle *) = ConvertToBase[Derived : Middle] : r0_6 -# 763| r0_8(glval) = FunctionAddress[operator=] : -#-----| r0_9(glval) = VariableAddress[p#0] : -#-----| r0_10(Derived &) = Load : &:r0_9, ~mu0_2 -#-----| r0_11(Middle *) = ConvertToBase[Derived : Middle] : r0_10 -# 763| r0_12(Middle &) = Call : func:r0_8, this:r0_7, 0:r0_11 -# 763| mu0_13(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_14(void) = ^IndirectReadSideEffect[-1] : &:r0_7, ~mu0_2 -#-----| v0_15(void) = ^IndirectReadSideEffect[0] : &:r0_11, ~mu0_2 -#-----| mu0_16(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_7 -#-----| mu0_17(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_11 -#-----| r0_18(Derived *) = CopyValue : r0_3 -#-----| r0_19(glval) = FieldAddress[derived_s] : r0_18 -# 763| r0_20(glval) = FunctionAddress[operator=] : -#-----| r0_21(glval) = VariableAddress[p#0] : -#-----| r0_22(Derived &) = Load : &:r0_21, ~mu0_2 -#-----| r0_23(glval) = FieldAddress[derived_s] : r0_22 -# 763| r0_24(String &) = Call : func:r0_20, this:r0_19, 0:r0_23 -# 763| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_26(void) = ^IndirectReadSideEffect[-1] : &:r0_19, ~mu0_2 -#-----| v0_27(void) = ^IndirectReadSideEffect[0] : &:r0_23, ~mu0_2 -#-----| mu0_28(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_19 -#-----| mu0_29(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_23 -#-----| r0_30(glval) = VariableAddress[#return] : -#-----| r0_31(Derived *) = CopyValue : r0_3 -#-----| mu0_32(Derived &) = Store : &:r0_30, r0_31 -# 763| r0_33(glval) = VariableAddress[#return] : -# 763| v0_34(void) = ReturnValue : &:r0_33, ~mu0_2 -# 763| v0_35(void) = UnmodeledUse : mu* -# 763| v0_36(void) = ExitFunction : +#-----| r0_6(Derived &) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +#-----| r0_8(Derived *) = CopyValue : r0_3 +#-----| r0_9(Middle *) = ConvertToBase[Derived : Middle] : r0_8 +# 763| r0_10(glval) = FunctionAddress[operator=] : +#-----| r0_11(glval) = VariableAddress[p#0] : +#-----| r0_12(Derived &) = Load : &:r0_11, ~mu0_2 +#-----| r0_13(Middle *) = ConvertToBase[Derived : Middle] : r0_12 +# 763| r0_14(Middle &) = Call : func:r0_10, this:r0_9, 0:r0_13 +# 763| mu0_15(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_16(void) = ^IndirectReadSideEffect[-1] : &:r0_9, ~mu0_2 +#-----| v0_17(void) = ^IndirectReadSideEffect[0] : &:r0_13, ~mu0_2 +#-----| mu0_18(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_9 +#-----| mu0_19(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_13 +#-----| r0_20(Derived *) = CopyValue : r0_3 +#-----| r0_21(glval) = FieldAddress[derived_s] : r0_20 +# 763| r0_22(glval) = FunctionAddress[operator=] : +#-----| r0_23(glval) = VariableAddress[p#0] : +#-----| r0_24(Derived &) = Load : &:r0_23, ~mu0_2 +#-----| r0_25(glval) = FieldAddress[derived_s] : r0_24 +# 763| r0_26(String &) = Call : func:r0_22, this:r0_21, 0:r0_25 +# 763| mu0_27(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_28(void) = ^IndirectReadSideEffect[-1] : &:r0_21, ~mu0_2 +#-----| v0_29(void) = ^IndirectReadSideEffect[0] : &:r0_25, ~mu0_2 +#-----| mu0_30(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_21 +#-----| mu0_31(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_25 +#-----| r0_32(glval) = VariableAddress[#return] : +#-----| r0_33(Derived *) = CopyValue : r0_3 +#-----| mu0_34(Derived &) = Store : &:r0_32, r0_33 +# 763| r0_35(glval) = VariableAddress[#return] : +# 763| v0_36(void) = ReturnValue : &:r0_35, ~mu0_2 +# 763| v0_37(void) = UnmodeledUse : mu* +# 763| v0_38(void) = ExitFunction : # 766| void Derived::Derived() # 766| Block 0 @@ -4035,20 +4069,22 @@ ir.cpp: # 883| mu0_4(..(*)(..)) = InitializeParameter[pfn] : &:r0_3 # 883| r0_5(glval) = VariableAddress[p] : # 883| mu0_6(void *) = InitializeParameter[p] : &:r0_5 -# 884| r0_7(glval<..(*)(..)>) = VariableAddress[pfn] : -# 884| r0_8(..(*)(..)) = Load : &:r0_7, ~mu0_2 -# 884| r0_9(void *) = Convert : r0_8 -# 884| r0_10(glval) = VariableAddress[p] : -# 884| mu0_11(void *) = Store : &:r0_10, r0_9 -# 885| r0_12(glval) = VariableAddress[p] : -# 885| r0_13(void *) = Load : &:r0_12, ~mu0_2 -# 885| r0_14(..(*)(..)) = Convert : r0_13 -# 885| r0_15(glval<..(*)(..)>) = VariableAddress[pfn] : -# 885| mu0_16(..(*)(..)) = Store : &:r0_15, r0_14 -# 886| v0_17(void) = NoOp : -# 883| v0_18(void) = ReturnVoid : -# 883| v0_19(void) = UnmodeledUse : mu* -# 883| v0_20(void) = ExitFunction : +# 883| r0_7(void *) = Load : &:r0_5, ~mu0_6 +# 883| mu0_8(unknown) = InitializeIndirection[p] : &:r0_7 +# 884| r0_9(glval<..(*)(..)>) = VariableAddress[pfn] : +# 884| r0_10(..(*)(..)) = Load : &:r0_9, ~mu0_2 +# 884| r0_11(void *) = Convert : r0_10 +# 884| r0_12(glval) = VariableAddress[p] : +# 884| mu0_13(void *) = Store : &:r0_12, r0_11 +# 885| r0_14(glval) = VariableAddress[p] : +# 885| r0_15(void *) = Load : &:r0_14, ~mu0_2 +# 885| r0_16(..(*)(..)) = Convert : r0_15 +# 885| r0_17(glval<..(*)(..)>) = VariableAddress[pfn] : +# 885| mu0_18(..(*)(..)) = Store : &:r0_17, r0_16 +# 886| v0_19(void) = NoOp : +# 883| v0_20(void) = ReturnVoid : +# 883| v0_21(void) = UnmodeledUse : mu* +# 883| v0_22(void) = ExitFunction : # 888| void VarArgUsage(int) # 888| Block 0 @@ -4483,25 +4519,27 @@ ir.cpp: # 987| mu0_2(unknown) = UnmodeledDefinition : # 987| r0_3(glval) = VariableAddress[a] : # 987| mu0_4(int *) = InitializeParameter[a] : &:r0_3 -# 987| r0_5(glval<..(*)(..)>) = VariableAddress[fn] : -# 987| mu0_6(..(*)(..)) = InitializeParameter[fn] : &:r0_5 -# 988| r0_7(glval) = VariableAddress[#return] : -# 988| r0_8(glval) = VariableAddress[a] : -# 988| r0_9(int *) = Load : &:r0_8, ~mu0_2 -# 988| r0_10(int) = Constant[0] : -# 988| r0_11(glval) = PointerAdd[4] : r0_9, r0_10 -# 988| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 988| r0_13(glval<..(*)(..)>) = VariableAddress[fn] : -# 988| r0_14(..(*)(..)) = Load : &:r0_13, ~mu0_2 -# 988| r0_15(float) = Constant[1.0] : -# 988| r0_16(int) = Call : func:r0_14, 0:r0_15 -# 988| mu0_17(unknown) = ^CallSideEffect : ~mu0_2 -# 988| r0_18(int) = Add : r0_12, r0_16 -# 988| mu0_19(int) = Store : &:r0_7, r0_18 -# 987| r0_20(glval) = VariableAddress[#return] : -# 987| v0_21(void) = ReturnValue : &:r0_20, ~mu0_2 -# 987| v0_22(void) = UnmodeledUse : mu* -# 987| v0_23(void) = ExitFunction : +# 987| r0_5(int *) = Load : &:r0_3, ~mu0_4 +# 987| mu0_6(unknown) = InitializeIndirection[a] : &:r0_5 +# 987| r0_7(glval<..(*)(..)>) = VariableAddress[fn] : +# 987| mu0_8(..(*)(..)) = InitializeParameter[fn] : &:r0_7 +# 988| r0_9(glval) = VariableAddress[#return] : +# 988| r0_10(glval) = VariableAddress[a] : +# 988| r0_11(int *) = Load : &:r0_10, ~mu0_2 +# 988| r0_12(int) = Constant[0] : +# 988| r0_13(glval) = PointerAdd[4] : r0_11, r0_12 +# 988| r0_14(int) = Load : &:r0_13, ~mu0_2 +# 988| r0_15(glval<..(*)(..)>) = VariableAddress[fn] : +# 988| r0_16(..(*)(..)) = Load : &:r0_15, ~mu0_2 +# 988| r0_17(float) = Constant[1.0] : +# 988| r0_18(int) = Call : func:r0_16, 0:r0_17 +# 988| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 +# 988| r0_20(int) = Add : r0_14, r0_18 +# 988| mu0_21(int) = Store : &:r0_9, r0_20 +# 987| r0_22(glval) = VariableAddress[#return] : +# 987| v0_23(void) = ReturnValue : &:r0_22, ~mu0_2 +# 987| v0_24(void) = UnmodeledUse : mu* +# 987| v0_25(void) = ExitFunction : # 991| int ExprStmt(int, int, int) # 991| Block 0 @@ -4608,16 +4646,18 @@ ir.cpp: # 1029| void (lambda [] type at line 1029, col. 12)::(constructor)((lambda [] type at line 1029, col. 12)&&) # 1029| Block 0 -# 1029| v0_0(void) = EnterFunction : -# 1029| mu0_1(unknown) = AliasedDefinition : -# 1029| mu0_2(unknown) = UnmodeledDefinition : -# 1029| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(lambda [] type at line 1029, col. 12 &&) = InitializeParameter[p#0] : &:r0_4 -# 1029| v0_6(void) = NoOp : -# 1029| v0_7(void) = ReturnVoid : -# 1029| v0_8(void) = UnmodeledUse : mu* -# 1029| v0_9(void) = ExitFunction : +# 1029| v0_0(void) = EnterFunction : +# 1029| mu0_1(unknown) = AliasedDefinition : +# 1029| mu0_2(unknown) = UnmodeledDefinition : +# 1029| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(lambda [] type at line 1029, col. 12 &&) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(lambda [] type at line 1029, col. 12 &&) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +# 1029| v0_8(void) = NoOp : +# 1029| v0_9(void) = ReturnVoid : +# 1029| v0_10(void) = UnmodeledUse : mu* +# 1029| v0_11(void) = ExitFunction : # 1029| void (lambda [] type at line 1029, col. 12)::operator()() const # 1029| Block 0 @@ -4653,169 +4693,173 @@ ir.cpp: # 1031| mu0_4(int) = InitializeParameter[x] : &:r0_3 # 1031| r0_5(glval) = VariableAddress[s] : # 1031| mu0_6(String &) = InitializeParameter[s] : &:r0_5 -# 1032| r0_7(glval) = VariableAddress[lambda_empty] : -# 1032| r0_8(glval) = VariableAddress[#temp1032:23] : -# 1032| mu0_9(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_8 -# 1032| r0_10(decltype([...](...){...})) = Load : &:r0_8, ~mu0_2 -# 1032| mu0_11(decltype([...](...){...})) = Store : &:r0_7, r0_10 -# 1033| r0_12(char) = Constant[65] : -# 1034| r0_13(glval) = VariableAddress[lambda_ref] : -# 1034| r0_14(glval) = VariableAddress[#temp1034:21] : -# 1034| mu0_15(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_14 -# 1034| r0_16(glval) = FieldAddress[s] : r0_14 -#-----| r0_17(glval) = VariableAddress[s] : -#-----| r0_18(String &) = Load : &:r0_17, ~mu0_2 -# 1034| mu0_19(String &) = Store : &:r0_16, r0_18 -# 1034| r0_20(glval) = FieldAddress[x] : r0_14 -#-----| r0_21(glval) = VariableAddress[x] : -#-----| mu0_22(int &) = Store : &:r0_20, r0_21 -# 1034| r0_23(decltype([...](...){...})) = Load : &:r0_14, ~mu0_2 -# 1034| mu0_24(decltype([...](...){...})) = Store : &:r0_13, r0_23 -# 1035| r0_25(glval) = VariableAddress[lambda_ref] : -# 1035| r0_26(glval) = Convert : r0_25 -# 1035| r0_27(glval) = FunctionAddress[operator()] : -# 1035| r0_28(float) = Constant[1.0] : -# 1035| r0_29(char) = Call : func:r0_27, this:r0_26, 0:r0_28 -# 1035| mu0_30(unknown) = ^CallSideEffect : ~mu0_2 -# 1035| v0_31(void) = ^IndirectReadSideEffect[-1] : &:r0_26, ~mu0_2 -# 1035| mu0_32(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_26 -# 1036| r0_33(glval) = VariableAddress[lambda_val] : -# 1036| r0_34(glval) = FunctionAddress[(constructor)] : -# 1036| r0_35(glval) = VariableAddress[#temp1036:21] : -# 1036| mu0_36(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_35 -# 1036| r0_37(glval) = FieldAddress[s] : r0_35 -#-----| r0_38(glval) = FunctionAddress[String] : -#-----| v0_39(void) = Call : func:r0_38, this:r0_37 -#-----| mu0_40(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| r0_41(glval) = FieldAddress[x] : r0_35 -#-----| r0_42(glval) = VariableAddress[x] : -#-----| r0_43(int) = Load : &:r0_42, ~mu0_2 -#-----| mu0_44(int) = Store : &:r0_41, r0_43 -# 1036| r0_45(decltype([...](...){...})) = Load : &:r0_35, ~mu0_2 -# 1036| v0_46(void) = Call : func:r0_34, this:r0_33, 0:r0_45 -# 1036| mu0_47(unknown) = ^CallSideEffect : ~mu0_2 -# 1036| v0_48(void) = ^IndirectReadSideEffect[0] : &:r0_45, ~mu0_2 -# 1036| mu0_49(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_45 -# 1037| r0_50(glval) = VariableAddress[lambda_val] : -# 1037| r0_51(glval) = Convert : r0_50 -# 1037| r0_52(glval) = FunctionAddress[operator()] : -# 1037| r0_53(float) = Constant[2.0] : -# 1037| r0_54(char) = Call : func:r0_52, this:r0_51, 0:r0_53 -# 1037| mu0_55(unknown) = ^CallSideEffect : ~mu0_2 -# 1037| v0_56(void) = ^IndirectReadSideEffect[-1] : &:r0_51, ~mu0_2 -# 1037| mu0_57(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_51 -# 1038| r0_58(glval) = VariableAddress[lambda_ref_explicit] : -# 1038| r0_59(glval) = VariableAddress[#temp1038:30] : -# 1038| mu0_60(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_59 -# 1038| r0_61(glval) = FieldAddress[s] : r0_59 -# 1038| r0_62(glval) = VariableAddress[s] : -# 1038| r0_63(String &) = Load : &:r0_62, ~mu0_2 -# 1038| mu0_64(String &) = Store : &:r0_61, r0_63 -# 1038| r0_65(decltype([...](...){...})) = Load : &:r0_59, ~mu0_2 -# 1038| mu0_66(decltype([...](...){...})) = Store : &:r0_58, r0_65 -# 1039| r0_67(glval) = VariableAddress[lambda_ref_explicit] : -# 1039| r0_68(glval) = Convert : r0_67 -# 1039| r0_69(glval) = FunctionAddress[operator()] : -# 1039| r0_70(float) = Constant[3.0] : -# 1039| r0_71(char) = Call : func:r0_69, this:r0_68, 0:r0_70 -# 1039| mu0_72(unknown) = ^CallSideEffect : ~mu0_2 -# 1039| v0_73(void) = ^IndirectReadSideEffect[-1] : &:r0_68, ~mu0_2 -# 1039| mu0_74(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_68 -# 1040| r0_75(glval) = VariableAddress[lambda_val_explicit] : -# 1040| r0_76(glval) = FunctionAddress[(constructor)] : -# 1040| r0_77(glval) = VariableAddress[#temp1040:30] : -# 1040| mu0_78(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_77 -# 1040| r0_79(glval) = FieldAddress[s] : r0_77 -#-----| r0_80(glval) = FunctionAddress[String] : -#-----| v0_81(void) = Call : func:r0_80, this:r0_79 -#-----| mu0_82(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| r0_83(decltype([...](...){...})) = Load : &:r0_77, ~mu0_2 -# 1040| v0_84(void) = Call : func:r0_76, this:r0_75, 0:r0_83 -# 1040| mu0_85(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| v0_86(void) = ^IndirectReadSideEffect[0] : &:r0_83, ~mu0_2 -# 1040| mu0_87(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_83 -# 1041| r0_88(glval) = VariableAddress[lambda_val_explicit] : -# 1041| r0_89(glval) = Convert : r0_88 -# 1041| r0_90(glval) = FunctionAddress[operator()] : -# 1041| r0_91(float) = Constant[4.0] : -# 1041| r0_92(char) = Call : func:r0_90, this:r0_89, 0:r0_91 -# 1041| mu0_93(unknown) = ^CallSideEffect : ~mu0_2 -# 1041| v0_94(void) = ^IndirectReadSideEffect[-1] : &:r0_89, ~mu0_2 -# 1041| mu0_95(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_89 -# 1042| r0_96(glval) = VariableAddress[lambda_mixed_explicit] : -# 1042| r0_97(glval) = VariableAddress[#temp1042:32] : -# 1042| mu0_98(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_97 -# 1042| r0_99(glval) = FieldAddress[s] : r0_97 -# 1042| r0_100(glval) = VariableAddress[s] : -# 1042| r0_101(String &) = Load : &:r0_100, ~mu0_2 -# 1042| mu0_102(String &) = Store : &:r0_99, r0_101 -# 1042| r0_103(glval) = FieldAddress[x] : r0_97 -# 1042| r0_104(glval) = VariableAddress[x] : -# 1042| r0_105(int) = Load : &:r0_104, ~mu0_2 -# 1042| mu0_106(int) = Store : &:r0_103, r0_105 -# 1042| r0_107(decltype([...](...){...})) = Load : &:r0_97, ~mu0_2 -# 1042| mu0_108(decltype([...](...){...})) = Store : &:r0_96, r0_107 -# 1043| r0_109(glval) = VariableAddress[lambda_mixed_explicit] : -# 1043| r0_110(glval) = Convert : r0_109 -# 1043| r0_111(glval) = FunctionAddress[operator()] : -# 1043| r0_112(float) = Constant[5.0] : -# 1043| r0_113(char) = Call : func:r0_111, this:r0_110, 0:r0_112 -# 1043| mu0_114(unknown) = ^CallSideEffect : ~mu0_2 -# 1043| v0_115(void) = ^IndirectReadSideEffect[-1] : &:r0_110, ~mu0_2 -# 1043| mu0_116(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 -# 1044| r0_117(glval) = VariableAddress[r] : -# 1044| r0_118(glval) = VariableAddress[x] : -# 1044| r0_119(int) = Load : &:r0_118, ~mu0_2 -# 1044| r0_120(int) = Constant[1] : -# 1044| r0_121(int) = Sub : r0_119, r0_120 -# 1044| mu0_122(int) = Store : &:r0_117, r0_121 -# 1045| r0_123(glval) = VariableAddress[lambda_inits] : -# 1045| r0_124(glval) = VariableAddress[#temp1045:23] : -# 1045| mu0_125(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_124 -# 1045| r0_126(glval) = FieldAddress[s] : r0_124 -# 1045| r0_127(glval) = VariableAddress[s] : -# 1045| r0_128(String &) = Load : &:r0_127, ~mu0_2 -# 1045| mu0_129(String &) = Store : &:r0_126, r0_128 -# 1045| r0_130(glval) = FieldAddress[x] : r0_124 -# 1045| r0_131(glval) = VariableAddress[x] : -# 1045| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 1045| mu0_133(int) = Store : &:r0_130, r0_132 -# 1045| r0_134(glval) = FieldAddress[i] : r0_124 -# 1045| r0_135(glval) = VariableAddress[x] : -# 1045| r0_136(int) = Load : &:r0_135, ~mu0_2 -# 1045| r0_137(int) = Constant[1] : -# 1045| r0_138(int) = Add : r0_136, r0_137 -# 1045| mu0_139(int) = Store : &:r0_134, r0_138 -# 1045| r0_140(glval) = FieldAddress[j] : r0_124 -# 1045| r0_141(glval) = VariableAddress[r] : -# 1045| mu0_142(int &) = Store : &:r0_140, r0_141 -# 1045| r0_143(decltype([...](...){...})) = Load : &:r0_124, ~mu0_2 -# 1045| mu0_144(decltype([...](...){...})) = Store : &:r0_123, r0_143 -# 1046| r0_145(glval) = VariableAddress[lambda_inits] : -# 1046| r0_146(glval) = Convert : r0_145 -# 1046| r0_147(glval) = FunctionAddress[operator()] : -# 1046| r0_148(float) = Constant[6.0] : -# 1046| r0_149(char) = Call : func:r0_147, this:r0_146, 0:r0_148 -# 1046| mu0_150(unknown) = ^CallSideEffect : ~mu0_2 -# 1046| v0_151(void) = ^IndirectReadSideEffect[-1] : &:r0_146, ~mu0_2 -# 1046| mu0_152(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_146 -# 1047| v0_153(void) = NoOp : -# 1031| v0_154(void) = ReturnVoid : -# 1031| v0_155(void) = UnmodeledUse : mu* -# 1031| v0_156(void) = ExitFunction : +# 1031| r0_7(String &) = Load : &:r0_5, ~mu0_6 +# 1031| mu0_8(unknown) = InitializeIndirection[s] : &:r0_7 +# 1032| r0_9(glval) = VariableAddress[lambda_empty] : +# 1032| r0_10(glval) = VariableAddress[#temp1032:23] : +# 1032| mu0_11(decltype([...](...){...})) = Uninitialized[#temp1032:23] : &:r0_10 +# 1032| r0_12(decltype([...](...){...})) = Load : &:r0_10, ~mu0_2 +# 1032| mu0_13(decltype([...](...){...})) = Store : &:r0_9, r0_12 +# 1033| r0_14(char) = Constant[65] : +# 1034| r0_15(glval) = VariableAddress[lambda_ref] : +# 1034| r0_16(glval) = VariableAddress[#temp1034:21] : +# 1034| mu0_17(decltype([...](...){...})) = Uninitialized[#temp1034:21] : &:r0_16 +# 1034| r0_18(glval) = FieldAddress[s] : r0_16 +#-----| r0_19(glval) = VariableAddress[s] : +#-----| r0_20(String &) = Load : &:r0_19, ~mu0_2 +# 1034| mu0_21(String &) = Store : &:r0_18, r0_20 +# 1034| r0_22(glval) = FieldAddress[x] : r0_16 +#-----| r0_23(glval) = VariableAddress[x] : +#-----| mu0_24(int &) = Store : &:r0_22, r0_23 +# 1034| r0_25(decltype([...](...){...})) = Load : &:r0_16, ~mu0_2 +# 1034| mu0_26(decltype([...](...){...})) = Store : &:r0_15, r0_25 +# 1035| r0_27(glval) = VariableAddress[lambda_ref] : +# 1035| r0_28(glval) = Convert : r0_27 +# 1035| r0_29(glval) = FunctionAddress[operator()] : +# 1035| r0_30(float) = Constant[1.0] : +# 1035| r0_31(char) = Call : func:r0_29, this:r0_28, 0:r0_30 +# 1035| mu0_32(unknown) = ^CallSideEffect : ~mu0_2 +# 1035| v0_33(void) = ^IndirectReadSideEffect[-1] : &:r0_28, ~mu0_2 +# 1035| mu0_34(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_28 +# 1036| r0_35(glval) = VariableAddress[lambda_val] : +# 1036| r0_36(glval) = FunctionAddress[(constructor)] : +# 1036| r0_37(glval) = VariableAddress[#temp1036:21] : +# 1036| mu0_38(decltype([...](...){...})) = Uninitialized[#temp1036:21] : &:r0_37 +# 1036| r0_39(glval) = FieldAddress[s] : r0_37 +#-----| r0_40(glval) = FunctionAddress[String] : +#-----| v0_41(void) = Call : func:r0_40, this:r0_39 +#-----| mu0_42(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| r0_43(glval) = FieldAddress[x] : r0_37 +#-----| r0_44(glval) = VariableAddress[x] : +#-----| r0_45(int) = Load : &:r0_44, ~mu0_2 +#-----| mu0_46(int) = Store : &:r0_43, r0_45 +# 1036| r0_47(decltype([...](...){...})) = Load : &:r0_37, ~mu0_2 +# 1036| v0_48(void) = Call : func:r0_36, this:r0_35, 0:r0_47 +# 1036| mu0_49(unknown) = ^CallSideEffect : ~mu0_2 +# 1036| v0_50(void) = ^IndirectReadSideEffect[0] : &:r0_47, ~mu0_2 +# 1036| mu0_51(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_47 +# 1037| r0_52(glval) = VariableAddress[lambda_val] : +# 1037| r0_53(glval) = Convert : r0_52 +# 1037| r0_54(glval) = FunctionAddress[operator()] : +# 1037| r0_55(float) = Constant[2.0] : +# 1037| r0_56(char) = Call : func:r0_54, this:r0_53, 0:r0_55 +# 1037| mu0_57(unknown) = ^CallSideEffect : ~mu0_2 +# 1037| v0_58(void) = ^IndirectReadSideEffect[-1] : &:r0_53, ~mu0_2 +# 1037| mu0_59(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_53 +# 1038| r0_60(glval) = VariableAddress[lambda_ref_explicit] : +# 1038| r0_61(glval) = VariableAddress[#temp1038:30] : +# 1038| mu0_62(decltype([...](...){...})) = Uninitialized[#temp1038:30] : &:r0_61 +# 1038| r0_63(glval) = FieldAddress[s] : r0_61 +# 1038| r0_64(glval) = VariableAddress[s] : +# 1038| r0_65(String &) = Load : &:r0_64, ~mu0_2 +# 1038| mu0_66(String &) = Store : &:r0_63, r0_65 +# 1038| r0_67(decltype([...](...){...})) = Load : &:r0_61, ~mu0_2 +# 1038| mu0_68(decltype([...](...){...})) = Store : &:r0_60, r0_67 +# 1039| r0_69(glval) = VariableAddress[lambda_ref_explicit] : +# 1039| r0_70(glval) = Convert : r0_69 +# 1039| r0_71(glval) = FunctionAddress[operator()] : +# 1039| r0_72(float) = Constant[3.0] : +# 1039| r0_73(char) = Call : func:r0_71, this:r0_70, 0:r0_72 +# 1039| mu0_74(unknown) = ^CallSideEffect : ~mu0_2 +# 1039| v0_75(void) = ^IndirectReadSideEffect[-1] : &:r0_70, ~mu0_2 +# 1039| mu0_76(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_70 +# 1040| r0_77(glval) = VariableAddress[lambda_val_explicit] : +# 1040| r0_78(glval) = FunctionAddress[(constructor)] : +# 1040| r0_79(glval) = VariableAddress[#temp1040:30] : +# 1040| mu0_80(decltype([...](...){...})) = Uninitialized[#temp1040:30] : &:r0_79 +# 1040| r0_81(glval) = FieldAddress[s] : r0_79 +#-----| r0_82(glval) = FunctionAddress[String] : +#-----| v0_83(void) = Call : func:r0_82, this:r0_81 +#-----| mu0_84(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| r0_85(decltype([...](...){...})) = Load : &:r0_79, ~mu0_2 +# 1040| v0_86(void) = Call : func:r0_78, this:r0_77, 0:r0_85 +# 1040| mu0_87(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| v0_88(void) = ^IndirectReadSideEffect[0] : &:r0_85, ~mu0_2 +# 1040| mu0_89(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_85 +# 1041| r0_90(glval) = VariableAddress[lambda_val_explicit] : +# 1041| r0_91(glval) = Convert : r0_90 +# 1041| r0_92(glval) = FunctionAddress[operator()] : +# 1041| r0_93(float) = Constant[4.0] : +# 1041| r0_94(char) = Call : func:r0_92, this:r0_91, 0:r0_93 +# 1041| mu0_95(unknown) = ^CallSideEffect : ~mu0_2 +# 1041| v0_96(void) = ^IndirectReadSideEffect[-1] : &:r0_91, ~mu0_2 +# 1041| mu0_97(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_91 +# 1042| r0_98(glval) = VariableAddress[lambda_mixed_explicit] : +# 1042| r0_99(glval) = VariableAddress[#temp1042:32] : +# 1042| mu0_100(decltype([...](...){...})) = Uninitialized[#temp1042:32] : &:r0_99 +# 1042| r0_101(glval) = FieldAddress[s] : r0_99 +# 1042| r0_102(glval) = VariableAddress[s] : +# 1042| r0_103(String &) = Load : &:r0_102, ~mu0_2 +# 1042| mu0_104(String &) = Store : &:r0_101, r0_103 +# 1042| r0_105(glval) = FieldAddress[x] : r0_99 +# 1042| r0_106(glval) = VariableAddress[x] : +# 1042| r0_107(int) = Load : &:r0_106, ~mu0_2 +# 1042| mu0_108(int) = Store : &:r0_105, r0_107 +# 1042| r0_109(decltype([...](...){...})) = Load : &:r0_99, ~mu0_2 +# 1042| mu0_110(decltype([...](...){...})) = Store : &:r0_98, r0_109 +# 1043| r0_111(glval) = VariableAddress[lambda_mixed_explicit] : +# 1043| r0_112(glval) = Convert : r0_111 +# 1043| r0_113(glval) = FunctionAddress[operator()] : +# 1043| r0_114(float) = Constant[5.0] : +# 1043| r0_115(char) = Call : func:r0_113, this:r0_112, 0:r0_114 +# 1043| mu0_116(unknown) = ^CallSideEffect : ~mu0_2 +# 1043| v0_117(void) = ^IndirectReadSideEffect[-1] : &:r0_112, ~mu0_2 +# 1043| mu0_118(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_112 +# 1044| r0_119(glval) = VariableAddress[r] : +# 1044| r0_120(glval) = VariableAddress[x] : +# 1044| r0_121(int) = Load : &:r0_120, ~mu0_2 +# 1044| r0_122(int) = Constant[1] : +# 1044| r0_123(int) = Sub : r0_121, r0_122 +# 1044| mu0_124(int) = Store : &:r0_119, r0_123 +# 1045| r0_125(glval) = VariableAddress[lambda_inits] : +# 1045| r0_126(glval) = VariableAddress[#temp1045:23] : +# 1045| mu0_127(decltype([...](...){...})) = Uninitialized[#temp1045:23] : &:r0_126 +# 1045| r0_128(glval) = FieldAddress[s] : r0_126 +# 1045| r0_129(glval) = VariableAddress[s] : +# 1045| r0_130(String &) = Load : &:r0_129, ~mu0_2 +# 1045| mu0_131(String &) = Store : &:r0_128, r0_130 +# 1045| r0_132(glval) = FieldAddress[x] : r0_126 +# 1045| r0_133(glval) = VariableAddress[x] : +# 1045| r0_134(int) = Load : &:r0_133, ~mu0_2 +# 1045| mu0_135(int) = Store : &:r0_132, r0_134 +# 1045| r0_136(glval) = FieldAddress[i] : r0_126 +# 1045| r0_137(glval) = VariableAddress[x] : +# 1045| r0_138(int) = Load : &:r0_137, ~mu0_2 +# 1045| r0_139(int) = Constant[1] : +# 1045| r0_140(int) = Add : r0_138, r0_139 +# 1045| mu0_141(int) = Store : &:r0_136, r0_140 +# 1045| r0_142(glval) = FieldAddress[j] : r0_126 +# 1045| r0_143(glval) = VariableAddress[r] : +# 1045| mu0_144(int &) = Store : &:r0_142, r0_143 +# 1045| r0_145(decltype([...](...){...})) = Load : &:r0_126, ~mu0_2 +# 1045| mu0_146(decltype([...](...){...})) = Store : &:r0_125, r0_145 +# 1046| r0_147(glval) = VariableAddress[lambda_inits] : +# 1046| r0_148(glval) = Convert : r0_147 +# 1046| r0_149(glval) = FunctionAddress[operator()] : +# 1046| r0_150(float) = Constant[6.0] : +# 1046| r0_151(char) = Call : func:r0_149, this:r0_148, 0:r0_150 +# 1046| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 +# 1046| v0_153(void) = ^IndirectReadSideEffect[-1] : &:r0_148, ~mu0_2 +# 1046| mu0_154(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_148 +# 1047| v0_155(void) = NoOp : +# 1031| v0_156(void) = ReturnVoid : +# 1031| v0_157(void) = UnmodeledUse : mu* +# 1031| v0_158(void) = ExitFunction : # 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&) # 1032| Block 0 -# 1032| v0_0(void) = EnterFunction : -# 1032| mu0_1(unknown) = AliasedDefinition : -# 1032| mu0_2(unknown) = UnmodeledDefinition : -# 1032| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(lambda [] type at line 1032, col. 23 &&) = InitializeParameter[p#0] : &:r0_4 -# 1032| v0_6(void) = NoOp : -# 1032| v0_7(void) = ReturnVoid : -# 1032| v0_8(void) = UnmodeledUse : mu* -# 1032| v0_9(void) = ExitFunction : +# 1032| v0_0(void) = EnterFunction : +# 1032| mu0_1(unknown) = AliasedDefinition : +# 1032| mu0_2(unknown) = UnmodeledDefinition : +# 1032| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(lambda [] type at line 1032, col. 23 &&) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(lambda [] type at line 1032, col. 23 &&) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +# 1032| v0_8(void) = NoOp : +# 1032| v0_9(void) = ReturnVoid : +# 1032| v0_10(void) = UnmodeledUse : mu* +# 1032| v0_11(void) = ExitFunction : # 1032| char (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::operator()(float) const # 1032| Block 0 @@ -4946,20 +4990,22 @@ ir.cpp: # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) # 1040| Block 0 -# 1040| v0_0(void) = EnterFunction : -# 1040| mu0_1(unknown) = AliasedDefinition : -# 1040| mu0_2(unknown) = UnmodeledDefinition : -# 1040| r0_3(glval) = InitializeThis : -#-----| r0_4(glval) = VariableAddress[p#0] : -#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 -# 1040| r0_6(glval) = FieldAddress[s] : r0_3 -# 1040| r0_7(glval) = FunctionAddress[String] : -# 1040| v0_8(void) = Call : func:r0_7, this:r0_6 -# 1040| mu0_9(unknown) = ^CallSideEffect : ~mu0_2 -# 1040| v0_10(void) = NoOp : -# 1040| v0_11(void) = ReturnVoid : -# 1040| v0_12(void) = UnmodeledUse : mu* -# 1040| v0_13(void) = ExitFunction : +# 1040| v0_0(void) = EnterFunction : +# 1040| mu0_1(unknown) = AliasedDefinition : +# 1040| mu0_2(unknown) = UnmodeledDefinition : +# 1040| r0_3(glval) = InitializeThis : +#-----| r0_4(glval) = VariableAddress[p#0] : +#-----| mu0_5(lambda [] type at line 1040, col. 30 &&) = InitializeParameter[p#0] : &:r0_4 +#-----| r0_6(lambda [] type at line 1040, col. 30 &&) = Load : &:r0_4, ~mu0_5 +#-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 +# 1040| r0_8(glval) = FieldAddress[s] : r0_3 +# 1040| r0_9(glval) = FunctionAddress[String] : +# 1040| v0_10(void) = Call : func:r0_9, this:r0_8 +# 1040| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 +# 1040| v0_12(void) = NoOp : +# 1040| v0_13(void) = ReturnVoid : +# 1040| v0_14(void) = UnmodeledUse : mu* +# 1040| v0_15(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~() # 1040| Block 0 @@ -5073,28 +5119,30 @@ ir.cpp: # 1068| mu0_2(unknown) = UnmodeledDefinition : # 1068| r0_3(glval &>) = VariableAddress[v] : # 1068| mu0_4(vector &) = InitializeParameter[v] : &:r0_3 -# 1069| r0_5(glval &>) = VariableAddress[(__range)] : -# 1069| r0_6(glval &>) = VariableAddress[v] : -# 1069| r0_7(vector &) = Load : &:r0_6, ~mu0_2 -# 1069| mu0_8(vector &) = Store : &:r0_5, r0_7 -# 1069| r0_9(glval) = VariableAddress[(__begin)] : -#-----| r0_10(glval &>) = VariableAddress[(__range)] : -#-----| r0_11(vector &) = Load : &:r0_10, ~mu0_2 -# 1069| r0_12(glval) = FunctionAddress[begin] : -# 1069| r0_13(iterator) = Call : func:r0_12, this:r0_11 -# 1069| mu0_14(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_15(void) = ^IndirectReadSideEffect[-1] : &:r0_11, ~mu0_2 -#-----| mu0_16(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_11 -# 1069| mu0_17(iterator) = Store : &:r0_9, r0_13 -# 1069| r0_18(glval) = VariableAddress[(__end)] : -#-----| r0_19(glval &>) = VariableAddress[(__range)] : -#-----| r0_20(vector &) = Load : &:r0_19, ~mu0_2 -# 1069| r0_21(glval) = FunctionAddress[end] : -# 1069| r0_22(iterator) = Call : func:r0_21, this:r0_20 -# 1069| mu0_23(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v0_24(void) = ^IndirectReadSideEffect[-1] : &:r0_20, ~mu0_2 -#-----| mu0_25(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_20 -# 1069| mu0_26(iterator) = Store : &:r0_18, r0_22 +# 1068| r0_5(vector &) = Load : &:r0_3, ~mu0_4 +# 1068| mu0_6(unknown) = InitializeIndirection[v] : &:r0_5 +# 1069| r0_7(glval &>) = VariableAddress[(__range)] : +# 1069| r0_8(glval &>) = VariableAddress[v] : +# 1069| r0_9(vector &) = Load : &:r0_8, ~mu0_2 +# 1069| mu0_10(vector &) = Store : &:r0_7, r0_9 +# 1069| r0_11(glval) = VariableAddress[(__begin)] : +#-----| r0_12(glval &>) = VariableAddress[(__range)] : +#-----| r0_13(vector &) = Load : &:r0_12, ~mu0_2 +# 1069| r0_14(glval) = FunctionAddress[begin] : +# 1069| r0_15(iterator) = Call : func:r0_14, this:r0_13 +# 1069| mu0_16(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_17(void) = ^IndirectReadSideEffect[-1] : &:r0_13, ~mu0_2 +#-----| mu0_18(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_13 +# 1069| mu0_19(iterator) = Store : &:r0_11, r0_15 +# 1069| r0_20(glval) = VariableAddress[(__end)] : +#-----| r0_21(glval &>) = VariableAddress[(__range)] : +#-----| r0_22(vector &) = Load : &:r0_21, ~mu0_2 +# 1069| r0_23(glval) = FunctionAddress[end] : +# 1069| r0_24(iterator) = Call : func:r0_23, this:r0_22 +# 1069| mu0_25(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v0_26(void) = ^IndirectReadSideEffect[-1] : &:r0_22, ~mu0_2 +#-----| mu0_27(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 +# 1069| mu0_28(iterator) = Store : &:r0_20, r0_24 #-----| Goto -> Block 4 # 1075| Block 1 @@ -5242,26 +5290,34 @@ ir.cpp: # 1104| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&) # 1104| Block 0 -# 1104| v0_0(void) = EnterFunction : -# 1104| mu0_1(unknown) = AliasedDefinition : -# 1104| mu0_2(unknown) = UnmodeledDefinition : -# 1104| r0_3(glval) = VariableAddress[a] : -# 1104| mu0_4(unsigned int &) = InitializeParameter[a] : &:r0_3 -# 1104| r0_5(glval) = VariableAddress[b] : -# 1104| mu0_6(unsigned int &) = InitializeParameter[b] : &:r0_5 -# 1104| r0_7(glval) = VariableAddress[c] : -# 1104| mu0_8(unsigned int &) = InitializeParameter[c] : &:r0_7 -# 1104| r0_9(glval) = VariableAddress[d] : -# 1104| mu0_10(unsigned int &) = InitializeParameter[d] : &:r0_9 -# 1106| r0_11(glval) = VariableAddress[a] : -# 1106| r0_12(glval) = VariableAddress[b] : -# 1106| r0_13(glval) = VariableAddress[c] : -# 1106| r0_14(glval) = VariableAddress[d] : -# 1106| mu0_15(unknown) = InlineAsm : ~mu0_2, 0:r0_11, 1:r0_12, 2:r0_13, 3:r0_14 -# 1111| v0_16(void) = NoOp : -# 1104| v0_17(void) = ReturnVoid : -# 1104| v0_18(void) = UnmodeledUse : mu* -# 1104| v0_19(void) = ExitFunction : +# 1104| v0_0(void) = EnterFunction : +# 1104| mu0_1(unknown) = AliasedDefinition : +# 1104| mu0_2(unknown) = UnmodeledDefinition : +# 1104| r0_3(glval) = VariableAddress[a] : +# 1104| mu0_4(unsigned int &) = InitializeParameter[a] : &:r0_3 +# 1104| r0_5(unsigned int &) = Load : &:r0_3, ~mu0_4 +# 1104| mu0_6(unknown) = InitializeIndirection[a] : &:r0_5 +# 1104| r0_7(glval) = VariableAddress[b] : +# 1104| mu0_8(unsigned int &) = InitializeParameter[b] : &:r0_7 +# 1104| r0_9(unsigned int &) = Load : &:r0_7, ~mu0_8 +# 1104| mu0_10(unknown) = InitializeIndirection[b] : &:r0_9 +# 1104| r0_11(glval) = VariableAddress[c] : +# 1104| mu0_12(unsigned int &) = InitializeParameter[c] : &:r0_11 +# 1104| r0_13(unsigned int &) = Load : &:r0_11, ~mu0_12 +# 1104| mu0_14(unknown) = InitializeIndirection[c] : &:r0_13 +# 1104| r0_15(glval) = VariableAddress[d] : +# 1104| mu0_16(unsigned int &) = InitializeParameter[d] : &:r0_15 +# 1104| r0_17(unsigned int &) = Load : &:r0_15, ~mu0_16 +# 1104| mu0_18(unknown) = InitializeIndirection[d] : &:r0_17 +# 1106| r0_19(glval) = VariableAddress[a] : +# 1106| r0_20(glval) = VariableAddress[b] : +# 1106| r0_21(glval) = VariableAddress[c] : +# 1106| r0_22(glval) = VariableAddress[d] : +# 1106| mu0_23(unknown) = InlineAsm : ~mu0_2, 0:r0_19, 1:r0_20, 2:r0_21, 3:r0_22 +# 1111| v0_24(void) = NoOp : +# 1104| v0_25(void) = ReturnVoid : +# 1104| v0_26(void) = UnmodeledUse : mu* +# 1104| v0_27(void) = ExitFunction : # 1113| void ExternDeclarations() # 1113| Block 0 @@ -5397,15 +5453,17 @@ ir.cpp: # 1144| Block 10 # 1144| r10_0(glval) = VariableAddress[s] : # 1144| mu10_1(char *) = InitializeParameter[s] : &:r10_0 -# 1145| r10_2(glval) = VariableAddress[#throw1145:5] : -# 1145| r10_3(glval) = FunctionAddress[String] : -# 1145| r10_4(glval) = VariableAddress[s] : -# 1145| r10_5(char *) = Load : &:r10_4, ~mu0_2 -# 1145| v10_6(void) = Call : func:r10_3, this:r10_2, 0:r10_5 -# 1145| mu10_7(unknown) = ^CallSideEffect : ~mu0_2 -# 1145| v10_8(void) = ^IndirectReadSideEffect[0] : &:r10_5, ~mu0_2 -# 1145| mu10_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_5 -# 1145| v10_10(void) = ThrowValue : &:r10_2, ~mu0_2 +# 1144| r10_2(char *) = Load : &:r10_0, ~mu10_1 +# 1144| mu10_3(unknown) = InitializeIndirection[s] : &:r10_2 +# 1145| r10_4(glval) = VariableAddress[#throw1145:5] : +# 1145| r10_5(glval) = FunctionAddress[String] : +# 1145| r10_6(glval) = VariableAddress[s] : +# 1145| r10_7(char *) = Load : &:r10_6, ~mu0_2 +# 1145| v10_8(void) = Call : func:r10_5, this:r10_4, 0:r10_7 +# 1145| mu10_9(unknown) = ^CallSideEffect : ~mu0_2 +# 1145| v10_10(void) = ^IndirectReadSideEffect[0] : &:r10_7, ~mu0_2 +# 1145| mu10_11(unknown) = ^BufferMayWriteSideEffect[0] : &:r10_7 +# 1145| v10_12(void) = ThrowValue : &:r10_4, ~mu0_2 #-----| Exception -> Block 2 # 1147| Block 11 @@ -5414,9 +5472,11 @@ ir.cpp: #-----| Goto -> Block 12 # 1147| Block 12 -# 1147| r12_0(glval) = VariableAddress[e] : -# 1147| mu12_1(String &) = InitializeParameter[e] : &:r12_0 -# 1147| v12_2(void) = NoOp : +# 1147| r12_0(glval) = VariableAddress[e] : +# 1147| mu12_1(String &) = InitializeParameter[e] : &:r12_0 +# 1147| r12_2(String &) = Load : &:r12_0, ~mu12_1 +# 1147| mu12_3(unknown) = InitializeIndirection[e] : &:r12_2 +# 1147| v12_4(void) = NoOp : #-----| Goto -> Block 13 # 1149| Block 13 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 9d005c57ca8f..dadbfdea9e13 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -6,13 +6,16 @@ ssa.cpp: # 13| mu0_2(unknown) = UnmodeledDefinition : # 13| r0_3(glval) = VariableAddress[p] : # 13| m0_4(Point *) = InitializeParameter[p] : &:r0_3 -# 13| r0_5(glval) = VariableAddress[which1] : -# 13| m0_6(bool) = InitializeParameter[which1] : &:r0_5 -# 13| r0_7(glval) = VariableAddress[which2] : -# 13| m0_8(bool) = InitializeParameter[which2] : &:r0_7 -# 14| r0_9(glval) = VariableAddress[which1] : -# 14| r0_10(bool) = Load : &:r0_9, m0_6 -# 14| v0_11(void) = ConditionalBranch : r0_10 +# 13| r0_5(Point *) = Load : &:r0_3, m0_4 +# 13| m0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 13| m0_7(unknown) = Chi : total:m0_1, partial:m0_6 +# 13| r0_8(glval) = VariableAddress[which1] : +# 13| m0_9(bool) = InitializeParameter[which1] : &:r0_8 +# 13| r0_10(glval) = VariableAddress[which2] : +# 13| m0_11(bool) = InitializeParameter[which2] : &:r0_10 +# 14| r0_12(glval) = VariableAddress[which1] : +# 14| r0_13(bool) = Load : &:r0_12, m0_9 +# 14| v0_14(void) = ConditionalBranch : r0_13 #-----| False -> Block 2 #-----| True -> Block 1 @@ -20,28 +23,28 @@ ssa.cpp: # 15| r1_0(glval) = VariableAddress[p] : # 15| r1_1(Point *) = Load : &:r1_0, m0_4 # 15| r1_2(glval) = FieldAddress[x] : r1_1 -# 15| r1_3(int) = Load : &:r1_2, ~m0_1 +# 15| r1_3(int) = Load : &:r1_2, ~m0_7 # 15| r1_4(int) = Constant[1] : # 15| r1_5(int) = Add : r1_3, r1_4 # 15| m1_6(int) = Store : &:r1_2, r1_5 -# 15| m1_7(unknown) = Chi : total:m0_1, partial:m1_6 +# 15| m1_7(unknown) = Chi : total:m0_7, partial:m1_6 #-----| Goto -> Block 3 # 18| Block 2 # 18| r2_0(glval) = VariableAddress[p] : # 18| r2_1(Point *) = Load : &:r2_0, m0_4 # 18| r2_2(glval) = FieldAddress[y] : r2_1 -# 18| r2_3(int) = Load : &:r2_2, ~m0_1 +# 18| r2_3(int) = Load : &:r2_2, ~m0_7 # 18| r2_4(int) = Constant[1] : # 18| r2_5(int) = Add : r2_3, r2_4 # 18| m2_6(int) = Store : &:r2_2, r2_5 -# 18| m2_7(unknown) = Chi : total:m0_1, partial:m2_6 +# 18| m2_7(unknown) = Chi : total:m0_7, partial:m2_6 #-----| Goto -> Block 3 # 21| Block 3 # 21| m3_0(unknown) = Phi : from 1:~m1_7, from 2:~m2_7 # 21| r3_1(glval) = VariableAddress[which2] : -# 21| r3_2(bool) = Load : &:r3_1, m0_8 +# 21| r3_2(bool) = Load : &:r3_1, m0_11 # 21| v3_3(void) = ConditionalBranch : r3_2 #-----| False -> Block 5 #-----| True -> Block 4 @@ -195,13 +198,16 @@ ssa.cpp: # 68| void chiNodeAtEndOfLoop(int, char*) # 68| Block 0 -# 68| v0_0(void) = EnterFunction : -# 68| m0_1(unknown) = AliasedDefinition : -# 68| mu0_2(unknown) = UnmodeledDefinition : -# 68| r0_3(glval) = VariableAddress[n] : -# 68| m0_4(int) = InitializeParameter[n] : &:r0_3 -# 68| r0_5(glval) = VariableAddress[p] : -# 68| m0_6(char *) = InitializeParameter[p] : &:r0_5 +# 68| v0_0(void) = EnterFunction : +# 68| m0_1(unknown) = AliasedDefinition : +# 68| mu0_2(unknown) = UnmodeledDefinition : +# 68| r0_3(glval) = VariableAddress[n] : +# 68| m0_4(int) = InitializeParameter[n] : &:r0_3 +# 68| r0_5(glval) = VariableAddress[p] : +# 68| m0_6(char *) = InitializeParameter[p] : &:r0_5 +# 68| r0_7(char *) = Load : &:r0_5, m0_6 +# 68| m0_8(unknown) = InitializeIndirection[p] : &:r0_7 +# 68| m0_9(unknown) = Chi : total:m0_1, partial:m0_8 #-----| Goto -> Block 3 # 70| Block 1 @@ -222,7 +228,7 @@ ssa.cpp: # 68| v2_3(void) = ExitFunction : # 69| Block 3 -# 69| m3_0(unknown) = Phi : from 0:~m0_1, from 1:~m1_7 +# 69| m3_0(unknown) = Phi : from 0:~m0_9, from 1:~m1_7 # 69| m3_1(int) = Phi : from 0:m0_4, from 1:m3_7 # 69| m3_2(char *) = Phi : from 0:m0_6, from 1:m1_5 # 69| r3_3(glval) = VariableAddress[n] : @@ -723,99 +729,120 @@ ssa.cpp: # 179| int AsmStmt(int*) # 179| Block 0 -# 179| v0_0(void) = EnterFunction : -# 179| m0_1(unknown) = AliasedDefinition : -# 179| mu0_2(unknown) = UnmodeledDefinition : -# 179| r0_3(glval) = VariableAddress[p] : -# 179| m0_4(int *) = InitializeParameter[p] : &:r0_3 -# 180| m0_5(unknown) = InlineAsm : ~mu0_2 -# 180| m0_6(unknown) = Chi : total:m0_1, partial:m0_5 -# 181| r0_7(glval) = VariableAddress[#return] : -# 181| r0_8(glval) = VariableAddress[p] : -# 181| r0_9(int *) = Load : &:r0_8, m0_4 -# 181| r0_10(int) = Load : &:r0_9, ~m0_6 -# 181| m0_11(int) = Store : &:r0_7, r0_10 -# 179| r0_12(glval) = VariableAddress[#return] : -# 179| v0_13(void) = ReturnValue : &:r0_12, m0_11 -# 179| v0_14(void) = UnmodeledUse : mu* -# 179| v0_15(void) = ExitFunction : +# 179| v0_0(void) = EnterFunction : +# 179| m0_1(unknown) = AliasedDefinition : +# 179| mu0_2(unknown) = UnmodeledDefinition : +# 179| r0_3(glval) = VariableAddress[p] : +# 179| m0_4(int *) = InitializeParameter[p] : &:r0_3 +# 179| r0_5(int *) = Load : &:r0_3, m0_4 +# 179| m0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 179| m0_7(unknown) = Chi : total:m0_1, partial:m0_6 +# 180| m0_8(unknown) = InlineAsm : ~mu0_2 +# 180| m0_9(unknown) = Chi : total:m0_7, partial:m0_8 +# 181| r0_10(glval) = VariableAddress[#return] : +# 181| r0_11(glval) = VariableAddress[p] : +# 181| r0_12(int *) = Load : &:r0_11, m0_4 +# 181| r0_13(int) = Load : &:r0_12, ~m0_9 +# 181| m0_14(int) = Store : &:r0_10, r0_13 +# 179| r0_15(glval) = VariableAddress[#return] : +# 179| v0_16(void) = ReturnValue : &:r0_15, m0_14 +# 179| v0_17(void) = UnmodeledUse : mu* +# 179| v0_18(void) = ExitFunction : # 184| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&) # 184| Block 0 -# 184| v0_0(void) = EnterFunction : -# 184| m0_1(unknown) = AliasedDefinition : -# 184| mu0_2(unknown) = UnmodeledDefinition : -# 184| r0_3(glval) = VariableAddress[a] : -# 184| m0_4(unsigned int &) = InitializeParameter[a] : &:r0_3 -# 184| m0_5(unknown) = Chi : total:m0_1, partial:m0_4 -# 184| r0_6(glval) = VariableAddress[b] : -# 184| m0_7(unsigned int &) = InitializeParameter[b] : &:r0_6 -# 184| m0_8(unknown) = Chi : total:m0_5, partial:m0_7 -# 184| r0_9(glval) = VariableAddress[c] : -# 184| m0_10(unsigned int &) = InitializeParameter[c] : &:r0_9 -# 184| m0_11(unknown) = Chi : total:m0_8, partial:m0_10 -# 184| r0_12(glval) = VariableAddress[d] : -# 184| m0_13(unsigned int &) = InitializeParameter[d] : &:r0_12 -# 184| m0_14(unknown) = Chi : total:m0_11, partial:m0_13 -# 186| r0_15(glval) = VariableAddress[a] : -# 186| r0_16(glval) = VariableAddress[b] : -# 186| r0_17(glval) = VariableAddress[c] : -# 186| r0_18(glval) = VariableAddress[d] : -# 186| m0_19(unknown) = InlineAsm : ~mu0_2, 0:r0_15, 1:r0_16, 2:r0_17, 3:r0_18 -# 186| m0_20(unknown) = Chi : total:m0_14, partial:m0_19 -# 192| v0_21(void) = NoOp : -# 184| v0_22(void) = ReturnVoid : -# 184| v0_23(void) = UnmodeledUse : mu* -# 184| v0_24(void) = ExitFunction : +# 184| v0_0(void) = EnterFunction : +# 184| m0_1(unknown) = AliasedDefinition : +# 184| mu0_2(unknown) = UnmodeledDefinition : +# 184| r0_3(glval) = VariableAddress[a] : +# 184| m0_4(unsigned int &) = InitializeParameter[a] : &:r0_3 +# 184| m0_5(unknown) = Chi : total:m0_1, partial:m0_4 +# 184| r0_6(unsigned int &) = Load : &:r0_3, m0_4 +# 184| m0_7(unknown) = InitializeIndirection[a] : &:r0_6 +# 184| m0_8(unknown) = Chi : total:m0_5, partial:m0_7 +# 184| r0_9(glval) = VariableAddress[b] : +# 184| m0_10(unsigned int &) = InitializeParameter[b] : &:r0_9 +# 184| m0_11(unknown) = Chi : total:m0_8, partial:m0_10 +# 184| r0_12(unsigned int &) = Load : &:r0_9, m0_10 +# 184| m0_13(unknown) = InitializeIndirection[b] : &:r0_12 +# 184| m0_14(unknown) = Chi : total:m0_11, partial:m0_13 +# 184| r0_15(glval) = VariableAddress[c] : +# 184| m0_16(unsigned int &) = InitializeParameter[c] : &:r0_15 +# 184| m0_17(unknown) = Chi : total:m0_14, partial:m0_16 +# 184| r0_18(unsigned int &) = Load : &:r0_15, m0_16 +# 184| m0_19(unknown) = InitializeIndirection[c] : &:r0_18 +# 184| m0_20(unknown) = Chi : total:m0_17, partial:m0_19 +# 184| r0_21(glval) = VariableAddress[d] : +# 184| m0_22(unsigned int &) = InitializeParameter[d] : &:r0_21 +# 184| m0_23(unknown) = Chi : total:m0_20, partial:m0_22 +# 184| r0_24(unsigned int &) = Load : &:r0_21, m0_22 +# 184| m0_25(unknown) = InitializeIndirection[d] : &:r0_24 +# 184| m0_26(unknown) = Chi : total:m0_23, partial:m0_25 +# 186| r0_27(glval) = VariableAddress[a] : +# 186| r0_28(glval) = VariableAddress[b] : +# 186| r0_29(glval) = VariableAddress[c] : +# 186| r0_30(glval) = VariableAddress[d] : +# 186| m0_31(unknown) = InlineAsm : ~mu0_2, 0:r0_27, 1:r0_28, 2:r0_29, 3:r0_30 +# 186| m0_32(unknown) = Chi : total:m0_26, partial:m0_31 +# 192| v0_33(void) = NoOp : +# 184| v0_34(void) = ReturnVoid : +# 184| v0_35(void) = UnmodeledUse : mu* +# 184| v0_36(void) = ExitFunction : # 198| int PureFunctions(char*, char*, int) # 198| Block 0 -# 198| v0_0(void) = EnterFunction : -# 198| m0_1(unknown) = AliasedDefinition : -# 198| mu0_2(unknown) = UnmodeledDefinition : -# 198| r0_3(glval) = VariableAddress[str1] : -# 198| m0_4(char *) = InitializeParameter[str1] : &:r0_3 -# 198| r0_5(glval) = VariableAddress[str2] : -# 198| m0_6(char *) = InitializeParameter[str2] : &:r0_5 -# 198| r0_7(glval) = VariableAddress[x] : -# 198| m0_8(int) = InitializeParameter[x] : &:r0_7 -# 199| r0_9(glval) = VariableAddress[ret] : -# 199| r0_10(glval) = FunctionAddress[strcmp] : -# 199| r0_11(glval) = VariableAddress[str1] : -# 199| r0_12(char *) = Load : &:r0_11, m0_4 -# 199| r0_13(char *) = Convert : r0_12 -# 199| r0_14(glval) = VariableAddress[str2] : -# 199| r0_15(char *) = Load : &:r0_14, m0_6 -# 199| r0_16(char *) = Convert : r0_15 -# 199| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 -# 199| v0_18(void) = ^CallReadSideEffect : ~m0_1 -# 199| m0_19(int) = Store : &:r0_9, r0_17 -# 200| r0_20(glval) = FunctionAddress[strlen] : -# 200| r0_21(glval) = VariableAddress[str1] : -# 200| r0_22(char *) = Load : &:r0_21, m0_4 -# 200| r0_23(char *) = Convert : r0_22 -# 200| r0_24(int) = Call : func:r0_20, 0:r0_23 -# 200| v0_25(void) = ^CallReadSideEffect : ~m0_1 -# 200| r0_26(glval) = VariableAddress[ret] : -# 200| r0_27(int) = Load : &:r0_26, m0_19 -# 200| r0_28(int) = Add : r0_27, r0_24 -# 200| m0_29(int) = Store : &:r0_26, r0_28 -# 201| r0_30(glval) = FunctionAddress[abs] : -# 201| r0_31(glval) = VariableAddress[x] : -# 201| r0_32(int) = Load : &:r0_31, m0_8 -# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 -# 201| r0_34(glval) = VariableAddress[ret] : -# 201| r0_35(int) = Load : &:r0_34, m0_29 -# 201| r0_36(int) = Add : r0_35, r0_33 -# 201| m0_37(int) = Store : &:r0_34, r0_36 -# 202| r0_38(glval) = VariableAddress[#return] : -# 202| r0_39(glval) = VariableAddress[ret] : -# 202| r0_40(int) = Load : &:r0_39, m0_37 -# 202| m0_41(int) = Store : &:r0_38, r0_40 -# 198| r0_42(glval) = VariableAddress[#return] : -# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 -# 198| v0_44(void) = UnmodeledUse : mu* -# 198| v0_45(void) = ExitFunction : +# 198| v0_0(void) = EnterFunction : +# 198| m0_1(unknown) = AliasedDefinition : +# 198| mu0_2(unknown) = UnmodeledDefinition : +# 198| r0_3(glval) = VariableAddress[str1] : +# 198| m0_4(char *) = InitializeParameter[str1] : &:r0_3 +# 198| r0_5(char *) = Load : &:r0_3, m0_4 +# 198| m0_6(unknown) = InitializeIndirection[str1] : &:r0_5 +# 198| m0_7(unknown) = Chi : total:m0_1, partial:m0_6 +# 198| r0_8(glval) = VariableAddress[str2] : +# 198| m0_9(char *) = InitializeParameter[str2] : &:r0_8 +# 198| r0_10(char *) = Load : &:r0_8, m0_9 +# 198| m0_11(unknown) = InitializeIndirection[str2] : &:r0_10 +# 198| m0_12(unknown) = Chi : total:m0_7, partial:m0_11 +# 198| r0_13(glval) = VariableAddress[x] : +# 198| m0_14(int) = InitializeParameter[x] : &:r0_13 +# 199| r0_15(glval) = VariableAddress[ret] : +# 199| r0_16(glval) = FunctionAddress[strcmp] : +# 199| r0_17(glval) = VariableAddress[str1] : +# 199| r0_18(char *) = Load : &:r0_17, m0_4 +# 199| r0_19(char *) = Convert : r0_18 +# 199| r0_20(glval) = VariableAddress[str2] : +# 199| r0_21(char *) = Load : &:r0_20, m0_9 +# 199| r0_22(char *) = Convert : r0_21 +# 199| r0_23(int) = Call : func:r0_16, 0:r0_19, 1:r0_22 +# 199| v0_24(void) = ^CallReadSideEffect : ~m0_12 +# 199| m0_25(int) = Store : &:r0_15, r0_23 +# 200| r0_26(glval) = FunctionAddress[strlen] : +# 200| r0_27(glval) = VariableAddress[str1] : +# 200| r0_28(char *) = Load : &:r0_27, m0_4 +# 200| r0_29(char *) = Convert : r0_28 +# 200| r0_30(int) = Call : func:r0_26, 0:r0_29 +# 200| v0_31(void) = ^CallReadSideEffect : ~m0_12 +# 200| r0_32(glval) = VariableAddress[ret] : +# 200| r0_33(int) = Load : &:r0_32, m0_25 +# 200| r0_34(int) = Add : r0_33, r0_30 +# 200| m0_35(int) = Store : &:r0_32, r0_34 +# 201| r0_36(glval) = FunctionAddress[abs] : +# 201| r0_37(glval) = VariableAddress[x] : +# 201| r0_38(int) = Load : &:r0_37, m0_14 +# 201| r0_39(int) = Call : func:r0_36, 0:r0_38 +# 201| r0_40(glval) = VariableAddress[ret] : +# 201| r0_41(int) = Load : &:r0_40, m0_35 +# 201| r0_42(int) = Add : r0_41, r0_39 +# 201| m0_43(int) = Store : &:r0_40, r0_42 +# 202| r0_44(glval) = VariableAddress[#return] : +# 202| r0_45(glval) = VariableAddress[ret] : +# 202| r0_46(int) = Load : &:r0_45, m0_43 +# 202| m0_47(int) = Store : &:r0_44, r0_46 +# 198| r0_48(glval) = VariableAddress[#return] : +# 198| v0_49(void) = ReturnValue : &:r0_48, m0_47 +# 198| v0_50(void) = UnmodeledUse : mu* +# 198| v0_51(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index a68690c70559..66b377adf505 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -6,13 +6,15 @@ ssa.cpp: # 13| mu0_2(unknown) = UnmodeledDefinition : # 13| r0_3(glval) = VariableAddress[p] : # 13| m0_4(Point *) = InitializeParameter[p] : &:r0_3 -# 13| r0_5(glval) = VariableAddress[which1] : -# 13| m0_6(bool) = InitializeParameter[which1] : &:r0_5 -# 13| r0_7(glval) = VariableAddress[which2] : -# 13| m0_8(bool) = InitializeParameter[which2] : &:r0_7 -# 14| r0_9(glval) = VariableAddress[which1] : -# 14| r0_10(bool) = Load : &:r0_9, m0_6 -# 14| v0_11(void) = ConditionalBranch : r0_10 +# 13| r0_5(Point *) = Load : &:r0_3, m0_4 +# 13| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 13| r0_7(glval) = VariableAddress[which1] : +# 13| m0_8(bool) = InitializeParameter[which1] : &:r0_7 +# 13| r0_9(glval) = VariableAddress[which2] : +# 13| m0_10(bool) = InitializeParameter[which2] : &:r0_9 +# 14| r0_11(glval) = VariableAddress[which1] : +# 14| r0_12(bool) = Load : &:r0_11, m0_8 +# 14| v0_13(void) = ConditionalBranch : r0_12 #-----| False -> Block 2 #-----| True -> Block 1 @@ -38,7 +40,7 @@ ssa.cpp: # 21| Block 3 # 21| r3_0(glval) = VariableAddress[which2] : -# 21| r3_1(bool) = Load : &:r3_0, m0_8 +# 21| r3_1(bool) = Load : &:r3_0, m0_10 # 21| v3_2(void) = ConditionalBranch : r3_1 #-----| False -> Block 5 #-----| True -> Block 4 @@ -198,13 +200,15 @@ ssa.cpp: # 68| void chiNodeAtEndOfLoop(int, char*) # 68| Block 0 -# 68| v0_0(void) = EnterFunction : -# 68| mu0_1(unknown) = AliasedDefinition : -# 68| mu0_2(unknown) = UnmodeledDefinition : -# 68| r0_3(glval) = VariableAddress[n] : -# 68| m0_4(int) = InitializeParameter[n] : &:r0_3 -# 68| r0_5(glval) = VariableAddress[p] : -# 68| m0_6(char *) = InitializeParameter[p] : &:r0_5 +# 68| v0_0(void) = EnterFunction : +# 68| mu0_1(unknown) = AliasedDefinition : +# 68| mu0_2(unknown) = UnmodeledDefinition : +# 68| r0_3(glval) = VariableAddress[n] : +# 68| m0_4(int) = InitializeParameter[n] : &:r0_3 +# 68| r0_5(glval) = VariableAddress[p] : +# 68| m0_6(char *) = InitializeParameter[p] : &:r0_5 +# 68| r0_7(char *) = Load : &:r0_5, m0_6 +# 68| mu0_8(unknown) = InitializeIndirection[p] : &:r0_7 #-----| Goto -> Block 3 # 70| Block 1 @@ -697,88 +701,102 @@ ssa.cpp: # 179| mu0_2(unknown) = UnmodeledDefinition : # 179| r0_3(glval) = VariableAddress[p] : # 179| m0_4(int *) = InitializeParameter[p] : &:r0_3 -# 180| mu0_5(unknown) = InlineAsm : ~mu0_2 -# 181| r0_6(glval) = VariableAddress[#return] : -# 181| r0_7(glval) = VariableAddress[p] : -# 181| r0_8(int *) = Load : &:r0_7, m0_4 -# 181| r0_9(int) = Load : &:r0_8, ~mu0_2 -# 181| m0_10(int) = Store : &:r0_6, r0_9 -# 179| r0_11(glval) = VariableAddress[#return] : -# 179| v0_12(void) = ReturnValue : &:r0_11, m0_10 -# 179| v0_13(void) = UnmodeledUse : mu* -# 179| v0_14(void) = ExitFunction : +# 179| r0_5(int *) = Load : &:r0_3, m0_4 +# 179| mu0_6(unknown) = InitializeIndirection[p] : &:r0_5 +# 180| mu0_7(unknown) = InlineAsm : ~mu0_2 +# 181| r0_8(glval) = VariableAddress[#return] : +# 181| r0_9(glval) = VariableAddress[p] : +# 181| r0_10(int *) = Load : &:r0_9, m0_4 +# 181| r0_11(int) = Load : &:r0_10, ~mu0_2 +# 181| m0_12(int) = Store : &:r0_8, r0_11 +# 179| r0_13(glval) = VariableAddress[#return] : +# 179| v0_14(void) = ReturnValue : &:r0_13, m0_12 +# 179| v0_15(void) = UnmodeledUse : mu* +# 179| v0_16(void) = ExitFunction : # 184| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&) # 184| Block 0 -# 184| v0_0(void) = EnterFunction : -# 184| mu0_1(unknown) = AliasedDefinition : -# 184| mu0_2(unknown) = UnmodeledDefinition : -# 184| r0_3(glval) = VariableAddress[a] : -# 184| mu0_4(unsigned int &) = InitializeParameter[a] : &:r0_3 -# 184| r0_5(glval) = VariableAddress[b] : -# 184| mu0_6(unsigned int &) = InitializeParameter[b] : &:r0_5 -# 184| r0_7(glval) = VariableAddress[c] : -# 184| mu0_8(unsigned int &) = InitializeParameter[c] : &:r0_7 -# 184| r0_9(glval) = VariableAddress[d] : -# 184| mu0_10(unsigned int &) = InitializeParameter[d] : &:r0_9 -# 186| r0_11(glval) = VariableAddress[a] : -# 186| r0_12(glval) = VariableAddress[b] : -# 186| r0_13(glval) = VariableAddress[c] : -# 186| r0_14(glval) = VariableAddress[d] : -# 186| mu0_15(unknown) = InlineAsm : ~mu0_2, 0:r0_11, 1:r0_12, 2:r0_13, 3:r0_14 -# 192| v0_16(void) = NoOp : -# 184| v0_17(void) = ReturnVoid : -# 184| v0_18(void) = UnmodeledUse : mu* -# 184| v0_19(void) = ExitFunction : +# 184| v0_0(void) = EnterFunction : +# 184| mu0_1(unknown) = AliasedDefinition : +# 184| mu0_2(unknown) = UnmodeledDefinition : +# 184| r0_3(glval) = VariableAddress[a] : +# 184| mu0_4(unsigned int &) = InitializeParameter[a] : &:r0_3 +# 184| r0_5(unsigned int &) = Load : &:r0_3, ~mu0_2 +# 184| mu0_6(unknown) = InitializeIndirection[a] : &:r0_5 +# 184| r0_7(glval) = VariableAddress[b] : +# 184| mu0_8(unsigned int &) = InitializeParameter[b] : &:r0_7 +# 184| r0_9(unsigned int &) = Load : &:r0_7, ~mu0_2 +# 184| mu0_10(unknown) = InitializeIndirection[b] : &:r0_9 +# 184| r0_11(glval) = VariableAddress[c] : +# 184| mu0_12(unsigned int &) = InitializeParameter[c] : &:r0_11 +# 184| r0_13(unsigned int &) = Load : &:r0_11, ~mu0_2 +# 184| mu0_14(unknown) = InitializeIndirection[c] : &:r0_13 +# 184| r0_15(glval) = VariableAddress[d] : +# 184| mu0_16(unsigned int &) = InitializeParameter[d] : &:r0_15 +# 184| r0_17(unsigned int &) = Load : &:r0_15, ~mu0_2 +# 184| mu0_18(unknown) = InitializeIndirection[d] : &:r0_17 +# 186| r0_19(glval) = VariableAddress[a] : +# 186| r0_20(glval) = VariableAddress[b] : +# 186| r0_21(glval) = VariableAddress[c] : +# 186| r0_22(glval) = VariableAddress[d] : +# 186| mu0_23(unknown) = InlineAsm : ~mu0_2, 0:r0_19, 1:r0_20, 2:r0_21, 3:r0_22 +# 192| v0_24(void) = NoOp : +# 184| v0_25(void) = ReturnVoid : +# 184| v0_26(void) = UnmodeledUse : mu* +# 184| v0_27(void) = ExitFunction : # 198| int PureFunctions(char*, char*, int) # 198| Block 0 -# 198| v0_0(void) = EnterFunction : -# 198| mu0_1(unknown) = AliasedDefinition : -# 198| mu0_2(unknown) = UnmodeledDefinition : -# 198| r0_3(glval) = VariableAddress[str1] : -# 198| m0_4(char *) = InitializeParameter[str1] : &:r0_3 -# 198| r0_5(glval) = VariableAddress[str2] : -# 198| m0_6(char *) = InitializeParameter[str2] : &:r0_5 -# 198| r0_7(glval) = VariableAddress[x] : -# 198| m0_8(int) = InitializeParameter[x] : &:r0_7 -# 199| r0_9(glval) = VariableAddress[ret] : -# 199| r0_10(glval) = FunctionAddress[strcmp] : -# 199| r0_11(glval) = VariableAddress[str1] : -# 199| r0_12(char *) = Load : &:r0_11, m0_4 -# 199| r0_13(char *) = Convert : r0_12 -# 199| r0_14(glval) = VariableAddress[str2] : -# 199| r0_15(char *) = Load : &:r0_14, m0_6 -# 199| r0_16(char *) = Convert : r0_15 -# 199| r0_17(int) = Call : func:r0_10, 0:r0_13, 1:r0_16 -# 199| v0_18(void) = ^CallReadSideEffect : ~mu0_2 -# 199| m0_19(int) = Store : &:r0_9, r0_17 -# 200| r0_20(glval) = FunctionAddress[strlen] : -# 200| r0_21(glval) = VariableAddress[str1] : -# 200| r0_22(char *) = Load : &:r0_21, m0_4 -# 200| r0_23(char *) = Convert : r0_22 -# 200| r0_24(int) = Call : func:r0_20, 0:r0_23 -# 200| v0_25(void) = ^CallReadSideEffect : ~mu0_2 -# 200| r0_26(glval) = VariableAddress[ret] : -# 200| r0_27(int) = Load : &:r0_26, m0_19 -# 200| r0_28(int) = Add : r0_27, r0_24 -# 200| m0_29(int) = Store : &:r0_26, r0_28 -# 201| r0_30(glval) = FunctionAddress[abs] : -# 201| r0_31(glval) = VariableAddress[x] : -# 201| r0_32(int) = Load : &:r0_31, m0_8 -# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 -# 201| r0_34(glval) = VariableAddress[ret] : -# 201| r0_35(int) = Load : &:r0_34, m0_29 -# 201| r0_36(int) = Add : r0_35, r0_33 -# 201| m0_37(int) = Store : &:r0_34, r0_36 -# 202| r0_38(glval) = VariableAddress[#return] : -# 202| r0_39(glval) = VariableAddress[ret] : -# 202| r0_40(int) = Load : &:r0_39, m0_37 -# 202| m0_41(int) = Store : &:r0_38, r0_40 -# 198| r0_42(glval) = VariableAddress[#return] : -# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 -# 198| v0_44(void) = UnmodeledUse : mu* -# 198| v0_45(void) = ExitFunction : +# 198| v0_0(void) = EnterFunction : +# 198| mu0_1(unknown) = AliasedDefinition : +# 198| mu0_2(unknown) = UnmodeledDefinition : +# 198| r0_3(glval) = VariableAddress[str1] : +# 198| m0_4(char *) = InitializeParameter[str1] : &:r0_3 +# 198| r0_5(char *) = Load : &:r0_3, m0_4 +# 198| mu0_6(unknown) = InitializeIndirection[str1] : &:r0_5 +# 198| r0_7(glval) = VariableAddress[str2] : +# 198| m0_8(char *) = InitializeParameter[str2] : &:r0_7 +# 198| r0_9(char *) = Load : &:r0_7, m0_8 +# 198| mu0_10(unknown) = InitializeIndirection[str2] : &:r0_9 +# 198| r0_11(glval) = VariableAddress[x] : +# 198| m0_12(int) = InitializeParameter[x] : &:r0_11 +# 199| r0_13(glval) = VariableAddress[ret] : +# 199| r0_14(glval) = FunctionAddress[strcmp] : +# 199| r0_15(glval) = VariableAddress[str1] : +# 199| r0_16(char *) = Load : &:r0_15, m0_4 +# 199| r0_17(char *) = Convert : r0_16 +# 199| r0_18(glval) = VariableAddress[str2] : +# 199| r0_19(char *) = Load : &:r0_18, m0_8 +# 199| r0_20(char *) = Convert : r0_19 +# 199| r0_21(int) = Call : func:r0_14, 0:r0_17, 1:r0_20 +# 199| v0_22(void) = ^CallReadSideEffect : ~mu0_2 +# 199| m0_23(int) = Store : &:r0_13, r0_21 +# 200| r0_24(glval) = FunctionAddress[strlen] : +# 200| r0_25(glval) = VariableAddress[str1] : +# 200| r0_26(char *) = Load : &:r0_25, m0_4 +# 200| r0_27(char *) = Convert : r0_26 +# 200| r0_28(int) = Call : func:r0_24, 0:r0_27 +# 200| v0_29(void) = ^CallReadSideEffect : ~mu0_2 +# 200| r0_30(glval) = VariableAddress[ret] : +# 200| r0_31(int) = Load : &:r0_30, m0_23 +# 200| r0_32(int) = Add : r0_31, r0_28 +# 200| m0_33(int) = Store : &:r0_30, r0_32 +# 201| r0_34(glval) = FunctionAddress[abs] : +# 201| r0_35(glval) = VariableAddress[x] : +# 201| r0_36(int) = Load : &:r0_35, m0_12 +# 201| r0_37(int) = Call : func:r0_34, 0:r0_36 +# 201| r0_38(glval) = VariableAddress[ret] : +# 201| r0_39(int) = Load : &:r0_38, m0_33 +# 201| r0_40(int) = Add : r0_39, r0_37 +# 201| m0_41(int) = Store : &:r0_38, r0_40 +# 202| r0_42(glval) = VariableAddress[#return] : +# 202| r0_43(glval) = VariableAddress[ret] : +# 202| r0_44(int) = Load : &:r0_43, m0_41 +# 202| m0_45(int) = Store : &:r0_42, r0_44 +# 198| r0_46(glval) = VariableAddress[#return] : +# 198| v0_47(void) = ReturnValue : &:r0_46, m0_45 +# 198| v0_48(void) = UnmodeledUse : mu* +# 198| v0_49(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 5fb356f5701f..8f67f857d993 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -11,7 +11,7 @@ missingPhiOperand | cpp11.cpp:141:7:141:7 | Phi: g | cpp11.cpp:161:16:161:16 | NoOp: label ...: | missingOperandType instructionWithoutSuccessor -| VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | +| VacuousDestructorCall.cpp:2:29:2:29 | Chi: y | | assume0.cpp:7:2:7:2 | Chi: call to f | | condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt | | condition_decls.cpp:26:23:26:24 | Chi: call to BoxedInt | @@ -19,7 +19,7 @@ instructionWithoutSuccessor | condition_decls.cpp:48:52:48:53 | Chi: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | -| misc.c:219:47:219:48 | InitializeParameter: sp | +| misc.c:219:47:219:48 | Chi: sp | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | | ms_try_mix.cpp:11:12:11:15 | Chi: call to C | | ms_try_mix.cpp:28:12:28:15 | Chi: call to C | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 426424a5fd46..5d7c44473026 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -21,7 +21,7 @@ duplicateOperand missingPhiOperand missingOperandType instructionWithoutSuccessor -| VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | +| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | | VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | | VacuousDestructorCall.cpp:4:3:4:3 | Load: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | @@ -42,7 +42,7 @@ instructionWithoutSuccessor | misc.c:174:17:174:22 | CallSideEffect: call to getInt | | misc.c:174:30:174:35 | CallSideEffect: call to getInt | | misc.c:174:55:174:60 | Store: (char ****)... | -| misc.c:219:47:219:48 | InitializeParameter: sp | +| misc.c:219:47:219:48 | InitializeIndirection: sp | | misc.c:221:10:221:10 | Store: 1 | | misc.c:222:10:222:10 | Store: 2 | | ms_assume.cpp:20:12:20:12 | Constant: (bool)... | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 22a395b3f89f..a662f2e0e6cf 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -20,7 +20,7 @@ missingPhiOperand | range_analysis.c:389:3:389:32 | Phi: return ... | range_analysis.c:387:38:387:38 | Constant: 5 | missingOperandType instructionWithoutSuccessor -| VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | +| VacuousDestructorCall.cpp:2:29:2:29 | InitializeIndirection: y | | assume0.cpp:7:2:7:2 | CallSideEffect: call to f | | condition_decls.cpp:16:19:16:20 | CallSideEffect: call to BoxedInt | | condition_decls.cpp:26:23:26:24 | CallSideEffect: call to BoxedInt | @@ -28,7 +28,7 @@ instructionWithoutSuccessor | condition_decls.cpp:48:52:48:53 | CallSideEffect: call to BoxedInt | | cpp17.cpp:15:11:15:21 | Convert: (void *)... | | misc.c:171:10:171:13 | Uninitialized: definition of str2 | -| misc.c:219:47:219:48 | InitializeParameter: sp | +| misc.c:219:47:219:48 | InitializeIndirection: sp | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | | ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | | ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index 0c1009b4fac4..b0b51b5eca73 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -3,6 +3,7 @@ private newtype TOpcode = TUninitialized() or TError() or TInitializeParameter() or + TInitializeIndirection() or TInitializeThis() or TEnterFunction() or TExitFunction() or @@ -177,6 +178,11 @@ module Opcode { final override string toString() { result = "InitializeParameter" } } + class InitializeIndirection extends MemoryAccessOpcode, TInitializeIndirection { + final override string toString() { result = "InitializeIndirection" } + } + + class InitializeThis extends Opcode, TInitializeThis { final override string toString() { result = "InitializeThis" } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 3244afeb1447..f0a9c0e698ae 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -675,6 +675,14 @@ class InitializeParameterInstruction extends VariableInstruction { final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } } +class InitializeIndirectionInstruction extends VariableInstruction { + InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } + + final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } +} + /** * An instruction that initializes the `this` pointer parameter of the enclosing function. */ diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 3244afeb1447..f0a9c0e698ae 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -675,6 +675,14 @@ class InitializeParameterInstruction extends VariableInstruction { final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } } +class InitializeIndirectionInstruction extends VariableInstruction { + InitializeIndirectionInstruction() { getOpcode() instanceof Opcode::InitializeIndirection } + + final Language::Parameter getParameter() { result = var.(IRUserVariable).getVariable() } + + final override MemoryAccessKind getResultMemoryAccess() { result instanceof IndirectMemoryAccess } +} + /** * An instruction that initializes the `this` pointer parameter of the enclosing function. */ From bea9a1cbb2fa1bbb11e078f3eebfcacdef2d5c1c Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Fri, 18 Oct 2019 12:15:21 -0700 Subject: [PATCH 0061/2538] autoformat --- cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll | 1 - csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll | 1 - 2 files changed, 2 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index b0b51b5eca73..67507fce11d6 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -182,7 +182,6 @@ module Opcode { final override string toString() { result = "InitializeIndirection" } } - class InitializeThis extends Opcode, TInitializeThis { final override string toString() { result = "InitializeThis" } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index b0b51b5eca73..67507fce11d6 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -182,7 +182,6 @@ module Opcode { final override string toString() { result = "InitializeIndirection" } } - class InitializeThis extends Opcode, TInitializeThis { final override string toString() { result = "InitializeThis" } } From 28720679ad872ef6634161c28a11d5ec1ac90cd3 Mon Sep 17 00:00:00 2001 From: yh-semmle Date: Sat, 19 Oct 2019 20:55:46 -0400 Subject: [PATCH 0062/2538] Java: remove some obsolete metric queries --- .../Metrics/Internal/CallableDisplayStrings.ql | 18 ------------------ .../ql/src/Metrics/Internal/CallableExtents.ql | 13 ------------- .../Metrics/Internal/CallableSourceLinks.ql | 12 ------------ .../Metrics/Internal/ReftypeDisplayStrings.ql | 16 ---------------- java/ql/src/Metrics/Internal/ReftypeExtents.ql | 13 ------------- .../src/Metrics/Internal/ReftypeSourceLinks.ql | 12 ------------ 6 files changed, 84 deletions(-) delete mode 100644 java/ql/src/Metrics/Internal/CallableDisplayStrings.ql delete mode 100644 java/ql/src/Metrics/Internal/CallableExtents.ql delete mode 100644 java/ql/src/Metrics/Internal/CallableSourceLinks.ql delete mode 100644 java/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql delete mode 100644 java/ql/src/Metrics/Internal/ReftypeExtents.ql delete mode 100644 java/ql/src/Metrics/Internal/ReftypeSourceLinks.ql diff --git a/java/ql/src/Metrics/Internal/CallableDisplayStrings.ql b/java/ql/src/Metrics/Internal/CallableDisplayStrings.ql deleted file mode 100644 index 346d0eb061b5..000000000000 --- a/java/ql/src/Metrics/Internal/CallableDisplayStrings.ql +++ /dev/null @@ -1,18 +0,0 @@ -/** - * @name Display strings of callables - * @kind display-string - * @metricType callable - * @id java/callable-display-strings - */ - -import java - -private string prefix(Callable c) { - if c instanceof Constructor and c.getDeclaringType() instanceof AnonymousClass - then result = "" - else result = "" -} - -from Callable c -where c.fromSource() -select c, prefix(c) + c.getStringSignature() diff --git a/java/ql/src/Metrics/Internal/CallableExtents.ql b/java/ql/src/Metrics/Internal/CallableExtents.ql deleted file mode 100644 index def86a82f3da..000000000000 --- a/java/ql/src/Metrics/Internal/CallableExtents.ql +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @name Extents of callables - * @kind extent - * @metricType callable - * @id java/callable-extents - */ - -import java -import Extents - -from RangeCallable c -where c.fromSource() -select c.getLocation(), c diff --git a/java/ql/src/Metrics/Internal/CallableSourceLinks.ql b/java/ql/src/Metrics/Internal/CallableSourceLinks.ql deleted file mode 100644 index 94c8b8108c1d..000000000000 --- a/java/ql/src/Metrics/Internal/CallableSourceLinks.ql +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name Source links of callables - * @kind source-link - * @metricType callable - * @id java/callable-source-links - */ - -import java - -from Callable c -where c.fromSource() -select c, c.getFile() diff --git a/java/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql b/java/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql deleted file mode 100644 index 6351b207bfa0..000000000000 --- a/java/ql/src/Metrics/Internal/ReftypeDisplayStrings.ql +++ /dev/null @@ -1,16 +0,0 @@ -/** - * @name Display strings of reference types - * @kind display-string - * @metricType reftype - * @id java/reference-type-display-strings - */ - -import java - -private string suffix(RefType t) { - if t instanceof AnonymousClass then result = "" else result = "" -} - -from RefType t -where t.fromSource() -select t, t.nestedName() + suffix(t) diff --git a/java/ql/src/Metrics/Internal/ReftypeExtents.ql b/java/ql/src/Metrics/Internal/ReftypeExtents.ql deleted file mode 100644 index 8a1151fa51a0..000000000000 --- a/java/ql/src/Metrics/Internal/ReftypeExtents.ql +++ /dev/null @@ -1,13 +0,0 @@ -/** - * @name Extents of reftypes - * @kind extent - * @metricType reftype - * @id java/reference-type-extents - */ - -import java -import Extents - -from RangeRefType t -where t.fromSource() -select t.getLocation(), t diff --git a/java/ql/src/Metrics/Internal/ReftypeSourceLinks.ql b/java/ql/src/Metrics/Internal/ReftypeSourceLinks.ql deleted file mode 100644 index 693fad7f1df8..000000000000 --- a/java/ql/src/Metrics/Internal/ReftypeSourceLinks.ql +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @name Source links of reference types - * @kind source-link - * @metricType reftype - * @id java/reference-type-source-links - */ - -import java - -from RefType t -where t.fromSource() -select t, t.getFile() From 2e0244cda62deea17afe438c30e289d5c97913ca Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 21 Oct 2019 20:21:41 +0200 Subject: [PATCH 0063/2538] address review feedback --- .../ql/src/Expressions/ExprHasNoEffect.ql | 1 + .../ql/src/Expressions/ExprHasNoEffect.qll | 1 - .../src/Statements/UseOfReturnlessFunction.ql | 25 +++++++++++++++---- .../UseOfReturnlessFunction.expected | 8 +++--- .../Statements/UseOfReturnlessFunction/tst.js | 3 +++ 5 files changed, 28 insertions(+), 10 deletions(-) diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.ql b/javascript/ql/src/Expressions/ExprHasNoEffect.ql index 929e84616f07..917ab81a3e73 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.ql +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.ql @@ -14,6 +14,7 @@ import javascript import ExprHasNoEffect +import semmle.javascript.RestrictedLocations from Expr e diff --git a/javascript/ql/src/Expressions/ExprHasNoEffect.qll b/javascript/ql/src/Expressions/ExprHasNoEffect.qll index 822bcbb26fae..bee980e5fd84 100644 --- a/javascript/ql/src/Expressions/ExprHasNoEffect.qll +++ b/javascript/ql/src/Expressions/ExprHasNoEffect.qll @@ -5,7 +5,6 @@ import javascript import DOMProperties import semmle.javascript.frameworks.xUnit -import semmle.javascript.RestrictedLocations /** * Holds if `e` appears in a syntactic context where its value is discarded. diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 2d70cecb0d3a..fe03c66cf4ab 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -82,8 +82,19 @@ predicate alwaysThrows(Function f) { ) } +/** + * Holds if the last statement in the function is flagged by the js/useless-expression query. + */ +predicate alwaysHasNoEffect(Function f) { + exists(ReachableBasicBlock entry, DataFlow::Node noEffect | + entry = f.getEntryBB() and + hasNoEffect(noEffect.asExpr()) and + entry.dominates(noEffect.getBasicBlock()) + ) +} + predicate callToVoidFunction(DataFlow::CallNode call, Function func) { - not call.isIndefinite(_) and + not call.isIncomplete() and func = call.getACallee() and forall(Function f | f = call.getACallee() | returnsVoid(f) and not isStub(f) and not alwaysThrows(f) @@ -113,6 +124,11 @@ DataFlow::SourceNode array(DataFlow::TypeTracker t) { DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } +/** + * Holds if `call` is an Array or Lodash method accepting a callback `func`, + * where the `call` expects a callback that returns an expression, + * but `func` does return a value. + */ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { hasNonVoidCallbackMethod(call.getCalleeName()) and func = call.getAnArgument().getALocalSource().asExpr() and @@ -132,15 +148,14 @@ where ( callToVoidFunction(call, func) and msg = "the $@ does not return anything, yet the return value is used." and - name = "function " + call.getCalleeName() + name = func.describe() or voidArrayCallback(call, func) and - msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + "() is used." and + msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + " is used." and name = "callback function" ) and not benignContext(call.asExpr()) and - // Avoid double reporting from js/useless-expression - not hasNoEffect(func.getBodyStmt(func.getNumBodyStmt() - 1).(ExprStmt).getExpr()) and + not alwaysHasNoEffect(func) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected index 98ae4e3696c7..f23b702bf202 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/UseOfReturnlessFunction.expected @@ -1,7 +1,7 @@ | tst.js:20:17:20:33 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | | tst.js:24:13:24:29 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | | tst.js:30:20:30:36 | onlySideEffects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | -| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function bothOnlyHaveSideEffects | -| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | -| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter() is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:11:5:13:5 | functio ... )\\n } | function onlySideEffects | +| tst.js:53:10:53:34 | bothOnl ... fects() | the $@ does not return anything, yet the return value is used. | tst.js:48:2:50:5 | functio ... )\\n } | function onlySideEffects2 | +| tst.js:76:12:76:46 | [1,2,3] ... n, 3)}) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:76:27:76:45 | n => {equals(n, 3)} | callback function | +| tst.js:80:12:80:50 | filter( ... 3) } ) | the $@ does not return anything, yet the return value from the call to filter is used. | tst.js:80:28:80:48 | x => { ... x, 3) } | callback function | diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 2b523223e91f..8a6a44707edd 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -79,4 +79,7 @@ import { filter } from 'lodash' var bar = filter([1,2,4], x => { equals(x, 3) } ) // NOT OK! console.log(bar); + + var baz = [1,2,3].filter(n => {n === 3}) // OK + console.log(baz); })(); \ No newline at end of file From 22925189335f54dbd08c08cf1f4e20d178d94816 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 21 Oct 2019 17:04:46 -0700 Subject: [PATCH 0064/2538] [CPP-434] Change query so it flags overflows that were cast to `unsigned`. --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 4 ++-- .../BadAdditionOverflowCheck/SignedOverflowCheck.cpp | 2 +- .../BadAdditionOverflowCheck/SignedOverflowCheck.expected | 2 ++ .../Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp | 2 +- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 076e47df7014..9ad9fa15727b 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -15,8 +15,8 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering private predicate isSignedWithoutUnsignedCast(Expr e) { - e.getType().getUnspecifiedType().(IntegralType).isSigned() and - not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() + e.getType().getUnspecifiedType().(IntegralType).isSigned() /*and + not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned()*/ } from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index febb45e8ecc5..86757984326f 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -39,7 +39,7 @@ bool shortShort2(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (unsigned short)(n1 + delta) < n1; // GOOD + return (unsigned short)(n1 + delta) < n1; // BAD: n1 + delta overflow undefined } /* Distinguish `varname` from `ptr->varname` and `obj.varname` */ diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index d4fd6334eaaa..9f35d51c4e31 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -1,7 +1,9 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:42:9:42:41 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. | | test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. | +| test.cpp:8:11:8:37 | ... < ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp index 4669b709bc41..3c82f602cb9e 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp @@ -5,7 +5,7 @@ bool checkOverflow1(unsigned short a, unsigned short b) { // Test for BadAdditionOverflowCheck. bool checkOverflow2(unsigned short a, unsigned short b) { - return ((unsigned short)(a + b) < a); // GOOD: explicit cast + return ((unsigned short)(a + b) < a); // BAD: a + b overflow undefined } // Test for PointlessSelfComparison. From 9bc4c2d9a506a53568d1b1b68d1b065de0bbc8cc Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 21 Oct 2019 18:40:20 -0700 Subject: [PATCH 0065/2538] [CPP-434] Ctrl + Shift + F. --- .../src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 9ad9fa15727b..387a9397e43a 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -15,9 +15,13 @@ import cpp import semmle.code.cpp.valuenumbering.GlobalValueNumbering private predicate isSignedWithoutUnsignedCast(Expr e) { - e.getType().getUnspecifiedType().(IntegralType).isSigned() /*and - not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned()*/ -} + e.getType().getUnspecifiedType().(IntegralType).isSigned() + /* + * and + * not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() + */ + + } from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where From db22916850202d1e159fc21e651670f501d29bc2 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 22 Oct 2019 09:37:19 +0200 Subject: [PATCH 0066/2538] fix the alwaysHasNoEffect predicate, and rename it to lastStatementHasNoEffect --- .../ql/src/Statements/UseOfReturnlessFunction.ql | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index fe03c66cf4ab..0f168e263ddd 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -85,11 +85,11 @@ predicate alwaysThrows(Function f) { /** * Holds if the last statement in the function is flagged by the js/useless-expression query. */ -predicate alwaysHasNoEffect(Function f) { - exists(ReachableBasicBlock entry, DataFlow::Node noEffect | - entry = f.getEntryBB() and - hasNoEffect(noEffect.asExpr()) and - entry.dominates(noEffect.getBasicBlock()) +predicate lastStatementHasNoEffect(Function f) { + exists(DataFlow::Node noEffect | + noEffect.getContainer() = f and + hasNoEffect(noEffect.asExpr()) and + not exists(noEffect.getASuccessor()) ) } @@ -155,7 +155,7 @@ where name = "callback function" ) and not benignContext(call.asExpr()) and - not alwaysHasNoEffect(func) and + not lastStatementHasNoEffect(func) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. not oneshotClosure(call.asExpr()) select From ad3185c5586efc622cea59956868e729a545ae4a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 22 Oct 2019 10:33:05 +0200 Subject: [PATCH 0067/2538] simplify lastStatementHasNoEffect and use the control-flow to determine which statement is the last --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 0f168e263ddd..2fc3f01a560f 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -86,11 +86,7 @@ predicate alwaysThrows(Function f) { * Holds if the last statement in the function is flagged by the js/useless-expression query. */ predicate lastStatementHasNoEffect(Function f) { - exists(DataFlow::Node noEffect | - noEffect.getContainer() = f and - hasNoEffect(noEffect.asExpr()) and - not exists(noEffect.getASuccessor()) - ) + hasNoEffect(f.getExit().getAPredecessor()) } predicate callToVoidFunction(DataFlow::CallNode call, Function func) { From 2ffbb2ecd6c192f211a6a930ef97857c3c2b70f2 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Fri, 18 Oct 2019 15:05:44 +0200 Subject: [PATCH 0068/2538] Java: Refactor dataflow to simplify return flow. --- .../java/dataflow/internal/DataFlowImpl.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImplCommon.qll | 81 ++++++++- .../java/dataflow/internal/DataFlowUtil.qll | 2 +- 3 files changed, 124 insertions(+), 123 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index e52995407a72..7858d7711128 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index 5306d8b7dfe6..b9ed7d5e07e2 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -615,7 +615,7 @@ private module ImplCommon { cached newtype TReturnPosition = - TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } + TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) { returnPosition(_, c, kind) } cached newtype TLocalFlowCallContext = @@ -624,7 +624,7 @@ private module ImplCommon { } pragma[noinline] - private predicate returnPosition(ReturnNode ret, DataFlowCallable c, ReturnKind kind) { + private predicate returnPosition(ReturnNodeExt ret, DataFlowCallable c, ReturnKindExt kind) { c = returnNodeGetEnclosingCallable(ret) and kind = ret.getKind() } @@ -736,10 +736,68 @@ private module ImplCommon { else result instanceof LocalCallContextAny } + /** + * A node from which flow can return to the caller. This is either a regular + * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. + */ + class ReturnNodeExt extends Node { + ReturnNodeExt() { + this instanceof ReturnNode or + parameterValueFlowsToUpdate(_, this) + } + + /** Gets the kind of this returned value. */ + ReturnKindExt getKind() { + result = TValueReturn(this.(ReturnNode).getKind()) + or + exists(ParameterNode p, int pos | + parameterValueFlowsToUpdate(p, this) and + p.isParameterOf(_, pos) and + result = TParamUpdate(pos) + ) + } + } + + private newtype TReturnKindExt = + TValueReturn(ReturnKind kind) or + TParamUpdate(int pos) { + exists(ParameterNode p | parameterValueFlowsToUpdate(p, _) and p.isParameterOf(_, pos)) + } + + /** + * An extended return kind. A return kind describes how data can be returned + * from a callable. This can either be through a returned value or an updated + * parameter. + */ + abstract class ReturnKindExt extends TReturnKindExt { + /** Gets a textual representation of this return kind. */ + abstract string toString(); + } + + class ValueReturnKind extends ReturnKindExt, TValueReturn { + private ReturnKind kind; + + ValueReturnKind() { this = TValueReturn(kind) } + + ReturnKind getKind() { result = kind } + + override string toString() { result = kind.toString() } + } + + class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { + private int pos; + + ParamUpdateReturnKind() { this = TParamUpdate(pos) } + + int getPosition() { result = pos } + + override string toString() { result = "param update " + pos } + } + /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; + private ReturnKindExt kind; ReturnPosition() { this = TReturnPosition0(c, kind) } @@ -747,24 +805,33 @@ private module ImplCommon { DataFlowCallable getCallable() { result = c } /** Gets the return kind. */ - ReturnKind getKind() { result = kind } + ReturnKindExt getKind() { result = kind } /** Gets a textual representation of this return position. */ string toString() { result = "[" + kind + "] " + c } } pragma[noinline] - DataFlowCallable returnNodeGetEnclosingCallable(ReturnNode ret) { + DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) { result = ret.getEnclosingCallable() } pragma[noinline] - ReturnPosition getReturnPosition(ReturnNode ret) { - exists(DataFlowCallable c, ReturnKind k | returnPosition(ret, c, k) | + ReturnPosition getReturnPosition(ReturnNodeExt ret) { + exists(DataFlowCallable c, ReturnKindExt k | returnPosition(ret, c, k) | result = TReturnPosition0(c, k) ) } + Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { + result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) + or + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) + ) + } + bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll index 21f5415ef1a3..ffa1a86f6886 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowUtil.qll @@ -23,7 +23,7 @@ private newtype TNode = TExplicitExprPostUpdate(Expr e) { explicitInstanceArgument(_, e) or - e instanceof Argument + e instanceof Argument and not e.getType() instanceof ImmutableType or exists(FieldAccess fa | fa.getField() instanceof InstanceField and e = fa.getQualifier()) } or From c37195b226bd0aaee6e1663c2e5ed4be69bb3d9d Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 22 Oct 2019 11:41:47 +0200 Subject: [PATCH 0069/2538] Java/C++/C#: Sync. --- .../cpp/dataflow/internal/DataFlowImpl.qll | 164 ++++++------------ .../cpp/dataflow/internal/DataFlowImpl2.qll | 164 ++++++------------ .../cpp/dataflow/internal/DataFlowImpl3.qll | 164 ++++++------------ .../cpp/dataflow/internal/DataFlowImpl4.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImplCommon.qll | 81 ++++++++- .../dataflow/internal/DataFlowImplLocal.qll | 164 ++++++------------ .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 164 ++++++------------ .../ir/dataflow/internal/DataFlowImpl2.qll | 164 ++++++------------ .../ir/dataflow/internal/DataFlowImpl3.qll | 164 ++++++------------ .../ir/dataflow/internal/DataFlowImpl4.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImplCommon.qll | 81 ++++++++- .../csharp/dataflow/internal/DataFlowImpl.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImpl2.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImpl3.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImpl4.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImpl5.qll | 164 ++++++------------ .../dataflow/internal/DataFlowImplCommon.qll | 81 ++++++++- .../java/dataflow/internal/DataFlowImpl2.qll | 164 ++++++------------ .../java/dataflow/internal/DataFlowImpl3.qll | 164 ++++++------------ .../java/dataflow/internal/DataFlowImpl4.qll | 164 ++++++------------ .../java/dataflow/internal/DataFlowImpl5.qll | 164 ++++++------------ 21 files changed, 1104 insertions(+), 2091 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index 5306d8b7dfe6..b9ed7d5e07e2 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -615,7 +615,7 @@ private module ImplCommon { cached newtype TReturnPosition = - TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } + TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) { returnPosition(_, c, kind) } cached newtype TLocalFlowCallContext = @@ -624,7 +624,7 @@ private module ImplCommon { } pragma[noinline] - private predicate returnPosition(ReturnNode ret, DataFlowCallable c, ReturnKind kind) { + private predicate returnPosition(ReturnNodeExt ret, DataFlowCallable c, ReturnKindExt kind) { c = returnNodeGetEnclosingCallable(ret) and kind = ret.getKind() } @@ -736,10 +736,68 @@ private module ImplCommon { else result instanceof LocalCallContextAny } + /** + * A node from which flow can return to the caller. This is either a regular + * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. + */ + class ReturnNodeExt extends Node { + ReturnNodeExt() { + this instanceof ReturnNode or + parameterValueFlowsToUpdate(_, this) + } + + /** Gets the kind of this returned value. */ + ReturnKindExt getKind() { + result = TValueReturn(this.(ReturnNode).getKind()) + or + exists(ParameterNode p, int pos | + parameterValueFlowsToUpdate(p, this) and + p.isParameterOf(_, pos) and + result = TParamUpdate(pos) + ) + } + } + + private newtype TReturnKindExt = + TValueReturn(ReturnKind kind) or + TParamUpdate(int pos) { + exists(ParameterNode p | parameterValueFlowsToUpdate(p, _) and p.isParameterOf(_, pos)) + } + + /** + * An extended return kind. A return kind describes how data can be returned + * from a callable. This can either be through a returned value or an updated + * parameter. + */ + abstract class ReturnKindExt extends TReturnKindExt { + /** Gets a textual representation of this return kind. */ + abstract string toString(); + } + + class ValueReturnKind extends ReturnKindExt, TValueReturn { + private ReturnKind kind; + + ValueReturnKind() { this = TValueReturn(kind) } + + ReturnKind getKind() { result = kind } + + override string toString() { result = kind.toString() } + } + + class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { + private int pos; + + ParamUpdateReturnKind() { this = TParamUpdate(pos) } + + int getPosition() { result = pos } + + override string toString() { result = "param update " + pos } + } + /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; + private ReturnKindExt kind; ReturnPosition() { this = TReturnPosition0(c, kind) } @@ -747,24 +805,33 @@ private module ImplCommon { DataFlowCallable getCallable() { result = c } /** Gets the return kind. */ - ReturnKind getKind() { result = kind } + ReturnKindExt getKind() { result = kind } /** Gets a textual representation of this return position. */ string toString() { result = "[" + kind + "] " + c } } pragma[noinline] - DataFlowCallable returnNodeGetEnclosingCallable(ReturnNode ret) { + DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) { result = ret.getEnclosingCallable() } pragma[noinline] - ReturnPosition getReturnPosition(ReturnNode ret) { - exists(DataFlowCallable c, ReturnKind k | returnPosition(ret, c, k) | + ReturnPosition getReturnPosition(ReturnNodeExt ret) { + exists(DataFlowCallable c, ReturnKindExt k | returnPosition(ret, c, k) | result = TReturnPosition0(c, k) ) } + Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { + result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) + or + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) + ) + } + bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index e52995407a72..7858d7711128 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index 5306d8b7dfe6..b9ed7d5e07e2 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -615,7 +615,7 @@ private module ImplCommon { cached newtype TReturnPosition = - TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } + TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) { returnPosition(_, c, kind) } cached newtype TLocalFlowCallContext = @@ -624,7 +624,7 @@ private module ImplCommon { } pragma[noinline] - private predicate returnPosition(ReturnNode ret, DataFlowCallable c, ReturnKind kind) { + private predicate returnPosition(ReturnNodeExt ret, DataFlowCallable c, ReturnKindExt kind) { c = returnNodeGetEnclosingCallable(ret) and kind = ret.getKind() } @@ -736,10 +736,68 @@ private module ImplCommon { else result instanceof LocalCallContextAny } + /** + * A node from which flow can return to the caller. This is either a regular + * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. + */ + class ReturnNodeExt extends Node { + ReturnNodeExt() { + this instanceof ReturnNode or + parameterValueFlowsToUpdate(_, this) + } + + /** Gets the kind of this returned value. */ + ReturnKindExt getKind() { + result = TValueReturn(this.(ReturnNode).getKind()) + or + exists(ParameterNode p, int pos | + parameterValueFlowsToUpdate(p, this) and + p.isParameterOf(_, pos) and + result = TParamUpdate(pos) + ) + } + } + + private newtype TReturnKindExt = + TValueReturn(ReturnKind kind) or + TParamUpdate(int pos) { + exists(ParameterNode p | parameterValueFlowsToUpdate(p, _) and p.isParameterOf(_, pos)) + } + + /** + * An extended return kind. A return kind describes how data can be returned + * from a callable. This can either be through a returned value or an updated + * parameter. + */ + abstract class ReturnKindExt extends TReturnKindExt { + /** Gets a textual representation of this return kind. */ + abstract string toString(); + } + + class ValueReturnKind extends ReturnKindExt, TValueReturn { + private ReturnKind kind; + + ValueReturnKind() { this = TValueReturn(kind) } + + ReturnKind getKind() { result = kind } + + override string toString() { result = kind.toString() } + } + + class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { + private int pos; + + ParamUpdateReturnKind() { this = TParamUpdate(pos) } + + int getPosition() { result = pos } + + override string toString() { result = "param update " + pos } + } + /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; + private ReturnKindExt kind; ReturnPosition() { this = TReturnPosition0(c, kind) } @@ -747,24 +805,33 @@ private module ImplCommon { DataFlowCallable getCallable() { result = c } /** Gets the return kind. */ - ReturnKind getKind() { result = kind } + ReturnKindExt getKind() { result = kind } /** Gets a textual representation of this return position. */ string toString() { result = "[" + kind + "] " + c } } pragma[noinline] - DataFlowCallable returnNodeGetEnclosingCallable(ReturnNode ret) { + DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) { result = ret.getEnclosingCallable() } pragma[noinline] - ReturnPosition getReturnPosition(ReturnNode ret) { - exists(DataFlowCallable c, ReturnKind k | returnPosition(ret, c, k) | + ReturnPosition getReturnPosition(ReturnNodeExt ret) { + exists(DataFlowCallable c, ReturnKindExt k | returnPosition(ret, c, k) | result = TReturnPosition0(c, k) ) } + Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { + result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) + or + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) + ) + } + bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index e52995407a72..7858d7711128 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index e52995407a72..7858d7711128 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index e52995407a72..7858d7711128 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index e52995407a72..7858d7711128 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index e52995407a72..7858d7711128 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index 5306d8b7dfe6..b9ed7d5e07e2 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -615,7 +615,7 @@ private module ImplCommon { cached newtype TReturnPosition = - TReturnPosition0(DataFlowCallable c, ReturnKind kind) { returnPosition(_, c, kind) } + TReturnPosition0(DataFlowCallable c, ReturnKindExt kind) { returnPosition(_, c, kind) } cached newtype TLocalFlowCallContext = @@ -624,7 +624,7 @@ private module ImplCommon { } pragma[noinline] - private predicate returnPosition(ReturnNode ret, DataFlowCallable c, ReturnKind kind) { + private predicate returnPosition(ReturnNodeExt ret, DataFlowCallable c, ReturnKindExt kind) { c = returnNodeGetEnclosingCallable(ret) and kind = ret.getKind() } @@ -736,10 +736,68 @@ private module ImplCommon { else result instanceof LocalCallContextAny } + /** + * A node from which flow can return to the caller. This is either a regular + * `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter. + */ + class ReturnNodeExt extends Node { + ReturnNodeExt() { + this instanceof ReturnNode or + parameterValueFlowsToUpdate(_, this) + } + + /** Gets the kind of this returned value. */ + ReturnKindExt getKind() { + result = TValueReturn(this.(ReturnNode).getKind()) + or + exists(ParameterNode p, int pos | + parameterValueFlowsToUpdate(p, this) and + p.isParameterOf(_, pos) and + result = TParamUpdate(pos) + ) + } + } + + private newtype TReturnKindExt = + TValueReturn(ReturnKind kind) or + TParamUpdate(int pos) { + exists(ParameterNode p | parameterValueFlowsToUpdate(p, _) and p.isParameterOf(_, pos)) + } + + /** + * An extended return kind. A return kind describes how data can be returned + * from a callable. This can either be through a returned value or an updated + * parameter. + */ + abstract class ReturnKindExt extends TReturnKindExt { + /** Gets a textual representation of this return kind. */ + abstract string toString(); + } + + class ValueReturnKind extends ReturnKindExt, TValueReturn { + private ReturnKind kind; + + ValueReturnKind() { this = TValueReturn(kind) } + + ReturnKind getKind() { result = kind } + + override string toString() { result = kind.toString() } + } + + class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { + private int pos; + + ParamUpdateReturnKind() { this = TParamUpdate(pos) } + + int getPosition() { result = pos } + + override string toString() { result = "param update " + pos } + } + /** A callable tagged with a relevant return kind. */ class ReturnPosition extends TReturnPosition0 { private DataFlowCallable c; - private ReturnKind kind; + private ReturnKindExt kind; ReturnPosition() { this = TReturnPosition0(c, kind) } @@ -747,24 +805,33 @@ private module ImplCommon { DataFlowCallable getCallable() { result = c } /** Gets the return kind. */ - ReturnKind getKind() { result = kind } + ReturnKindExt getKind() { result = kind } /** Gets a textual representation of this return position. */ string toString() { result = "[" + kind + "] " + c } } pragma[noinline] - DataFlowCallable returnNodeGetEnclosingCallable(ReturnNode ret) { + DataFlowCallable returnNodeGetEnclosingCallable(ReturnNodeExt ret) { result = ret.getEnclosingCallable() } pragma[noinline] - ReturnPosition getReturnPosition(ReturnNode ret) { - exists(DataFlowCallable c, ReturnKind k | returnPosition(ret, c, k) | + ReturnPosition getReturnPosition(ReturnNodeExt ret) { + exists(DataFlowCallable c, ReturnKindExt k | returnPosition(ret, c, k) | result = TReturnPosition0(c, k) ) } + Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { + result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) + or + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) + ) + } + bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index e52995407a72..7858d7711128 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index e52995407a72..7858d7711128 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index e52995407a72..7858d7711128 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index e52995407a72..7858d7711128 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -258,8 +258,8 @@ private predicate additionalJumpStep(Node node1, Node node2, Configuration confi private predicate useFieldFlow(Configuration config) { config.fieldFlowBranchLimit() >= 1 } pragma[noinline] -private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKind kind) { - viableImpl(call) = result.getCallable() and +private ReturnPosition viableReturnPos(DataFlowCall call, ReturnKindExt kind) { + viableCallable(call) = result.getCallable() and kind = result.getKind() } @@ -313,18 +313,11 @@ private predicate nodeCandFwd1(Node node, Configuration config) { viableParamArg(_, node, arg) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - nodeCandFwd1(mid, config) and - parameterValueFlowsToUpdate(p, mid) and - viableParamArg(_, p, node.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnNode ret, ReturnKind kind | + exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNode(call, kind) + node = getAnOutNodeExt(call, kind) ) ) } @@ -403,22 +396,23 @@ private predicate nodeCand1(Node node, Configuration config) { nodeCand1(param, config) ) or - // flow out of an argument - exists(PostUpdateNode mid, ParameterNode p | - parameterValueFlowsToUpdate(p, node) and - viableParamArg(_, p, mid.getPreUpdateNode()) and - nodeCand1(mid, config) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind, OutNode out | - nodeCand1(out, config) and - getReturnPosition(node) = viableReturnPos(call, kind) and - out = getAnOutNode(call, kind) + exists(ReturnPosition pos | + nodeCand1ReturnPosition(pos, config) and + getReturnPosition(node) = pos ) ) } +pragma[noinline] +private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration config) { + exists(DataFlowCall call, ReturnKindExt kind, Node out | + nodeCand1(out, config) and + pos = viableReturnPos(call, kind) and + out = getAnOutNodeExt(call, kind) + ) +} + /** * Holds if `f` is the target of a read in the flow covered by `nodeCand1`. */ @@ -565,28 +559,24 @@ private predicate additionalLocalFlowStepOrFlowThroughCallable( simpleArgumentFlowsThrough(node1, node2, _, config) } +pragma[noinline] +private ReturnPosition getReturnPosition1(Node node, Configuration config) { + result = getReturnPosition(node) and + nodeCand1(node, config) +} + /** * Holds if data can flow out of a callable from `node1` to `node2`, either * through a `ReturnNode` or through an argument that has been mutated, and * that this step is part of a path from a source to a sink. */ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config) { - nodeCand1(node1, unbind(config)) and nodeCand1(node2, config) and not outBarrier(node1, config) and not inBarrier(node2, config) and - ( - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or - // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | - getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) - ) + exists(DataFlowCall call, ReturnKindExt kind | + getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and + node2 = getAnOutNodeExt(call, kind) ) } @@ -1762,8 +1752,6 @@ private predicate pathStep(PathNodeMid mid, Node node, CallContext cc, AccessPat or exists(Content f, AccessPath ap0 | contentStoreStep(mid, node, ap0, f, cc) and push(ap0, f, ap)) or - pathOutOfArgument(mid, node, cc) and ap = mid.getAp() - or pathIntoCallable(mid, node, _, cc, _) and ap = mid.getAp() or pathOutOfCallable(mid, node, cc) and ap = mid.getAp() @@ -1799,7 +1787,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo pragma[noinline] private predicate pathOutOfCallable1( - PathNodeMid mid, DataFlowCall call, ReturnKind kind, CallContext cc + PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | pathOutOfCallable0(mid, pos, innercc) and @@ -1816,29 +1804,9 @@ private predicate pathOutOfCallable1( * is a return from a callable and is recorded by `cc`, if needed. */ pragma[noinline] -private predicate pathOutOfCallable(PathNodeMid mid, OutNode out, CallContext cc) { - exists(ReturnKind kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNode(call, kind) - ) -} - -private predicate pathOutOfArgument(PathNodeMid mid, PostUpdateNode node, CallContext cc) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - flow(node, unbind(mid.getConfiguration())) - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() +private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { + exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | + out = getAnOutNodeExt(call, kind) ) } @@ -1900,9 +1868,9 @@ private predicate pathIntoCallable( /** Holds if data may flow from `p` to a return of kind `kind`. */ pragma[nomagic] private predicate paramFlowsThrough( - ParameterNode p, ReturnKind kind, CallContextCall cc, AccessPathNil apnil, Configuration config + ParameterNode p, ReturnKindExt kind, CallContextCall cc, AccessPathNil apnil, Configuration config ) { - exists(PathNodeMid mid, ReturnNode ret | + exists(PathNodeMid mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -1919,12 +1887,12 @@ private predicate paramFlowsThrough( pragma[noinline] private predicate pathThroughCallable0( - DataFlowCall call, PathNodeMid mid, ReturnKind kind, CallContext cc, AccessPathNil apnil + DataFlowCall call, PathNodeMid mid, ReturnKindExt kind, CallContext cc, AccessPathNil apnil ) { exists(ParameterNode p, CallContext innercc | pathIntoCallable(mid, p, cc, innercc, call) and paramFlowsThrough(p, kind, innercc, apnil, unbind(mid.getConfiguration())) and - not parameterValueFlowsThrough(p, kind, innercc) and + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) and mid.getAp() instanceof AccessPathNil ) } @@ -1934,12 +1902,10 @@ private predicate pathThroughCallable0( * The context `cc` is restored to its value prior to entering the callable. */ pragma[noinline] -private predicate pathThroughCallable( - PathNodeMid mid, OutNode out, CallContext cc, AccessPathNil apnil -) { - exists(DataFlowCall call, ReturnKind kind | +private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { + exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } @@ -1996,16 +1962,10 @@ private module FlowExploration { // flow into callable viableParamArg(_, node2, node1) or - // flow out of an argument - exists(ParameterNode p | - parameterValueFlowsToUpdate(p, node1) and - viableParamArg(_, p, node2.(PostUpdateNode).getPreUpdateNode()) - ) - or // flow out of a callable - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNode(call, kind) + node2 = getAnOutNodeExt(call, kind) ) | c1 = node1.getEnclosingCallable() and @@ -2250,8 +2210,6 @@ private module FlowExploration { apConsFwd(ap, f, ap0, config) ) or - partialPathOutOfArgument(mid, node, cc, ap, config) - or partialPathIntoCallable(mid, node, _, cc, _, ap, config) or partialPathOutOfCallable(mid, node, cc, ap, config) @@ -2310,7 +2268,7 @@ private module FlowExploration { pragma[noinline] private predicate partialPathOutOfCallable1( - PartialPathNodePriv mid, DataFlowCall call, ReturnKind kind, CallContext cc, + PartialPathNodePriv mid, DataFlowCall call, ReturnKindExt kind, CallContext cc, PartialAccessPath ap, Configuration config ) { exists(ReturnPosition pos, DataFlowCallable c, CallContext innercc | @@ -2324,36 +2282,12 @@ private module FlowExploration { } private predicate partialPathOutOfCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPath ap, Configuration config + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPath ap, Configuration config ) { - exists(ReturnKind kind, DataFlowCall call | + exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNode(call, kind) - ) - } - - private predicate partialPathOutOfArgument( - PartialPathNodePriv mid, PostUpdateNode node, CallContext cc, PartialAccessPath ap, - Configuration config - ) { - exists( - PostUpdateNode n, ParameterNode p, DataFlowCallable callable, CallContext innercc, int i, - DataFlowCall call, ArgumentNode arg - | - mid.getNode() = n and - parameterValueFlowsToUpdate(p, n) and - innercc = mid.getCallContext() and - p.isParameterOf(callable, i) and - resolveReturn(innercc, callable, call) and - node.getPreUpdateNode() = arg and - arg.argumentOf(call, i) and - ap = mid.getAp() and - config = mid.getConfiguration() - | - if reducedViableImplInReturn(callable, call) - then cc = TReturn(callable, call) - else cc = TAnyCallContext() + out = getAnOutNodeExt(call, kind) ) } @@ -2400,10 +2334,10 @@ private module FlowExploration { pragma[nomagic] private predicate paramFlowsThroughInPartialPath( - ParameterNode p, ReturnKind kind, CallContextCall cc, PartialAccessPathNil apnil, + ParameterNode p, ReturnKindExt kind, CallContextCall cc, PartialAccessPathNil apnil, Configuration config ) { - exists(PartialPathNodePriv mid, ReturnNode ret | + exists(PartialPathNodePriv mid, ReturnNodeExt ret | mid.getNode() = ret and kind = ret.getKind() and cc = mid.getCallContext() and @@ -2420,23 +2354,23 @@ private module FlowExploration { pragma[noinline] private predicate partialPathThroughCallable0( - DataFlowCall call, PartialPathNodePriv mid, ReturnKind kind, CallContext cc, + DataFlowCall call, PartialPathNodePriv mid, ReturnKindExt kind, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { exists(ParameterNode p, CallContext innercc, PartialAccessPathNil midapnil | partialPathIntoCallable(mid, p, cc, innercc, call, midapnil, config) and paramFlowsThroughInPartialPath(p, kind, innercc, apnil, config) and - not parameterValueFlowsThrough(p, kind, innercc) + not parameterValueFlowsThrough(p, kind.(ValueReturnKind).getKind(), innercc) ) } private predicate partialPathThroughCallable( - PartialPathNodePriv mid, OutNode out, CallContext cc, PartialAccessPathNil apnil, + PartialPathNodePriv mid, Node out, CallContext cc, PartialAccessPathNil apnil, Configuration config ) { - exists(DataFlowCall call, ReturnKind kind | + exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNode(call, kind) + out = getAnOutNodeExt(call, kind) ) } From 06f63c54779ddb2232dceccb071d1189a055a585 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 22 Oct 2019 13:06:33 -0700 Subject: [PATCH 0070/2538] [CPP-434] Incremental changes to SignedOverflowCheck.cpp test suite. --- .../BadAdditionOverflowCheck/SignedOverflowCheck.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 86757984326f..af6593dc0c39 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -32,14 +32,14 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD + return n1 + delta < n1; // BAD: will always be false } bool shortShort2(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (unsigned short)(n1 + delta) < n1; // BAD: n1 + delta overflow undefined + return (unsigned short)(n1 + delta) < n1; // GOOD } /* Distinguish `varname` from `ptr->varname` and `obj.varname` */ @@ -110,9 +110,14 @@ bool multipleCasts2(char x) { // clang 9.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD [FALSE POSITIVE] + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // BAD } int does_it_overflow(int n1, unsigned short delta) { return n1 + (unsigned)delta < n1; // GOOD } + +int overflow12b(int n) { + // not deleted by gcc or clang + return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD +} From e8dd0227ae01c54d8ff1dc9be39550f1cbf173c8 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Tue, 22 Oct 2019 14:27:43 -0700 Subject: [PATCH 0071/2538] C++: accept test changes --- .../dataflow-tests/test_diff.expected | 1 + .../dataflow/dataflow-tests/test_ir.expected | 2 - .../GlobalValueNumbering/ir_gvn.expected | 414 ++++++++++-------- 3 files changed, 226 insertions(+), 191 deletions(-) diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index a7aa78c03af6..aee4ac265058 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -1,3 +1,4 @@ +| clang.cpp:12:9:12:20 | clang.cpp:18:8:18:19 | AST only | | clang.cpp:12:9:12:20 | clang.cpp:22:8:22:20 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 83ba546480f9..ec1fc39b04e7 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -1,7 +1,5 @@ | acrossLinkTargets.cpp:12:8:12:8 | Convert: (int)... | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source | | acrossLinkTargets.cpp:12:8:12:8 | Load: x | acrossLinkTargets.cpp:19:27:19:32 | Call: call to source | -| clang.cpp:18:8:18:19 | Convert: (const int *)... | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 | -| clang.cpp:18:8:18:19 | Load: sourceArray1 | clang.cpp:12:9:12:20 | InitializeParameter: sourceArray1 | | clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source | | clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source | | clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 8be4cf4e2c11..3b386c2c1ec8 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -259,118 +259,136 @@ test.cpp: # 39| valnum = r0_7 # 39| m0_8(int *) = InitializeParameter[p2] : &:r0_7 # 39| valnum = m0_8 -# 40| r0_9(glval) = VariableAddress[x] : -# 40| valnum = r0_9 -# 40| m0_10(int) = Uninitialized[x] : &:r0_9 +# 39| r0_9(int *) = Load : &:r0_7, m0_8 +# 39| valnum = m0_8 +# 39| m0_10(unknown) = InitializeIndirection[p2] : &:r0_9 +# 39| valnum = unique +# 39| m0_11(unknown) = Chi : total:m0_1, partial:m0_10 +# 39| valnum = unique +# 40| r0_12(glval) = VariableAddress[x] : +# 40| valnum = r0_12 +# 40| m0_13(int) = Uninitialized[x] : &:r0_12 # 40| valnum = unique -# 40| r0_11(glval) = VariableAddress[y] : -# 40| valnum = r0_11 -# 40| m0_12(int) = Uninitialized[y] : &:r0_11 +# 40| r0_14(glval) = VariableAddress[y] : +# 40| valnum = r0_14 +# 40| m0_15(int) = Uninitialized[y] : &:r0_14 # 40| valnum = unique -# 41| r0_13(glval) = VariableAddress[b] : +# 41| r0_16(glval) = VariableAddress[b] : # 41| valnum = unique -# 41| m0_14(unsigned char) = Uninitialized[b] : &:r0_13 +# 41| m0_17(unsigned char) = Uninitialized[b] : &:r0_16 # 41| valnum = unique -# 43| r0_15(glval) = VariableAddress[p0] : +# 43| r0_18(glval) = VariableAddress[p0] : # 43| valnum = r0_3 -# 43| r0_16(int) = Load : &:r0_15, m0_4 +# 43| r0_19(int) = Load : &:r0_18, m0_4 # 43| valnum = m0_4 -# 43| r0_17(glval) = VariableAddress[p1] : +# 43| r0_20(glval) = VariableAddress[p1] : # 43| valnum = r0_5 -# 43| r0_18(int) = Load : &:r0_17, m0_6 +# 43| r0_21(int) = Load : &:r0_20, m0_6 # 43| valnum = m0_6 -# 43| r0_19(int) = Add : r0_16, r0_18 -# 43| valnum = r0_19 -# 43| r0_20(glval) = VariableAddress[global03] : -# 43| valnum = r0_20 -# 43| r0_21(int) = Load : &:r0_20, ~m0_1 -# 43| valnum = unique # 43| r0_22(int) = Add : r0_19, r0_21 # 43| valnum = r0_22 -# 43| r0_23(glval) = VariableAddress[x] : -# 43| valnum = r0_9 -# 43| m0_24(int) = Store : &:r0_23, r0_22 -# 43| valnum = r0_22 -# 44| r0_25(int) = Constant[0] : -# 44| valnum = r0_25 -# 44| r0_26(glval) = VariableAddress[p2] : +# 43| r0_23(glval) = VariableAddress[global03] : +# 43| valnum = r0_23 +# 43| r0_24(int) = Load : &:r0_23, ~m0_11 +# 43| valnum = unique +# 43| r0_25(int) = Add : r0_22, r0_24 +# 43| valnum = r0_25 +# 43| r0_26(glval) = VariableAddress[x] : +# 43| valnum = r0_12 +# 43| m0_27(int) = Store : &:r0_26, r0_25 +# 43| valnum = r0_25 +# 44| r0_28(int) = Constant[0] : +# 44| valnum = r0_28 +# 44| r0_29(glval) = VariableAddress[p2] : # 44| valnum = r0_7 -# 44| r0_27(int *) = Load : &:r0_26, m0_8 +# 44| r0_30(int *) = Load : &:r0_29, m0_8 # 44| valnum = m0_8 -# 44| m0_28(int) = Store : &:r0_27, r0_25 -# 44| valnum = r0_25 -# 44| m0_29(unknown) = Chi : total:m0_1, partial:m0_28 +# 44| m0_31(int) = Store : &:r0_30, r0_28 +# 44| valnum = r0_28 +# 44| m0_32(unknown) = Chi : total:m0_11, partial:m0_31 # 44| valnum = unique -# 45| r0_30(glval) = VariableAddress[p0] : +# 45| r0_33(glval) = VariableAddress[p0] : # 45| valnum = r0_3 -# 45| r0_31(int) = Load : &:r0_30, m0_4 +# 45| r0_34(int) = Load : &:r0_33, m0_4 # 45| valnum = m0_4 -# 45| r0_32(glval) = VariableAddress[p1] : +# 45| r0_35(glval) = VariableAddress[p1] : # 45| valnum = r0_5 -# 45| r0_33(int) = Load : &:r0_32, m0_6 +# 45| r0_36(int) = Load : &:r0_35, m0_6 # 45| valnum = m0_6 -# 45| r0_34(int) = Add : r0_31, r0_33 -# 45| valnum = r0_19 -# 45| r0_35(glval) = VariableAddress[global03] : -# 45| valnum = r0_20 -# 45| r0_36(int) = Load : &:r0_35, ~m0_29 -# 45| valnum = unique # 45| r0_37(int) = Add : r0_34, r0_36 -# 45| valnum = r0_37 -# 45| r0_38(glval) = VariableAddress[x] : -# 45| valnum = r0_9 -# 45| m0_39(int) = Store : &:r0_38, r0_37 -# 45| valnum = r0_37 -# 46| r0_40(glval) = VariableAddress[x] : -# 46| valnum = r0_9 -# 46| r0_41(int) = Load : &:r0_40, m0_39 -# 46| valnum = r0_37 -# 46| r0_42(glval) = VariableAddress[y] : -# 46| valnum = r0_11 -# 46| m0_43(int) = Store : &:r0_42, r0_41 -# 46| valnum = r0_37 -# 47| v0_44(void) = NoOp : -# 39| r0_45(glval) = VariableAddress[#return] : +# 45| valnum = r0_22 +# 45| r0_38(glval) = VariableAddress[global03] : +# 45| valnum = r0_23 +# 45| r0_39(int) = Load : &:r0_38, ~m0_32 +# 45| valnum = unique +# 45| r0_40(int) = Add : r0_37, r0_39 +# 45| valnum = r0_40 +# 45| r0_41(glval) = VariableAddress[x] : +# 45| valnum = r0_12 +# 45| m0_42(int) = Store : &:r0_41, r0_40 +# 45| valnum = r0_40 +# 46| r0_43(glval) = VariableAddress[x] : +# 46| valnum = r0_12 +# 46| r0_44(int) = Load : &:r0_43, m0_42 +# 46| valnum = r0_40 +# 46| r0_45(glval) = VariableAddress[y] : +# 46| valnum = r0_14 +# 46| m0_46(int) = Store : &:r0_45, r0_44 +# 46| valnum = r0_40 +# 47| v0_47(void) = NoOp : +# 39| r0_48(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_46(void) = ReturnValue : &:r0_45 -# 39| v0_47(void) = UnmodeledUse : mu* -# 39| v0_48(void) = ExitFunction : +# 39| v0_49(void) = ReturnValue : &:r0_48 +# 39| v0_50(void) = UnmodeledUse : mu* +# 39| v0_51(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 -# 49| v0_0(void) = EnterFunction : -# 49| m0_1(unknown) = AliasedDefinition : +# 49| v0_0(void) = EnterFunction : +# 49| m0_1(unknown) = AliasedDefinition : # 49| valnum = unique -# 49| mu0_2(unknown) = UnmodeledDefinition : +# 49| mu0_2(unknown) = UnmodeledDefinition : # 49| valnum = unique -# 49| r0_3(glval) = VariableAddress[str] : +# 49| r0_3(glval) = VariableAddress[str] : # 49| valnum = r0_3 -# 49| m0_4(char *) = InitializeParameter[str] : &:r0_3 +# 49| m0_4(char *) = InitializeParameter[str] : &:r0_3 +# 49| valnum = m0_4 +# 49| r0_5(char *) = Load : &:r0_3, m0_4 # 49| valnum = m0_4 -# 49| r0_5(glval) = VariableAddress[chars] : -# 49| valnum = r0_5 -# 49| m0_6(char *) = InitializeParameter[chars] : &:r0_5 -# 49| valnum = m0_6 -# 50| r0_7(glval) = VariableAddress[ptr] : -# 50| valnum = r0_7 -# 50| m0_8(char *) = Uninitialized[ptr] : &:r0_7 +# 49| m0_6(unknown) = InitializeIndirection[str] : &:r0_5 +# 49| valnum = unique +# 49| m0_7(unknown) = Chi : total:m0_1, partial:m0_6 +# 49| valnum = unique +# 49| r0_8(glval) = VariableAddress[chars] : +# 49| valnum = r0_8 +# 49| m0_9(char *) = InitializeParameter[chars] : &:r0_8 +# 49| valnum = m0_9 +# 49| r0_10(char *) = Load : &:r0_8, m0_9 +# 49| valnum = m0_9 +# 49| m0_11(unknown) = InitializeIndirection[chars] : &:r0_10 +# 49| valnum = unique +# 49| m0_12(unknown) = Chi : total:m0_7, partial:m0_11 +# 49| valnum = unique +# 50| r0_13(glval) = VariableAddress[ptr] : +# 50| valnum = r0_13 +# 50| m0_14(char *) = Uninitialized[ptr] : &:r0_13 # 50| valnum = unique -# 51| r0_9(glval) = VariableAddress[result] : -# 51| valnum = r0_9 -# 51| r0_10(unsigned int) = Constant[0] : -# 51| valnum = r0_10 -# 51| m0_11(unsigned int) = Store : &:r0_9, r0_10 -# 51| valnum = r0_10 +# 51| r0_15(glval) = VariableAddress[result] : +# 51| valnum = r0_15 +# 51| r0_16(unsigned int) = Constant[0] : +# 51| valnum = r0_16 +# 51| m0_17(unsigned int) = Store : &:r0_15, r0_16 +# 51| valnum = r0_16 #-----| Goto -> Block 1 # 53| Block 1 -# 53| m1_0(unsigned int) = Phi : from 0:m0_11, from 8:m8_4 +# 53| m1_0(unsigned int) = Phi : from 0:m0_17, from 8:m8_4 # 53| valnum = m1_0 # 53| r1_1(glval) = VariableAddress[str] : # 53| valnum = r0_3 # 53| r1_2(char *) = Load : &:r1_1, m0_4 # 53| valnum = m0_4 -# 53| r1_3(char) = Load : &:r1_2, ~m0_1 +# 53| r1_3(char) = Load : &:r1_2, ~m0_12 # 53| valnum = unique # 53| r1_4(int) = Convert : r1_3 # 53| valnum = unique @@ -384,23 +402,23 @@ test.cpp: # 55| Block 2 # 55| r2_0(glval) = VariableAddress[chars] : -# 55| valnum = r0_5 -# 55| r2_1(char *) = Load : &:r2_0, m0_6 -# 55| valnum = m0_6 +# 55| valnum = r0_8 +# 55| r2_1(char *) = Load : &:r2_0, m0_9 +# 55| valnum = m0_9 # 55| r2_2(glval) = VariableAddress[ptr] : -# 55| valnum = r0_7 +# 55| valnum = r0_13 # 55| m2_3(char *) = Store : &:r2_2, r2_1 -# 55| valnum = m0_6 +# 55| valnum = m0_9 #-----| Goto -> Block 3 # 56| Block 3 # 56| m3_0(char *) = Phi : from 2:m2_3, from 5:m5_4 # 56| valnum = m3_0 # 56| r3_1(glval) = VariableAddress[ptr] : -# 56| valnum = r0_7 +# 56| valnum = r0_13 # 56| r3_2(char *) = Load : &:r3_1, m3_0 # 56| valnum = m3_0 -# 56| r3_3(char) = Load : &:r3_2, ~m0_1 +# 56| r3_3(char) = Load : &:r3_2, ~m0_12 # 56| valnum = unique # 56| r3_4(int) = Convert : r3_3 # 56| valnum = unique @@ -408,7 +426,7 @@ test.cpp: # 56| valnum = r0_3 # 56| r3_6(char *) = Load : &:r3_5, m0_4 # 56| valnum = m0_4 -# 56| r3_7(char) = Load : &:r3_6, ~m0_1 +# 56| r3_7(char) = Load : &:r3_6, ~m0_12 # 56| valnum = unique # 56| r3_8(int) = Convert : r3_7 # 56| valnum = unique @@ -420,10 +438,10 @@ test.cpp: # 56| Block 4 # 56| r4_0(glval) = VariableAddress[ptr] : -# 56| valnum = r0_7 +# 56| valnum = r0_13 # 56| r4_1(char *) = Load : &:r4_0, m3_0 # 56| valnum = m3_0 -# 56| r4_2(char) = Load : &:r4_1, ~m0_1 +# 56| r4_2(char) = Load : &:r4_1, ~m0_12 # 56| valnum = unique # 56| r4_3(int) = Convert : r4_2 # 56| valnum = unique @@ -437,7 +455,7 @@ test.cpp: # 56| Block 5 # 56| r5_0(glval) = VariableAddress[ptr] : -# 56| valnum = r0_7 +# 56| valnum = r0_13 # 56| r5_1(char *) = Load : &:r5_0, m3_0 # 56| valnum = m3_0 # 56| r5_2(int) = Constant[1] : @@ -450,10 +468,10 @@ test.cpp: # 59| Block 6 # 59| r6_0(glval) = VariableAddress[ptr] : -# 59| valnum = r0_7 +# 59| valnum = r0_13 # 59| r6_1(char *) = Load : &:r6_0, m3_0 # 59| valnum = m3_0 -# 59| r6_2(char) = Load : &:r6_1, ~m0_1 +# 59| r6_2(char) = Load : &:r6_1, ~m0_12 # 59| valnum = unique # 59| r6_3(int) = Convert : r6_2 # 59| valnum = unique @@ -471,7 +489,7 @@ test.cpp: # 62| Block 8 # 62| r8_0(glval) = VariableAddress[result] : -# 62| valnum = r0_9 +# 62| valnum = r0_15 # 62| r8_1(unsigned int) = Load : &:r8_0, m1_0 # 62| valnum = m1_0 # 62| r8_2(unsigned int) = Constant[1] : @@ -487,7 +505,7 @@ test.cpp: # 65| r9_1(glval) = VariableAddress[#return] : # 65| valnum = r9_1 # 65| r9_2(glval) = VariableAddress[result] : -# 65| valnum = r0_9 +# 65| valnum = r0_15 # 65| r9_3(unsigned int) = Load : &:r9_2, m1_0 # 65| valnum = m1_0 # 65| m9_4(unsigned int) = Store : &:r9_1, r9_3 @@ -500,60 +518,66 @@ test.cpp: # 75| void test04(two_values*) # 75| Block 0 -# 75| v0_0(void) = EnterFunction : -# 75| m0_1(unknown) = AliasedDefinition : +# 75| v0_0(void) = EnterFunction : +# 75| m0_1(unknown) = AliasedDefinition : # 75| valnum = unique -# 75| mu0_2(unknown) = UnmodeledDefinition : +# 75| mu0_2(unknown) = UnmodeledDefinition : # 75| valnum = unique -# 75| r0_3(glval) = VariableAddress[vals] : +# 75| r0_3(glval) = VariableAddress[vals] : # 75| valnum = r0_3 -# 75| m0_4(two_values *) = InitializeParameter[vals] : &:r0_3 +# 75| m0_4(two_values *) = InitializeParameter[vals] : &:r0_3 +# 75| valnum = m0_4 +# 75| r0_5(two_values *) = Load : &:r0_3, m0_4 # 75| valnum = m0_4 -# 77| r0_5(glval) = VariableAddress[v] : -# 77| valnum = r0_5 -# 77| r0_6(glval) = FunctionAddress[getAValue] : +# 75| m0_6(unknown) = InitializeIndirection[vals] : &:r0_5 +# 75| valnum = unique +# 75| m0_7(unknown) = Chi : total:m0_1, partial:m0_6 +# 75| valnum = unique +# 77| r0_8(glval) = VariableAddress[v] : +# 77| valnum = r0_8 +# 77| r0_9(glval) = FunctionAddress[getAValue] : # 77| valnum = unique -# 77| r0_7(int) = Call : func:r0_6 +# 77| r0_10(int) = Call : func:r0_9 # 77| valnum = unique -# 77| m0_8(unknown) = ^CallSideEffect : ~m0_1 +# 77| m0_11(unknown) = ^CallSideEffect : ~m0_7 # 77| valnum = unique -# 77| m0_9(unknown) = Chi : total:m0_1, partial:m0_8 +# 77| m0_12(unknown) = Chi : total:m0_7, partial:m0_11 # 77| valnum = unique -# 77| r0_10(signed short) = Convert : r0_7 -# 77| valnum = r0_10 -# 77| m0_11(signed short) = Store : &:r0_5, r0_10 -# 77| valnum = r0_10 -# 79| r0_12(glval) = VariableAddress[v] : -# 79| valnum = r0_5 -# 79| r0_13(signed short) = Load : &:r0_12, m0_11 -# 79| valnum = r0_10 -# 79| r0_14(int) = Convert : r0_13 +# 77| r0_13(signed short) = Convert : r0_10 +# 77| valnum = r0_13 +# 77| m0_14(signed short) = Store : &:r0_8, r0_13 +# 77| valnum = r0_13 +# 79| r0_15(glval) = VariableAddress[v] : +# 79| valnum = r0_8 +# 79| r0_16(signed short) = Load : &:r0_15, m0_14 +# 79| valnum = r0_13 +# 79| r0_17(int) = Convert : r0_16 # 79| valnum = unique -# 79| r0_15(glval) = VariableAddress[vals] : +# 79| r0_18(glval) = VariableAddress[vals] : # 79| valnum = r0_3 -# 79| r0_16(two_values *) = Load : &:r0_15, m0_4 +# 79| r0_19(two_values *) = Load : &:r0_18, m0_4 # 79| valnum = m0_4 -# 79| r0_17(glval) = FieldAddress[val1] : r0_16 +# 79| r0_20(glval) = FieldAddress[val1] : r0_19 # 79| valnum = unique -# 79| r0_18(signed short) = Load : &:r0_17, ~m0_9 +# 79| r0_21(signed short) = Load : &:r0_20, ~m0_12 # 79| valnum = unique -# 79| r0_19(int) = Convert : r0_18 +# 79| r0_22(int) = Convert : r0_21 # 79| valnum = unique -# 79| r0_20(glval) = VariableAddress[vals] : +# 79| r0_23(glval) = VariableAddress[vals] : # 79| valnum = r0_3 -# 79| r0_21(two_values *) = Load : &:r0_20, m0_4 +# 79| r0_24(two_values *) = Load : &:r0_23, m0_4 # 79| valnum = m0_4 -# 79| r0_22(glval) = FieldAddress[val2] : r0_21 +# 79| r0_25(glval) = FieldAddress[val2] : r0_24 # 79| valnum = unique -# 79| r0_23(signed short) = Load : &:r0_22, ~m0_9 +# 79| r0_26(signed short) = Load : &:r0_25, ~m0_12 # 79| valnum = unique -# 79| r0_24(int) = Convert : r0_23 +# 79| r0_27(int) = Convert : r0_26 # 79| valnum = unique -# 79| r0_25(int) = Add : r0_19, r0_24 +# 79| r0_28(int) = Add : r0_22, r0_27 # 79| valnum = unique -# 79| r0_26(bool) = CompareLT : r0_14, r0_25 +# 79| r0_29(bool) = CompareLT : r0_17, r0_28 # 79| valnum = unique -# 79| v0_27(void) = ConditionalBranch : r0_26 +# 79| v0_30(void) = ConditionalBranch : r0_29 #-----| False -> Block 2 #-----| True -> Block 1 @@ -562,14 +586,14 @@ test.cpp: # 80| valnum = unique # 80| r1_1(int) = Call : func:r1_0 # 80| valnum = unique -# 80| m1_2(unknown) = ^CallSideEffect : ~m0_9 +# 80| m1_2(unknown) = ^CallSideEffect : ~m0_12 # 80| valnum = unique -# 80| m1_3(unknown) = Chi : total:m0_9, partial:m1_2 +# 80| m1_3(unknown) = Chi : total:m0_12, partial:m1_2 # 80| valnum = unique # 80| r1_4(signed short) = Convert : r1_1 # 80| valnum = r1_4 # 80| r1_5(glval) = VariableAddress[v] : -# 80| valnum = r0_5 +# 80| valnum = r0_8 # 80| m1_6(signed short) = Store : &:r1_5, r1_4 # 80| valnum = r1_4 #-----| Goto -> Block 2 @@ -582,36 +606,42 @@ test.cpp: # 84| void test05(int, int, void*) # 84| Block 0 -# 84| v0_0(void) = EnterFunction : -# 84| m0_1(unknown) = AliasedDefinition : +# 84| v0_0(void) = EnterFunction : +# 84| m0_1(unknown) = AliasedDefinition : # 84| valnum = unique -# 84| mu0_2(unknown) = UnmodeledDefinition : +# 84| mu0_2(unknown) = UnmodeledDefinition : # 84| valnum = unique -# 84| r0_3(glval) = VariableAddress[x] : +# 84| r0_3(glval) = VariableAddress[x] : # 84| valnum = r0_3 -# 84| m0_4(int) = InitializeParameter[x] : &:r0_3 +# 84| m0_4(int) = InitializeParameter[x] : &:r0_3 # 84| valnum = m0_4 -# 84| r0_5(glval) = VariableAddress[y] : +# 84| r0_5(glval) = VariableAddress[y] : # 84| valnum = r0_5 -# 84| m0_6(int) = InitializeParameter[y] : &:r0_5 +# 84| m0_6(int) = InitializeParameter[y] : &:r0_5 # 84| valnum = m0_6 -# 84| r0_7(glval) = VariableAddress[p] : +# 84| r0_7(glval) = VariableAddress[p] : # 84| valnum = r0_7 -# 84| m0_8(void *) = InitializeParameter[p] : &:r0_7 +# 84| m0_8(void *) = InitializeParameter[p] : &:r0_7 +# 84| valnum = m0_8 +# 84| r0_9(void *) = Load : &:r0_7, m0_8 # 84| valnum = m0_8 -# 86| r0_9(glval) = VariableAddress[v] : -# 86| valnum = r0_9 -# 86| m0_10(int) = Uninitialized[v] : &:r0_9 +# 84| m0_10(unknown) = InitializeIndirection[p] : &:r0_9 +# 84| valnum = unique +# 84| m0_11(unknown) = Chi : total:m0_1, partial:m0_10 +# 84| valnum = unique +# 86| r0_12(glval) = VariableAddress[v] : +# 86| valnum = r0_12 +# 86| m0_13(int) = Uninitialized[v] : &:r0_12 # 86| valnum = unique -# 88| r0_11(glval) = VariableAddress[p] : +# 88| r0_14(glval) = VariableAddress[p] : # 88| valnum = r0_7 -# 88| r0_12(void *) = Load : &:r0_11, m0_8 +# 88| r0_15(void *) = Load : &:r0_14, m0_8 # 88| valnum = m0_8 -# 88| r0_13(void *) = Constant[0] : +# 88| r0_16(void *) = Constant[0] : # 88| valnum = unique -# 88| r0_14(bool) = CompareNE : r0_12, r0_13 +# 88| r0_17(bool) = CompareNE : r0_15, r0_16 # 88| valnum = unique -# 88| v0_15(void) = ConditionalBranch : r0_14 +# 88| v0_18(void) = ConditionalBranch : r0_17 #-----| False -> Block 2 #-----| True -> Block 1 @@ -645,7 +675,7 @@ test.cpp: # 88| r3_2(int) = Load : &:r3_1, m3_0 # 88| valnum = m3_0 # 88| r3_3(glval) = VariableAddress[v] : -# 88| valnum = r0_9 +# 88| valnum = r0_12 # 88| m3_4(int) = Store : &:r3_3, r3_2 # 88| valnum = m3_0 # 89| v3_5(void) = NoOp : @@ -695,55 +725,61 @@ test.cpp: # 104| valnum = r0_3 # 104| m0_4(Derived *) = InitializeParameter[pd] : &:r0_3 # 104| valnum = m0_4 -# 105| r0_5(glval) = VariableAddress[x] : +# 104| r0_5(Derived *) = Load : &:r0_3, m0_4 +# 104| valnum = m0_4 +# 104| m0_6(unknown) = InitializeIndirection[pd] : &:r0_5 +# 104| valnum = unique +# 104| m0_7(unknown) = Chi : total:m0_1, partial:m0_6 +# 104| valnum = unique +# 105| r0_8(glval) = VariableAddress[x] : # 105| valnum = unique -# 105| r0_6(glval) = VariableAddress[pd] : +# 105| r0_9(glval) = VariableAddress[pd] : # 105| valnum = r0_3 -# 105| r0_7(Derived *) = Load : &:r0_6, m0_4 +# 105| r0_10(Derived *) = Load : &:r0_9, m0_4 # 105| valnum = m0_4 -# 105| r0_8(Base *) = ConvertToBase[Derived : Base] : r0_7 -# 105| valnum = r0_8 -# 105| r0_9(glval) = FieldAddress[b] : r0_8 -# 105| valnum = r0_9 -# 105| r0_10(int) = Load : &:r0_9, ~m0_1 -# 105| valnum = r0_10 -# 105| m0_11(int) = Store : &:r0_5, r0_10 -# 105| valnum = r0_10 -# 106| r0_12(glval) = VariableAddress[pb] : -# 106| valnum = r0_12 -# 106| r0_13(glval) = VariableAddress[pd] : +# 105| r0_11(Base *) = ConvertToBase[Derived : Base] : r0_10 +# 105| valnum = r0_11 +# 105| r0_12(glval) = FieldAddress[b] : r0_11 +# 105| valnum = r0_12 +# 105| r0_13(int) = Load : &:r0_12, ~m0_7 +# 105| valnum = r0_13 +# 105| m0_14(int) = Store : &:r0_8, r0_13 +# 105| valnum = r0_13 +# 106| r0_15(glval) = VariableAddress[pb] : +# 106| valnum = r0_15 +# 106| r0_16(glval) = VariableAddress[pd] : # 106| valnum = r0_3 -# 106| r0_14(Derived *) = Load : &:r0_13, m0_4 +# 106| r0_17(Derived *) = Load : &:r0_16, m0_4 # 106| valnum = m0_4 -# 106| r0_15(Base *) = ConvertToBase[Derived : Base] : r0_14 -# 106| valnum = r0_8 -# 106| m0_16(Base *) = Store : &:r0_12, r0_15 -# 106| valnum = r0_8 -# 107| r0_17(glval) = VariableAddress[y] : -# 107| valnum = r0_17 -# 107| r0_18(glval) = VariableAddress[pb] : +# 106| r0_18(Base *) = ConvertToBase[Derived : Base] : r0_17 +# 106| valnum = r0_11 +# 106| m0_19(Base *) = Store : &:r0_15, r0_18 +# 106| valnum = r0_11 +# 107| r0_20(glval) = VariableAddress[y] : +# 107| valnum = r0_20 +# 107| r0_21(glval) = VariableAddress[pb] : +# 107| valnum = r0_15 +# 107| r0_22(Base *) = Load : &:r0_21, m0_19 +# 107| valnum = r0_11 +# 107| r0_23(glval) = FieldAddress[b] : r0_22 # 107| valnum = r0_12 -# 107| r0_19(Base *) = Load : &:r0_18, m0_16 -# 107| valnum = r0_8 -# 107| r0_20(glval) = FieldAddress[b] : r0_19 -# 107| valnum = r0_9 -# 107| r0_21(int) = Load : &:r0_20, ~m0_1 -# 107| valnum = r0_21 -# 107| m0_22(int) = Store : &:r0_17, r0_21 -# 107| valnum = r0_21 -# 109| r0_23(glval) = VariableAddress[#return] : -# 109| valnum = r0_23 -# 109| r0_24(glval) = VariableAddress[y] : -# 109| valnum = r0_17 -# 109| r0_25(int) = Load : &:r0_24, m0_22 -# 109| valnum = r0_21 -# 109| m0_26(int) = Store : &:r0_23, r0_25 -# 109| valnum = r0_21 -# 104| r0_27(glval) = VariableAddress[#return] : -# 104| valnum = r0_23 -# 104| v0_28(void) = ReturnValue : &:r0_27, m0_26 -# 104| v0_29(void) = UnmodeledUse : mu* -# 104| v0_30(void) = ExitFunction : +# 107| r0_24(int) = Load : &:r0_23, ~m0_7 +# 107| valnum = r0_24 +# 107| m0_25(int) = Store : &:r0_20, r0_24 +# 107| valnum = r0_24 +# 109| r0_26(glval) = VariableAddress[#return] : +# 109| valnum = r0_26 +# 109| r0_27(glval) = VariableAddress[y] : +# 109| valnum = r0_20 +# 109| r0_28(int) = Load : &:r0_27, m0_25 +# 109| valnum = r0_24 +# 109| m0_29(int) = Store : &:r0_26, r0_28 +# 109| valnum = r0_24 +# 104| r0_30(glval) = VariableAddress[#return] : +# 104| valnum = r0_26 +# 104| v0_31(void) = ReturnValue : &:r0_30, m0_29 +# 104| v0_32(void) = UnmodeledUse : mu* +# 104| v0_33(void) = ExitFunction : # 112| void test06() # 112| Block 0 From ad5aa182dfb0b4e8a6342c66c527a4265aae6d3b Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 22 Oct 2019 15:21:30 -0700 Subject: [PATCH 0072/2538] [CPP-434] When analyzing overflow, discard any explicit casts. Use the simple range analysis library to detect which additions may in fact overflow. --- .../Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 15 ++++----------- .../SignedOverflowCheck.cpp | 12 ++++++------ .../SignedOverflowCheck.expected | 7 +------ .../Arithmetic/BadAdditionOverflowCheck/test.cpp | 4 ++-- 4 files changed, 13 insertions(+), 25 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 387a9397e43a..f1b65dd4a967 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -12,16 +12,8 @@ */ import cpp -import semmle.code.cpp.valuenumbering.GlobalValueNumbering - -private predicate isSignedWithoutUnsignedCast(Expr e) { - e.getType().getUnspecifiedType().(IntegralType).isSigned() - /* - * and - * not e.getExplicitlyConverted().getType().getUnspecifiedType().(IntegralType).isUnsigned() - */ - - } +private import semmle.code.cpp.valuenumbering.GlobalValueNumbering +private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 where @@ -29,5 +21,6 @@ where add.getAnOperand() = va1 and ro.getAnOperand() = va2 and globalValueNumber(va1) = globalValueNumber(va2) and - isSignedWithoutUnsignedCast(add) + add.getType().getUnspecifiedType().(IntegralType).isSigned() and + exprMightOverflowPositively(add) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index af6593dc0c39..72767c54aab5 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -32,7 +32,7 @@ bool shortShort1(unsigned short n1, unsigned short delta) { // clang 8.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // BAD: will always be false + return n1 + delta < n1; // GOOD: always false, but will never overflow } bool shortShort2(unsigned short n1, unsigned short delta) { @@ -96,28 +96,28 @@ int checkOverflow4(unsigned int ioff, C c) { int overflow12(int n) { // not deleted by gcc or clang - return (n + 32 <= (unsigned)n? -1: 1); // BAD + return (n + 32 <= (unsigned)n? -1: 1); // BAD: n + 32 can overflow } bool multipleCasts(char x) { // clang 9.0.0 -O2: deleted // gcc 9.2 -O2: deleted // msvc 19.22 /O2: deleted - return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // BAD + return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow } bool multipleCasts2(char x) { // clang 9.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted // msvc 19.22 /O2: not deleted - return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // BAD + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD: cannot overflow } int does_it_overflow(int n1, unsigned short delta) { - return n1 + (unsigned)delta < n1; // GOOD + return n1 + (unsigned)delta < n1; // GOOD: everything converted to unsigned } int overflow12b(int n) { // not deleted by gcc or clang - return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD + return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index 9f35d51c4e31..eaf6a7ac1e4d 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -1,9 +1,4 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:35:9:35:23 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:42:9:42:41 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:106:12:106:62 | ... < ... | Testing for signed overflow may produce undefined results. | -| SignedOverflowCheck.cpp:113:12:113:66 | ... < ... | Testing for signed overflow may produce undefined results. | -| test.cpp:3:11:3:19 | ... < ... | Testing for signed overflow may produce undefined results. | -| test.cpp:8:11:8:37 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp index 3c82f602cb9e..e36956f9c690 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/test.cpp @@ -1,11 +1,11 @@ // Test for BadAdditionOverflowCheck. bool checkOverflow1(unsigned short a, unsigned short b) { - return (a + b < a); // BAD: a + b is automatically promoted to int. + return (a + b < a); // BAD: comparison always false (due to promotion). } // Test for BadAdditionOverflowCheck. bool checkOverflow2(unsigned short a, unsigned short b) { - return ((unsigned short)(a + b) < a); // BAD: a + b overflow undefined + return ((unsigned short)(a + b) < a); // GOOD } // Test for PointlessSelfComparison. From 6eb0f0709ae6e191a15c831d0708c9f187580d5d Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 22 Oct 2019 17:28:35 -0700 Subject: [PATCH 0073/2538] [CPP-434] Update Qhelp. --- .../Arithmetic/SignedOverflowCheck-bad2.cpp | 3 ++- .../Arithmetic/SignedOverflowCheck.qhelp | 20 ++++++++++--------- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp index 293a8c6e49e2..d4d9cd75393b 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -1,3 +1,4 @@ bool bar(unsigned short n1, unsigned short delta) { - return n1 + delta < n1; // BAD + // NB: Comparison is always false + return n1 + delta < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 741dda54a820..9b9d358dea2b 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,17 +22,19 @@ In the following example, even though delta has been declared unsigned short, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, namely a signed int. As a result, the entire expression is -evaluated using signed values and its value is therefore undefined. +evaluated using signed integers and may overflow, and hence +is undefined.

    In the following example, even though both n and delta -have been declared unsigned short, C/C++ type promotion rules -require that both parameters be promoted to the next bigger signed -integer type (in this case signed int) before being added together. -As a result, the entire expression is evaluated using signed values -and its value is therefore undefined. (Note, however, that the addition cannot -overflow since we are adding two "small" unsigned short values.) +have been declared unsigned short, both are promoted to +signed int prior to addition. Because we started out with the +narrower short type, the addition is guaranteed not to overflow +and is therefore defined. But the fact that n1 + delta never +overflows means that the condition n1 + delta < n1 will never +hold true, which likely is not what the programmer intended. (see also the +BadArithmeticOverflow.Check.ql query).

    @@ -40,7 +42,7 @@ The following example builds upon the previous one. Again, we have two unsigned short values getting promoted to a wider type. However, since delta is explicitly cast to an unsigned type, n1 (on both sides of the comparison) is promoted to -unsigned as well. Since we are now operating on +unsigned int as well. Since we are now operating on unsigned values, the overflow check is defined and supported by standard C/C++.

    @@ -48,7 +50,7 @@ standard C/C++.

    In the next example, a value of type signed int is added to a value of type unsigned int. Because -the types are of the same size, C/C++ promotion rules dictate that +the types are of the same size, C/C++ conversion rules dictate that unsigned int is chosen as the overall type of the addition operation. The entire expression is evaluated using unsigned values, which is allowed and defined behavior per the C/C++ standard. From 7a6ec83572aa387e042328328b2607148dc19410 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 23 Oct 2019 11:50:58 +0200 Subject: [PATCH 0074/2538] C++: No CopyValue for immediately discarded exprs Expressions like the `e` in `e;` or `e, e2`, whose result is immediately discarded, should not get a synthetic `CopyValue`. This removes a lot of redundancy from the IR. To prevent these expressions from being confused with the expressions from which they get their result, the predicate `getInstructionConvertedResultExpression` now suppresses results for expressions that don't produce their own result. This should fix the mapping between expressions and IR data-flow nodes. --- .../raw/internal/IRConstruction.qll | 11 +- .../raw/internal/TranslatedExpr.qll | 60 +- .../ir/escape/points_to.expected | 19 - .../test/library-tests/ir/ir/raw_ir.expected | 2120 ++++++++--------- .../ir/ssa/aliased_ssa_ir.expected | 83 +- .../ir/ssa/unaliased_ssa_ir.expected | 83 +- .../syntax-zoo/aliased_ssa_sanity.expected | 2 +- .../syntax-zoo/raw_sanity.expected | 13 +- .../syntax-zoo/unaliased_ssa_sanity.expected | 2 +- 9 files changed, 1092 insertions(+), 1301 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index 314eda43a4cd..d0f70f614983 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -49,20 +49,23 @@ private module Cached { Expr getInstructionConvertedResultExpression(Instruction instruction) { exists(TranslatedExpr translatedExpr | translatedExpr = getTranslatedExpr(result) and - instruction = translatedExpr.getResult() + instruction = translatedExpr.getResult() and + // Only associate `instruction` with this expression if the translated + // expression actually produced the instruction; not if it merely + // forwarded the result of another translated expression. + instruction = translatedExpr.getInstruction(_) ) } cached Expr getInstructionUnconvertedResultExpression(Instruction instruction) { - exists(Expr converted, TranslatedExpr translatedExpr | + exists(Expr converted | result = converted.(Conversion).getExpr+() or result = converted | not result instanceof Conversion and - translatedExpr = getTranslatedExpr(converted) and - instruction = translatedExpr.getResult() + converted = getInstructionConvertedResultExpression(instruction) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll index fbecb10cd242..7b9417b570db 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll @@ -2547,27 +2547,45 @@ class TranslatedErrorExpr extends TranslatedSingleInstructionExpr { // This should ideally be a dispatch predicate on TranslatedNonConstantExpr, // but it doesn't look monotonic to QL. predicate exprNeedsCopyIfNotLoaded(Expr expr) { - expr instanceof AssignExpr - or - expr instanceof AssignOperation and - not expr.isPRValueCategory() // is C++ - or - expr instanceof PrefixCrementOperation and - not expr.isPRValueCategory() // is C++ - or - expr instanceof PointerDereferenceExpr - or - expr instanceof AddressOfExpr - or - expr instanceof BuiltInOperationBuiltInAddressOf - or - // No case for ParenthesisExpr to avoid getting too many instructions - expr instanceof ReferenceDereferenceExpr - or - expr instanceof ReferenceToExpr + ( + expr instanceof AssignExpr + or + expr instanceof AssignOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PrefixCrementOperation and + not expr.isPRValueCategory() // is C++ + or + expr instanceof PointerDereferenceExpr + or + expr instanceof AddressOfExpr + or + expr instanceof BuiltInOperationBuiltInAddressOf + or + // No case for ParenthesisExpr to avoid getting too many instructions + expr instanceof ReferenceDereferenceExpr + or + expr instanceof ReferenceToExpr + or + expr instanceof CommaExpr + or + expr instanceof ConditionDeclExpr + // TODO: simplify TranslatedStmtExpr too + ) and + not exprImmediatelyDiscarded(expr) +} + +/** + * Holds if `expr` is immediately discarded. Such expressions do not need a + * `CopyValue` because it's unlikely that anyone is interested in their value. + */ +private predicate exprImmediatelyDiscarded(Expr expr) { + exists(ExprStmt s | + s = expr.getParent() and + not exists(StmtExpr se | s = se.getStmt().(Block).getLastStmt()) + ) or - expr instanceof CommaExpr + exists(CommaExpr c | c.getLeftOperand() = expr) or - expr instanceof ConditionDeclExpr - // TODO: simplify TranslatedStmtExpr too + exists(ForStmt for | for.getUpdate() = expr) } diff --git a/cpp/ql/test/library-tests/ir/escape/points_to.expected b/cpp/ql/test/library-tests/ir/escape/points_to.expected index e6fefda7bb55..c58d97f79881 100644 --- a/cpp/ql/test/library-tests/ir/escape/points_to.expected +++ b/cpp/ql/test/library-tests/ir/escape/points_to.expected @@ -1,24 +1,14 @@ -| escape.cpp:108:5:108:11 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:109:5:109:13 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:110:5:110:19 | CopyValue | no_result+0:0 | no_result+0:0 | -| escape.cpp:111:5:111:21 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:111:18:111:21 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:114:5:114:8 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:115:5:115:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:115:19:115:28 | PointerAdd[4] | no_+0:0 | no_+0:0 | | escape.cpp:115:20:115:23 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:116:5:116:29 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:116:19:116:28 | PointerSub[4] | no_+0:0 | no_+0:0 | | escape.cpp:116:20:116:23 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:117:5:117:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:117:19:117:26 | PointerAdd[4] | no_+0:0 | no_+0:0 | | escape.cpp:117:23:117:26 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:118:9:118:12 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:120:12:120:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:123:14:123:17 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:124:9:124:12 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:124:15:124:18 | CopyValue | no_+0:0 | no_+0:0 | -| escape.cpp:124:21:124:24 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:127:9:127:12 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:129:12:129:15 | CopyValue | no_+0:0 | no_+0:0 | | escape.cpp:134:5:134:18 | Convert | no_Array+0:0 | no_Array+0:0 | @@ -27,38 +17,31 @@ | escape.cpp:135:5:135:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:5:136:15 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:136:7:136:14 | Convert | no_Array+0:0 | no_Array+0:0 | -| escape.cpp:137:5:137:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:137:17:137:24 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:137:17:137:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | -| escape.cpp:138:5:138:27 | CopyValue | no_result+0:0 | no_result+0:0 | | escape.cpp:138:17:138:27 | PointerAdd[4] | no_Array+20:0 | no_Array+20:0 | | escape.cpp:138:19:138:26 | Convert | no_Array+0:0 | no_Array+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | | escape.cpp:140:21:140:32 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:140:21:140:32 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:141:27:141:27 | FieldAddress[x] | no_Point+0:0 | no_Point+0:0 | -| escape.cpp:142:5:142:21 | CopyValue | no_Point+4:0 | no_Point+4:0 | | escape.cpp:142:14:142:14 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:143:19:143:27 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:143:31:143:31 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | -| escape.cpp:144:5:144:25 | CopyValue | no_Point+4:0 | no_Point+4:0 | | escape.cpp:144:6:144:14 | CopyValue | no_Point+0:0 | no_Point+0:0 | | escape.cpp:144:18:144:18 | FieldAddress[y] | no_Point+4:0 | no_Point+4:0 | | escape.cpp:145:20:145:30 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:145:30:145:30 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:5:146:18 | CopyValue | no_Point+8:0 | no_Point+8:0 | -| escape.cpp:146:5:146:25 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:7:146:17 | CopyValue | no_Point+8:0 | no_Point+8:0 | | escape.cpp:146:17:146:17 | FieldAddress[z] | no_Point+8:0 | no_Point+8:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:5:149:14 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | -| escape.cpp:149:5:149:20 | CopyValue | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:149:16:149:16 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Derived : Intermediate1] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:18:150:27 | ConvertToBase[Intermediate1 : Base] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:150:29:150:29 | FieldAddress[b] | no_Derived+0:0 | no_Derived+0:0 | | escape.cpp:151:5:151:14 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | -| escape.cpp:151:5:151:21 | CopyValue | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:151:16:151:17 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | | escape.cpp:152:19:152:28 | ConvertToBase[Derived : Intermediate2] | no_Derived+12:0 | no_Derived+12:0 | | escape.cpp:152:30:152:31 | FieldAddress[i2] | no_Derived+16:0 | no_Derived+16:0 | @@ -97,9 +80,7 @@ | escape.cpp:217:14:217:16 | CopyValue | c2+0:0 | c2+0:0 | | escape.cpp:221:8:221:19 | Call | none | c3+0:0 | | escape.cpp:225:17:225:28 | Call | none | c4+0:0 | -| escape.cpp:247:2:247:27 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:247:2:247:27 | Store | condEscape1+0:0 | condEscape1+0:0 | | escape.cpp:247:16:247:27 | CopyValue | condEscape1+0:0 | condEscape1+0:0 | -| escape.cpp:249:9:249:34 | CopyValue | no_condTemp+0:0 | no_condTemp+0:0 | | escape.cpp:249:9:249:34 | Store | condEscape2+0:0 | condEscape2+0:0 | | escape.cpp:249:23:249:34 | CopyValue | condEscape2+0:0 | condEscape2+0:0 | diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 9c80e889a020..d7c144f7181e 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -66,11 +66,10 @@ bad_asts.cpp: #-----| r0_10(error) = Load : &:r0_9, ~mu0_2 # 33| r0_11(glval) = VariableAddress[x] : # 33| mu0_12(int) = Store : &:r0_11, r0_10 -# 33| r0_13(glval) = CopyValue : r0_11 -# 34| v0_14(void) = NoOp : -# 30| v0_15(void) = ReturnVoid : -# 30| v0_16(void) = UnmodeledUse : mu* -# 30| v0_17(void) = ExitFunction : +# 34| v0_13(void) = NoOp : +# 30| v0_14(void) = ReturnVoid : +# 30| v0_15(void) = UnmodeledUse : mu* +# 30| v0_16(void) = ExitFunction : clang.cpp: # 5| int* globalIntAddress() @@ -202,20 +201,18 @@ ir.cpp: # 46| r0_15(short) = Convert : r0_14 # 46| r0_16(glval) = VariableAddress[y] : # 46| mu0_17(short) = Store : &:r0_16, r0_15 -# 46| r0_18(glval) = CopyValue : r0_16 -# 47| r0_19(glval) = VariableAddress[x] : -# 47| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 47| r0_21(glval) = VariableAddress[y] : -# 47| r0_22(short) = Load : &:r0_21, ~mu0_2 -# 47| r0_23(int) = Convert : r0_22 -# 47| r0_24(int) = Mul : r0_20, r0_23 -# 47| r0_25(glval) = VariableAddress[x] : -# 47| mu0_26(int) = Store : &:r0_25, r0_24 -# 47| r0_27(glval) = CopyValue : r0_25 -# 48| v0_28(void) = NoOp : -# 43| v0_29(void) = ReturnVoid : -# 43| v0_30(void) = UnmodeledUse : mu* -# 43| v0_31(void) = ExitFunction : +# 47| r0_18(glval) = VariableAddress[x] : +# 47| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 47| r0_20(glval) = VariableAddress[y] : +# 47| r0_21(short) = Load : &:r0_20, ~mu0_2 +# 47| r0_22(int) = Convert : r0_21 +# 47| r0_23(int) = Mul : r0_19, r0_22 +# 47| r0_24(glval) = VariableAddress[x] : +# 47| mu0_25(int) = Store : &:r0_24, r0_23 +# 48| v0_26(void) = NoOp : +# 43| v0_27(void) = ReturnVoid : +# 43| v0_28(void) = UnmodeledUse : mu* +# 43| v0_29(void) = ExitFunction : # 50| void IntegerOps(int, int) # 50| Block 0 @@ -235,185 +232,160 @@ ir.cpp: # 53| r0_13(int) = Add : r0_10, r0_12 # 53| r0_14(glval) = VariableAddress[z] : # 53| mu0_15(int) = Store : &:r0_14, r0_13 -# 53| r0_16(glval) = CopyValue : r0_14 -# 54| r0_17(glval) = VariableAddress[x] : -# 54| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 54| r0_19(glval) = VariableAddress[y] : -# 54| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 54| r0_21(int) = Sub : r0_18, r0_20 -# 54| r0_22(glval) = VariableAddress[z] : -# 54| mu0_23(int) = Store : &:r0_22, r0_21 -# 54| r0_24(glval) = CopyValue : r0_22 -# 55| r0_25(glval) = VariableAddress[x] : +# 54| r0_16(glval) = VariableAddress[x] : +# 54| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 54| r0_18(glval) = VariableAddress[y] : +# 54| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 54| r0_20(int) = Sub : r0_17, r0_19 +# 54| r0_21(glval) = VariableAddress[z] : +# 54| mu0_22(int) = Store : &:r0_21, r0_20 +# 55| r0_23(glval) = VariableAddress[x] : +# 55| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 55| r0_25(glval) = VariableAddress[y] : # 55| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 55| r0_27(glval) = VariableAddress[y] : -# 55| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 55| r0_29(int) = Mul : r0_26, r0_28 -# 55| r0_30(glval) = VariableAddress[z] : -# 55| mu0_31(int) = Store : &:r0_30, r0_29 -# 55| r0_32(glval) = CopyValue : r0_30 -# 56| r0_33(glval) = VariableAddress[x] : -# 56| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 56| r0_35(glval) = VariableAddress[y] : -# 56| r0_36(int) = Load : &:r0_35, ~mu0_2 -# 56| r0_37(int) = Div : r0_34, r0_36 -# 56| r0_38(glval) = VariableAddress[z] : -# 56| mu0_39(int) = Store : &:r0_38, r0_37 -# 56| r0_40(glval) = CopyValue : r0_38 -# 57| r0_41(glval) = VariableAddress[x] : -# 57| r0_42(int) = Load : &:r0_41, ~mu0_2 -# 57| r0_43(glval) = VariableAddress[y] : -# 57| r0_44(int) = Load : &:r0_43, ~mu0_2 -# 57| r0_45(int) = Rem : r0_42, r0_44 -# 57| r0_46(glval) = VariableAddress[z] : -# 57| mu0_47(int) = Store : &:r0_46, r0_45 -# 57| r0_48(glval) = CopyValue : r0_46 -# 59| r0_49(glval) = VariableAddress[x] : -# 59| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 59| r0_51(glval) = VariableAddress[y] : -# 59| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 59| r0_53(int) = BitAnd : r0_50, r0_52 -# 59| r0_54(glval) = VariableAddress[z] : -# 59| mu0_55(int) = Store : &:r0_54, r0_53 -# 59| r0_56(glval) = CopyValue : r0_54 -# 60| r0_57(glval) = VariableAddress[x] : -# 60| r0_58(int) = Load : &:r0_57, ~mu0_2 -# 60| r0_59(glval) = VariableAddress[y] : -# 60| r0_60(int) = Load : &:r0_59, ~mu0_2 -# 60| r0_61(int) = BitOr : r0_58, r0_60 -# 60| r0_62(glval) = VariableAddress[z] : -# 60| mu0_63(int) = Store : &:r0_62, r0_61 -# 60| r0_64(glval) = CopyValue : r0_62 -# 61| r0_65(glval) = VariableAddress[x] : -# 61| r0_66(int) = Load : &:r0_65, ~mu0_2 -# 61| r0_67(glval) = VariableAddress[y] : -# 61| r0_68(int) = Load : &:r0_67, ~mu0_2 -# 61| r0_69(int) = BitXor : r0_66, r0_68 -# 61| r0_70(glval) = VariableAddress[z] : -# 61| mu0_71(int) = Store : &:r0_70, r0_69 -# 61| r0_72(glval) = CopyValue : r0_70 -# 63| r0_73(glval) = VariableAddress[x] : -# 63| r0_74(int) = Load : &:r0_73, ~mu0_2 -# 63| r0_75(glval) = VariableAddress[y] : -# 63| r0_76(int) = Load : &:r0_75, ~mu0_2 -# 63| r0_77(int) = ShiftLeft : r0_74, r0_76 -# 63| r0_78(glval) = VariableAddress[z] : -# 63| mu0_79(int) = Store : &:r0_78, r0_77 -# 63| r0_80(glval) = CopyValue : r0_78 -# 64| r0_81(glval) = VariableAddress[x] : -# 64| r0_82(int) = Load : &:r0_81, ~mu0_2 -# 64| r0_83(glval) = VariableAddress[y] : -# 64| r0_84(int) = Load : &:r0_83, ~mu0_2 -# 64| r0_85(int) = ShiftRight : r0_82, r0_84 -# 64| r0_86(glval) = VariableAddress[z] : -# 64| mu0_87(int) = Store : &:r0_86, r0_85 -# 64| r0_88(glval) = CopyValue : r0_86 -# 66| r0_89(glval) = VariableAddress[x] : -# 66| r0_90(int) = Load : &:r0_89, ~mu0_2 -# 66| r0_91(glval) = VariableAddress[z] : -# 66| mu0_92(int) = Store : &:r0_91, r0_90 -# 66| r0_93(glval) = CopyValue : r0_91 -# 68| r0_94(glval) = VariableAddress[x] : -# 68| r0_95(int) = Load : &:r0_94, ~mu0_2 -# 68| r0_96(glval) = VariableAddress[z] : -# 68| r0_97(int) = Load : &:r0_96, ~mu0_2 -# 68| r0_98(int) = Add : r0_97, r0_95 -# 68| mu0_99(int) = Store : &:r0_96, r0_98 -# 68| r0_100(glval) = CopyValue : r0_96 -# 69| r0_101(glval) = VariableAddress[x] : -# 69| r0_102(int) = Load : &:r0_101, ~mu0_2 -# 69| r0_103(glval) = VariableAddress[z] : -# 69| r0_104(int) = Load : &:r0_103, ~mu0_2 -# 69| r0_105(int) = Sub : r0_104, r0_102 -# 69| mu0_106(int) = Store : &:r0_103, r0_105 -# 69| r0_107(glval) = CopyValue : r0_103 -# 70| r0_108(glval) = VariableAddress[x] : -# 70| r0_109(int) = Load : &:r0_108, ~mu0_2 -# 70| r0_110(glval) = VariableAddress[z] : -# 70| r0_111(int) = Load : &:r0_110, ~mu0_2 -# 70| r0_112(int) = Mul : r0_111, r0_109 -# 70| mu0_113(int) = Store : &:r0_110, r0_112 -# 70| r0_114(glval) = CopyValue : r0_110 -# 71| r0_115(glval) = VariableAddress[x] : -# 71| r0_116(int) = Load : &:r0_115, ~mu0_2 -# 71| r0_117(glval) = VariableAddress[z] : -# 71| r0_118(int) = Load : &:r0_117, ~mu0_2 -# 71| r0_119(int) = Div : r0_118, r0_116 -# 71| mu0_120(int) = Store : &:r0_117, r0_119 -# 71| r0_121(glval) = CopyValue : r0_117 -# 72| r0_122(glval) = VariableAddress[x] : -# 72| r0_123(int) = Load : &:r0_122, ~mu0_2 -# 72| r0_124(glval) = VariableAddress[z] : -# 72| r0_125(int) = Load : &:r0_124, ~mu0_2 -# 72| r0_126(int) = Rem : r0_125, r0_123 -# 72| mu0_127(int) = Store : &:r0_124, r0_126 -# 72| r0_128(glval) = CopyValue : r0_124 -# 74| r0_129(glval) = VariableAddress[x] : -# 74| r0_130(int) = Load : &:r0_129, ~mu0_2 -# 74| r0_131(glval) = VariableAddress[z] : -# 74| r0_132(int) = Load : &:r0_131, ~mu0_2 -# 74| r0_133(int) = BitAnd : r0_132, r0_130 -# 74| mu0_134(int) = Store : &:r0_131, r0_133 -# 74| r0_135(glval) = CopyValue : r0_131 -# 75| r0_136(glval) = VariableAddress[x] : -# 75| r0_137(int) = Load : &:r0_136, ~mu0_2 -# 75| r0_138(glval) = VariableAddress[z] : -# 75| r0_139(int) = Load : &:r0_138, ~mu0_2 -# 75| r0_140(int) = BitOr : r0_139, r0_137 -# 75| mu0_141(int) = Store : &:r0_138, r0_140 -# 75| r0_142(glval) = CopyValue : r0_138 -# 76| r0_143(glval) = VariableAddress[x] : -# 76| r0_144(int) = Load : &:r0_143, ~mu0_2 -# 76| r0_145(glval) = VariableAddress[z] : -# 76| r0_146(int) = Load : &:r0_145, ~mu0_2 -# 76| r0_147(int) = BitXor : r0_146, r0_144 -# 76| mu0_148(int) = Store : &:r0_145, r0_147 -# 76| r0_149(glval) = CopyValue : r0_145 -# 78| r0_150(glval) = VariableAddress[x] : -# 78| r0_151(int) = Load : &:r0_150, ~mu0_2 -# 78| r0_152(glval) = VariableAddress[z] : -# 78| r0_153(int) = Load : &:r0_152, ~mu0_2 -# 78| r0_154(int) = ShiftLeft : r0_153, r0_151 -# 78| mu0_155(int) = Store : &:r0_152, r0_154 -# 78| r0_156(glval) = CopyValue : r0_152 -# 79| r0_157(glval) = VariableAddress[x] : -# 79| r0_158(int) = Load : &:r0_157, ~mu0_2 -# 79| r0_159(glval) = VariableAddress[z] : -# 79| r0_160(int) = Load : &:r0_159, ~mu0_2 -# 79| r0_161(int) = ShiftRight : r0_160, r0_158 -# 79| mu0_162(int) = Store : &:r0_159, r0_161 -# 79| r0_163(glval) = CopyValue : r0_159 -# 81| r0_164(glval) = VariableAddress[x] : -# 81| r0_165(int) = Load : &:r0_164, ~mu0_2 -# 81| r0_166(int) = CopyValue : r0_165 -# 81| r0_167(glval) = VariableAddress[z] : -# 81| mu0_168(int) = Store : &:r0_167, r0_166 -# 81| r0_169(glval) = CopyValue : r0_167 -# 82| r0_170(glval) = VariableAddress[x] : -# 82| r0_171(int) = Load : &:r0_170, ~mu0_2 -# 82| r0_172(int) = Negate : r0_171 -# 82| r0_173(glval) = VariableAddress[z] : -# 82| mu0_174(int) = Store : &:r0_173, r0_172 -# 82| r0_175(glval) = CopyValue : r0_173 -# 83| r0_176(glval) = VariableAddress[x] : -# 83| r0_177(int) = Load : &:r0_176, ~mu0_2 -# 83| r0_178(int) = BitComplement : r0_177 -# 83| r0_179(glval) = VariableAddress[z] : -# 83| mu0_180(int) = Store : &:r0_179, r0_178 -# 83| r0_181(glval) = CopyValue : r0_179 -# 84| r0_182(glval) = VariableAddress[x] : -# 84| r0_183(int) = Load : &:r0_182, ~mu0_2 -# 84| r0_184(int) = Constant[0] : -# 84| r0_185(bool) = CompareNE : r0_183, r0_184 -# 84| r0_186(bool) = LogicalNot : r0_185 -# 84| r0_187(int) = Convert : r0_186 -# 84| r0_188(glval) = VariableAddress[z] : -# 84| mu0_189(int) = Store : &:r0_188, r0_187 -# 84| r0_190(glval) = CopyValue : r0_188 -# 85| v0_191(void) = NoOp : -# 50| v0_192(void) = ReturnVoid : -# 50| v0_193(void) = UnmodeledUse : mu* -# 50| v0_194(void) = ExitFunction : +# 55| r0_27(int) = Mul : r0_24, r0_26 +# 55| r0_28(glval) = VariableAddress[z] : +# 55| mu0_29(int) = Store : &:r0_28, r0_27 +# 56| r0_30(glval) = VariableAddress[x] : +# 56| r0_31(int) = Load : &:r0_30, ~mu0_2 +# 56| r0_32(glval) = VariableAddress[y] : +# 56| r0_33(int) = Load : &:r0_32, ~mu0_2 +# 56| r0_34(int) = Div : r0_31, r0_33 +# 56| r0_35(glval) = VariableAddress[z] : +# 56| mu0_36(int) = Store : &:r0_35, r0_34 +# 57| r0_37(glval) = VariableAddress[x] : +# 57| r0_38(int) = Load : &:r0_37, ~mu0_2 +# 57| r0_39(glval) = VariableAddress[y] : +# 57| r0_40(int) = Load : &:r0_39, ~mu0_2 +# 57| r0_41(int) = Rem : r0_38, r0_40 +# 57| r0_42(glval) = VariableAddress[z] : +# 57| mu0_43(int) = Store : &:r0_42, r0_41 +# 59| r0_44(glval) = VariableAddress[x] : +# 59| r0_45(int) = Load : &:r0_44, ~mu0_2 +# 59| r0_46(glval) = VariableAddress[y] : +# 59| r0_47(int) = Load : &:r0_46, ~mu0_2 +# 59| r0_48(int) = BitAnd : r0_45, r0_47 +# 59| r0_49(glval) = VariableAddress[z] : +# 59| mu0_50(int) = Store : &:r0_49, r0_48 +# 60| r0_51(glval) = VariableAddress[x] : +# 60| r0_52(int) = Load : &:r0_51, ~mu0_2 +# 60| r0_53(glval) = VariableAddress[y] : +# 60| r0_54(int) = Load : &:r0_53, ~mu0_2 +# 60| r0_55(int) = BitOr : r0_52, r0_54 +# 60| r0_56(glval) = VariableAddress[z] : +# 60| mu0_57(int) = Store : &:r0_56, r0_55 +# 61| r0_58(glval) = VariableAddress[x] : +# 61| r0_59(int) = Load : &:r0_58, ~mu0_2 +# 61| r0_60(glval) = VariableAddress[y] : +# 61| r0_61(int) = Load : &:r0_60, ~mu0_2 +# 61| r0_62(int) = BitXor : r0_59, r0_61 +# 61| r0_63(glval) = VariableAddress[z] : +# 61| mu0_64(int) = Store : &:r0_63, r0_62 +# 63| r0_65(glval) = VariableAddress[x] : +# 63| r0_66(int) = Load : &:r0_65, ~mu0_2 +# 63| r0_67(glval) = VariableAddress[y] : +# 63| r0_68(int) = Load : &:r0_67, ~mu0_2 +# 63| r0_69(int) = ShiftLeft : r0_66, r0_68 +# 63| r0_70(glval) = VariableAddress[z] : +# 63| mu0_71(int) = Store : &:r0_70, r0_69 +# 64| r0_72(glval) = VariableAddress[x] : +# 64| r0_73(int) = Load : &:r0_72, ~mu0_2 +# 64| r0_74(glval) = VariableAddress[y] : +# 64| r0_75(int) = Load : &:r0_74, ~mu0_2 +# 64| r0_76(int) = ShiftRight : r0_73, r0_75 +# 64| r0_77(glval) = VariableAddress[z] : +# 64| mu0_78(int) = Store : &:r0_77, r0_76 +# 66| r0_79(glval) = VariableAddress[x] : +# 66| r0_80(int) = Load : &:r0_79, ~mu0_2 +# 66| r0_81(glval) = VariableAddress[z] : +# 66| mu0_82(int) = Store : &:r0_81, r0_80 +# 68| r0_83(glval) = VariableAddress[x] : +# 68| r0_84(int) = Load : &:r0_83, ~mu0_2 +# 68| r0_85(glval) = VariableAddress[z] : +# 68| r0_86(int) = Load : &:r0_85, ~mu0_2 +# 68| r0_87(int) = Add : r0_86, r0_84 +# 68| mu0_88(int) = Store : &:r0_85, r0_87 +# 69| r0_89(glval) = VariableAddress[x] : +# 69| r0_90(int) = Load : &:r0_89, ~mu0_2 +# 69| r0_91(glval) = VariableAddress[z] : +# 69| r0_92(int) = Load : &:r0_91, ~mu0_2 +# 69| r0_93(int) = Sub : r0_92, r0_90 +# 69| mu0_94(int) = Store : &:r0_91, r0_93 +# 70| r0_95(glval) = VariableAddress[x] : +# 70| r0_96(int) = Load : &:r0_95, ~mu0_2 +# 70| r0_97(glval) = VariableAddress[z] : +# 70| r0_98(int) = Load : &:r0_97, ~mu0_2 +# 70| r0_99(int) = Mul : r0_98, r0_96 +# 70| mu0_100(int) = Store : &:r0_97, r0_99 +# 71| r0_101(glval) = VariableAddress[x] : +# 71| r0_102(int) = Load : &:r0_101, ~mu0_2 +# 71| r0_103(glval) = VariableAddress[z] : +# 71| r0_104(int) = Load : &:r0_103, ~mu0_2 +# 71| r0_105(int) = Div : r0_104, r0_102 +# 71| mu0_106(int) = Store : &:r0_103, r0_105 +# 72| r0_107(glval) = VariableAddress[x] : +# 72| r0_108(int) = Load : &:r0_107, ~mu0_2 +# 72| r0_109(glval) = VariableAddress[z] : +# 72| r0_110(int) = Load : &:r0_109, ~mu0_2 +# 72| r0_111(int) = Rem : r0_110, r0_108 +# 72| mu0_112(int) = Store : &:r0_109, r0_111 +# 74| r0_113(glval) = VariableAddress[x] : +# 74| r0_114(int) = Load : &:r0_113, ~mu0_2 +# 74| r0_115(glval) = VariableAddress[z] : +# 74| r0_116(int) = Load : &:r0_115, ~mu0_2 +# 74| r0_117(int) = BitAnd : r0_116, r0_114 +# 74| mu0_118(int) = Store : &:r0_115, r0_117 +# 75| r0_119(glval) = VariableAddress[x] : +# 75| r0_120(int) = Load : &:r0_119, ~mu0_2 +# 75| r0_121(glval) = VariableAddress[z] : +# 75| r0_122(int) = Load : &:r0_121, ~mu0_2 +# 75| r0_123(int) = BitOr : r0_122, r0_120 +# 75| mu0_124(int) = Store : &:r0_121, r0_123 +# 76| r0_125(glval) = VariableAddress[x] : +# 76| r0_126(int) = Load : &:r0_125, ~mu0_2 +# 76| r0_127(glval) = VariableAddress[z] : +# 76| r0_128(int) = Load : &:r0_127, ~mu0_2 +# 76| r0_129(int) = BitXor : r0_128, r0_126 +# 76| mu0_130(int) = Store : &:r0_127, r0_129 +# 78| r0_131(glval) = VariableAddress[x] : +# 78| r0_132(int) = Load : &:r0_131, ~mu0_2 +# 78| r0_133(glval) = VariableAddress[z] : +# 78| r0_134(int) = Load : &:r0_133, ~mu0_2 +# 78| r0_135(int) = ShiftLeft : r0_134, r0_132 +# 78| mu0_136(int) = Store : &:r0_133, r0_135 +# 79| r0_137(glval) = VariableAddress[x] : +# 79| r0_138(int) = Load : &:r0_137, ~mu0_2 +# 79| r0_139(glval) = VariableAddress[z] : +# 79| r0_140(int) = Load : &:r0_139, ~mu0_2 +# 79| r0_141(int) = ShiftRight : r0_140, r0_138 +# 79| mu0_142(int) = Store : &:r0_139, r0_141 +# 81| r0_143(glval) = VariableAddress[x] : +# 81| r0_144(int) = Load : &:r0_143, ~mu0_2 +# 81| r0_145(int) = CopyValue : r0_144 +# 81| r0_146(glval) = VariableAddress[z] : +# 81| mu0_147(int) = Store : &:r0_146, r0_145 +# 82| r0_148(glval) = VariableAddress[x] : +# 82| r0_149(int) = Load : &:r0_148, ~mu0_2 +# 82| r0_150(int) = Negate : r0_149 +# 82| r0_151(glval) = VariableAddress[z] : +# 82| mu0_152(int) = Store : &:r0_151, r0_150 +# 83| r0_153(glval) = VariableAddress[x] : +# 83| r0_154(int) = Load : &:r0_153, ~mu0_2 +# 83| r0_155(int) = BitComplement : r0_154 +# 83| r0_156(glval) = VariableAddress[z] : +# 83| mu0_157(int) = Store : &:r0_156, r0_155 +# 84| r0_158(glval) = VariableAddress[x] : +# 84| r0_159(int) = Load : &:r0_158, ~mu0_2 +# 84| r0_160(int) = Constant[0] : +# 84| r0_161(bool) = CompareNE : r0_159, r0_160 +# 84| r0_162(bool) = LogicalNot : r0_161 +# 84| r0_163(int) = Convert : r0_162 +# 84| r0_164(glval) = VariableAddress[z] : +# 84| mu0_165(int) = Store : &:r0_164, r0_163 +# 85| v0_166(void) = NoOp : +# 50| v0_167(void) = ReturnVoid : +# 50| v0_168(void) = UnmodeledUse : mu* +# 50| v0_169(void) = ExitFunction : # 87| void IntegerCompare(int, int) # 87| Block 0 @@ -433,51 +405,45 @@ ir.cpp: # 90| r0_13(bool) = CompareEQ : r0_10, r0_12 # 90| r0_14(glval) = VariableAddress[b] : # 90| mu0_15(bool) = Store : &:r0_14, r0_13 -# 90| r0_16(glval) = CopyValue : r0_14 -# 91| r0_17(glval) = VariableAddress[x] : -# 91| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 91| r0_19(glval) = VariableAddress[y] : -# 91| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 91| r0_21(bool) = CompareNE : r0_18, r0_20 -# 91| r0_22(glval) = VariableAddress[b] : -# 91| mu0_23(bool) = Store : &:r0_22, r0_21 -# 91| r0_24(glval) = CopyValue : r0_22 -# 92| r0_25(glval) = VariableAddress[x] : +# 91| r0_16(glval) = VariableAddress[x] : +# 91| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 91| r0_18(glval) = VariableAddress[y] : +# 91| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 91| r0_20(bool) = CompareNE : r0_17, r0_19 +# 91| r0_21(glval) = VariableAddress[b] : +# 91| mu0_22(bool) = Store : &:r0_21, r0_20 +# 92| r0_23(glval) = VariableAddress[x] : +# 92| r0_24(int) = Load : &:r0_23, ~mu0_2 +# 92| r0_25(glval) = VariableAddress[y] : # 92| r0_26(int) = Load : &:r0_25, ~mu0_2 -# 92| r0_27(glval) = VariableAddress[y] : -# 92| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 92| r0_29(bool) = CompareLT : r0_26, r0_28 -# 92| r0_30(glval) = VariableAddress[b] : -# 92| mu0_31(bool) = Store : &:r0_30, r0_29 -# 92| r0_32(glval) = CopyValue : r0_30 -# 93| r0_33(glval) = VariableAddress[x] : -# 93| r0_34(int) = Load : &:r0_33, ~mu0_2 -# 93| r0_35(glval) = VariableAddress[y] : -# 93| r0_36(int) = Load : &:r0_35, ~mu0_2 -# 93| r0_37(bool) = CompareGT : r0_34, r0_36 -# 93| r0_38(glval) = VariableAddress[b] : -# 93| mu0_39(bool) = Store : &:r0_38, r0_37 -# 93| r0_40(glval) = CopyValue : r0_38 -# 94| r0_41(glval) = VariableAddress[x] : -# 94| r0_42(int) = Load : &:r0_41, ~mu0_2 -# 94| r0_43(glval) = VariableAddress[y] : -# 94| r0_44(int) = Load : &:r0_43, ~mu0_2 -# 94| r0_45(bool) = CompareLE : r0_42, r0_44 -# 94| r0_46(glval) = VariableAddress[b] : -# 94| mu0_47(bool) = Store : &:r0_46, r0_45 -# 94| r0_48(glval) = CopyValue : r0_46 -# 95| r0_49(glval) = VariableAddress[x] : -# 95| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 95| r0_51(glval) = VariableAddress[y] : -# 95| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 95| r0_53(bool) = CompareGE : r0_50, r0_52 -# 95| r0_54(glval) = VariableAddress[b] : -# 95| mu0_55(bool) = Store : &:r0_54, r0_53 -# 95| r0_56(glval) = CopyValue : r0_54 -# 96| v0_57(void) = NoOp : -# 87| v0_58(void) = ReturnVoid : -# 87| v0_59(void) = UnmodeledUse : mu* -# 87| v0_60(void) = ExitFunction : +# 92| r0_27(bool) = CompareLT : r0_24, r0_26 +# 92| r0_28(glval) = VariableAddress[b] : +# 92| mu0_29(bool) = Store : &:r0_28, r0_27 +# 93| r0_30(glval) = VariableAddress[x] : +# 93| r0_31(int) = Load : &:r0_30, ~mu0_2 +# 93| r0_32(glval) = VariableAddress[y] : +# 93| r0_33(int) = Load : &:r0_32, ~mu0_2 +# 93| r0_34(bool) = CompareGT : r0_31, r0_33 +# 93| r0_35(glval) = VariableAddress[b] : +# 93| mu0_36(bool) = Store : &:r0_35, r0_34 +# 94| r0_37(glval) = VariableAddress[x] : +# 94| r0_38(int) = Load : &:r0_37, ~mu0_2 +# 94| r0_39(glval) = VariableAddress[y] : +# 94| r0_40(int) = Load : &:r0_39, ~mu0_2 +# 94| r0_41(bool) = CompareLE : r0_38, r0_40 +# 94| r0_42(glval) = VariableAddress[b] : +# 94| mu0_43(bool) = Store : &:r0_42, r0_41 +# 95| r0_44(glval) = VariableAddress[x] : +# 95| r0_45(int) = Load : &:r0_44, ~mu0_2 +# 95| r0_46(glval) = VariableAddress[y] : +# 95| r0_47(int) = Load : &:r0_46, ~mu0_2 +# 95| r0_48(bool) = CompareGE : r0_45, r0_47 +# 95| r0_49(glval) = VariableAddress[b] : +# 95| mu0_50(bool) = Store : &:r0_49, r0_48 +# 96| v0_51(void) = NoOp : +# 87| v0_52(void) = ReturnVoid : +# 87| v0_53(void) = UnmodeledUse : mu* +# 87| v0_54(void) = ExitFunction : # 98| void IntegerCrement(int) # 98| Block 0 @@ -495,35 +461,31 @@ ir.cpp: # 101| mu0_11(int) = Store : &:r0_7, r0_10 # 101| r0_12(glval) = VariableAddress[y] : # 101| mu0_13(int) = Store : &:r0_12, r0_10 -# 101| r0_14(glval) = CopyValue : r0_12 -# 102| r0_15(glval) = VariableAddress[x] : -# 102| r0_16(int) = Load : &:r0_15, ~mu0_2 -# 102| r0_17(int) = Constant[1] : -# 102| r0_18(int) = Sub : r0_16, r0_17 -# 102| mu0_19(int) = Store : &:r0_15, r0_18 -# 102| r0_20(glval) = VariableAddress[y] : -# 102| mu0_21(int) = Store : &:r0_20, r0_18 -# 102| r0_22(glval) = CopyValue : r0_20 -# 103| r0_23(glval) = VariableAddress[x] : -# 103| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 103| r0_25(int) = Constant[1] : -# 103| r0_26(int) = Add : r0_24, r0_25 -# 103| mu0_27(int) = Store : &:r0_23, r0_26 -# 103| r0_28(glval) = VariableAddress[y] : -# 103| mu0_29(int) = Store : &:r0_28, r0_24 -# 103| r0_30(glval) = CopyValue : r0_28 -# 104| r0_31(glval) = VariableAddress[x] : -# 104| r0_32(int) = Load : &:r0_31, ~mu0_2 -# 104| r0_33(int) = Constant[1] : -# 104| r0_34(int) = Sub : r0_32, r0_33 -# 104| mu0_35(int) = Store : &:r0_31, r0_34 -# 104| r0_36(glval) = VariableAddress[y] : -# 104| mu0_37(int) = Store : &:r0_36, r0_32 -# 104| r0_38(glval) = CopyValue : r0_36 -# 105| v0_39(void) = NoOp : -# 98| v0_40(void) = ReturnVoid : -# 98| v0_41(void) = UnmodeledUse : mu* -# 98| v0_42(void) = ExitFunction : +# 102| r0_14(glval) = VariableAddress[x] : +# 102| r0_15(int) = Load : &:r0_14, ~mu0_2 +# 102| r0_16(int) = Constant[1] : +# 102| r0_17(int) = Sub : r0_15, r0_16 +# 102| mu0_18(int) = Store : &:r0_14, r0_17 +# 102| r0_19(glval) = VariableAddress[y] : +# 102| mu0_20(int) = Store : &:r0_19, r0_17 +# 103| r0_21(glval) = VariableAddress[x] : +# 103| r0_22(int) = Load : &:r0_21, ~mu0_2 +# 103| r0_23(int) = Constant[1] : +# 103| r0_24(int) = Add : r0_22, r0_23 +# 103| mu0_25(int) = Store : &:r0_21, r0_24 +# 103| r0_26(glval) = VariableAddress[y] : +# 103| mu0_27(int) = Store : &:r0_26, r0_22 +# 104| r0_28(glval) = VariableAddress[x] : +# 104| r0_29(int) = Load : &:r0_28, ~mu0_2 +# 104| r0_30(int) = Constant[1] : +# 104| r0_31(int) = Sub : r0_29, r0_30 +# 104| mu0_32(int) = Store : &:r0_28, r0_31 +# 104| r0_33(glval) = VariableAddress[y] : +# 104| mu0_34(int) = Store : &:r0_33, r0_29 +# 105| v0_35(void) = NoOp : +# 98| v0_36(void) = ReturnVoid : +# 98| v0_37(void) = UnmodeledUse : mu* +# 98| v0_38(void) = ExitFunction : # 107| void IntegerCrement_LValue(int) # 107| Block 0 @@ -543,21 +505,19 @@ ir.cpp: # 110| r0_13(int *) = CopyValue : r0_12 # 110| r0_14(glval) = VariableAddress[p] : # 110| mu0_15(int *) = Store : &:r0_14, r0_13 -# 110| r0_16(glval) = CopyValue : r0_14 -# 111| r0_17(glval) = VariableAddress[x] : -# 111| r0_18(int) = Load : &:r0_17, ~mu0_2 -# 111| r0_19(int) = Constant[1] : -# 111| r0_20(int) = Sub : r0_18, r0_19 -# 111| mu0_21(int) = Store : &:r0_17, r0_20 -# 111| r0_22(glval) = CopyValue : r0_17 -# 111| r0_23(int *) = CopyValue : r0_22 -# 111| r0_24(glval) = VariableAddress[p] : -# 111| mu0_25(int *) = Store : &:r0_24, r0_23 -# 111| r0_26(glval) = CopyValue : r0_24 -# 112| v0_27(void) = NoOp : -# 107| v0_28(void) = ReturnVoid : -# 107| v0_29(void) = UnmodeledUse : mu* -# 107| v0_30(void) = ExitFunction : +# 111| r0_16(glval) = VariableAddress[x] : +# 111| r0_17(int) = Load : &:r0_16, ~mu0_2 +# 111| r0_18(int) = Constant[1] : +# 111| r0_19(int) = Sub : r0_17, r0_18 +# 111| mu0_20(int) = Store : &:r0_16, r0_19 +# 111| r0_21(glval) = CopyValue : r0_16 +# 111| r0_22(int *) = CopyValue : r0_21 +# 111| r0_23(glval) = VariableAddress[p] : +# 111| mu0_24(int *) = Store : &:r0_23, r0_22 +# 112| v0_25(void) = NoOp : +# 107| v0_26(void) = ReturnVoid : +# 107| v0_27(void) = UnmodeledUse : mu* +# 107| v0_28(void) = ExitFunction : # 114| void FloatOps(double, double) # 114| Block 0 @@ -577,80 +537,69 @@ ir.cpp: # 117| r0_13(double) = Add : r0_10, r0_12 # 117| r0_14(glval) = VariableAddress[z] : # 117| mu0_15(double) = Store : &:r0_14, r0_13 -# 117| r0_16(glval) = CopyValue : r0_14 -# 118| r0_17(glval) = VariableAddress[x] : -# 118| r0_18(double) = Load : &:r0_17, ~mu0_2 -# 118| r0_19(glval) = VariableAddress[y] : -# 118| r0_20(double) = Load : &:r0_19, ~mu0_2 -# 118| r0_21(double) = Sub : r0_18, r0_20 -# 118| r0_22(glval) = VariableAddress[z] : -# 118| mu0_23(double) = Store : &:r0_22, r0_21 -# 118| r0_24(glval) = CopyValue : r0_22 -# 119| r0_25(glval) = VariableAddress[x] : +# 118| r0_16(glval) = VariableAddress[x] : +# 118| r0_17(double) = Load : &:r0_16, ~mu0_2 +# 118| r0_18(glval) = VariableAddress[y] : +# 118| r0_19(double) = Load : &:r0_18, ~mu0_2 +# 118| r0_20(double) = Sub : r0_17, r0_19 +# 118| r0_21(glval) = VariableAddress[z] : +# 118| mu0_22(double) = Store : &:r0_21, r0_20 +# 119| r0_23(glval) = VariableAddress[x] : +# 119| r0_24(double) = Load : &:r0_23, ~mu0_2 +# 119| r0_25(glval) = VariableAddress[y] : # 119| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 119| r0_27(glval) = VariableAddress[y] : -# 119| r0_28(double) = Load : &:r0_27, ~mu0_2 -# 119| r0_29(double) = Mul : r0_26, r0_28 -# 119| r0_30(glval) = VariableAddress[z] : -# 119| mu0_31(double) = Store : &:r0_30, r0_29 -# 119| r0_32(glval) = CopyValue : r0_30 -# 120| r0_33(glval) = VariableAddress[x] : -# 120| r0_34(double) = Load : &:r0_33, ~mu0_2 -# 120| r0_35(glval) = VariableAddress[y] : -# 120| r0_36(double) = Load : &:r0_35, ~mu0_2 -# 120| r0_37(double) = Div : r0_34, r0_36 -# 120| r0_38(glval) = VariableAddress[z] : -# 120| mu0_39(double) = Store : &:r0_38, r0_37 -# 120| r0_40(glval) = CopyValue : r0_38 -# 122| r0_41(glval) = VariableAddress[x] : -# 122| r0_42(double) = Load : &:r0_41, ~mu0_2 -# 122| r0_43(glval) = VariableAddress[z] : -# 122| mu0_44(double) = Store : &:r0_43, r0_42 -# 122| r0_45(glval) = CopyValue : r0_43 -# 124| r0_46(glval) = VariableAddress[x] : -# 124| r0_47(double) = Load : &:r0_46, ~mu0_2 -# 124| r0_48(glval) = VariableAddress[z] : -# 124| r0_49(double) = Load : &:r0_48, ~mu0_2 -# 124| r0_50(double) = Add : r0_49, r0_47 -# 124| mu0_51(double) = Store : &:r0_48, r0_50 -# 124| r0_52(glval) = CopyValue : r0_48 -# 125| r0_53(glval) = VariableAddress[x] : -# 125| r0_54(double) = Load : &:r0_53, ~mu0_2 -# 125| r0_55(glval) = VariableAddress[z] : -# 125| r0_56(double) = Load : &:r0_55, ~mu0_2 -# 125| r0_57(double) = Sub : r0_56, r0_54 -# 125| mu0_58(double) = Store : &:r0_55, r0_57 -# 125| r0_59(glval) = CopyValue : r0_55 -# 126| r0_60(glval) = VariableAddress[x] : -# 126| r0_61(double) = Load : &:r0_60, ~mu0_2 -# 126| r0_62(glval) = VariableAddress[z] : -# 126| r0_63(double) = Load : &:r0_62, ~mu0_2 -# 126| r0_64(double) = Mul : r0_63, r0_61 -# 126| mu0_65(double) = Store : &:r0_62, r0_64 -# 126| r0_66(glval) = CopyValue : r0_62 -# 127| r0_67(glval) = VariableAddress[x] : -# 127| r0_68(double) = Load : &:r0_67, ~mu0_2 -# 127| r0_69(glval) = VariableAddress[z] : -# 127| r0_70(double) = Load : &:r0_69, ~mu0_2 -# 127| r0_71(double) = Div : r0_70, r0_68 -# 127| mu0_72(double) = Store : &:r0_69, r0_71 -# 127| r0_73(glval) = CopyValue : r0_69 -# 129| r0_74(glval) = VariableAddress[x] : -# 129| r0_75(double) = Load : &:r0_74, ~mu0_2 -# 129| r0_76(double) = CopyValue : r0_75 -# 129| r0_77(glval) = VariableAddress[z] : -# 129| mu0_78(double) = Store : &:r0_77, r0_76 -# 129| r0_79(glval) = CopyValue : r0_77 -# 130| r0_80(glval) = VariableAddress[x] : -# 130| r0_81(double) = Load : &:r0_80, ~mu0_2 -# 130| r0_82(double) = Negate : r0_81 -# 130| r0_83(glval) = VariableAddress[z] : -# 130| mu0_84(double) = Store : &:r0_83, r0_82 -# 130| r0_85(glval) = CopyValue : r0_83 -# 131| v0_86(void) = NoOp : -# 114| v0_87(void) = ReturnVoid : -# 114| v0_88(void) = UnmodeledUse : mu* -# 114| v0_89(void) = ExitFunction : +# 119| r0_27(double) = Mul : r0_24, r0_26 +# 119| r0_28(glval) = VariableAddress[z] : +# 119| mu0_29(double) = Store : &:r0_28, r0_27 +# 120| r0_30(glval) = VariableAddress[x] : +# 120| r0_31(double) = Load : &:r0_30, ~mu0_2 +# 120| r0_32(glval) = VariableAddress[y] : +# 120| r0_33(double) = Load : &:r0_32, ~mu0_2 +# 120| r0_34(double) = Div : r0_31, r0_33 +# 120| r0_35(glval) = VariableAddress[z] : +# 120| mu0_36(double) = Store : &:r0_35, r0_34 +# 122| r0_37(glval) = VariableAddress[x] : +# 122| r0_38(double) = Load : &:r0_37, ~mu0_2 +# 122| r0_39(glval) = VariableAddress[z] : +# 122| mu0_40(double) = Store : &:r0_39, r0_38 +# 124| r0_41(glval) = VariableAddress[x] : +# 124| r0_42(double) = Load : &:r0_41, ~mu0_2 +# 124| r0_43(glval) = VariableAddress[z] : +# 124| r0_44(double) = Load : &:r0_43, ~mu0_2 +# 124| r0_45(double) = Add : r0_44, r0_42 +# 124| mu0_46(double) = Store : &:r0_43, r0_45 +# 125| r0_47(glval) = VariableAddress[x] : +# 125| r0_48(double) = Load : &:r0_47, ~mu0_2 +# 125| r0_49(glval) = VariableAddress[z] : +# 125| r0_50(double) = Load : &:r0_49, ~mu0_2 +# 125| r0_51(double) = Sub : r0_50, r0_48 +# 125| mu0_52(double) = Store : &:r0_49, r0_51 +# 126| r0_53(glval) = VariableAddress[x] : +# 126| r0_54(double) = Load : &:r0_53, ~mu0_2 +# 126| r0_55(glval) = VariableAddress[z] : +# 126| r0_56(double) = Load : &:r0_55, ~mu0_2 +# 126| r0_57(double) = Mul : r0_56, r0_54 +# 126| mu0_58(double) = Store : &:r0_55, r0_57 +# 127| r0_59(glval) = VariableAddress[x] : +# 127| r0_60(double) = Load : &:r0_59, ~mu0_2 +# 127| r0_61(glval) = VariableAddress[z] : +# 127| r0_62(double) = Load : &:r0_61, ~mu0_2 +# 127| r0_63(double) = Div : r0_62, r0_60 +# 127| mu0_64(double) = Store : &:r0_61, r0_63 +# 129| r0_65(glval) = VariableAddress[x] : +# 129| r0_66(double) = Load : &:r0_65, ~mu0_2 +# 129| r0_67(double) = CopyValue : r0_66 +# 129| r0_68(glval) = VariableAddress[z] : +# 129| mu0_69(double) = Store : &:r0_68, r0_67 +# 130| r0_70(glval) = VariableAddress[x] : +# 130| r0_71(double) = Load : &:r0_70, ~mu0_2 +# 130| r0_72(double) = Negate : r0_71 +# 130| r0_73(glval) = VariableAddress[z] : +# 130| mu0_74(double) = Store : &:r0_73, r0_72 +# 131| v0_75(void) = NoOp : +# 114| v0_76(void) = ReturnVoid : +# 114| v0_77(void) = UnmodeledUse : mu* +# 114| v0_78(void) = ExitFunction : # 133| void FloatCompare(double, double) # 133| Block 0 @@ -670,51 +619,45 @@ ir.cpp: # 136| r0_13(bool) = CompareEQ : r0_10, r0_12 # 136| r0_14(glval) = VariableAddress[b] : # 136| mu0_15(bool) = Store : &:r0_14, r0_13 -# 136| r0_16(glval) = CopyValue : r0_14 -# 137| r0_17(glval) = VariableAddress[x] : -# 137| r0_18(double) = Load : &:r0_17, ~mu0_2 -# 137| r0_19(glval) = VariableAddress[y] : -# 137| r0_20(double) = Load : &:r0_19, ~mu0_2 -# 137| r0_21(bool) = CompareNE : r0_18, r0_20 -# 137| r0_22(glval) = VariableAddress[b] : -# 137| mu0_23(bool) = Store : &:r0_22, r0_21 -# 137| r0_24(glval) = CopyValue : r0_22 -# 138| r0_25(glval) = VariableAddress[x] : +# 137| r0_16(glval) = VariableAddress[x] : +# 137| r0_17(double) = Load : &:r0_16, ~mu0_2 +# 137| r0_18(glval) = VariableAddress[y] : +# 137| r0_19(double) = Load : &:r0_18, ~mu0_2 +# 137| r0_20(bool) = CompareNE : r0_17, r0_19 +# 137| r0_21(glval) = VariableAddress[b] : +# 137| mu0_22(bool) = Store : &:r0_21, r0_20 +# 138| r0_23(glval) = VariableAddress[x] : +# 138| r0_24(double) = Load : &:r0_23, ~mu0_2 +# 138| r0_25(glval) = VariableAddress[y] : # 138| r0_26(double) = Load : &:r0_25, ~mu0_2 -# 138| r0_27(glval) = VariableAddress[y] : -# 138| r0_28(double) = Load : &:r0_27, ~mu0_2 -# 138| r0_29(bool) = CompareLT : r0_26, r0_28 -# 138| r0_30(glval) = VariableAddress[b] : -# 138| mu0_31(bool) = Store : &:r0_30, r0_29 -# 138| r0_32(glval) = CopyValue : r0_30 -# 139| r0_33(glval) = VariableAddress[x] : -# 139| r0_34(double) = Load : &:r0_33, ~mu0_2 -# 139| r0_35(glval) = VariableAddress[y] : -# 139| r0_36(double) = Load : &:r0_35, ~mu0_2 -# 139| r0_37(bool) = CompareGT : r0_34, r0_36 -# 139| r0_38(glval) = VariableAddress[b] : -# 139| mu0_39(bool) = Store : &:r0_38, r0_37 -# 139| r0_40(glval) = CopyValue : r0_38 -# 140| r0_41(glval) = VariableAddress[x] : -# 140| r0_42(double) = Load : &:r0_41, ~mu0_2 -# 140| r0_43(glval) = VariableAddress[y] : -# 140| r0_44(double) = Load : &:r0_43, ~mu0_2 -# 140| r0_45(bool) = CompareLE : r0_42, r0_44 -# 140| r0_46(glval) = VariableAddress[b] : -# 140| mu0_47(bool) = Store : &:r0_46, r0_45 -# 140| r0_48(glval) = CopyValue : r0_46 -# 141| r0_49(glval) = VariableAddress[x] : -# 141| r0_50(double) = Load : &:r0_49, ~mu0_2 -# 141| r0_51(glval) = VariableAddress[y] : -# 141| r0_52(double) = Load : &:r0_51, ~mu0_2 -# 141| r0_53(bool) = CompareGE : r0_50, r0_52 -# 141| r0_54(glval) = VariableAddress[b] : -# 141| mu0_55(bool) = Store : &:r0_54, r0_53 -# 141| r0_56(glval) = CopyValue : r0_54 -# 142| v0_57(void) = NoOp : -# 133| v0_58(void) = ReturnVoid : -# 133| v0_59(void) = UnmodeledUse : mu* -# 133| v0_60(void) = ExitFunction : +# 138| r0_27(bool) = CompareLT : r0_24, r0_26 +# 138| r0_28(glval) = VariableAddress[b] : +# 138| mu0_29(bool) = Store : &:r0_28, r0_27 +# 139| r0_30(glval) = VariableAddress[x] : +# 139| r0_31(double) = Load : &:r0_30, ~mu0_2 +# 139| r0_32(glval) = VariableAddress[y] : +# 139| r0_33(double) = Load : &:r0_32, ~mu0_2 +# 139| r0_34(bool) = CompareGT : r0_31, r0_33 +# 139| r0_35(glval) = VariableAddress[b] : +# 139| mu0_36(bool) = Store : &:r0_35, r0_34 +# 140| r0_37(glval) = VariableAddress[x] : +# 140| r0_38(double) = Load : &:r0_37, ~mu0_2 +# 140| r0_39(glval) = VariableAddress[y] : +# 140| r0_40(double) = Load : &:r0_39, ~mu0_2 +# 140| r0_41(bool) = CompareLE : r0_38, r0_40 +# 140| r0_42(glval) = VariableAddress[b] : +# 140| mu0_43(bool) = Store : &:r0_42, r0_41 +# 141| r0_44(glval) = VariableAddress[x] : +# 141| r0_45(double) = Load : &:r0_44, ~mu0_2 +# 141| r0_46(glval) = VariableAddress[y] : +# 141| r0_47(double) = Load : &:r0_46, ~mu0_2 +# 141| r0_48(bool) = CompareGE : r0_45, r0_47 +# 141| r0_49(glval) = VariableAddress[b] : +# 141| mu0_50(bool) = Store : &:r0_49, r0_48 +# 142| v0_51(void) = NoOp : +# 133| v0_52(void) = ReturnVoid : +# 133| v0_53(void) = UnmodeledUse : mu* +# 133| v0_54(void) = ExitFunction : # 144| void FloatCrement(float) # 144| Block 0 @@ -732,35 +675,31 @@ ir.cpp: # 147| mu0_11(float) = Store : &:r0_7, r0_10 # 147| r0_12(glval) = VariableAddress[y] : # 147| mu0_13(float) = Store : &:r0_12, r0_10 -# 147| r0_14(glval) = CopyValue : r0_12 -# 148| r0_15(glval) = VariableAddress[x] : -# 148| r0_16(float) = Load : &:r0_15, ~mu0_2 -# 148| r0_17(float) = Constant[1.0] : -# 148| r0_18(float) = Sub : r0_16, r0_17 -# 148| mu0_19(float) = Store : &:r0_15, r0_18 -# 148| r0_20(glval) = VariableAddress[y] : -# 148| mu0_21(float) = Store : &:r0_20, r0_18 -# 148| r0_22(glval) = CopyValue : r0_20 -# 149| r0_23(glval) = VariableAddress[x] : -# 149| r0_24(float) = Load : &:r0_23, ~mu0_2 -# 149| r0_25(float) = Constant[1.0] : -# 149| r0_26(float) = Add : r0_24, r0_25 -# 149| mu0_27(float) = Store : &:r0_23, r0_26 -# 149| r0_28(glval) = VariableAddress[y] : -# 149| mu0_29(float) = Store : &:r0_28, r0_24 -# 149| r0_30(glval) = CopyValue : r0_28 -# 150| r0_31(glval) = VariableAddress[x] : -# 150| r0_32(float) = Load : &:r0_31, ~mu0_2 -# 150| r0_33(float) = Constant[1.0] : -# 150| r0_34(float) = Sub : r0_32, r0_33 -# 150| mu0_35(float) = Store : &:r0_31, r0_34 -# 150| r0_36(glval) = VariableAddress[y] : -# 150| mu0_37(float) = Store : &:r0_36, r0_32 -# 150| r0_38(glval) = CopyValue : r0_36 -# 151| v0_39(void) = NoOp : -# 144| v0_40(void) = ReturnVoid : -# 144| v0_41(void) = UnmodeledUse : mu* -# 144| v0_42(void) = ExitFunction : +# 148| r0_14(glval) = VariableAddress[x] : +# 148| r0_15(float) = Load : &:r0_14, ~mu0_2 +# 148| r0_16(float) = Constant[1.0] : +# 148| r0_17(float) = Sub : r0_15, r0_16 +# 148| mu0_18(float) = Store : &:r0_14, r0_17 +# 148| r0_19(glval) = VariableAddress[y] : +# 148| mu0_20(float) = Store : &:r0_19, r0_17 +# 149| r0_21(glval) = VariableAddress[x] : +# 149| r0_22(float) = Load : &:r0_21, ~mu0_2 +# 149| r0_23(float) = Constant[1.0] : +# 149| r0_24(float) = Add : r0_22, r0_23 +# 149| mu0_25(float) = Store : &:r0_21, r0_24 +# 149| r0_26(glval) = VariableAddress[y] : +# 149| mu0_27(float) = Store : &:r0_26, r0_22 +# 150| r0_28(glval) = VariableAddress[x] : +# 150| r0_29(float) = Load : &:r0_28, ~mu0_2 +# 150| r0_30(float) = Constant[1.0] : +# 150| r0_31(float) = Sub : r0_29, r0_30 +# 150| mu0_32(float) = Store : &:r0_28, r0_31 +# 150| r0_33(glval) = VariableAddress[y] : +# 150| mu0_34(float) = Store : &:r0_33, r0_29 +# 151| v0_35(void) = NoOp : +# 144| v0_36(void) = ReturnVoid : +# 144| v0_37(void) = UnmodeledUse : mu* +# 144| v0_38(void) = ExitFunction : # 153| void PointerOps(int*, int) # 153| Block 0 @@ -782,70 +721,61 @@ ir.cpp: # 157| r0_15(int *) = PointerAdd[4] : r0_12, r0_14 # 157| r0_16(glval) = VariableAddress[q] : # 157| mu0_17(int *) = Store : &:r0_16, r0_15 -# 157| r0_18(glval) = CopyValue : r0_16 -# 158| r0_19(glval) = VariableAddress[i] : -# 158| r0_20(int) = Load : &:r0_19, ~mu0_2 -# 158| r0_21(glval) = VariableAddress[p] : -# 158| r0_22(int *) = Load : &:r0_21, ~mu0_2 -# 158| r0_23(int *) = PointerAdd[4] : r0_22, r0_20 -# 158| r0_24(glval) = VariableAddress[q] : -# 158| mu0_25(int *) = Store : &:r0_24, r0_23 -# 158| r0_26(glval) = CopyValue : r0_24 -# 159| r0_27(glval) = VariableAddress[p] : -# 159| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 159| r0_29(glval) = VariableAddress[i] : -# 159| r0_30(int) = Load : &:r0_29, ~mu0_2 -# 159| r0_31(int *) = PointerSub[4] : r0_28, r0_30 -# 159| r0_32(glval) = VariableAddress[q] : -# 159| mu0_33(int *) = Store : &:r0_32, r0_31 -# 159| r0_34(glval) = CopyValue : r0_32 -# 160| r0_35(glval) = VariableAddress[p] : -# 160| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 160| r0_37(glval) = VariableAddress[q] : -# 160| r0_38(int *) = Load : &:r0_37, ~mu0_2 -# 160| r0_39(long) = PointerDiff[4] : r0_36, r0_38 -# 160| r0_40(int) = Convert : r0_39 -# 160| r0_41(glval) = VariableAddress[i] : -# 160| mu0_42(int) = Store : &:r0_41, r0_40 -# 160| r0_43(glval) = CopyValue : r0_41 -# 162| r0_44(glval) = VariableAddress[p] : -# 162| r0_45(int *) = Load : &:r0_44, ~mu0_2 -# 162| r0_46(glval) = VariableAddress[q] : -# 162| mu0_47(int *) = Store : &:r0_46, r0_45 -# 162| r0_48(glval) = CopyValue : r0_46 -# 164| r0_49(glval) = VariableAddress[i] : -# 164| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 164| r0_51(glval) = VariableAddress[q] : -# 164| r0_52(int *) = Load : &:r0_51, ~mu0_2 -# 164| r0_53(int *) = PointerAdd[4] : r0_52, r0_50 -# 164| mu0_54(int *) = Store : &:r0_51, r0_53 -# 164| r0_55(glval) = CopyValue : r0_51 -# 165| r0_56(glval) = VariableAddress[i] : -# 165| r0_57(int) = Load : &:r0_56, ~mu0_2 -# 165| r0_58(glval) = VariableAddress[q] : -# 165| r0_59(int *) = Load : &:r0_58, ~mu0_2 -# 165| r0_60(int *) = PointerSub[4] : r0_59, r0_57 -# 165| mu0_61(int *) = Store : &:r0_58, r0_60 -# 165| r0_62(glval) = CopyValue : r0_58 -# 167| r0_63(glval) = VariableAddress[p] : -# 167| r0_64(int *) = Load : &:r0_63, ~mu0_2 -# 167| r0_65(int *) = Constant[0] : -# 167| r0_66(bool) = CompareNE : r0_64, r0_65 -# 167| r0_67(glval) = VariableAddress[b] : -# 167| mu0_68(bool) = Store : &:r0_67, r0_66 -# 167| r0_69(glval) = CopyValue : r0_67 -# 168| r0_70(glval) = VariableAddress[p] : -# 168| r0_71(int *) = Load : &:r0_70, ~mu0_2 -# 168| r0_72(int *) = Constant[0] : -# 168| r0_73(bool) = CompareNE : r0_71, r0_72 -# 168| r0_74(bool) = LogicalNot : r0_73 -# 168| r0_75(glval) = VariableAddress[b] : -# 168| mu0_76(bool) = Store : &:r0_75, r0_74 -# 168| r0_77(glval) = CopyValue : r0_75 -# 169| v0_78(void) = NoOp : -# 153| v0_79(void) = ReturnVoid : -# 153| v0_80(void) = UnmodeledUse : mu* -# 153| v0_81(void) = ExitFunction : +# 158| r0_18(glval) = VariableAddress[i] : +# 158| r0_19(int) = Load : &:r0_18, ~mu0_2 +# 158| r0_20(glval) = VariableAddress[p] : +# 158| r0_21(int *) = Load : &:r0_20, ~mu0_2 +# 158| r0_22(int *) = PointerAdd[4] : r0_21, r0_19 +# 158| r0_23(glval) = VariableAddress[q] : +# 158| mu0_24(int *) = Store : &:r0_23, r0_22 +# 159| r0_25(glval) = VariableAddress[p] : +# 159| r0_26(int *) = Load : &:r0_25, ~mu0_2 +# 159| r0_27(glval) = VariableAddress[i] : +# 159| r0_28(int) = Load : &:r0_27, ~mu0_2 +# 159| r0_29(int *) = PointerSub[4] : r0_26, r0_28 +# 159| r0_30(glval) = VariableAddress[q] : +# 159| mu0_31(int *) = Store : &:r0_30, r0_29 +# 160| r0_32(glval) = VariableAddress[p] : +# 160| r0_33(int *) = Load : &:r0_32, ~mu0_2 +# 160| r0_34(glval) = VariableAddress[q] : +# 160| r0_35(int *) = Load : &:r0_34, ~mu0_2 +# 160| r0_36(long) = PointerDiff[4] : r0_33, r0_35 +# 160| r0_37(int) = Convert : r0_36 +# 160| r0_38(glval) = VariableAddress[i] : +# 160| mu0_39(int) = Store : &:r0_38, r0_37 +# 162| r0_40(glval) = VariableAddress[p] : +# 162| r0_41(int *) = Load : &:r0_40, ~mu0_2 +# 162| r0_42(glval) = VariableAddress[q] : +# 162| mu0_43(int *) = Store : &:r0_42, r0_41 +# 164| r0_44(glval) = VariableAddress[i] : +# 164| r0_45(int) = Load : &:r0_44, ~mu0_2 +# 164| r0_46(glval) = VariableAddress[q] : +# 164| r0_47(int *) = Load : &:r0_46, ~mu0_2 +# 164| r0_48(int *) = PointerAdd[4] : r0_47, r0_45 +# 164| mu0_49(int *) = Store : &:r0_46, r0_48 +# 165| r0_50(glval) = VariableAddress[i] : +# 165| r0_51(int) = Load : &:r0_50, ~mu0_2 +# 165| r0_52(glval) = VariableAddress[q] : +# 165| r0_53(int *) = Load : &:r0_52, ~mu0_2 +# 165| r0_54(int *) = PointerSub[4] : r0_53, r0_51 +# 165| mu0_55(int *) = Store : &:r0_52, r0_54 +# 167| r0_56(glval) = VariableAddress[p] : +# 167| r0_57(int *) = Load : &:r0_56, ~mu0_2 +# 167| r0_58(int *) = Constant[0] : +# 167| r0_59(bool) = CompareNE : r0_57, r0_58 +# 167| r0_60(glval) = VariableAddress[b] : +# 167| mu0_61(bool) = Store : &:r0_60, r0_59 +# 168| r0_62(glval) = VariableAddress[p] : +# 168| r0_63(int *) = Load : &:r0_62, ~mu0_2 +# 168| r0_64(int *) = Constant[0] : +# 168| r0_65(bool) = CompareNE : r0_63, r0_64 +# 168| r0_66(bool) = LogicalNot : r0_65 +# 168| r0_67(glval) = VariableAddress[b] : +# 168| mu0_68(bool) = Store : &:r0_67, r0_66 +# 169| v0_69(void) = NoOp : +# 153| v0_70(void) = ReturnVoid : +# 153| v0_71(void) = UnmodeledUse : mu* +# 153| v0_72(void) = ExitFunction : # 171| void ArrayAccess(int*, int) # 171| Block 0 @@ -866,76 +796,68 @@ ir.cpp: # 174| r0_14(int) = Load : &:r0_13, ~mu0_2 # 174| r0_15(glval) = VariableAddress[x] : # 174| mu0_16(int) = Store : &:r0_15, r0_14 -# 174| r0_17(glval) = CopyValue : r0_15 -# 175| r0_18(glval) = VariableAddress[p] : -# 175| r0_19(int *) = Load : &:r0_18, ~mu0_2 -# 175| r0_20(glval) = VariableAddress[i] : -# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 -# 175| r0_22(glval) = PointerAdd[4] : r0_19, r0_21 -# 175| r0_23(int) = Load : &:r0_22, ~mu0_2 -# 175| r0_24(glval) = VariableAddress[x] : -# 175| mu0_25(int) = Store : &:r0_24, r0_23 -# 175| r0_26(glval) = CopyValue : r0_24 -# 177| r0_27(glval) = VariableAddress[x] : -# 177| r0_28(int) = Load : &:r0_27, ~mu0_2 -# 177| r0_29(glval) = VariableAddress[p] : -# 177| r0_30(int *) = Load : &:r0_29, ~mu0_2 -# 177| r0_31(glval) = VariableAddress[i] : -# 177| r0_32(int) = Load : &:r0_31, ~mu0_2 -# 177| r0_33(glval) = PointerAdd[4] : r0_30, r0_32 -# 177| mu0_34(int) = Store : &:r0_33, r0_28 -# 177| r0_35(glval) = CopyValue : r0_33 -# 178| r0_36(glval) = VariableAddress[x] : -# 178| r0_37(int) = Load : &:r0_36, ~mu0_2 -# 178| r0_38(glval) = VariableAddress[p] : -# 178| r0_39(int *) = Load : &:r0_38, ~mu0_2 -# 178| r0_40(glval) = VariableAddress[i] : -# 178| r0_41(int) = Load : &:r0_40, ~mu0_2 -# 178| r0_42(glval) = PointerAdd[4] : r0_39, r0_41 -# 178| mu0_43(int) = Store : &:r0_42, r0_37 -# 178| r0_44(glval) = CopyValue : r0_42 -# 180| r0_45(glval) = VariableAddress[a] : -# 180| mu0_46(int[10]) = Uninitialized[a] : &:r0_45 -# 181| r0_47(glval) = VariableAddress[a] : -# 181| r0_48(int *) = Convert : r0_47 -# 181| r0_49(glval) = VariableAddress[i] : -# 181| r0_50(int) = Load : &:r0_49, ~mu0_2 -# 181| r0_51(glval) = PointerAdd[4] : r0_48, r0_50 -# 181| r0_52(int) = Load : &:r0_51, ~mu0_2 -# 181| r0_53(glval) = VariableAddress[x] : -# 181| mu0_54(int) = Store : &:r0_53, r0_52 -# 181| r0_55(glval) = CopyValue : r0_53 -# 182| r0_56(glval) = VariableAddress[a] : -# 182| r0_57(int *) = Convert : r0_56 -# 182| r0_58(glval) = VariableAddress[i] : -# 182| r0_59(int) = Load : &:r0_58, ~mu0_2 -# 182| r0_60(glval) = PointerAdd[4] : r0_57, r0_59 -# 182| r0_61(int) = Load : &:r0_60, ~mu0_2 -# 182| r0_62(glval) = VariableAddress[x] : -# 182| mu0_63(int) = Store : &:r0_62, r0_61 -# 182| r0_64(glval) = CopyValue : r0_62 -# 183| r0_65(glval) = VariableAddress[x] : -# 183| r0_66(int) = Load : &:r0_65, ~mu0_2 -# 183| r0_67(glval) = VariableAddress[a] : -# 183| r0_68(int *) = Convert : r0_67 -# 183| r0_69(glval) = VariableAddress[i] : -# 183| r0_70(int) = Load : &:r0_69, ~mu0_2 -# 183| r0_71(glval) = PointerAdd[4] : r0_68, r0_70 -# 183| mu0_72(int) = Store : &:r0_71, r0_66 -# 183| r0_73(glval) = CopyValue : r0_71 -# 184| r0_74(glval) = VariableAddress[x] : -# 184| r0_75(int) = Load : &:r0_74, ~mu0_2 -# 184| r0_76(glval) = VariableAddress[a] : -# 184| r0_77(int *) = Convert : r0_76 -# 184| r0_78(glval) = VariableAddress[i] : -# 184| r0_79(int) = Load : &:r0_78, ~mu0_2 -# 184| r0_80(glval) = PointerAdd[4] : r0_77, r0_79 -# 184| mu0_81(int) = Store : &:r0_80, r0_75 -# 184| r0_82(glval) = CopyValue : r0_80 -# 185| v0_83(void) = NoOp : -# 171| v0_84(void) = ReturnVoid : -# 171| v0_85(void) = UnmodeledUse : mu* -# 171| v0_86(void) = ExitFunction : +# 175| r0_17(glval) = VariableAddress[p] : +# 175| r0_18(int *) = Load : &:r0_17, ~mu0_2 +# 175| r0_19(glval) = VariableAddress[i] : +# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 175| r0_21(glval) = PointerAdd[4] : r0_18, r0_20 +# 175| r0_22(int) = Load : &:r0_21, ~mu0_2 +# 175| r0_23(glval) = VariableAddress[x] : +# 175| mu0_24(int) = Store : &:r0_23, r0_22 +# 177| r0_25(glval) = VariableAddress[x] : +# 177| r0_26(int) = Load : &:r0_25, ~mu0_2 +# 177| r0_27(glval) = VariableAddress[p] : +# 177| r0_28(int *) = Load : &:r0_27, ~mu0_2 +# 177| r0_29(glval) = VariableAddress[i] : +# 177| r0_30(int) = Load : &:r0_29, ~mu0_2 +# 177| r0_31(glval) = PointerAdd[4] : r0_28, r0_30 +# 177| mu0_32(int) = Store : &:r0_31, r0_26 +# 178| r0_33(glval) = VariableAddress[x] : +# 178| r0_34(int) = Load : &:r0_33, ~mu0_2 +# 178| r0_35(glval) = VariableAddress[p] : +# 178| r0_36(int *) = Load : &:r0_35, ~mu0_2 +# 178| r0_37(glval) = VariableAddress[i] : +# 178| r0_38(int) = Load : &:r0_37, ~mu0_2 +# 178| r0_39(glval) = PointerAdd[4] : r0_36, r0_38 +# 178| mu0_40(int) = Store : &:r0_39, r0_34 +# 180| r0_41(glval) = VariableAddress[a] : +# 180| mu0_42(int[10]) = Uninitialized[a] : &:r0_41 +# 181| r0_43(glval) = VariableAddress[a] : +# 181| r0_44(int *) = Convert : r0_43 +# 181| r0_45(glval) = VariableAddress[i] : +# 181| r0_46(int) = Load : &:r0_45, ~mu0_2 +# 181| r0_47(glval) = PointerAdd[4] : r0_44, r0_46 +# 181| r0_48(int) = Load : &:r0_47, ~mu0_2 +# 181| r0_49(glval) = VariableAddress[x] : +# 181| mu0_50(int) = Store : &:r0_49, r0_48 +# 182| r0_51(glval) = VariableAddress[a] : +# 182| r0_52(int *) = Convert : r0_51 +# 182| r0_53(glval) = VariableAddress[i] : +# 182| r0_54(int) = Load : &:r0_53, ~mu0_2 +# 182| r0_55(glval) = PointerAdd[4] : r0_52, r0_54 +# 182| r0_56(int) = Load : &:r0_55, ~mu0_2 +# 182| r0_57(glval) = VariableAddress[x] : +# 182| mu0_58(int) = Store : &:r0_57, r0_56 +# 183| r0_59(glval) = VariableAddress[x] : +# 183| r0_60(int) = Load : &:r0_59, ~mu0_2 +# 183| r0_61(glval) = VariableAddress[a] : +# 183| r0_62(int *) = Convert : r0_61 +# 183| r0_63(glval) = VariableAddress[i] : +# 183| r0_64(int) = Load : &:r0_63, ~mu0_2 +# 183| r0_65(glval) = PointerAdd[4] : r0_62, r0_64 +# 183| mu0_66(int) = Store : &:r0_65, r0_60 +# 184| r0_67(glval) = VariableAddress[x] : +# 184| r0_68(int) = Load : &:r0_67, ~mu0_2 +# 184| r0_69(glval) = VariableAddress[a] : +# 184| r0_70(int *) = Convert : r0_69 +# 184| r0_71(glval) = VariableAddress[i] : +# 184| r0_72(int) = Load : &:r0_71, ~mu0_2 +# 184| r0_73(glval) = PointerAdd[4] : r0_70, r0_72 +# 184| mu0_74(int) = Store : &:r0_73, r0_68 +# 185| v0_75(void) = NoOp : +# 171| v0_76(void) = ReturnVoid : +# 171| v0_77(void) = UnmodeledUse : mu* +# 171| v0_78(void) = ExitFunction : # 187| void StringLiteral(int) # 187| Block 0 @@ -988,51 +910,45 @@ ir.cpp: # 196| r0_13(bool) = CompareEQ : r0_10, r0_12 # 196| r0_14(glval) = VariableAddress[b] : # 196| mu0_15(bool) = Store : &:r0_14, r0_13 -# 196| r0_16(glval) = CopyValue : r0_14 -# 197| r0_17(glval) = VariableAddress[p] : -# 197| r0_18(int *) = Load : &:r0_17, ~mu0_2 -# 197| r0_19(glval) = VariableAddress[q] : -# 197| r0_20(int *) = Load : &:r0_19, ~mu0_2 -# 197| r0_21(bool) = CompareNE : r0_18, r0_20 -# 197| r0_22(glval) = VariableAddress[b] : -# 197| mu0_23(bool) = Store : &:r0_22, r0_21 -# 197| r0_24(glval) = CopyValue : r0_22 -# 198| r0_25(glval) = VariableAddress[p] : +# 197| r0_16(glval) = VariableAddress[p] : +# 197| r0_17(int *) = Load : &:r0_16, ~mu0_2 +# 197| r0_18(glval) = VariableAddress[q] : +# 197| r0_19(int *) = Load : &:r0_18, ~mu0_2 +# 197| r0_20(bool) = CompareNE : r0_17, r0_19 +# 197| r0_21(glval) = VariableAddress[b] : +# 197| mu0_22(bool) = Store : &:r0_21, r0_20 +# 198| r0_23(glval) = VariableAddress[p] : +# 198| r0_24(int *) = Load : &:r0_23, ~mu0_2 +# 198| r0_25(glval) = VariableAddress[q] : # 198| r0_26(int *) = Load : &:r0_25, ~mu0_2 -# 198| r0_27(glval) = VariableAddress[q] : -# 198| r0_28(int *) = Load : &:r0_27, ~mu0_2 -# 198| r0_29(bool) = CompareLT : r0_26, r0_28 -# 198| r0_30(glval) = VariableAddress[b] : -# 198| mu0_31(bool) = Store : &:r0_30, r0_29 -# 198| r0_32(glval) = CopyValue : r0_30 -# 199| r0_33(glval) = VariableAddress[p] : -# 199| r0_34(int *) = Load : &:r0_33, ~mu0_2 -# 199| r0_35(glval) = VariableAddress[q] : -# 199| r0_36(int *) = Load : &:r0_35, ~mu0_2 -# 199| r0_37(bool) = CompareGT : r0_34, r0_36 -# 199| r0_38(glval) = VariableAddress[b] : -# 199| mu0_39(bool) = Store : &:r0_38, r0_37 -# 199| r0_40(glval) = CopyValue : r0_38 -# 200| r0_41(glval) = VariableAddress[p] : -# 200| r0_42(int *) = Load : &:r0_41, ~mu0_2 -# 200| r0_43(glval) = VariableAddress[q] : -# 200| r0_44(int *) = Load : &:r0_43, ~mu0_2 -# 200| r0_45(bool) = CompareLE : r0_42, r0_44 -# 200| r0_46(glval) = VariableAddress[b] : -# 200| mu0_47(bool) = Store : &:r0_46, r0_45 -# 200| r0_48(glval) = CopyValue : r0_46 -# 201| r0_49(glval) = VariableAddress[p] : -# 201| r0_50(int *) = Load : &:r0_49, ~mu0_2 -# 201| r0_51(glval) = VariableAddress[q] : -# 201| r0_52(int *) = Load : &:r0_51, ~mu0_2 -# 201| r0_53(bool) = CompareGE : r0_50, r0_52 -# 201| r0_54(glval) = VariableAddress[b] : -# 201| mu0_55(bool) = Store : &:r0_54, r0_53 -# 201| r0_56(glval) = CopyValue : r0_54 -# 202| v0_57(void) = NoOp : -# 193| v0_58(void) = ReturnVoid : -# 193| v0_59(void) = UnmodeledUse : mu* -# 193| v0_60(void) = ExitFunction : +# 198| r0_27(bool) = CompareLT : r0_24, r0_26 +# 198| r0_28(glval) = VariableAddress[b] : +# 198| mu0_29(bool) = Store : &:r0_28, r0_27 +# 199| r0_30(glval) = VariableAddress[p] : +# 199| r0_31(int *) = Load : &:r0_30, ~mu0_2 +# 199| r0_32(glval) = VariableAddress[q] : +# 199| r0_33(int *) = Load : &:r0_32, ~mu0_2 +# 199| r0_34(bool) = CompareGT : r0_31, r0_33 +# 199| r0_35(glval) = VariableAddress[b] : +# 199| mu0_36(bool) = Store : &:r0_35, r0_34 +# 200| r0_37(glval) = VariableAddress[p] : +# 200| r0_38(int *) = Load : &:r0_37, ~mu0_2 +# 200| r0_39(glval) = VariableAddress[q] : +# 200| r0_40(int *) = Load : &:r0_39, ~mu0_2 +# 200| r0_41(bool) = CompareLE : r0_38, r0_40 +# 200| r0_42(glval) = VariableAddress[b] : +# 200| mu0_43(bool) = Store : &:r0_42, r0_41 +# 201| r0_44(glval) = VariableAddress[p] : +# 201| r0_45(int *) = Load : &:r0_44, ~mu0_2 +# 201| r0_46(glval) = VariableAddress[q] : +# 201| r0_47(int *) = Load : &:r0_46, ~mu0_2 +# 201| r0_48(bool) = CompareGE : r0_45, r0_47 +# 201| r0_49(glval) = VariableAddress[b] : +# 201| mu0_50(bool) = Store : &:r0_49, r0_48 +# 202| v0_51(void) = NoOp : +# 193| v0_52(void) = ReturnVoid : +# 193| v0_53(void) = UnmodeledUse : mu* +# 193| v0_54(void) = ExitFunction : # 204| void PointerCrement(int*) # 204| Block 0 @@ -1050,35 +966,31 @@ ir.cpp: # 207| mu0_11(int *) = Store : &:r0_7, r0_10 # 207| r0_12(glval) = VariableAddress[q] : # 207| mu0_13(int *) = Store : &:r0_12, r0_10 -# 207| r0_14(glval) = CopyValue : r0_12 -# 208| r0_15(glval) = VariableAddress[p] : -# 208| r0_16(int *) = Load : &:r0_15, ~mu0_2 -# 208| r0_17(int) = Constant[1] : -# 208| r0_18(int *) = PointerSub[4] : r0_16, r0_17 -# 208| mu0_19(int *) = Store : &:r0_15, r0_18 -# 208| r0_20(glval) = VariableAddress[q] : -# 208| mu0_21(int *) = Store : &:r0_20, r0_18 -# 208| r0_22(glval) = CopyValue : r0_20 -# 209| r0_23(glval) = VariableAddress[p] : -# 209| r0_24(int *) = Load : &:r0_23, ~mu0_2 -# 209| r0_25(int) = Constant[1] : -# 209| r0_26(int *) = PointerAdd[4] : r0_24, r0_25 -# 209| mu0_27(int *) = Store : &:r0_23, r0_26 -# 209| r0_28(glval) = VariableAddress[q] : -# 209| mu0_29(int *) = Store : &:r0_28, r0_24 -# 209| r0_30(glval) = CopyValue : r0_28 -# 210| r0_31(glval) = VariableAddress[p] : -# 210| r0_32(int *) = Load : &:r0_31, ~mu0_2 -# 210| r0_33(int) = Constant[1] : -# 210| r0_34(int *) = PointerSub[4] : r0_32, r0_33 -# 210| mu0_35(int *) = Store : &:r0_31, r0_34 -# 210| r0_36(glval) = VariableAddress[q] : -# 210| mu0_37(int *) = Store : &:r0_36, r0_32 -# 210| r0_38(glval) = CopyValue : r0_36 -# 211| v0_39(void) = NoOp : -# 204| v0_40(void) = ReturnVoid : -# 204| v0_41(void) = UnmodeledUse : mu* -# 204| v0_42(void) = ExitFunction : +# 208| r0_14(glval) = VariableAddress[p] : +# 208| r0_15(int *) = Load : &:r0_14, ~mu0_2 +# 208| r0_16(int) = Constant[1] : +# 208| r0_17(int *) = PointerSub[4] : r0_15, r0_16 +# 208| mu0_18(int *) = Store : &:r0_14, r0_17 +# 208| r0_19(glval) = VariableAddress[q] : +# 208| mu0_20(int *) = Store : &:r0_19, r0_17 +# 209| r0_21(glval) = VariableAddress[p] : +# 209| r0_22(int *) = Load : &:r0_21, ~mu0_2 +# 209| r0_23(int) = Constant[1] : +# 209| r0_24(int *) = PointerAdd[4] : r0_22, r0_23 +# 209| mu0_25(int *) = Store : &:r0_21, r0_24 +# 209| r0_26(glval) = VariableAddress[q] : +# 209| mu0_27(int *) = Store : &:r0_26, r0_22 +# 210| r0_28(glval) = VariableAddress[p] : +# 210| r0_29(int *) = Load : &:r0_28, ~mu0_2 +# 210| r0_30(int) = Constant[1] : +# 210| r0_31(int *) = PointerSub[4] : r0_29, r0_30 +# 210| mu0_32(int *) = Store : &:r0_28, r0_31 +# 210| r0_33(glval) = VariableAddress[q] : +# 210| mu0_34(int *) = Store : &:r0_33, r0_29 +# 211| v0_35(void) = NoOp : +# 204| v0_36(void) = ReturnVoid : +# 204| v0_37(void) = UnmodeledUse : mu* +# 204| v0_38(void) = ExitFunction : # 213| void CompoundAssignment() # 213| Block 0 @@ -1093,40 +1005,36 @@ ir.cpp: # 216| r0_8(int) = Load : &:r0_7, ~mu0_2 # 216| r0_9(int) = Add : r0_8, r0_6 # 216| mu0_10(int) = Store : &:r0_7, r0_9 -# 216| r0_11(glval) = CopyValue : r0_7 -# 219| r0_12(glval) = VariableAddress[y] : -# 219| r0_13(short) = Constant[5] : -# 219| mu0_14(short) = Store : &:r0_12, r0_13 -# 220| r0_15(glval) = VariableAddress[x] : -# 220| r0_16(int) = Load : &:r0_15, ~mu0_2 -# 220| r0_17(glval) = VariableAddress[y] : -# 220| r0_18(short) = Load : &:r0_17, ~mu0_2 -# 220| r0_19(int) = Convert : r0_18 -# 220| r0_20(int) = Add : r0_19, r0_16 -# 220| r0_21(short) = Convert : r0_20 -# 220| mu0_22(short) = Store : &:r0_17, r0_21 -# 220| r0_23(glval) = CopyValue : r0_17 -# 223| r0_24(int) = Constant[1] : -# 223| r0_25(glval) = VariableAddress[y] : -# 223| r0_26(short) = Load : &:r0_25, ~mu0_2 -# 223| r0_27(short) = ShiftLeft : r0_26, r0_24 -# 223| mu0_28(short) = Store : &:r0_25, r0_27 -# 223| r0_29(glval) = CopyValue : r0_25 -# 226| r0_30(glval) = VariableAddress[z] : -# 226| r0_31(long) = Constant[7] : -# 226| mu0_32(long) = Store : &:r0_30, r0_31 -# 227| r0_33(float) = Constant[2.0] : -# 227| r0_34(glval) = VariableAddress[z] : -# 227| r0_35(long) = Load : &:r0_34, ~mu0_2 -# 227| r0_36(float) = Convert : r0_35 -# 227| r0_37(float) = Add : r0_36, r0_33 -# 227| r0_38(long) = Convert : r0_37 -# 227| mu0_39(long) = Store : &:r0_34, r0_38 -# 227| r0_40(glval) = CopyValue : r0_34 -# 228| v0_41(void) = NoOp : -# 213| v0_42(void) = ReturnVoid : -# 213| v0_43(void) = UnmodeledUse : mu* -# 213| v0_44(void) = ExitFunction : +# 219| r0_11(glval) = VariableAddress[y] : +# 219| r0_12(short) = Constant[5] : +# 219| mu0_13(short) = Store : &:r0_11, r0_12 +# 220| r0_14(glval) = VariableAddress[x] : +# 220| r0_15(int) = Load : &:r0_14, ~mu0_2 +# 220| r0_16(glval) = VariableAddress[y] : +# 220| r0_17(short) = Load : &:r0_16, ~mu0_2 +# 220| r0_18(int) = Convert : r0_17 +# 220| r0_19(int) = Add : r0_18, r0_15 +# 220| r0_20(short) = Convert : r0_19 +# 220| mu0_21(short) = Store : &:r0_16, r0_20 +# 223| r0_22(int) = Constant[1] : +# 223| r0_23(glval) = VariableAddress[y] : +# 223| r0_24(short) = Load : &:r0_23, ~mu0_2 +# 223| r0_25(short) = ShiftLeft : r0_24, r0_22 +# 223| mu0_26(short) = Store : &:r0_23, r0_25 +# 226| r0_27(glval) = VariableAddress[z] : +# 226| r0_28(long) = Constant[7] : +# 226| mu0_29(long) = Store : &:r0_27, r0_28 +# 227| r0_30(float) = Constant[2.0] : +# 227| r0_31(glval) = VariableAddress[z] : +# 227| r0_32(long) = Load : &:r0_31, ~mu0_2 +# 227| r0_33(float) = Convert : r0_32 +# 227| r0_34(float) = Add : r0_33, r0_30 +# 227| r0_35(long) = Convert : r0_34 +# 227| mu0_36(long) = Store : &:r0_31, r0_35 +# 228| v0_37(void) = NoOp : +# 213| v0_38(void) = ReturnVoid : +# 213| v0_39(void) = UnmodeledUse : mu* +# 213| v0_40(void) = ExitFunction : # 230| void UninitializedVariables() # 230| Block 0 @@ -1194,7 +1102,6 @@ ir.cpp: # 244| r2_1(int) = Load : &:r2_0, ~mu0_2 # 244| r2_2(glval) = VariableAddress[x] : # 244| mu2_3(int) = Store : &:r2_2, r2_1 -# 244| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 247| Block 3 @@ -1210,14 +1117,12 @@ ir.cpp: # 248| r4_0(int) = Constant[2] : # 248| r4_1(glval) = VariableAddress[x] : # 248| mu4_2(int) = Store : &:r4_1, r4_0 -# 248| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 250| Block 5 # 250| r5_0(int) = Constant[7] : # 250| r5_1(glval) = VariableAddress[x] : # 250| mu5_2(int) = Store : &:r5_1, r5_0 -# 250| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 251| Block 6 @@ -1245,7 +1150,6 @@ ir.cpp: # 255| r1_2(int) = Load : &:r1_1, ~mu0_2 # 255| r1_3(int) = Sub : r1_2, r1_0 # 255| mu1_4(int) = Store : &:r1_1, r1_3 -# 255| r1_5(glval) = CopyValue : r1_1 #-----| Goto (back edge) -> Block 3 # 257| Block 2 @@ -1278,12 +1182,11 @@ ir.cpp: # 261| r1_2(int) = Load : &:r1_1, ~mu0_2 # 261| r1_3(int) = Sub : r1_2, r1_0 # 261| mu1_4(int) = Store : &:r1_1, r1_3 -# 261| r1_5(glval) = CopyValue : r1_1 -# 262| r1_6(glval) = VariableAddress[n] : -# 262| r1_7(int) = Load : &:r1_6, ~mu0_2 -# 262| r1_8(int) = Constant[0] : -# 262| r1_9(bool) = CompareGT : r1_7, r1_8 -# 262| v1_10(void) = ConditionalBranch : r1_9 +# 262| r1_5(glval) = VariableAddress[n] : +# 262| r1_6(int) = Load : &:r1_5, ~mu0_2 +# 262| r1_7(int) = Constant[0] : +# 262| r1_8(bool) = CompareGT : r1_6, r1_7 +# 262| v1_9(void) = ConditionalBranch : r1_8 #-----| False -> Block 2 #-----| True (back edge) -> Block 1 @@ -1381,7 +1284,6 @@ ir.cpp: # 287| r2_3(int) = Load : &:r2_2, ~mu0_2 # 287| r2_4(int) = Add : r2_3, r2_1 # 287| mu2_5(int) = Store : &:r2_2, r2_4 -# 287| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 292| void For_InitCondition() @@ -1435,7 +1337,6 @@ ir.cpp: # 299| r2_3(int) = Load : &:r2_2, ~mu0_2 # 299| r2_4(int) = Add : r2_3, r2_1 # 299| mu2_5(int) = Store : &:r2_2, r2_4 -# 299| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 2 # 304| void For_ConditionUpdate() @@ -1464,7 +1365,6 @@ ir.cpp: # 306| r2_3(int) = Load : &:r2_2, ~mu0_2 # 306| r2_4(int) = Add : r2_3, r2_1 # 306| mu2_5(int) = Store : &:r2_2, r2_4 -# 306| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 309| Block 3 @@ -1499,7 +1399,6 @@ ir.cpp: # 312| r2_3(int) = Load : &:r2_2, ~mu0_2 # 312| r2_4(int) = Add : r2_3, r2_1 # 312| mu2_5(int) = Store : &:r2_2, r2_4 -# 312| r2_6(glval) = CopyValue : r2_2 #-----| Goto (back edge) -> Block 1 # 315| Block 3 @@ -1533,7 +1432,6 @@ ir.cpp: # 318| r2_2(int) = Load : &:r2_1, ~mu0_2 # 318| r2_3(int) = Add : r2_2, r2_0 # 318| mu2_4(int) = Store : &:r2_1, r2_3 -# 318| r2_5(glval) = CopyValue : r2_1 #-----| Goto (back edge) -> Block 1 # 319| Block 3 @@ -1595,7 +1493,6 @@ ir.cpp: # 326| r4_3(int) = Load : &:r4_2, ~mu0_2 # 326| r4_4(int) = Add : r4_3, r4_1 # 326| mu4_5(int) = Store : &:r4_2, r4_4 -# 326| r4_6(glval) = CopyValue : r4_2 #-----| Goto (back edge) -> Block 1 # 331| Block 5 @@ -1658,16 +1555,15 @@ ir.cpp: # 342| r0_7(int *) = Load : &:r0_6, ~mu0_2 # 342| r0_8(glval) = CopyValue : r0_7 # 342| mu0_9(int) = Store : &:r0_8, r0_5 -# 342| r0_10(glval) = CopyValue : r0_8 -# 343| r0_11(glval) = VariableAddress[#return] : -# 343| r0_12(glval) = VariableAddress[p] : -# 343| r0_13(int *) = Load : &:r0_12, ~mu0_2 -# 343| r0_14(int) = Load : &:r0_13, ~mu0_2 -# 343| mu0_15(int) = Store : &:r0_11, r0_14 -# 341| r0_16(glval) = VariableAddress[#return] : -# 341| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 -# 341| v0_18(void) = UnmodeledUse : mu* -# 341| v0_19(void) = ExitFunction : +# 343| r0_10(glval) = VariableAddress[#return] : +# 343| r0_11(glval) = VariableAddress[p] : +# 343| r0_12(int *) = Load : &:r0_11, ~mu0_2 +# 343| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 343| mu0_14(int) = Store : &:r0_10, r0_13 +# 341| r0_15(glval) = VariableAddress[#return] : +# 341| v0_16(void) = ReturnValue : &:r0_15, ~mu0_2 +# 341| v0_17(void) = UnmodeledUse : mu* +# 341| v0_18(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -1711,7 +1607,6 @@ ir.cpp: # 356| r3_2(int) = Load : &:r3_1, ~mu0_2 # 356| r3_3(int) = Sub : r3_2, r3_0 # 356| mu3_4(int) = Store : &:r3_1, r3_3 -# 356| r3_5(glval) = CopyValue : r3_1 #-----| Goto (back edge) -> Block 5 # 357| Block 4 @@ -1758,7 +1653,6 @@ ir.cpp: # 365| r3_2(int) = Load : &:r3_1, ~mu0_2 # 365| r3_3(int) = Sub : r3_2, r3_0 # 365| mu3_4(int) = Store : &:r3_1, r3_3 -# 365| r3_5(glval) = CopyValue : r3_1 #-----| Goto -> Block 4 # 361| Block 4 @@ -1863,7 +1757,6 @@ ir.cpp: # 387| r1_0(int) = Constant[1234] : # 387| r1_1(glval) = VariableAddress[y] : # 387| mu1_2(int) = Store : &:r1_1, r1_0 -# 387| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 389| Block 2 @@ -1871,8 +1764,7 @@ ir.cpp: # 390| r2_1(int) = Constant[-1] : # 390| r2_2(glval) = VariableAddress[y] : # 390| mu2_3(int) = Store : &:r2_2, r2_1 -# 390| r2_4(glval) = CopyValue : r2_2 -# 391| v2_5(void) = NoOp : +# 391| v2_4(void) = NoOp : #-----| Goto -> Block 9 # 393| Block 3 @@ -1884,8 +1776,7 @@ ir.cpp: # 395| r4_1(int) = Constant[1] : # 395| r4_2(glval) = VariableAddress[y] : # 395| mu4_3(int) = Store : &:r4_2, r4_1 -# 395| r4_4(glval) = CopyValue : r4_2 -# 396| v4_5(void) = NoOp : +# 396| v4_4(void) = NoOp : #-----| Goto -> Block 9 # 398| Block 5 @@ -1893,7 +1784,6 @@ ir.cpp: # 399| r5_1(int) = Constant[3] : # 399| r5_2(glval) = VariableAddress[y] : # 399| mu5_3(int) = Store : &:r5_2, r5_1 -# 399| r5_4(glval) = CopyValue : r5_2 #-----| Goto -> Block 6 # 400| Block 6 @@ -1901,8 +1791,7 @@ ir.cpp: # 401| r6_1(int) = Constant[4] : # 401| r6_2(glval) = VariableAddress[y] : # 401| mu6_3(int) = Store : &:r6_2, r6_1 -# 401| r6_4(glval) = CopyValue : r6_2 -# 402| v6_5(void) = NoOp : +# 402| v6_4(void) = NoOp : #-----| Goto -> Block 9 # 404| Block 7 @@ -1910,15 +1799,13 @@ ir.cpp: # 405| r7_1(int) = Constant[0] : # 405| r7_2(glval) = VariableAddress[y] : # 405| mu7_3(int) = Store : &:r7_2, r7_1 -# 405| r7_4(glval) = CopyValue : r7_2 -# 406| v7_5(void) = NoOp : +# 406| v7_4(void) = NoOp : #-----| Goto -> Block 9 # 408| Block 8 # 408| r8_0(int) = Constant[5678] : # 408| r8_1(glval) = VariableAddress[y] : # 408| mu8_2(int) = Store : &:r8_1, r8_0 -# 408| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 9 # 409| Block 9 @@ -1955,23 +1842,21 @@ ir.cpp: # 428| r0_6(glval) = VariableAddress[pt] : # 428| r0_7(glval) = FieldAddress[x] : r0_6 # 428| mu0_8(int) = Store : &:r0_7, r0_5 -# 428| r0_9(glval) = CopyValue : r0_7 -# 429| r0_10(glval) = VariableAddress[pt] : -# 429| r0_11(glval) = FieldAddress[x] : r0_10 -# 429| r0_12(int) = Load : &:r0_11, ~mu0_2 -# 429| r0_13(glval) = VariableAddress[pt] : -# 429| r0_14(glval) = FieldAddress[y] : r0_13 -# 429| mu0_15(int) = Store : &:r0_14, r0_12 -# 429| r0_16(glval) = CopyValue : r0_14 -# 430| r0_17(glval) = VariableAddress[p] : -# 430| r0_18(glval) = VariableAddress[pt] : -# 430| r0_19(glval) = FieldAddress[y] : r0_18 -# 430| r0_20(int *) = CopyValue : r0_19 -# 430| mu0_21(int *) = Store : &:r0_17, r0_20 -# 431| v0_22(void) = NoOp : -# 426| v0_23(void) = ReturnVoid : -# 426| v0_24(void) = UnmodeledUse : mu* -# 426| v0_25(void) = ExitFunction : +# 429| r0_9(glval) = VariableAddress[pt] : +# 429| r0_10(glval) = FieldAddress[x] : r0_9 +# 429| r0_11(int) = Load : &:r0_10, ~mu0_2 +# 429| r0_12(glval) = VariableAddress[pt] : +# 429| r0_13(glval) = FieldAddress[y] : r0_12 +# 429| mu0_14(int) = Store : &:r0_13, r0_11 +# 430| r0_15(glval) = VariableAddress[p] : +# 430| r0_16(glval) = VariableAddress[pt] : +# 430| r0_17(glval) = FieldAddress[y] : r0_16 +# 430| r0_18(int *) = CopyValue : r0_17 +# 430| mu0_19(int *) = Store : &:r0_15, r0_18 +# 431| v0_20(void) = NoOp : +# 426| v0_21(void) = ReturnVoid : +# 426| v0_22(void) = UnmodeledUse : mu* +# 426| v0_23(void) = ExitFunction : # 433| void LogicalOr(bool, bool) # 433| Block 0 @@ -2001,7 +1886,6 @@ ir.cpp: # 436| r2_0(int) = Constant[7] : # 436| r2_1(glval) = VariableAddress[x] : # 436| mu2_2(int) = Store : &:r2_1, r2_0 -# 436| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 439| Block 3 @@ -2022,14 +1906,12 @@ ir.cpp: # 440| r5_0(int) = Constant[1] : # 440| r5_1(glval) = VariableAddress[x] : # 440| mu5_2(int) = Store : &:r5_1, r5_0 -# 440| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 443| Block 6 # 443| r6_0(int) = Constant[5] : # 443| r6_1(glval) = VariableAddress[x] : # 443| mu6_2(int) = Store : &:r6_1, r6_0 -# 443| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 445| Block 7 @@ -2066,7 +1948,6 @@ ir.cpp: # 450| r2_0(int) = Constant[7] : # 450| r2_1(glval) = VariableAddress[x] : # 450| mu2_2(int) = Store : &:r2_1, r2_0 -# 450| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 453| Block 3 @@ -2087,14 +1968,12 @@ ir.cpp: # 454| r5_0(int) = Constant[1] : # 454| r5_1(glval) = VariableAddress[x] : # 454| mu5_2(int) = Store : &:r5_1, r5_0 -# 454| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 7 # 457| Block 6 # 457| r6_0(int) = Constant[5] : # 457| r6_1(glval) = VariableAddress[x] : # 457| mu6_2(int) = Store : &:r6_1, r6_0 -# 457| r6_3(glval) = CopyValue : r6_1 #-----| Goto -> Block 7 # 459| Block 7 @@ -2124,7 +2003,6 @@ ir.cpp: # 464| r1_0(int) = Constant[1] : # 464| r1_1(glval) = VariableAddress[x] : # 464| mu1_2(int) = Store : &:r1_1, r1_0 -# 464| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 2 # 467| Block 2 @@ -2145,14 +2023,12 @@ ir.cpp: # 468| r4_0(int) = Constant[2] : # 468| r4_1(glval) = VariableAddress[x] : # 468| mu4_2(int) = Store : &:r4_1, r4_0 -# 468| r4_3(glval) = CopyValue : r4_1 #-----| Goto -> Block 6 # 471| Block 5 # 471| r5_0(int) = Constant[3] : # 471| r5_1(glval) = VariableAddress[x] : # 471| mu5_2(int) = Store : &:r5_1, r5_0 -# 471| r5_3(glval) = CopyValue : r5_1 #-----| Goto -> Block 6 # 473| Block 6 @@ -2196,10 +2072,9 @@ ir.cpp: # 478| r3_1(bool) = Load : &:r3_0, ~mu0_2 # 478| r3_2(glval) = VariableAddress[x] : # 478| mu3_3(bool) = Store : &:r3_2, r3_1 -# 478| r3_4(glval) = CopyValue : r3_2 -# 479| r3_5(glval) = VariableAddress[a] : -# 479| r3_6(bool) = Load : &:r3_5, ~mu0_2 -# 479| v3_7(void) = ConditionalBranch : r3_6 +# 479| r3_4(glval) = VariableAddress[a] : +# 479| r3_5(bool) = Load : &:r3_4, ~mu0_2 +# 479| v3_6(void) = ConditionalBranch : r3_5 #-----| False -> Block 9 #-----| True -> Block 8 @@ -2228,11 +2103,10 @@ ir.cpp: # 479| r7_2(bool) = LogicalNot : r7_1 # 479| r7_3(glval) = VariableAddress[x] : # 479| mu7_4(bool) = Store : &:r7_3, r7_2 -# 479| r7_5(glval) = CopyValue : r7_3 -# 480| v7_6(void) = NoOp : -# 475| v7_7(void) = ReturnVoid : -# 475| v7_8(void) = UnmodeledUse : mu* -# 475| v7_9(void) = ExitFunction : +# 480| v7_5(void) = NoOp : +# 475| v7_6(void) = ReturnVoid : +# 475| v7_7(void) = UnmodeledUse : mu* +# 475| v7_8(void) = ExitFunction : # 479| Block 8 # 479| r8_0(glval) = VariableAddress[#temp479:11] : @@ -2258,10 +2132,9 @@ ir.cpp: # 477| r11_1(bool) = Load : &:r11_0, ~mu0_2 # 477| r11_2(glval) = VariableAddress[x] : # 477| mu11_3(bool) = Store : &:r11_2, r11_1 -# 477| r11_4(glval) = CopyValue : r11_2 -# 478| r11_5(glval) = VariableAddress[a] : -# 478| r11_6(bool) = Load : &:r11_5, ~mu0_2 -# 478| v11_7(void) = ConditionalBranch : r11_6 +# 478| r11_4(glval) = VariableAddress[a] : +# 478| r11_5(bool) = Load : &:r11_4, ~mu0_2 +# 478| v11_6(void) = ConditionalBranch : r11_5 #-----| False -> Block 5 #-----| True -> Block 4 @@ -2334,11 +2207,10 @@ ir.cpp: # 489| r1_0(glval) = VariableAddress[#temp489:6] : # 489| r1_1(glval) = Load : &:r1_0, ~mu0_2 # 489| mu1_2(int) = Store : &:r1_1, r0_9 -# 489| r1_3(glval) = CopyValue : r1_1 -# 490| v1_4(void) = NoOp : -# 486| v1_5(void) = ReturnVoid : -# 486| v1_6(void) = UnmodeledUse : mu* -# 486| v1_7(void) = ExitFunction : +# 490| v1_3(void) = NoOp : +# 486| v1_4(void) = ReturnVoid : +# 486| v1_5(void) = UnmodeledUse : mu* +# 486| v1_6(void) = ExitFunction : # 489| Block 2 # 489| r2_0(glval) = VariableAddress[x] : @@ -2397,15 +2269,13 @@ ir.cpp: # 499| r0_9(int *) = Constant[0] : # 499| r0_10(glval) = VariableAddress[p] : # 499| mu0_11(int *) = Store : &:r0_10, r0_9 -# 499| r0_12(glval) = CopyValue : r0_10 -# 500| r0_13(int *) = Constant[0] : -# 500| r0_14(glval) = VariableAddress[q] : -# 500| mu0_15(int *) = Store : &:r0_14, r0_13 -# 500| r0_16(glval) = CopyValue : r0_14 -# 501| v0_17(void) = NoOp : -# 496| v0_18(void) = ReturnVoid : -# 496| v0_19(void) = UnmodeledUse : mu* -# 496| v0_20(void) = ExitFunction : +# 500| r0_12(int *) = Constant[0] : +# 500| r0_13(glval) = VariableAddress[q] : +# 500| mu0_14(int *) = Store : &:r0_13, r0_12 +# 501| v0_15(void) = NoOp : +# 496| v0_16(void) = ReturnVoid : +# 496| v0_17(void) = UnmodeledUse : mu* +# 496| v0_18(void) = ExitFunction : # 503| void InitList(int, float) # 503| Block 0 @@ -2633,8 +2503,7 @@ ir.cpp: # 540| r3_1(int) = Load : &:r3_0, ~mu0_2 # 540| r3_2(glval) = VariableAddress[y] : # 540| mu3_3(int) = Store : &:r3_2, r3_1 -# 540| r3_4(glval) = CopyValue : r3_2 -# 541| v3_5(void) = NoOp : +# 541| v3_4(void) = NoOp : #-----| Goto -> Block 1 # 543| int EarlyReturnValue(int, int) @@ -2837,24 +2706,21 @@ ir.cpp: # 592| r0_7(..(*)(..)) = CopyValue : r0_6 # 592| r0_8(glval<..(*)(..)>) = VariableAddress[pfn] : # 592| mu0_9(..(*)(..)) = Store : &:r0_8, r0_7 -# 592| r0_10(glval<..(*)(..)>) = CopyValue : r0_8 -# 593| r0_11(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : -# 593| r0_12(..(*)(..)) = CopyValue : r0_11 -# 593| r0_13(glval<..(*)(..)>) = VariableAddress[pfn] : -# 593| mu0_14(..(*)(..)) = Store : &:r0_13, r0_12 -# 593| r0_15(glval<..(*)(..)>) = CopyValue : r0_13 -# 594| r0_16(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 593| r0_10(glval<..(*)(..)>) = FunctionAddress[FuncPtrTarget] : +# 593| r0_11(..(*)(..)) = CopyValue : r0_10 +# 593| r0_12(glval<..(*)(..)>) = VariableAddress[pfn] : +# 593| mu0_13(..(*)(..)) = Store : &:r0_12, r0_11 +# 594| r0_14(glval<..()(..)>) = FunctionAddress[FuncPtrTarget] : +# 594| r0_15(..(*)(..)) = CopyValue : r0_14 +# 594| r0_16(..(*)(..)) = CopyValue : r0_15 # 594| r0_17(..(*)(..)) = CopyValue : r0_16 # 594| r0_18(..(*)(..)) = CopyValue : r0_17 -# 594| r0_19(..(*)(..)) = CopyValue : r0_18 -# 594| r0_20(..(*)(..)) = CopyValue : r0_19 -# 594| r0_21(glval<..(*)(..)>) = VariableAddress[pfn] : -# 594| mu0_22(..(*)(..)) = Store : &:r0_21, r0_20 -# 594| r0_23(glval<..(*)(..)>) = CopyValue : r0_21 -# 595| v0_24(void) = NoOp : -# 590| v0_25(void) = ReturnVoid : -# 590| v0_26(void) = UnmodeledUse : mu* -# 590| v0_27(void) = ExitFunction : +# 594| r0_19(glval<..(*)(..)>) = VariableAddress[pfn] : +# 594| mu0_20(..(*)(..)) = Store : &:r0_19, r0_18 +# 595| v0_21(void) = NoOp : +# 590| v0_22(void) = ReturnVoid : +# 590| v0_23(void) = UnmodeledUse : mu* +# 590| v0_24(void) = ExitFunction : # 615| void DeclareObject() # 615| Block 0 @@ -2991,43 +2857,37 @@ ir.cpp: # 643| r0_5(C *) = CopyValue : r0_3 # 643| r0_6(glval) = FieldAddress[m_a] : r0_5 # 643| mu0_7(int) = Store : &:r0_6, r0_4 -# 643| r0_8(glval) = CopyValue : r0_6 -# 644| r0_9(int) = Constant[1] : -# 644| r0_10(C *) = CopyValue : r0_3 -# 644| r0_11(glval) = CopyValue : r0_10 -# 644| r0_12(glval) = FieldAddress[m_a] : r0_11 -# 644| mu0_13(int) = Store : &:r0_12, r0_9 -# 644| r0_14(glval) = CopyValue : r0_12 -# 645| r0_15(int) = Constant[2] : -#-----| r0_16(C *) = CopyValue : r0_3 -# 645| r0_17(glval) = FieldAddress[m_a] : r0_16 -# 645| mu0_18(int) = Store : &:r0_17, r0_15 -# 645| r0_19(glval) = CopyValue : r0_17 -# 646| r0_20(glval) = VariableAddress[x] : -# 646| mu0_21(int) = Uninitialized[x] : &:r0_20 -# 647| r0_22(C *) = CopyValue : r0_3 -# 647| r0_23(glval) = FieldAddress[m_a] : r0_22 -# 647| r0_24(int) = Load : &:r0_23, ~mu0_2 -# 647| r0_25(glval) = VariableAddress[x] : -# 647| mu0_26(int) = Store : &:r0_25, r0_24 -# 647| r0_27(glval) = CopyValue : r0_25 -# 648| r0_28(C *) = CopyValue : r0_3 -# 648| r0_29(glval) = CopyValue : r0_28 -# 648| r0_30(glval) = FieldAddress[m_a] : r0_29 -# 648| r0_31(int) = Load : &:r0_30, ~mu0_2 -# 648| r0_32(glval) = VariableAddress[x] : -# 648| mu0_33(int) = Store : &:r0_32, r0_31 -# 648| r0_34(glval) = CopyValue : r0_32 -#-----| r0_35(C *) = CopyValue : r0_3 -# 649| r0_36(glval) = FieldAddress[m_a] : r0_35 -# 649| r0_37(int) = Load : &:r0_36, ~mu0_2 -# 649| r0_38(glval) = VariableAddress[x] : -# 649| mu0_39(int) = Store : &:r0_38, r0_37 -# 649| r0_40(glval) = CopyValue : r0_38 -# 650| v0_41(void) = NoOp : -# 642| v0_42(void) = ReturnVoid : -# 642| v0_43(void) = UnmodeledUse : mu* -# 642| v0_44(void) = ExitFunction : +# 644| r0_8(int) = Constant[1] : +# 644| r0_9(C *) = CopyValue : r0_3 +# 644| r0_10(glval) = CopyValue : r0_9 +# 644| r0_11(glval) = FieldAddress[m_a] : r0_10 +# 644| mu0_12(int) = Store : &:r0_11, r0_8 +# 645| r0_13(int) = Constant[2] : +#-----| r0_14(C *) = CopyValue : r0_3 +# 645| r0_15(glval) = FieldAddress[m_a] : r0_14 +# 645| mu0_16(int) = Store : &:r0_15, r0_13 +# 646| r0_17(glval) = VariableAddress[x] : +# 646| mu0_18(int) = Uninitialized[x] : &:r0_17 +# 647| r0_19(C *) = CopyValue : r0_3 +# 647| r0_20(glval) = FieldAddress[m_a] : r0_19 +# 647| r0_21(int) = Load : &:r0_20, ~mu0_2 +# 647| r0_22(glval) = VariableAddress[x] : +# 647| mu0_23(int) = Store : &:r0_22, r0_21 +# 648| r0_24(C *) = CopyValue : r0_3 +# 648| r0_25(glval) = CopyValue : r0_24 +# 648| r0_26(glval) = FieldAddress[m_a] : r0_25 +# 648| r0_27(int) = Load : &:r0_26, ~mu0_2 +# 648| r0_28(glval) = VariableAddress[x] : +# 648| mu0_29(int) = Store : &:r0_28, r0_27 +#-----| r0_30(C *) = CopyValue : r0_3 +# 649| r0_31(glval) = FieldAddress[m_a] : r0_30 +# 649| r0_32(int) = Load : &:r0_31, ~mu0_2 +# 649| r0_33(glval) = VariableAddress[x] : +# 649| mu0_34(int) = Store : &:r0_33, r0_32 +# 650| v0_35(void) = NoOp : +# 642| v0_36(void) = ReturnVoid : +# 642| v0_37(void) = UnmodeledUse : mu* +# 642| v0_38(void) = ExitFunction : # 652| void C::MethodCalls() # 652| Block 0 @@ -3363,7 +3223,6 @@ ir.cpp: # 731| r6_4(int) = Load : &:r6_3, ~mu0_2 # 731| r6_5(glval) = VariableAddress[x] : # 731| mu6_6(int) = Store : &:r6_5, r6_4 -# 731| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 731| Block 7 @@ -3382,7 +3241,6 @@ ir.cpp: # 733| r8_0(int) = Constant[7] : # 733| r8_1(glval) = VariableAddress[x] : # 733| mu8_2(int) = Store : &:r8_1, r8_0 -# 733| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 14 # 735| Block 9 @@ -3898,219 +3756,203 @@ ir.cpp: # 811| r0_79(Base *) = ConvertToBase[Middle : Base] : r0_78 # 811| r0_80(glval) = VariableAddress[pb] : # 811| mu0_81(Base *) = Store : &:r0_80, r0_79 -# 811| r0_82(glval) = CopyValue : r0_80 -# 812| r0_83(glval) = VariableAddress[pm] : -# 812| r0_84(Middle *) = Load : &:r0_83, ~mu0_2 -# 812| r0_85(Base *) = ConvertToBase[Middle : Base] : r0_84 -# 812| r0_86(glval) = VariableAddress[pb] : -# 812| mu0_87(Base *) = Store : &:r0_86, r0_85 -# 812| r0_88(glval) = CopyValue : r0_86 -# 813| r0_89(glval) = VariableAddress[pm] : -# 813| r0_90(Middle *) = Load : &:r0_89, ~mu0_2 -# 813| r0_91(Base *) = ConvertToBase[Middle : Base] : r0_90 -# 813| r0_92(glval) = VariableAddress[pb] : -# 813| mu0_93(Base *) = Store : &:r0_92, r0_91 -# 813| r0_94(glval) = CopyValue : r0_92 -# 814| r0_95(glval) = VariableAddress[pm] : -# 814| r0_96(Middle *) = Load : &:r0_95, ~mu0_2 -# 814| r0_97(Base *) = Convert : r0_96 -# 814| r0_98(glval) = VariableAddress[pb] : -# 814| mu0_99(Base *) = Store : &:r0_98, r0_97 -# 814| r0_100(glval) = CopyValue : r0_98 -# 816| r0_101(glval) = VariableAddress[m] : -# 816| r0_102(glval) = FunctionAddress[operator=] : -# 816| r0_103(glval) = VariableAddress[b] : -# 816| r0_104(glval) = ConvertToDerived[Middle : Base] : r0_103 -# 816| r0_105(glval) = Convert : r0_104 -# 816| r0_106(Middle &) = CopyValue : r0_105 -# 816| r0_107(Middle &) = Call : func:r0_102, this:r0_101, 0:r0_106 -# 816| mu0_108(unknown) = ^CallSideEffect : ~mu0_2 -# 816| v0_109(void) = ^IndirectReadSideEffect[-1] : &:r0_101, ~mu0_2 -# 816| v0_110(void) = ^IndirectReadSideEffect[0] : &:r0_106, ~mu0_2 -# 816| mu0_111(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_101 -# 816| mu0_112(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_106 -# 816| r0_113(glval) = CopyValue : r0_107 -# 817| r0_114(glval) = VariableAddress[m] : -# 817| r0_115(glval) = FunctionAddress[operator=] : -# 817| r0_116(glval) = VariableAddress[b] : -# 817| r0_117(glval) = ConvertToDerived[Middle : Base] : r0_116 -# 817| r0_118(glval) = Convert : r0_117 -# 817| r0_119(Middle &) = CopyValue : r0_118 -# 817| r0_120(Middle &) = Call : func:r0_115, this:r0_114, 0:r0_119 -# 817| mu0_121(unknown) = ^CallSideEffect : ~mu0_2 -# 817| v0_122(void) = ^IndirectReadSideEffect[-1] : &:r0_114, ~mu0_2 -# 817| v0_123(void) = ^IndirectReadSideEffect[0] : &:r0_119, ~mu0_2 -# 817| mu0_124(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_114 -# 817| mu0_125(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_119 -# 817| r0_126(glval) = CopyValue : r0_120 -# 818| r0_127(glval) = VariableAddress[pb] : -# 818| r0_128(Base *) = Load : &:r0_127, ~mu0_2 -# 818| r0_129(Middle *) = ConvertToDerived[Middle : Base] : r0_128 -# 818| r0_130(glval) = VariableAddress[pm] : -# 818| mu0_131(Middle *) = Store : &:r0_130, r0_129 -# 818| r0_132(glval) = CopyValue : r0_130 -# 819| r0_133(glval) = VariableAddress[pb] : -# 819| r0_134(Base *) = Load : &:r0_133, ~mu0_2 -# 819| r0_135(Middle *) = ConvertToDerived[Middle : Base] : r0_134 -# 819| r0_136(glval) = VariableAddress[pm] : -# 819| mu0_137(Middle *) = Store : &:r0_136, r0_135 -# 819| r0_138(glval) = CopyValue : r0_136 -# 820| r0_139(glval) = VariableAddress[pb] : -# 820| r0_140(Base *) = Load : &:r0_139, ~mu0_2 -# 820| r0_141(Middle *) = Convert : r0_140 -# 820| r0_142(glval) = VariableAddress[pm] : -# 820| mu0_143(Middle *) = Store : &:r0_142, r0_141 -# 820| r0_144(glval) = CopyValue : r0_142 -# 822| r0_145(glval) = VariableAddress[b] : -# 822| r0_146(glval) = FunctionAddress[operator=] : -# 822| r0_147(glval) = VariableAddress[d] : -# 822| r0_148(glval) = ConvertToBase[Derived : Middle] : r0_147 -# 822| r0_149(glval) = ConvertToBase[Middle : Base] : r0_148 -# 822| r0_150(Base &) = CopyValue : r0_149 -# 822| r0_151(Base &) = Call : func:r0_146, this:r0_145, 0:r0_150 -# 822| mu0_152(unknown) = ^CallSideEffect : ~mu0_2 -# 822| v0_153(void) = ^IndirectReadSideEffect[-1] : &:r0_145, ~mu0_2 -# 822| v0_154(void) = ^IndirectReadSideEffect[0] : &:r0_150, ~mu0_2 -# 822| mu0_155(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_145 -# 822| mu0_156(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_150 -# 822| r0_157(glval) = CopyValue : r0_151 -# 823| r0_158(glval) = VariableAddress[b] : -# 823| r0_159(glval) = FunctionAddress[operator=] : -# 823| r0_160(glval) = FunctionAddress[Base] : -# 823| r0_161(glval) = VariableAddress[d] : -# 823| r0_162(glval) = ConvertToBase[Derived : Middle] : r0_161 -# 823| r0_163(glval) = ConvertToBase[Middle : Base] : r0_162 -# 823| r0_164(Base &) = CopyValue : r0_163 -# 823| v0_165(void) = Call : func:r0_160, 0:r0_164 -# 823| mu0_166(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_167(void) = ^IndirectReadSideEffect[0] : &:r0_164, ~mu0_2 -# 823| mu0_168(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_164 -# 823| r0_169(glval) = Convert : v0_165 -# 823| r0_170(Base &) = CopyValue : r0_169 -# 823| r0_171(Base &) = Call : func:r0_159, this:r0_158, 0:r0_170 -# 823| mu0_172(unknown) = ^CallSideEffect : ~mu0_2 -# 823| v0_173(void) = ^IndirectReadSideEffect[-1] : &:r0_158, ~mu0_2 -# 823| v0_174(void) = ^IndirectReadSideEffect[0] : &:r0_170, ~mu0_2 -# 823| mu0_175(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_158 -# 823| mu0_176(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_170 -# 823| r0_177(glval) = CopyValue : r0_171 -# 824| r0_178(glval) = VariableAddress[b] : -# 824| r0_179(glval) = FunctionAddress[operator=] : -# 824| r0_180(glval) = FunctionAddress[Base] : -# 824| r0_181(glval) = VariableAddress[d] : -# 824| r0_182(glval) = ConvertToBase[Derived : Middle] : r0_181 -# 824| r0_183(glval) = ConvertToBase[Middle : Base] : r0_182 -# 824| r0_184(Base &) = CopyValue : r0_183 -# 824| v0_185(void) = Call : func:r0_180, 0:r0_184 -# 824| mu0_186(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_187(void) = ^IndirectReadSideEffect[0] : &:r0_184, ~mu0_2 -# 824| mu0_188(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_184 -# 824| r0_189(glval) = Convert : v0_185 -# 824| r0_190(Base &) = CopyValue : r0_189 -# 824| r0_191(Base &) = Call : func:r0_179, this:r0_178, 0:r0_190 -# 824| mu0_192(unknown) = ^CallSideEffect : ~mu0_2 -# 824| v0_193(void) = ^IndirectReadSideEffect[-1] : &:r0_178, ~mu0_2 -# 824| v0_194(void) = ^IndirectReadSideEffect[0] : &:r0_190, ~mu0_2 -# 824| mu0_195(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_178 -# 824| mu0_196(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_190 -# 824| r0_197(glval) = CopyValue : r0_191 -# 825| r0_198(glval) = VariableAddress[pd] : -# 825| r0_199(Derived *) = Load : &:r0_198, ~mu0_2 -# 825| r0_200(Middle *) = ConvertToBase[Derived : Middle] : r0_199 -# 825| r0_201(Base *) = ConvertToBase[Middle : Base] : r0_200 -# 825| r0_202(glval) = VariableAddress[pb] : -# 825| mu0_203(Base *) = Store : &:r0_202, r0_201 -# 825| r0_204(glval) = CopyValue : r0_202 -# 826| r0_205(glval) = VariableAddress[pd] : -# 826| r0_206(Derived *) = Load : &:r0_205, ~mu0_2 -# 826| r0_207(Middle *) = ConvertToBase[Derived : Middle] : r0_206 -# 826| r0_208(Base *) = ConvertToBase[Middle : Base] : r0_207 -# 826| r0_209(glval) = VariableAddress[pb] : -# 826| mu0_210(Base *) = Store : &:r0_209, r0_208 -# 826| r0_211(glval) = CopyValue : r0_209 -# 827| r0_212(glval) = VariableAddress[pd] : -# 827| r0_213(Derived *) = Load : &:r0_212, ~mu0_2 -# 827| r0_214(Middle *) = ConvertToBase[Derived : Middle] : r0_213 -# 827| r0_215(Base *) = ConvertToBase[Middle : Base] : r0_214 -# 827| r0_216(glval) = VariableAddress[pb] : -# 827| mu0_217(Base *) = Store : &:r0_216, r0_215 -# 827| r0_218(glval) = CopyValue : r0_216 -# 828| r0_219(glval) = VariableAddress[pd] : -# 828| r0_220(Derived *) = Load : &:r0_219, ~mu0_2 -# 828| r0_221(Base *) = Convert : r0_220 -# 828| r0_222(glval) = VariableAddress[pb] : -# 828| mu0_223(Base *) = Store : &:r0_222, r0_221 -# 828| r0_224(glval) = CopyValue : r0_222 -# 830| r0_225(glval) = VariableAddress[d] : -# 830| r0_226(glval) = FunctionAddress[operator=] : -# 830| r0_227(glval) = VariableAddress[b] : -# 830| r0_228(glval) = ConvertToDerived[Middle : Base] : r0_227 -# 830| r0_229(glval) = ConvertToDerived[Derived : Middle] : r0_228 -# 830| r0_230(glval) = Convert : r0_229 -# 830| r0_231(Derived &) = CopyValue : r0_230 -# 830| r0_232(Derived &) = Call : func:r0_226, this:r0_225, 0:r0_231 -# 830| mu0_233(unknown) = ^CallSideEffect : ~mu0_2 -# 830| v0_234(void) = ^IndirectReadSideEffect[-1] : &:r0_225, ~mu0_2 -# 830| v0_235(void) = ^IndirectReadSideEffect[0] : &:r0_231, ~mu0_2 -# 830| mu0_236(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_225 -# 830| mu0_237(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_231 -# 830| r0_238(glval) = CopyValue : r0_232 -# 831| r0_239(glval) = VariableAddress[d] : -# 831| r0_240(glval) = FunctionAddress[operator=] : -# 831| r0_241(glval) = VariableAddress[b] : -# 831| r0_242(glval) = ConvertToDerived[Middle : Base] : r0_241 -# 831| r0_243(glval) = ConvertToDerived[Derived : Middle] : r0_242 -# 831| r0_244(glval) = Convert : r0_243 -# 831| r0_245(Derived &) = CopyValue : r0_244 -# 831| r0_246(Derived &) = Call : func:r0_240, this:r0_239, 0:r0_245 -# 831| mu0_247(unknown) = ^CallSideEffect : ~mu0_2 -# 831| v0_248(void) = ^IndirectReadSideEffect[-1] : &:r0_239, ~mu0_2 -# 831| v0_249(void) = ^IndirectReadSideEffect[0] : &:r0_245, ~mu0_2 -# 831| mu0_250(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_239 -# 831| mu0_251(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_245 -# 831| r0_252(glval) = CopyValue : r0_246 -# 832| r0_253(glval) = VariableAddress[pb] : -# 832| r0_254(Base *) = Load : &:r0_253, ~mu0_2 -# 832| r0_255(Middle *) = ConvertToDerived[Middle : Base] : r0_254 -# 832| r0_256(Derived *) = ConvertToDerived[Derived : Middle] : r0_255 -# 832| r0_257(glval) = VariableAddress[pd] : -# 832| mu0_258(Derived *) = Store : &:r0_257, r0_256 -# 832| r0_259(glval) = CopyValue : r0_257 -# 833| r0_260(glval) = VariableAddress[pb] : -# 833| r0_261(Base *) = Load : &:r0_260, ~mu0_2 -# 833| r0_262(Middle *) = ConvertToDerived[Middle : Base] : r0_261 -# 833| r0_263(Derived *) = ConvertToDerived[Derived : Middle] : r0_262 -# 833| r0_264(glval) = VariableAddress[pd] : -# 833| mu0_265(Derived *) = Store : &:r0_264, r0_263 -# 833| r0_266(glval) = CopyValue : r0_264 -# 834| r0_267(glval) = VariableAddress[pb] : -# 834| r0_268(Base *) = Load : &:r0_267, ~mu0_2 -# 834| r0_269(Derived *) = Convert : r0_268 -# 834| r0_270(glval) = VariableAddress[pd] : -# 834| mu0_271(Derived *) = Store : &:r0_270, r0_269 -# 834| r0_272(glval) = CopyValue : r0_270 -# 836| r0_273(glval) = VariableAddress[pmv] : -# 836| r0_274(MiddleVB1 *) = Constant[0] : -# 836| mu0_275(MiddleVB1 *) = Store : &:r0_273, r0_274 -# 837| r0_276(glval) = VariableAddress[pdv] : -# 837| r0_277(DerivedVB *) = Constant[0] : -# 837| mu0_278(DerivedVB *) = Store : &:r0_276, r0_277 -# 838| r0_279(glval) = VariableAddress[pmv] : -# 838| r0_280(MiddleVB1 *) = Load : &:r0_279, ~mu0_2 -# 838| r0_281(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_280 -# 838| r0_282(glval) = VariableAddress[pb] : -# 838| mu0_283(Base *) = Store : &:r0_282, r0_281 -# 838| r0_284(glval) = CopyValue : r0_282 -# 839| r0_285(glval) = VariableAddress[pdv] : -# 839| r0_286(DerivedVB *) = Load : &:r0_285, ~mu0_2 -# 839| r0_287(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_286 -# 839| r0_288(glval) = VariableAddress[pb] : -# 839| mu0_289(Base *) = Store : &:r0_288, r0_287 -# 839| r0_290(glval) = CopyValue : r0_288 -# 840| v0_291(void) = NoOp : -# 799| v0_292(void) = ReturnVoid : -# 799| v0_293(void) = UnmodeledUse : mu* -# 799| v0_294(void) = ExitFunction : +# 812| r0_82(glval) = VariableAddress[pm] : +# 812| r0_83(Middle *) = Load : &:r0_82, ~mu0_2 +# 812| r0_84(Base *) = ConvertToBase[Middle : Base] : r0_83 +# 812| r0_85(glval) = VariableAddress[pb] : +# 812| mu0_86(Base *) = Store : &:r0_85, r0_84 +# 813| r0_87(glval) = VariableAddress[pm] : +# 813| r0_88(Middle *) = Load : &:r0_87, ~mu0_2 +# 813| r0_89(Base *) = ConvertToBase[Middle : Base] : r0_88 +# 813| r0_90(glval) = VariableAddress[pb] : +# 813| mu0_91(Base *) = Store : &:r0_90, r0_89 +# 814| r0_92(glval) = VariableAddress[pm] : +# 814| r0_93(Middle *) = Load : &:r0_92, ~mu0_2 +# 814| r0_94(Base *) = Convert : r0_93 +# 814| r0_95(glval) = VariableAddress[pb] : +# 814| mu0_96(Base *) = Store : &:r0_95, r0_94 +# 816| r0_97(glval) = VariableAddress[m] : +# 816| r0_98(glval) = FunctionAddress[operator=] : +# 816| r0_99(glval) = VariableAddress[b] : +# 816| r0_100(glval) = ConvertToDerived[Middle : Base] : r0_99 +# 816| r0_101(glval) = Convert : r0_100 +# 816| r0_102(Middle &) = CopyValue : r0_101 +# 816| r0_103(Middle &) = Call : func:r0_98, this:r0_97, 0:r0_102 +# 816| mu0_104(unknown) = ^CallSideEffect : ~mu0_2 +# 816| v0_105(void) = ^IndirectReadSideEffect[-1] : &:r0_97, ~mu0_2 +# 816| v0_106(void) = ^IndirectReadSideEffect[0] : &:r0_102, ~mu0_2 +# 816| mu0_107(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_97 +# 816| mu0_108(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_102 +# 816| r0_109(glval) = CopyValue : r0_103 +# 817| r0_110(glval) = VariableAddress[m] : +# 817| r0_111(glval) = FunctionAddress[operator=] : +# 817| r0_112(glval) = VariableAddress[b] : +# 817| r0_113(glval) = ConvertToDerived[Middle : Base] : r0_112 +# 817| r0_114(glval) = Convert : r0_113 +# 817| r0_115(Middle &) = CopyValue : r0_114 +# 817| r0_116(Middle &) = Call : func:r0_111, this:r0_110, 0:r0_115 +# 817| mu0_117(unknown) = ^CallSideEffect : ~mu0_2 +# 817| v0_118(void) = ^IndirectReadSideEffect[-1] : &:r0_110, ~mu0_2 +# 817| v0_119(void) = ^IndirectReadSideEffect[0] : &:r0_115, ~mu0_2 +# 817| mu0_120(Middle) = ^IndirectMayWriteSideEffect[-1] : &:r0_110 +# 817| mu0_121(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_115 +# 817| r0_122(glval) = CopyValue : r0_116 +# 818| r0_123(glval) = VariableAddress[pb] : +# 818| r0_124(Base *) = Load : &:r0_123, ~mu0_2 +# 818| r0_125(Middle *) = ConvertToDerived[Middle : Base] : r0_124 +# 818| r0_126(glval) = VariableAddress[pm] : +# 818| mu0_127(Middle *) = Store : &:r0_126, r0_125 +# 819| r0_128(glval) = VariableAddress[pb] : +# 819| r0_129(Base *) = Load : &:r0_128, ~mu0_2 +# 819| r0_130(Middle *) = ConvertToDerived[Middle : Base] : r0_129 +# 819| r0_131(glval) = VariableAddress[pm] : +# 819| mu0_132(Middle *) = Store : &:r0_131, r0_130 +# 820| r0_133(glval) = VariableAddress[pb] : +# 820| r0_134(Base *) = Load : &:r0_133, ~mu0_2 +# 820| r0_135(Middle *) = Convert : r0_134 +# 820| r0_136(glval) = VariableAddress[pm] : +# 820| mu0_137(Middle *) = Store : &:r0_136, r0_135 +# 822| r0_138(glval) = VariableAddress[b] : +# 822| r0_139(glval) = FunctionAddress[operator=] : +# 822| r0_140(glval) = VariableAddress[d] : +# 822| r0_141(glval) = ConvertToBase[Derived : Middle] : r0_140 +# 822| r0_142(glval) = ConvertToBase[Middle : Base] : r0_141 +# 822| r0_143(Base &) = CopyValue : r0_142 +# 822| r0_144(Base &) = Call : func:r0_139, this:r0_138, 0:r0_143 +# 822| mu0_145(unknown) = ^CallSideEffect : ~mu0_2 +# 822| v0_146(void) = ^IndirectReadSideEffect[-1] : &:r0_138, ~mu0_2 +# 822| v0_147(void) = ^IndirectReadSideEffect[0] : &:r0_143, ~mu0_2 +# 822| mu0_148(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_138 +# 822| mu0_149(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_143 +# 822| r0_150(glval) = CopyValue : r0_144 +# 823| r0_151(glval) = VariableAddress[b] : +# 823| r0_152(glval) = FunctionAddress[operator=] : +# 823| r0_153(glval) = FunctionAddress[Base] : +# 823| r0_154(glval) = VariableAddress[d] : +# 823| r0_155(glval) = ConvertToBase[Derived : Middle] : r0_154 +# 823| r0_156(glval) = ConvertToBase[Middle : Base] : r0_155 +# 823| r0_157(Base &) = CopyValue : r0_156 +# 823| v0_158(void) = Call : func:r0_153, 0:r0_157 +# 823| mu0_159(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_160(void) = ^IndirectReadSideEffect[0] : &:r0_157, ~mu0_2 +# 823| mu0_161(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_157 +# 823| r0_162(glval) = Convert : v0_158 +# 823| r0_163(Base &) = CopyValue : r0_162 +# 823| r0_164(Base &) = Call : func:r0_152, this:r0_151, 0:r0_163 +# 823| mu0_165(unknown) = ^CallSideEffect : ~mu0_2 +# 823| v0_166(void) = ^IndirectReadSideEffect[-1] : &:r0_151, ~mu0_2 +# 823| v0_167(void) = ^IndirectReadSideEffect[0] : &:r0_163, ~mu0_2 +# 823| mu0_168(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_151 +# 823| mu0_169(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_163 +# 823| r0_170(glval) = CopyValue : r0_164 +# 824| r0_171(glval) = VariableAddress[b] : +# 824| r0_172(glval) = FunctionAddress[operator=] : +# 824| r0_173(glval) = FunctionAddress[Base] : +# 824| r0_174(glval) = VariableAddress[d] : +# 824| r0_175(glval) = ConvertToBase[Derived : Middle] : r0_174 +# 824| r0_176(glval) = ConvertToBase[Middle : Base] : r0_175 +# 824| r0_177(Base &) = CopyValue : r0_176 +# 824| v0_178(void) = Call : func:r0_173, 0:r0_177 +# 824| mu0_179(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_180(void) = ^IndirectReadSideEffect[0] : &:r0_177, ~mu0_2 +# 824| mu0_181(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_177 +# 824| r0_182(glval) = Convert : v0_178 +# 824| r0_183(Base &) = CopyValue : r0_182 +# 824| r0_184(Base &) = Call : func:r0_172, this:r0_171, 0:r0_183 +# 824| mu0_185(unknown) = ^CallSideEffect : ~mu0_2 +# 824| v0_186(void) = ^IndirectReadSideEffect[-1] : &:r0_171, ~mu0_2 +# 824| v0_187(void) = ^IndirectReadSideEffect[0] : &:r0_183, ~mu0_2 +# 824| mu0_188(Base) = ^IndirectMayWriteSideEffect[-1] : &:r0_171 +# 824| mu0_189(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_183 +# 824| r0_190(glval) = CopyValue : r0_184 +# 825| r0_191(glval) = VariableAddress[pd] : +# 825| r0_192(Derived *) = Load : &:r0_191, ~mu0_2 +# 825| r0_193(Middle *) = ConvertToBase[Derived : Middle] : r0_192 +# 825| r0_194(Base *) = ConvertToBase[Middle : Base] : r0_193 +# 825| r0_195(glval) = VariableAddress[pb] : +# 825| mu0_196(Base *) = Store : &:r0_195, r0_194 +# 826| r0_197(glval) = VariableAddress[pd] : +# 826| r0_198(Derived *) = Load : &:r0_197, ~mu0_2 +# 826| r0_199(Middle *) = ConvertToBase[Derived : Middle] : r0_198 +# 826| r0_200(Base *) = ConvertToBase[Middle : Base] : r0_199 +# 826| r0_201(glval) = VariableAddress[pb] : +# 826| mu0_202(Base *) = Store : &:r0_201, r0_200 +# 827| r0_203(glval) = VariableAddress[pd] : +# 827| r0_204(Derived *) = Load : &:r0_203, ~mu0_2 +# 827| r0_205(Middle *) = ConvertToBase[Derived : Middle] : r0_204 +# 827| r0_206(Base *) = ConvertToBase[Middle : Base] : r0_205 +# 827| r0_207(glval) = VariableAddress[pb] : +# 827| mu0_208(Base *) = Store : &:r0_207, r0_206 +# 828| r0_209(glval) = VariableAddress[pd] : +# 828| r0_210(Derived *) = Load : &:r0_209, ~mu0_2 +# 828| r0_211(Base *) = Convert : r0_210 +# 828| r0_212(glval) = VariableAddress[pb] : +# 828| mu0_213(Base *) = Store : &:r0_212, r0_211 +# 830| r0_214(glval) = VariableAddress[d] : +# 830| r0_215(glval) = FunctionAddress[operator=] : +# 830| r0_216(glval) = VariableAddress[b] : +# 830| r0_217(glval) = ConvertToDerived[Middle : Base] : r0_216 +# 830| r0_218(glval) = ConvertToDerived[Derived : Middle] : r0_217 +# 830| r0_219(glval) = Convert : r0_218 +# 830| r0_220(Derived &) = CopyValue : r0_219 +# 830| r0_221(Derived &) = Call : func:r0_215, this:r0_214, 0:r0_220 +# 830| mu0_222(unknown) = ^CallSideEffect : ~mu0_2 +# 830| v0_223(void) = ^IndirectReadSideEffect[-1] : &:r0_214, ~mu0_2 +# 830| v0_224(void) = ^IndirectReadSideEffect[0] : &:r0_220, ~mu0_2 +# 830| mu0_225(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_214 +# 830| mu0_226(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_220 +# 830| r0_227(glval) = CopyValue : r0_221 +# 831| r0_228(glval) = VariableAddress[d] : +# 831| r0_229(glval) = FunctionAddress[operator=] : +# 831| r0_230(glval) = VariableAddress[b] : +# 831| r0_231(glval) = ConvertToDerived[Middle : Base] : r0_230 +# 831| r0_232(glval) = ConvertToDerived[Derived : Middle] : r0_231 +# 831| r0_233(glval) = Convert : r0_232 +# 831| r0_234(Derived &) = CopyValue : r0_233 +# 831| r0_235(Derived &) = Call : func:r0_229, this:r0_228, 0:r0_234 +# 831| mu0_236(unknown) = ^CallSideEffect : ~mu0_2 +# 831| v0_237(void) = ^IndirectReadSideEffect[-1] : &:r0_228, ~mu0_2 +# 831| v0_238(void) = ^IndirectReadSideEffect[0] : &:r0_234, ~mu0_2 +# 831| mu0_239(Derived) = ^IndirectMayWriteSideEffect[-1] : &:r0_228 +# 831| mu0_240(unknown) = ^BufferMayWriteSideEffect[0] : &:r0_234 +# 831| r0_241(glval) = CopyValue : r0_235 +# 832| r0_242(glval) = VariableAddress[pb] : +# 832| r0_243(Base *) = Load : &:r0_242, ~mu0_2 +# 832| r0_244(Middle *) = ConvertToDerived[Middle : Base] : r0_243 +# 832| r0_245(Derived *) = ConvertToDerived[Derived : Middle] : r0_244 +# 832| r0_246(glval) = VariableAddress[pd] : +# 832| mu0_247(Derived *) = Store : &:r0_246, r0_245 +# 833| r0_248(glval) = VariableAddress[pb] : +# 833| r0_249(Base *) = Load : &:r0_248, ~mu0_2 +# 833| r0_250(Middle *) = ConvertToDerived[Middle : Base] : r0_249 +# 833| r0_251(Derived *) = ConvertToDerived[Derived : Middle] : r0_250 +# 833| r0_252(glval) = VariableAddress[pd] : +# 833| mu0_253(Derived *) = Store : &:r0_252, r0_251 +# 834| r0_254(glval) = VariableAddress[pb] : +# 834| r0_255(Base *) = Load : &:r0_254, ~mu0_2 +# 834| r0_256(Derived *) = Convert : r0_255 +# 834| r0_257(glval) = VariableAddress[pd] : +# 834| mu0_258(Derived *) = Store : &:r0_257, r0_256 +# 836| r0_259(glval) = VariableAddress[pmv] : +# 836| r0_260(MiddleVB1 *) = Constant[0] : +# 836| mu0_261(MiddleVB1 *) = Store : &:r0_259, r0_260 +# 837| r0_262(glval) = VariableAddress[pdv] : +# 837| r0_263(DerivedVB *) = Constant[0] : +# 837| mu0_264(DerivedVB *) = Store : &:r0_262, r0_263 +# 838| r0_265(glval) = VariableAddress[pmv] : +# 838| r0_266(MiddleVB1 *) = Load : &:r0_265, ~mu0_2 +# 838| r0_267(Base *) = ConvertToVirtualBase[MiddleVB1 : Base] : r0_266 +# 838| r0_268(glval) = VariableAddress[pb] : +# 838| mu0_269(Base *) = Store : &:r0_268, r0_267 +# 839| r0_270(glval) = VariableAddress[pdv] : +# 839| r0_271(DerivedVB *) = Load : &:r0_270, ~mu0_2 +# 839| r0_272(Base *) = ConvertToVirtualBase[DerivedVB : Base] : r0_271 +# 839| r0_273(glval) = VariableAddress[pb] : +# 839| mu0_274(Base *) = Store : &:r0_273, r0_272 +# 840| v0_275(void) = NoOp : +# 799| v0_276(void) = ReturnVoid : +# 799| v0_277(void) = UnmodeledUse : mu* +# 799| v0_278(void) = ExitFunction : # 842| void PolymorphicBase::PolymorphicBase() # 842| Block 0 @@ -4179,37 +4021,35 @@ ir.cpp: # 857| r0_21(PolymorphicBase *) = CheckedConvertOrNull : r0_20 # 857| r0_22(glval) = VariableAddress[pb] : # 857| mu0_23(PolymorphicBase *) = Store : &:r0_22, r0_21 -# 857| r0_24(glval) = CopyValue : r0_22 -# 858| r0_25(glval) = VariableAddress[rb] : -# 858| r0_26(glval) = VariableAddress[d] : -# 858| r0_27(glval) = CheckedConvertOrThrow : r0_26 -# 858| r0_28(PolymorphicBase &) = CopyValue : r0_27 -# 858| mu0_29(PolymorphicBase &) = Store : &:r0_25, r0_28 -# 860| r0_30(glval) = VariableAddress[pb] : -# 860| r0_31(PolymorphicBase *) = Load : &:r0_30, ~mu0_2 -# 860| r0_32(PolymorphicDerived *) = CheckedConvertOrNull : r0_31 -# 860| r0_33(glval) = VariableAddress[pd] : -# 860| mu0_34(PolymorphicDerived *) = Store : &:r0_33, r0_32 -# 860| r0_35(glval) = CopyValue : r0_33 -# 861| r0_36(glval) = VariableAddress[rd] : -# 861| r0_37(glval) = VariableAddress[b] : -# 861| r0_38(glval) = CheckedConvertOrThrow : r0_37 -# 861| r0_39(PolymorphicDerived &) = CopyValue : r0_38 -# 861| mu0_40(PolymorphicDerived &) = Store : &:r0_36, r0_39 -# 863| r0_41(glval) = VariableAddress[pv] : -# 863| r0_42(glval) = VariableAddress[pb] : -# 863| r0_43(PolymorphicBase *) = Load : &:r0_42, ~mu0_2 -# 863| r0_44(void *) = DynamicCastToVoid : r0_43 -# 863| mu0_45(void *) = Store : &:r0_41, r0_44 -# 864| r0_46(glval) = VariableAddress[pcv] : -# 864| r0_47(glval) = VariableAddress[pd] : -# 864| r0_48(PolymorphicDerived *) = Load : &:r0_47, ~mu0_2 -# 864| r0_49(void *) = DynamicCastToVoid : r0_48 -# 864| mu0_50(void *) = Store : &:r0_46, r0_49 -# 865| v0_51(void) = NoOp : -# 849| v0_52(void) = ReturnVoid : -# 849| v0_53(void) = UnmodeledUse : mu* -# 849| v0_54(void) = ExitFunction : +# 858| r0_24(glval) = VariableAddress[rb] : +# 858| r0_25(glval) = VariableAddress[d] : +# 858| r0_26(glval) = CheckedConvertOrThrow : r0_25 +# 858| r0_27(PolymorphicBase &) = CopyValue : r0_26 +# 858| mu0_28(PolymorphicBase &) = Store : &:r0_24, r0_27 +# 860| r0_29(glval) = VariableAddress[pb] : +# 860| r0_30(PolymorphicBase *) = Load : &:r0_29, ~mu0_2 +# 860| r0_31(PolymorphicDerived *) = CheckedConvertOrNull : r0_30 +# 860| r0_32(glval) = VariableAddress[pd] : +# 860| mu0_33(PolymorphicDerived *) = Store : &:r0_32, r0_31 +# 861| r0_34(glval) = VariableAddress[rd] : +# 861| r0_35(glval) = VariableAddress[b] : +# 861| r0_36(glval) = CheckedConvertOrThrow : r0_35 +# 861| r0_37(PolymorphicDerived &) = CopyValue : r0_36 +# 861| mu0_38(PolymorphicDerived &) = Store : &:r0_34, r0_37 +# 863| r0_39(glval) = VariableAddress[pv] : +# 863| r0_40(glval) = VariableAddress[pb] : +# 863| r0_41(PolymorphicBase *) = Load : &:r0_40, ~mu0_2 +# 863| r0_42(void *) = DynamicCastToVoid : r0_41 +# 863| mu0_43(void *) = Store : &:r0_39, r0_42 +# 864| r0_44(glval) = VariableAddress[pcv] : +# 864| r0_45(glval) = VariableAddress[pd] : +# 864| r0_46(PolymorphicDerived *) = Load : &:r0_45, ~mu0_2 +# 864| r0_47(void *) = DynamicCastToVoid : r0_46 +# 864| mu0_48(void *) = Store : &:r0_44, r0_47 +# 865| v0_49(void) = NoOp : +# 849| v0_50(void) = ReturnVoid : +# 849| v0_51(void) = UnmodeledUse : mu* +# 849| v0_52(void) = ExitFunction : # 867| void String::String() # 867| Block 0 @@ -4245,46 +4085,42 @@ ir.cpp: # 874| r0_11(char *) = Convert : r0_10 # 874| r0_12(glval) = VariableAddress[p] : # 874| mu0_13(char *) = Store : &:r0_12, r0_11 -# 874| r0_14(glval) = CopyValue : r0_12 -# 875| r0_15(glval) = VariableAddress[a] : -# 875| r0_16(char *) = Convert : r0_15 -# 875| r0_17(int) = Constant[0] : -# 875| r0_18(glval) = PointerAdd[1] : r0_16, r0_17 -# 875| r0_19(char *) = CopyValue : r0_18 -# 875| r0_20(char *) = Convert : r0_19 -# 875| r0_21(glval) = VariableAddress[p] : -# 875| mu0_22(char *) = Store : &:r0_21, r0_20 -# 875| r0_23(glval) = CopyValue : r0_21 -# 876| r0_24(glval) = StringConstant["test"] : -# 876| r0_25(char *) = Convert : r0_24 -# 876| r0_26(int) = Constant[0] : -# 876| r0_27(glval) = PointerAdd[1] : r0_25, r0_26 -# 876| r0_28(char *) = CopyValue : r0_27 -# 876| r0_29(glval) = VariableAddress[p] : -# 876| mu0_30(char *) = Store : &:r0_29, r0_28 -# 876| r0_31(glval) = CopyValue : r0_29 -# 877| r0_32(glval) = VariableAddress[ra] : -# 877| r0_33(glval) = VariableAddress[a] : -# 877| r0_34(char(&)[5]) = CopyValue : r0_33 -# 877| mu0_35(char(&)[5]) = Store : &:r0_32, r0_34 -# 878| r0_36(glval) = VariableAddress[rs] : -# 878| r0_37(glval) = StringConstant["test"] : -# 878| r0_38(char(&)[5]) = CopyValue : r0_37 -# 878| mu0_39(char(&)[5]) = Store : &:r0_36, r0_38 -# 879| r0_40(glval) = VariableAddress[pa] : -# 879| r0_41(glval) = VariableAddress[a] : -# 879| r0_42(char(*)[5]) = CopyValue : r0_41 -# 879| r0_43(char(*)[5]) = Convert : r0_42 -# 879| mu0_44(char(*)[5]) = Store : &:r0_40, r0_43 -# 880| r0_45(glval) = StringConstant["test"] : -# 880| r0_46(char(*)[5]) = CopyValue : r0_45 -# 880| r0_47(glval) = VariableAddress[pa] : -# 880| mu0_48(char(*)[5]) = Store : &:r0_47, r0_46 -# 880| r0_49(glval) = CopyValue : r0_47 -# 881| v0_50(void) = NoOp : -# 871| v0_51(void) = ReturnVoid : -# 871| v0_52(void) = UnmodeledUse : mu* -# 871| v0_53(void) = ExitFunction : +# 875| r0_14(glval) = VariableAddress[a] : +# 875| r0_15(char *) = Convert : r0_14 +# 875| r0_16(int) = Constant[0] : +# 875| r0_17(glval) = PointerAdd[1] : r0_15, r0_16 +# 875| r0_18(char *) = CopyValue : r0_17 +# 875| r0_19(char *) = Convert : r0_18 +# 875| r0_20(glval) = VariableAddress[p] : +# 875| mu0_21(char *) = Store : &:r0_20, r0_19 +# 876| r0_22(glval) = StringConstant["test"] : +# 876| r0_23(char *) = Convert : r0_22 +# 876| r0_24(int) = Constant[0] : +# 876| r0_25(glval) = PointerAdd[1] : r0_23, r0_24 +# 876| r0_26(char *) = CopyValue : r0_25 +# 876| r0_27(glval) = VariableAddress[p] : +# 876| mu0_28(char *) = Store : &:r0_27, r0_26 +# 877| r0_29(glval) = VariableAddress[ra] : +# 877| r0_30(glval) = VariableAddress[a] : +# 877| r0_31(char(&)[5]) = CopyValue : r0_30 +# 877| mu0_32(char(&)[5]) = Store : &:r0_29, r0_31 +# 878| r0_33(glval) = VariableAddress[rs] : +# 878| r0_34(glval) = StringConstant["test"] : +# 878| r0_35(char(&)[5]) = CopyValue : r0_34 +# 878| mu0_36(char(&)[5]) = Store : &:r0_33, r0_35 +# 879| r0_37(glval) = VariableAddress[pa] : +# 879| r0_38(glval) = VariableAddress[a] : +# 879| r0_39(char(*)[5]) = CopyValue : r0_38 +# 879| r0_40(char(*)[5]) = Convert : r0_39 +# 879| mu0_41(char(*)[5]) = Store : &:r0_37, r0_40 +# 880| r0_42(glval) = StringConstant["test"] : +# 880| r0_43(char(*)[5]) = CopyValue : r0_42 +# 880| r0_44(glval) = VariableAddress[pa] : +# 880| mu0_45(char(*)[5]) = Store : &:r0_44, r0_43 +# 881| v0_46(void) = NoOp : +# 871| v0_47(void) = ReturnVoid : +# 871| v0_48(void) = UnmodeledUse : mu* +# 871| v0_49(void) = ExitFunction : # 883| void FuncPtrConversions(int(*)(int), void*) # 883| Block 0 @@ -4300,17 +4136,15 @@ ir.cpp: # 884| r0_9(void *) = Convert : r0_8 # 884| r0_10(glval) = VariableAddress[p] : # 884| mu0_11(void *) = Store : &:r0_10, r0_9 -# 884| r0_12(glval) = CopyValue : r0_10 -# 885| r0_13(glval) = VariableAddress[p] : -# 885| r0_14(void *) = Load : &:r0_13, ~mu0_2 -# 885| r0_15(..(*)(..)) = Convert : r0_14 -# 885| r0_16(glval<..(*)(..)>) = VariableAddress[pfn] : -# 885| mu0_17(..(*)(..)) = Store : &:r0_16, r0_15 -# 885| r0_18(glval<..(*)(..)>) = CopyValue : r0_16 -# 886| v0_19(void) = NoOp : -# 883| v0_20(void) = ReturnVoid : -# 883| v0_21(void) = UnmodeledUse : mu* -# 883| v0_22(void) = ExitFunction : +# 885| r0_12(glval) = VariableAddress[p] : +# 885| r0_13(void *) = Load : &:r0_12, ~mu0_2 +# 885| r0_14(..(*)(..)) = Convert : r0_13 +# 885| r0_15(glval<..(*)(..)>) = VariableAddress[pfn] : +# 885| mu0_16(..(*)(..)) = Store : &:r0_15, r0_14 +# 886| v0_17(void) = NoOp : +# 883| v0_18(void) = ReturnVoid : +# 883| v0_19(void) = UnmodeledUse : mu* +# 883| v0_20(void) = ExitFunction : # 888| void VarArgUsage(int) # 888| Block 0 @@ -4619,7 +4453,6 @@ ir.cpp: # 968| r1_0(int) = Constant[5] : # 968| r1_1(glval) = VariableAddress[x] : # 968| mu1_2(int) = Store : &:r1_1, r1_0 -# 968| r1_3(glval) = CopyValue : r1_1 #-----| Goto -> Block 6 # 970| Block 2 @@ -4643,7 +4476,6 @@ ir.cpp: # 971| r3_0(int) = Constant[7] : # 971| r3_1(glval) = VariableAddress[y] : # 971| mu3_2(int) = Store : &:r3_1, r3_0 -# 971| r3_3(glval) = CopyValue : r3_1 #-----| Goto -> Block 6 # 973| Block 4 @@ -4666,7 +4498,6 @@ ir.cpp: # 974| r5_2(int *) = Load : &:r5_1, ~mu0_2 # 974| r5_3(glval) = CopyValue : r5_2 # 974| mu5_4(int) = Store : &:r5_3, r5_0 -# 974| r5_5(glval) = CopyValue : r5_3 #-----| Goto -> Block 6 # 976| Block 6 @@ -4804,7 +4635,6 @@ ir.cpp: # 995| r1_1(int) = Load : &:r1_0, ~mu0_2 # 995| r1_2(glval) = VariableAddress[w] : # 995| mu1_3(int) = Store : &:r1_2, r1_1 -# 995| r1_4(glval) = CopyValue : r1_2 #-----| Goto -> Block 3 # 997| Block 2 @@ -4812,7 +4642,6 @@ ir.cpp: # 997| r2_1(int) = Load : &:r2_0, ~mu0_2 # 997| r2_2(glval) = VariableAddress[w] : # 997| mu2_3(int) = Store : &:r2_2, r2_1 -# 997| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 999| Block 3 @@ -5608,7 +5437,6 @@ ir.cpp: # 1130| r2_2(int) = Constant[1] : # 1130| r2_3(int) = Add : r2_1, r2_2 # 1130| mu2_4(int) = Store : &:r2_0, r2_3 -# 1130| r2_5(glval) = CopyValue : r2_0 #-----| Goto (back edge) -> Block 1 # 1130| Block 3 @@ -5674,7 +5502,6 @@ ir.cpp: # 1140| r6_4(int) = Load : &:r6_3, ~mu0_2 # 1140| r6_5(glval) = VariableAddress[x] : # 1140| mu6_6(int) = Store : &:r6_5, r6_4 -# 1140| r6_7(glval) = CopyValue : r6_5 #-----| Goto -> Block 8 # 1140| Block 7 @@ -5693,7 +5520,6 @@ ir.cpp: # 1142| r8_0(int) = Constant[7] : # 1142| r8_1(glval) = VariableAddress[x] : # 1142| mu8_2(int) = Store : &:r8_1, r8_0 -# 1142| r8_3(glval) = CopyValue : r8_1 #-----| Goto -> Block 13 # 1144| Block 9 @@ -5770,30 +5596,28 @@ ir.cpp: # 1156| r0_34(int) = Load : &:r0_33, ~mu0_2 # 1156| r0_35(glval) = PointerAdd[4] : r0_32, r0_34 # 1156| mu0_36(int) = Store : &:r0_35, r0_31 -# 1156| r0_37(glval) = CopyValue : r0_35 -# 1157| r0_38(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : -# 1157| r0_39(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1157| r0_40(__attribute((vector_size(16UL))) int) = Load : &:r0_39, ~mu0_2 -# 1157| r0_41(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1157| r0_42(__attribute((vector_size(16UL))) int) = Load : &:r0_41, ~mu0_2 -#-----| r0_43(int) = Constant[3] : -# 1157| r0_44(int) = Constant[2] : -# 1157| r0_45(int) = Constant[1] : -# 1157| r0_46(int) = Constant[0] : -# 1157| r0_47(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_40, 1:r0_42, 2:r0_43, 3:r0_44, 4:r0_45, 5:r0_46 -# 1157| mu0_48(__attribute((vector_size(16UL))) int) = Store : &:r0_38, r0_47 -# 1158| r0_49(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1158| r0_50(__attribute((vector_size(16UL))) int) = Load : &:r0_49, ~mu0_2 -# 1158| r0_51(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : -# 1158| r0_52(__attribute((vector_size(16UL))) int) = Load : &:r0_51, ~mu0_2 -# 1158| r0_53(__attribute((vector_size(16UL))) int) = Add : r0_50, r0_52 -# 1158| r0_54(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : -# 1158| mu0_55(__attribute((vector_size(16UL))) int) = Store : &:r0_54, r0_53 -# 1158| r0_56(glval<__attribute((vector_size(16UL))) int>) = CopyValue : r0_54 -# 1159| v0_57(void) = NoOp : -# 1153| v0_58(void) = ReturnVoid : -# 1153| v0_59(void) = UnmodeledUse : mu* -# 1153| v0_60(void) = ExitFunction : +# 1157| r0_37(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : +# 1157| r0_38(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1157| r0_39(__attribute((vector_size(16UL))) int) = Load : &:r0_38, ~mu0_2 +# 1157| r0_40(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1157| r0_41(__attribute((vector_size(16UL))) int) = Load : &:r0_40, ~mu0_2 +#-----| r0_42(int) = Constant[3] : +# 1157| r0_43(int) = Constant[2] : +# 1157| r0_44(int) = Constant[1] : +# 1157| r0_45(int) = Constant[0] : +# 1157| r0_46(__attribute((vector_size(16))) int) = BuiltIn[__builtin_shufflevector] : 0:r0_39, 1:r0_41, 2:r0_42, 3:r0_43, 4:r0_44, 5:r0_45 +# 1157| mu0_47(__attribute((vector_size(16UL))) int) = Store : &:r0_37, r0_46 +# 1158| r0_48(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1158| r0_49(__attribute((vector_size(16UL))) int) = Load : &:r0_48, ~mu0_2 +# 1158| r0_50(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4_shuffle] : +# 1158| r0_51(__attribute((vector_size(16UL))) int) = Load : &:r0_50, ~mu0_2 +# 1158| r0_52(__attribute((vector_size(16UL))) int) = Add : r0_49, r0_51 +# 1158| r0_53(glval<__attribute((vector_size(16UL))) int>) = VariableAddress[vi4] : +# 1158| mu0_54(__attribute((vector_size(16UL))) int) = Store : &:r0_53, r0_52 +# 1159| v0_55(void) = NoOp : +# 1153| v0_56(void) = ReturnVoid : +# 1153| v0_57(void) = UnmodeledUse : mu* +# 1153| v0_58(void) = ExitFunction : # 1163| int ModeledCallTarget(int) # 1163| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 9f13acbb1ffd..ff8c2b30a05f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -214,7 +214,6 @@ ssa.cpp: # 70| r1_6(glval) = CopyValue : r1_2 # 70| m1_7(char) = Store : &:r1_6, r1_0 # 70| m1_8(unknown) = Chi : total:m3_0, partial:m1_7 -# 70| r1_9(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -264,23 +263,20 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 80| r1_3(glval) = CopyValue : r1_1 -# 81| r1_4(int) = Constant[4] : -# 81| r1_5(glval) = VariableAddress[y] : -# 81| m1_6(int) = Store : &:r1_5, r1_4 -# 81| r1_7(glval) = CopyValue : r1_5 +# 81| r1_3(int) = Constant[4] : +# 81| r1_4(glval) = VariableAddress[y] : +# 81| m1_5(int) = Store : &:r1_4, r1_3 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 -# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -501,7 +497,6 @@ ssa.cpp: # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| m1_4(int) = Store : &:r1_3, r1_1 # 125| m1_5(Point) = Chi : total:m0_18, partial:m1_4 -# 125| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -511,7 +506,6 @@ ssa.cpp: # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| m2_4(int) = Store : &:r2_3, r2_1 # 128| m2_5(Point) = Chi : total:m0_18, partial:m2_4 -# 128| r2_6(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -565,7 +559,6 @@ ssa.cpp: # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| m1_4(int) = Store : &:r1_3, r1_1 # 137| m1_5(Point) = Chi : total:m0_18, partial:m1_4 -# 137| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -573,7 +566,6 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| m2_3(Point) = Store : &:r2_2, r2_1 -# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -623,7 +615,6 @@ ssa.cpp: # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| m1_4(int) = Store : &:r1_3, r1_1 # 148| m1_5(Point) = Chi : total:m0_18, partial:m1_4 -# 148| r1_6(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -631,7 +622,6 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| m2_3(Point) = Store : &:r2_2, r2_1 -# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -680,7 +670,6 @@ ssa.cpp: # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| m1_5(int) = Store : &:r1_4, r1_1 # 159| m1_6(Rect) = Chi : total:m0_18, partial:m1_5 -# 159| r1_7(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -688,7 +677,6 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| m2_3(Rect) = Store : &:r2_2, r2_1 -# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -723,22 +711,19 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| m0_17(int) = Store : &:r0_16, r0_14 -# 174| r0_18(glval) = CopyValue : r0_16 -# 175| r0_19(glval) = VariableAddress[w] : -# 175| r0_20(glval) = FieldAddress[f] : r0_19 -# 175| r0_21(int) = Load : &:r0_20, m0_17 -# 175| r0_22(glval) = VariableAddress[a] : -# 175| m0_23(int) = Store : &:r0_22, r0_21 -# 175| r0_24(glval) = CopyValue : r0_22 -# 176| r0_25(glval) = VariableAddress[w] : -# 176| r0_26(Wrapper) = Load : &:r0_25, ~m0_17 -# 176| r0_27(glval) = VariableAddress[x] : -# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 -# 176| r0_29(glval) = CopyValue : r0_27 -# 177| v0_30(void) = NoOp : -# 171| v0_31(void) = ReturnVoid : -# 171| v0_32(void) = UnmodeledUse : mu* -# 171| v0_33(void) = ExitFunction : +# 175| r0_18(glval) = VariableAddress[w] : +# 175| r0_19(glval) = FieldAddress[f] : r0_18 +# 175| r0_20(int) = Load : &:r0_19, m0_17 +# 175| r0_21(glval) = VariableAddress[a] : +# 175| m0_22(int) = Store : &:r0_21, r0_20 +# 176| r0_23(glval) = VariableAddress[w] : +# 176| r0_24(Wrapper) = Load : &:r0_23, ~m0_17 +# 176| r0_25(glval) = VariableAddress[x] : +# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 +# 177| v0_27(void) = NoOp : +# 171| v0_28(void) = ReturnVoid : +# 171| v0_29(void) = UnmodeledUse : mu* +# 171| v0_30(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -819,24 +804,22 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 200| r0_30(glval) = CopyValue : r0_26 -# 201| r0_31(glval) = FunctionAddress[abs] : -# 201| r0_32(glval) = VariableAddress[x] : -# 201| r0_33(int) = Load : &:r0_32, m0_8 -# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 -# 201| r0_35(glval) = VariableAddress[ret] : -# 201| r0_36(int) = Load : &:r0_35, m0_29 -# 201| r0_37(int) = Add : r0_36, r0_34 -# 201| m0_38(int) = Store : &:r0_35, r0_37 -# 201| r0_39(glval) = CopyValue : r0_35 -# 202| r0_40(glval) = VariableAddress[#return] : -# 202| r0_41(glval) = VariableAddress[ret] : -# 202| r0_42(int) = Load : &:r0_41, m0_38 -# 202| m0_43(int) = Store : &:r0_40, r0_42 -# 198| r0_44(glval) = VariableAddress[#return] : -# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 -# 198| v0_46(void) = UnmodeledUse : mu* -# 198| v0_47(void) = ExitFunction : +# 201| r0_30(glval) = FunctionAddress[abs] : +# 201| r0_31(glval) = VariableAddress[x] : +# 201| r0_32(int) = Load : &:r0_31, m0_8 +# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 +# 201| r0_34(glval) = VariableAddress[ret] : +# 201| r0_35(int) = Load : &:r0_34, m0_29 +# 201| r0_36(int) = Add : r0_35, r0_33 +# 201| m0_37(int) = Store : &:r0_34, r0_36 +# 202| r0_38(glval) = VariableAddress[#return] : +# 202| r0_39(glval) = VariableAddress[ret] : +# 202| r0_40(int) = Load : &:r0_39, m0_37 +# 202| m0_41(int) = Store : &:r0_38, r0_40 +# 198| r0_42(glval) = VariableAddress[#return] : +# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 +# 198| v0_44(void) = UnmodeledUse : mu* +# 198| v0_45(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index fd21c3f2d71c..8204cdad960f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -216,7 +216,6 @@ ssa.cpp: # 70| m1_5(char *) = Store : &:r1_1, r1_4 # 70| r1_6(glval) = CopyValue : r1_2 # 70| mu1_7(char) = Store : &:r1_6, r1_0 -# 70| r1_8(glval) = CopyValue : r1_6 #-----| Goto (back edge) -> Block 3 # 71| Block 2 @@ -265,23 +264,20 @@ ssa.cpp: # 80| r1_0(int) = Constant[3] : # 80| r1_1(glval) = VariableAddress[x] : # 80| m1_2(int) = Store : &:r1_1, r1_0 -# 80| r1_3(glval) = CopyValue : r1_1 -# 81| r1_4(int) = Constant[4] : -# 81| r1_5(glval) = VariableAddress[y] : -# 81| m1_6(int) = Store : &:r1_5, r1_4 -# 81| r1_7(glval) = CopyValue : r1_5 +# 81| r1_3(int) = Constant[4] : +# 81| r1_4(glval) = VariableAddress[y] : +# 81| m1_5(int) = Store : &:r1_4, r1_3 #-----| Goto -> Block 3 # 84| Block 2 # 84| r2_0(int) = Constant[5] : # 84| r2_1(glval) = VariableAddress[x] : # 84| m2_2(int) = Store : &:r2_1, r2_0 -# 84| r2_3(glval) = CopyValue : r2_1 #-----| Goto -> Block 3 # 86| Block 3 # 86| m3_0(int) = Phi : from 1:m1_2, from 2:m2_2 -# 86| m3_1(int) = Phi : from 1:m1_6, from 2:m0_10 +# 86| m3_1(int) = Phi : from 1:m1_5, from 2:m0_10 # 86| r3_2(glval) = VariableAddress[x_merge] : # 86| r3_3(glval) = VariableAddress[x] : # 86| r3_4(int) = Load : &:r3_3, m3_0 @@ -486,7 +482,6 @@ ssa.cpp: # 125| r1_2(glval) = VariableAddress[a] : # 125| r1_3(glval) = FieldAddress[x] : r1_2 # 125| mu1_4(int) = Store : &:r1_3, r1_1 -# 125| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 128| Block 2 @@ -495,7 +490,6 @@ ssa.cpp: # 128| r2_2(glval) = VariableAddress[a] : # 128| r2_3(glval) = FieldAddress[x] : r2_2 # 128| mu2_4(int) = Store : &:r2_3, r2_1 -# 128| r2_5(glval) = CopyValue : r2_3 #-----| Goto -> Block 3 # 130| Block 3 @@ -544,7 +538,6 @@ ssa.cpp: # 137| r1_2(glval) = VariableAddress[a] : # 137| r1_3(glval) = FieldAddress[x] : r1_2 # 137| mu1_4(int) = Store : &:r1_3, r1_1 -# 137| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 140| Block 2 @@ -552,7 +545,6 @@ ssa.cpp: # 140| r2_1(Point) = Load : &:r2_0, m0_6 # 140| r2_2(glval) = VariableAddress[a] : # 140| mu2_3(Point) = Store : &:r2_2, r2_1 -# 140| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 142| Block 3 @@ -597,7 +589,6 @@ ssa.cpp: # 148| r1_2(glval) = VariableAddress[a] : # 148| r1_3(glval) = FieldAddress[x] : r1_2 # 148| mu1_4(int) = Store : &:r1_3, r1_1 -# 148| r1_5(glval) = CopyValue : r1_3 #-----| Goto -> Block 3 # 151| Block 2 @@ -605,7 +596,6 @@ ssa.cpp: # 151| r2_1(Point) = Load : &:r2_0, m0_6 # 151| r2_2(glval) = VariableAddress[a] : # 151| mu2_3(Point) = Store : &:r2_2, r2_1 -# 151| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 153| Block 3 @@ -650,7 +640,6 @@ ssa.cpp: # 159| r1_3(glval) = FieldAddress[topLeft] : r1_2 # 159| r1_4(glval) = FieldAddress[x] : r1_3 # 159| mu1_5(int) = Store : &:r1_4, r1_1 -# 159| r1_6(glval) = CopyValue : r1_4 #-----| Goto -> Block 3 # 162| Block 2 @@ -658,7 +647,6 @@ ssa.cpp: # 162| r2_1(Rect) = Load : &:r2_0, m0_6 # 162| r2_2(glval) = VariableAddress[a] : # 162| mu2_3(Rect) = Store : &:r2_2, r2_1 -# 162| r2_4(glval) = CopyValue : r2_2 #-----| Goto -> Block 3 # 164| Block 3 @@ -692,22 +680,19 @@ ssa.cpp: # 174| r0_15(glval) = VariableAddress[w] : # 174| r0_16(glval) = FieldAddress[f] : r0_15 # 174| mu0_17(int) = Store : &:r0_16, r0_14 -# 174| r0_18(glval) = CopyValue : r0_16 -# 175| r0_19(glval) = VariableAddress[w] : -# 175| r0_20(glval) = FieldAddress[f] : r0_19 -# 175| r0_21(int) = Load : &:r0_20, ~mu0_2 -# 175| r0_22(glval) = VariableAddress[a] : -# 175| m0_23(int) = Store : &:r0_22, r0_21 -# 175| r0_24(glval) = CopyValue : r0_22 -# 176| r0_25(glval) = VariableAddress[w] : -# 176| r0_26(Wrapper) = Load : &:r0_25, ~mu0_2 -# 176| r0_27(glval) = VariableAddress[x] : -# 176| m0_28(Wrapper) = Store : &:r0_27, r0_26 -# 176| r0_29(glval) = CopyValue : r0_27 -# 177| v0_30(void) = NoOp : -# 171| v0_31(void) = ReturnVoid : -# 171| v0_32(void) = UnmodeledUse : mu* -# 171| v0_33(void) = ExitFunction : +# 175| r0_18(glval) = VariableAddress[w] : +# 175| r0_19(glval) = FieldAddress[f] : r0_18 +# 175| r0_20(int) = Load : &:r0_19, ~mu0_2 +# 175| r0_21(glval) = VariableAddress[a] : +# 175| m0_22(int) = Store : &:r0_21, r0_20 +# 176| r0_23(glval) = VariableAddress[w] : +# 176| r0_24(Wrapper) = Load : &:r0_23, ~mu0_2 +# 176| r0_25(glval) = VariableAddress[x] : +# 176| m0_26(Wrapper) = Store : &:r0_25, r0_24 +# 177| v0_27(void) = NoOp : +# 171| v0_28(void) = ReturnVoid : +# 171| v0_29(void) = UnmodeledUse : mu* +# 171| v0_30(void) = ExitFunction : # 179| int AsmStmt(int*) # 179| Block 0 @@ -782,24 +767,22 @@ ssa.cpp: # 200| r0_27(int) = Load : &:r0_26, m0_19 # 200| r0_28(int) = Add : r0_27, r0_24 # 200| m0_29(int) = Store : &:r0_26, r0_28 -# 200| r0_30(glval) = CopyValue : r0_26 -# 201| r0_31(glval) = FunctionAddress[abs] : -# 201| r0_32(glval) = VariableAddress[x] : -# 201| r0_33(int) = Load : &:r0_32, m0_8 -# 201| r0_34(int) = Call : func:r0_31, 0:r0_33 -# 201| r0_35(glval) = VariableAddress[ret] : -# 201| r0_36(int) = Load : &:r0_35, m0_29 -# 201| r0_37(int) = Add : r0_36, r0_34 -# 201| m0_38(int) = Store : &:r0_35, r0_37 -# 201| r0_39(glval) = CopyValue : r0_35 -# 202| r0_40(glval) = VariableAddress[#return] : -# 202| r0_41(glval) = VariableAddress[ret] : -# 202| r0_42(int) = Load : &:r0_41, m0_38 -# 202| m0_43(int) = Store : &:r0_40, r0_42 -# 198| r0_44(glval) = VariableAddress[#return] : -# 198| v0_45(void) = ReturnValue : &:r0_44, m0_43 -# 198| v0_46(void) = UnmodeledUse : mu* -# 198| v0_47(void) = ExitFunction : +# 201| r0_30(glval) = FunctionAddress[abs] : +# 201| r0_31(glval) = VariableAddress[x] : +# 201| r0_32(int) = Load : &:r0_31, m0_8 +# 201| r0_33(int) = Call : func:r0_30, 0:r0_32 +# 201| r0_34(glval) = VariableAddress[ret] : +# 201| r0_35(int) = Load : &:r0_34, m0_29 +# 201| r0_36(int) = Add : r0_35, r0_33 +# 201| m0_37(int) = Store : &:r0_34, r0_36 +# 202| r0_38(glval) = VariableAddress[#return] : +# 202| r0_39(glval) = VariableAddress[ret] : +# 202| r0_40(int) = Load : &:r0_39, m0_37 +# 202| m0_41(int) = Store : &:r0_38, r0_40 +# 198| r0_42(glval) = VariableAddress[#return] : +# 198| v0_43(void) = ReturnValue : &:r0_42, m0_41 +# 198| v0_44(void) = UnmodeledUse : mu* +# 198| v0_45(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index 589678d9f77b..9e8588507ff6 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -26,7 +26,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | Chi: call to C | | ms_try_mix.cpp:48:10:48:13 | Chi: call to C | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index bb312fa7691c..1bcffed07361 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -4,7 +4,6 @@ missingOperand | condition_decls.cpp:41:9:41:23 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | | condition_decls.cpp:48:39:48:53 | CopyValue: (condition decl) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | | misc.c:125:5:125:11 | CopyValue: (statement expression) | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:97:6:97:10 | IR: misc3 | void misc3() | -| misc.c:220:3:223:3 | CopyValue: ... = ... | Instruction 'CopyValue' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:3:223:3 | Store: ... = ... | Instruction 'Store' is missing an expected operand with tag 'StoreValue' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:9:223:3 | FieldAddress: {...} | Instruction 'FieldAddress' is missing an expected operand with tag 'Unary' in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | @@ -49,13 +48,13 @@ instructionWithoutSuccessor | misc.c:222:10:222:10 | Store: 2 | | ms_assume.cpp:20:12:20:12 | Constant: (bool)... | | ms_try_except.cpp:3:9:3:9 | Uninitialized: definition of x | -| ms_try_except.cpp:7:13:7:17 | CopyValue: ... = ... | +| ms_try_except.cpp:7:13:7:17 | Store: ... = ... | | ms_try_except.cpp:9:19:9:19 | Load: j | -| ms_try_except.cpp:10:13:10:17 | CopyValue: ... = ... | -| ms_try_except.cpp:14:13:14:17 | CopyValue: ... = ... | -| ms_try_except.cpp:17:13:17:17 | CopyValue: ... = ... | +| ms_try_except.cpp:10:13:10:17 | Store: ... = ... | +| ms_try_except.cpp:14:13:14:17 | Store: ... = ... | +| ms_try_except.cpp:17:13:17:17 | Store: ... = ... | | ms_try_except.cpp:19:17:19:21 | Sub: ... - ... | -| ms_try_except.cpp:20:9:20:13 | CopyValue: ... = ... | +| ms_try_except.cpp:20:9:20:13 | Store: ... = ... | | ms_try_mix.cpp:11:12:11:15 | CallSideEffect: call to C | | ms_try_mix.cpp:16:13:16:19 | ThrowValue: throw ... | | ms_try_mix.cpp:18:16:18:19 | CallSideEffect: call to C | @@ -77,7 +76,7 @@ instructionWithoutSuccessor | static_init_templates.cpp:97:27:97:36 | Convert: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | | static_init_templates.cpp:105:27:105:27 | Constant: (void *)... | -| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | stmt_expr.cpp:29:11:32:11 | CopyValue: (statement expression) | | stmt_in_type.cpp:5:53:5:53 | Constant: 1 | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index 0f8088f9a253..d064a1264ecb 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -35,7 +35,7 @@ instructionWithoutSuccessor | ms_try_mix.cpp:28:12:28:15 | CallSideEffect: call to C | | ms_try_mix.cpp:48:10:48:13 | CallSideEffect: call to C | | pointer_to_member.cpp:36:11:36:30 | FieldAddress: {...} | -| stmt_expr.cpp:27:5:27:15 | CopyValue: ... = ... | +| stmt_expr.cpp:27:5:27:15 | Store: ... = ... | | vla.c:5:9:5:14 | Uninitialized: definition of matrix | | vla.c:11:6:11:16 | UnmodeledDefinition: vla_typedef | ambiguousSuccessors From 59e09d6d5d9981953d22f103778840d88ea07ce1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Sep 2019 12:29:44 +0200 Subject: [PATCH 0075/2538] Python: Add nullary pointsTo to Expr class Like the one existing in ControlFlowNode. This is useful for checking class of value being poitned to, as expr.pointsTo().getClass() = someClass Without this you need to do exists(Value v | v.getClass() = someClass | expr.pointsTo(v)) --- python/ql/src/semmle/python/Exprs.qll | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/python/ql/src/semmle/python/Exprs.qll b/python/ql/src/semmle/python/Exprs.qll index 264bc826150a..e90210edc652 100644 --- a/python/ql/src/semmle/python/Exprs.qll +++ b/python/ql/src/semmle/python/Exprs.qll @@ -126,6 +126,11 @@ class Expr extends Expr_, AstNode { this.pointsTo(value, _) } + /** Gets a value that this expression might "point-to". */ + Value pointsTo() { + this.pointsTo(result) + } + } /** An attribute expression, such as `value.attr` */ From 66a0e153a538518f069978ce394410955413d2a7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Sep 2019 15:33:24 +0200 Subject: [PATCH 0076/2538] Python: Modernise pyramid library --- python/ql/src/semmle/python/web/pyramid/Redirect.qll | 6 +++--- python/ql/src/semmle/python/web/pyramid/Response.qll | 2 +- python/ql/src/semmle/python/web/pyramid/View.qll | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/python/ql/src/semmle/python/web/pyramid/Redirect.qll b/python/ql/src/semmle/python/web/pyramid/Redirect.qll index ee47a885d221..4a96dce5f7ee 100644 --- a/python/ql/src/semmle/python/web/pyramid/Redirect.qll +++ b/python/ql/src/semmle/python/web/pyramid/Redirect.qll @@ -8,8 +8,8 @@ import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic import semmle.python.web.Http -private ClassObject redirectClass() { - exists(ModuleObject ex | +private ClassValue redirectClass() { + exists(ModuleValue ex | ex.getName() = "pyramid.httpexceptions" | ex.attr("HTTPFound") = result or @@ -28,7 +28,7 @@ class PyramidRedirect extends HttpRedirectTaintSink { PyramidRedirect() { exists(CallNode call | - call.getFunction().refersTo(redirectClass()) + call.getFunction().pointsTo(redirectClass()) | call.getArg(0) = this or diff --git a/python/ql/src/semmle/python/web/pyramid/Response.qll b/python/ql/src/semmle/python/web/pyramid/Response.qll index cecf30a9e6e7..383f33d4ac03 100644 --- a/python/ql/src/semmle/python/web/pyramid/Response.qll +++ b/python/ql/src/semmle/python/web/pyramid/Response.qll @@ -35,7 +35,7 @@ class PyramidCookieSet extends CookieSet, CallNode { PyramidCookieSet() { exists(ControlFlowNode f | f = this.getFunction().(AttrNode).getObject("set_cookie") and - f.refersTo(_, ModuleObject::named("pyramid").attr("Response"), _) + f.pointsTo().getClass() = Value::named("pyramid.Response") ) } diff --git a/python/ql/src/semmle/python/web/pyramid/View.qll b/python/ql/src/semmle/python/web/pyramid/View.qll index 64cb4cf3271f..88f505bda87c 100644 --- a/python/ql/src/semmle/python/web/pyramid/View.qll +++ b/python/ql/src/semmle/python/web/pyramid/View.qll @@ -1,14 +1,14 @@ import python -ModuleObject thePyramidViewModule() { +ModuleValue thePyramidViewModule() { result.getName() = "pyramid.view" } -Object thePyramidViewConfig() { +Value thePyramidViewConfig() { result = thePyramidViewModule().attr("view_config") } predicate is_pyramid_view_function(Function func) { - func.getADecorator().refersTo(_, thePyramidViewConfig(), _) + func.getADecorator().pointsTo().getClass() = thePyramidViewConfig() } From 4463b30ce7c30157e487ce9d4e73e54303a12245 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Sep 2019 15:34:26 +0200 Subject: [PATCH 0077/2538] Python: Update pyramid library to use correct response class Tested with pyramid 1.10.4 and python 3.6.8 --- python/ql/src/semmle/python/web/pyramid/Response.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/ql/src/semmle/python/web/pyramid/Response.qll b/python/ql/src/semmle/python/web/pyramid/Response.qll index 383f33d4ac03..f31b13a8bbe3 100644 --- a/python/ql/src/semmle/python/web/pyramid/Response.qll +++ b/python/ql/src/semmle/python/web/pyramid/Response.qll @@ -35,7 +35,7 @@ class PyramidCookieSet extends CookieSet, CallNode { PyramidCookieSet() { exists(ControlFlowNode f | f = this.getFunction().(AttrNode).getObject("set_cookie") and - f.pointsTo().getClass() = Value::named("pyramid.Response") + f.pointsTo().getClass() = Value::named("pyramid.response.Response") ) } From 7c44c37d8bc0a944eb64a167fa1fa665e181b29d Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Sep 2019 15:43:59 +0200 Subject: [PATCH 0078/2538] Python: Autoformat (4 spaces) pyramid library --- .../semmle/python/web/pyramid/Redirect.qll | 18 +++++---------- .../src/semmle/python/web/pyramid/Request.qll | 22 ++++--------------- .../semmle/python/web/pyramid/Response.qll | 22 +++++-------------- .../ql/src/semmle/python/web/pyramid/View.qll | 9 ++------ 4 files changed, 18 insertions(+), 53 deletions(-) diff --git a/python/ql/src/semmle/python/web/pyramid/Redirect.qll b/python/ql/src/semmle/python/web/pyramid/Redirect.qll index 4a96dce5f7ee..8c7e57a4285b 100644 --- a/python/ql/src/semmle/python/web/pyramid/Redirect.qll +++ b/python/ql/src/semmle/python/web/pyramid/Redirect.qll @@ -1,16 +1,16 @@ -/** Provides class representing the `pyramid.redirect` function. +/** + * Provides class representing the `pyramid.redirect` function. * This module is intended to be imported into a taint-tracking query * to extend `TaintSink`. */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic import semmle.python.web.Http private ClassValue redirectClass() { - exists(ModuleValue ex | - ex.getName() = "pyramid.httpexceptions" | + exists(ModuleValue ex | ex.getName() = "pyramid.httpexceptions" | ex.attr("HTTPFound") = result or ex.attr("HTTPTemporaryRedirect") = result @@ -21,19 +21,13 @@ private ClassValue redirectClass() { * Represents an argument to the `tornado.redirect` function. */ class PyramidRedirect extends HttpRedirectTaintSink { - - override string toString() { - result = "pyramid.redirect" - } + override string toString() { result = "pyramid.redirect" } PyramidRedirect() { - exists(CallNode call | - call.getFunction().pointsTo(redirectClass()) - | + exists(CallNode call | call.getFunction().pointsTo(redirectClass()) | call.getArg(0) = this or call.getArgByName("location") = this ) } - } diff --git a/python/ql/src/semmle/python/web/pyramid/Request.qll b/python/ql/src/semmle/python/web/pyramid/Request.qll index 53750b3cb7c2..2514e77d5ac0 100644 --- a/python/ql/src/semmle/python/web/pyramid/Request.qll +++ b/python/ql/src/semmle/python/web/pyramid/Request.qll @@ -1,25 +1,17 @@ import python - import semmle.python.security.TaintTracking import semmle.python.web.Http private import semmle.python.web.webob.Request private import semmle.python.web.pyramid.View class PyramidRequest extends BaseWebobRequest { + PyramidRequest() { this = "pyramid.request" } - PyramidRequest() { - this = "pyramid.request" - } - - override ClassValue getType() { - result = Value::named("pyramid.request.Request") - } - + override ClassValue getType() { result = Value::named("pyramid.request.Request") } } /** Source of pyramid request objects */ class PyramidViewArgument extends TaintSource { - PyramidViewArgument() { exists(Function view_func | is_pyramid_view_function(view_func) and @@ -27,13 +19,7 @@ class PyramidViewArgument extends TaintSource { ) } - override predicate isSourceOf(TaintKind kind) { - kind instanceof PyramidRequest - } - - override string toString() { - result = "pyramid.view.argument" - } + override predicate isSourceOf(TaintKind kind) { kind instanceof PyramidRequest } + override string toString() { result = "pyramid.view.argument" } } - diff --git a/python/ql/src/semmle/python/web/pyramid/Response.qll b/python/ql/src/semmle/python/web/pyramid/Response.qll index f31b13a8bbe3..511d1e283228 100644 --- a/python/ql/src/semmle/python/web/pyramid/Response.qll +++ b/python/ql/src/semmle/python/web/pyramid/Response.qll @@ -1,17 +1,15 @@ import python - - import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic import semmle.python.web.Http - private import semmle.python.web.pyramid.View private import semmle.python.web.Http -/** A pyramid response, which is vulnerable to any sort of - * http response malice. */ +/** + * A pyramid response, which is vulnerable to any sort of + * http response malice. + */ class PyramidRoutedResponse extends HttpResponseTaintSink { - PyramidRoutedResponse() { exists(PyFunctionObject view | is_pyramid_view_function(view.getFunction()) and @@ -19,19 +17,12 @@ class PyramidRoutedResponse extends HttpResponseTaintSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof StringKind - } - - override string toString() { - result = "pyramid.routed.response" - } + override predicate sinks(TaintKind kind) { kind instanceof StringKind } + override string toString() { result = "pyramid.routed.response" } } - class PyramidCookieSet extends CookieSet, CallNode { - PyramidCookieSet() { exists(ControlFlowNode f | f = this.getFunction().(AttrNode).getObject("set_cookie") and @@ -44,5 +35,4 @@ class PyramidCookieSet extends CookieSet, CallNode { override ControlFlowNode getKey() { result = this.getArg(0) } override ControlFlowNode getValue() { result = this.getArg(1) } - } diff --git a/python/ql/src/semmle/python/web/pyramid/View.qll b/python/ql/src/semmle/python/web/pyramid/View.qll index 88f505bda87c..3bf49de87c32 100644 --- a/python/ql/src/semmle/python/web/pyramid/View.qll +++ b/python/ql/src/semmle/python/web/pyramid/View.qll @@ -1,14 +1,9 @@ import python -ModuleValue thePyramidViewModule() { - result.getName() = "pyramid.view" -} +ModuleValue thePyramidViewModule() { result.getName() = "pyramid.view" } -Value thePyramidViewConfig() { - result = thePyramidViewModule().attr("view_config") -} +Value thePyramidViewConfig() { result = thePyramidViewModule().attr("view_config") } predicate is_pyramid_view_function(Function func) { func.getADecorator().pointsTo().getClass() = thePyramidViewConfig() } - From 2874c54133cb445aa4df03371b096ee2cbf1f1f2 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 30 Sep 2019 16:23:47 +0200 Subject: [PATCH 0079/2538] Python: Move pyramid tests from internal repo Use minimal mock instead of full library --- .../web/pyramid/Routing.expected | 3 +++ .../test/library-tests/web/pyramid/Routing.ql | 9 +++++++ .../library-tests/web/pyramid/Sinks.expected | 3 +++ .../test/library-tests/web/pyramid/Sinks.ql | 11 ++++++++ .../web/pyramid/Sources.expected | 3 +++ .../test/library-tests/web/pyramid/Sources.ql | 11 ++++++++ .../library-tests/web/pyramid/Taint.expected | 11 ++++++++ .../test/library-tests/web/pyramid/Taint.ql | 12 +++++++++ .../ql/test/library-tests/web/pyramid/options | 2 ++ .../ql/test/library-tests/web/pyramid/test.py | 25 +++++++++++++++++++ .../Security/lib/pyramid/__init__.py | 0 .../Security/lib/pyramid/response.py | 2 ++ .../query-tests/Security/lib/pyramid/view.py | 7 ++++++ 13 files changed, 99 insertions(+) create mode 100644 python/ql/test/library-tests/web/pyramid/Routing.expected create mode 100644 python/ql/test/library-tests/web/pyramid/Routing.ql create mode 100644 python/ql/test/library-tests/web/pyramid/Sinks.expected create mode 100644 python/ql/test/library-tests/web/pyramid/Sinks.ql create mode 100644 python/ql/test/library-tests/web/pyramid/Sources.expected create mode 100644 python/ql/test/library-tests/web/pyramid/Sources.ql create mode 100644 python/ql/test/library-tests/web/pyramid/Taint.expected create mode 100644 python/ql/test/library-tests/web/pyramid/Taint.ql create mode 100644 python/ql/test/library-tests/web/pyramid/options create mode 100644 python/ql/test/library-tests/web/pyramid/test.py create mode 100644 python/ql/test/query-tests/Security/lib/pyramid/__init__.py create mode 100644 python/ql/test/query-tests/Security/lib/pyramid/response.py create mode 100644 python/ql/test/query-tests/Security/lib/pyramid/view.py diff --git a/python/ql/test/library-tests/web/pyramid/Routing.expected b/python/ql/test/library-tests/web/pyramid/Routing.expected new file mode 100644 index 000000000000..795f604b1f9d --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Routing.expected @@ -0,0 +1,3 @@ +| test.py:7 | Function home | +| test.py:15 | Function greet | +| test.py:24 | Function stuff | diff --git a/python/ql/test/library-tests/web/pyramid/Routing.ql b/python/ql/test/library-tests/web/pyramid/Routing.ql new file mode 100644 index 000000000000..ef21e5510fee --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Routing.ql @@ -0,0 +1,9 @@ +import python + +import semmle.python.web.pyramid.View + +from Function func + +where is_pyramid_view_function(func) + +select func.getLocation().toString(), func.toString() diff --git a/python/ql/test/library-tests/web/pyramid/Sinks.expected b/python/ql/test/library-tests/web/pyramid/Sinks.expected new file mode 100644 index 000000000000..03e32dac04a6 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Sinks.expected @@ -0,0 +1,3 @@ +| test.py:8 | Response() | externally controlled string | +| test.py:17 | Response() | externally controlled string | +| test.py:25 | Dict | externally controlled string | diff --git a/python/ql/test/library-tests/web/pyramid/Sinks.ql b/python/ql/test/library-tests/web/pyramid/Sinks.ql new file mode 100644 index 000000000000..5fb6ad477d4e --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Sinks.ql @@ -0,0 +1,11 @@ + +import python + +import semmle.python.web.HttpRequest +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + + +from TaintSink sink, TaintKind kind +where sink.sinks(kind) and sink.getLocation().getFile().getName().matches("%test.py") +select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/pyramid/Sources.expected b/python/ql/test/library-tests/web/pyramid/Sources.expected new file mode 100644 index 000000000000..f7fe4bb2c5c2 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Sources.expected @@ -0,0 +1,3 @@ +| test.py:7 | request | pyramid.request | +| test.py:15 | request | pyramid.request | +| test.py:24 | request | pyramid.request | diff --git a/python/ql/test/library-tests/web/pyramid/Sources.ql b/python/ql/test/library-tests/web/pyramid/Sources.ql new file mode 100644 index 000000000000..b1b7fe3e08bc --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Sources.ql @@ -0,0 +1,11 @@ + +import python + +import semmle.python.web.HttpRequest +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + + +from TaintSource src, TaintKind kind +where src.isSourceOf(kind) +select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/pyramid/Taint.expected b/python/ql/test/library-tests/web/pyramid/Taint.expected new file mode 100644 index 000000000000..94b8f844efb9 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Taint.expected @@ -0,0 +1,11 @@ +| test.py:7 | request | pyramid.request | +| test.py:15 | request | pyramid.request | +| test.py:16 | Attribute | {externally controlled string} | +| test.py:16 | Subscript | externally controlled string | +| test.py:16 | request | pyramid.request | +| test.py:17 | BinaryExpr | externally controlled string | +| test.py:17 | name | externally controlled string | +| test.py:24 | request | pyramid.request | +| test.py:25 | Attribute | externally controlled string | +| test.py:25 | Dict | {externally controlled string} | +| test.py:25 | request | pyramid.request | diff --git a/python/ql/test/library-tests/web/pyramid/Taint.ql b/python/ql/test/library-tests/web/pyramid/Taint.ql new file mode 100644 index 000000000000..54af91f3300b --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/Taint.ql @@ -0,0 +1,12 @@ + +import python + +import semmle.python.web.HttpRequest +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from TaintedNode node +where node.getLocation().getFile().getName().matches("%test.py") + +select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind() + diff --git a/python/ql/test/library-tests/web/pyramid/options b/python/ql/test/library-tests/web/pyramid/options new file mode 100644 index 000000000000..0267f80a6d65 --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/options @@ -0,0 +1,2 @@ +semmle-extractor-options: --max-import-depth=2 -p ../../../query-tests/Security/lib/ +optimize: true diff --git a/python/ql/test/library-tests/web/pyramid/test.py b/python/ql/test/library-tests/web/pyramid/test.py new file mode 100644 index 000000000000..9fad8a7ba00a --- /dev/null +++ b/python/ql/test/library-tests/web/pyramid/test.py @@ -0,0 +1,25 @@ +from pyramid.view import view_config +from pyramid.response import Response + +@view_config( + route_name='home' +) +def home(request): + return Response('Welcome!') + + +@view_config( + route_name='greet', + request_method='POST' +) +def greet(request): + name = request.POST['arg'] + return Response('Welcome %s!' % name) + + +@view_config( + route_name='stuff', + renderer='json' +) +def stuff(request): + return {"err": 0, "body": request.body} diff --git a/python/ql/test/query-tests/Security/lib/pyramid/__init__.py b/python/ql/test/query-tests/Security/lib/pyramid/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/ql/test/query-tests/Security/lib/pyramid/response.py b/python/ql/test/query-tests/Security/lib/pyramid/response.py new file mode 100644 index 000000000000..a482ac919fff --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/pyramid/response.py @@ -0,0 +1,2 @@ +class Response(object): + pass diff --git a/python/ql/test/query-tests/Security/lib/pyramid/view.py b/python/ql/test/query-tests/Security/lib/pyramid/view.py new file mode 100644 index 000000000000..c7487bf827b6 --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/pyramid/view.py @@ -0,0 +1,7 @@ +# https://docs.pylonsproject.org/projects/pyramid/en/1.10-branch/_modules/pyramid/view.html#view_config +class view_config(object): + def __init__(self, **settings): + pass + + def __call__(self, wrapped): + pass From 4248a8418bae7f7da649260b1e91db900e2ea13a Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 1 Oct 2019 14:18:30 +0200 Subject: [PATCH 0080/2538] Python: Move tornado tests from internal repo --- .../web/tornado/Classes.expected | 7 ++ .../test/library-tests/web/tornado/Classes.ql | 9 +++ .../web/tornado/Methods.expected | 76 +++++++++++++++++++ .../test/library-tests/web/tornado/Methods.ql | 12 +++ .../library-tests/web/tornado/Sinks.expected | 6 ++ .../test/library-tests/web/tornado/Sinks.ql | 11 +++ .../web/tornado/Sources.expected | 15 ++++ .../test/library-tests/web/tornado/Sources.ql | 13 ++++ .../library-tests/web/tornado/Taint.expected | 38 ++++++++++ .../test/library-tests/web/tornado/Taint.ql | 14 ++++ .../ql/test/library-tests/web/tornado/options | 2 + .../ql/test/library-tests/web/tornado/test.py | 20 +++++ 12 files changed, 223 insertions(+) create mode 100644 python/ql/test/library-tests/web/tornado/Classes.expected create mode 100644 python/ql/test/library-tests/web/tornado/Classes.ql create mode 100644 python/ql/test/library-tests/web/tornado/Methods.expected create mode 100644 python/ql/test/library-tests/web/tornado/Methods.ql create mode 100644 python/ql/test/library-tests/web/tornado/Sinks.expected create mode 100644 python/ql/test/library-tests/web/tornado/Sinks.ql create mode 100644 python/ql/test/library-tests/web/tornado/Sources.expected create mode 100644 python/ql/test/library-tests/web/tornado/Sources.ql create mode 100644 python/ql/test/library-tests/web/tornado/Taint.expected create mode 100644 python/ql/test/library-tests/web/tornado/Taint.ql create mode 100644 python/ql/test/library-tests/web/tornado/options create mode 100644 python/ql/test/library-tests/web/tornado/test.py diff --git a/python/ql/test/library-tests/web/tornado/Classes.expected b/python/ql/test/library-tests/web/tornado/Classes.expected new file mode 100644 index 000000000000..c303fda39e77 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Classes.expected @@ -0,0 +1,7 @@ +| class ErrorHandler | resources/lib/python/lib/tornado/web.py:2260 | +| class FallbackHandler | resources/lib/python/lib/tornado/web.py:2806 | +| class Handler1 | test.py:4 | +| class Handler2 | test.py:8 | +| class Handler3 | test.py:14 | +| class RedirectHandler | resources/lib/python/lib/tornado/web.py:2275 | +| class StaticFileHandler | resources/lib/python/lib/tornado/web.py:2319 | diff --git a/python/ql/test/library-tests/web/tornado/Classes.ql b/python/ql/test/library-tests/web/tornado/Classes.ql new file mode 100644 index 000000000000..a4915037ac3b --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Classes.ql @@ -0,0 +1,9 @@ + +import python + +import semmle.python.TestUtils + +import semmle.python.web.tornado.Tornado +from ClassObject cls +where cls = aTornadoRequestHandlerClass() +select cls.toString(), remove_library_prefix(cls.getPyClass().getLocation()) diff --git a/python/ql/test/library-tests/web/tornado/Methods.expected b/python/ql/test/library-tests/web/tornado/Methods.expected new file mode 100644 index 000000000000..684d18ca9dab --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Methods.expected @@ -0,0 +1,76 @@ +| __init__ | Function __init__ | resources/lib/python/lib/tornado/web.py:168 | +| _break_cycles | Function _break_cycles | resources/lib/python/lib/tornado/web.py:1025 | +| _clear_headers_for_304 | Function _clear_headers_for_304 | resources/lib/python/lib/tornado/web.py:1636 | +| _convert_header_value | Function _convert_header_value | resources/lib/python/lib/tornado/web.py:363 | +| _decode_xsrf_token | Function _decode_xsrf_token | resources/lib/python/lib/tornado/web.py:1294 | +| _get_argument | Function _get_argument | resources/lib/python/lib/tornado/web.py:479 | +| _get_arguments | Function _get_arguments | resources/lib/python/lib/tornado/web.py:487 | +| _get_raw_xsrf_token | Function _get_raw_xsrf_token | resources/lib/python/lib/tornado/web.py:1270 | +| _handle_request_exception | Function _handle_request_exception | resources/lib/python/lib/tornado/web.py:1581 | +| _log | Function _log | resources/lib/python/lib/tornado/web.py:1568 | +| _request_summary | Function _request_summary | resources/lib/python/lib/tornado/web.py:1577 | +| _stack_context_handle_exception | Function _stack_context_handle_exception | resources/lib/python/lib/tornado/web.py:1493 | +| _ui_method | Function _ui_method | resources/lib/python/lib/tornado/web.py:1633 | +| _ui_module | Function _ui_module | resources/lib/python/lib/tornado/web.py:1623 | +| add_header | Function add_header | resources/lib/python/lib/tornado/web.py:343 | +| check_etag_header | Function check_etag_header | resources/lib/python/lib/tornado/web.py:1452 | +| check_xsrf_cookie | Function check_xsrf_cookie | resources/lib/python/lib/tornado/web.py:1330 | +| clear | Function clear | resources/lib/python/lib/tornado/web.py:288 | +| clear_all_cookies | Function clear_all_cookies | resources/lib/python/lib/tornado/web.py:597 | +| clear_cookie | Function clear_cookie | resources/lib/python/lib/tornado/web.py:582 | +| clear_header | Function clear_header | resources/lib/python/lib/tornado/web.py:352 | +| compute_etag | Function compute_etag | resources/lib/python/lib/tornado/web.py:1428 | +| create_signed_value | Function create_signed_value | resources/lib/python/lib/tornado/web.py:642 | +| create_template_loader | Function create_template_loader | resources/lib/python/lib/tornado/web.py:916 | +| data_received | Function data_received | resources/lib/python/lib/tornado/web.py:1561 | +| decode_argument | Function decode_argument | resources/lib/python/lib/tornado/web.py:500 | +| delete | Function delete | resources/lib/python/lib/tornado/web.py:230 | +| finish | Function finish | resources/lib/python/lib/tornado/web.py:985 | +| flush | Function flush | resources/lib/python/lib/tornado/web.py:937 | +| get | Function get | resources/lib/python/lib/tornado/web.py:224 | +| get_argument | Function get_argument | resources/lib/python/lib/tornado/web.py:395 | +| get_arguments | Function get_arguments | resources/lib/python/lib/tornado/web.py:408 | +| get_body_argument | Function get_body_argument | resources/lib/python/lib/tornado/web.py:423 | +| get_body_arguments | Function get_body_arguments | resources/lib/python/lib/tornado/web.py:440 | +| get_browser_locale | Function get_browser_locale | resources/lib/python/lib/tornado/web.py:1127 | +| get_cookie | Function get_cookie | resources/lib/python/lib/tornado/web.py:525 | +| get_current_user | Function get_current_user | resources/lib/python/lib/tornado/web.py:1191 | +| get_login_url | Function get_login_url | resources/lib/python/lib/tornado/web.py:1198 | +| get_query_argument | Function get_query_argument | resources/lib/python/lib/tornado/web.py:451 | +| get_query_arguments | Function get_query_arguments | resources/lib/python/lib/tornado/web.py:468 | +| get_secure_cookie | Function get_secure_cookie | resources/lib/python/lib/tornado/web.py:665 | +| get_secure_cookie_key_version | Function get_secure_cookie_key_version | resources/lib/python/lib/tornado/web.py:688 | +| get_status | Function get_status | resources/lib/python/lib/tornado/web.py:329 | +| get_template_namespace | Function get_template_namespace | resources/lib/python/lib/tornado/web.py:893 | +| get_template_path | Function get_template_path | resources/lib/python/lib/tornado/web.py:1206 | +| get_user_locale | Function get_user_locale | resources/lib/python/lib/tornado/web.py:1117 | +| head | Function head | resources/lib/python/lib/tornado/web.py:221 | +| initialize | Function initialize | resources/lib/python/lib/tornado/web.py:195 | +| log_exception | Function log_exception | resources/lib/python/lib/tornado/web.py:1603 | +| on_connection_close | Function on_connection_close | resources/lib/python/lib/tornado/web.py:269 | +| on_finish | Function on_finish | resources/lib/python/lib/tornado/web.py:259 | +| options | Function options | resources/lib/python/lib/tornado/web.py:239 | +| patch | Function patch | resources/lib/python/lib/tornado/web.py:233 | +| post | Function post | resources/lib/python/lib/tornado/web.py:227 | +| prepare | Function prepare | resources/lib/python/lib/tornado/web.py:242 | +| put | Function put | resources/lib/python/lib/tornado/web.py:236 | +| redirect | Function redirect | resources/lib/python/lib/tornado/web.py:698 | +| render | Function render | resources/lib/python/lib/tornado/web.py:746 | +| render_embed_css | Function render_embed_css | resources/lib/python/lib/tornado/web.py:859 | +| render_embed_js | Function render_embed_js | resources/lib/python/lib/tornado/web.py:830 | +| render_linked_css | Function render_linked_css | resources/lib/python/lib/tornado/web.py:839 | +| render_linked_js | Function render_linked_js | resources/lib/python/lib/tornado/web.py:810 | +| render_string | Function render_string | resources/lib/python/lib/tornado/web.py:868 | +| require_setting | Function require_setting | resources/lib/python/lib/tornado/web.py:1418 | +| reverse_url | Function reverse_url | resources/lib/python/lib/tornado/web.py:1424 | +| send_error | Function send_error | resources/lib/python/lib/tornado/web.py:1030 | +| set_cookie | Function set_cookie | resources/lib/python/lib/tornado/web.py:538 | +| set_default_headers | Function set_default_headers | resources/lib/python/lib/tornado/web.py:300 | +| set_etag_header | Function set_etag_header | resources/lib/python/lib/tornado/web.py:1441 | +| set_header | Function set_header | resources/lib/python/lib/tornado/web.py:333 | +| set_secure_cookie | Function set_secure_cookie | resources/lib/python/lib/tornado/web.py:613 | +| set_status | Function set_status | resources/lib/python/lib/tornado/web.py:310 | +| static_url | Function static_url | resources/lib/python/lib/tornado/web.py:1383 | +| write | Function write | resources/lib/python/lib/tornado/web.py:716 | +| write_error | Function write_error | resources/lib/python/lib/tornado/web.py:1069 | +| xsrf_form_html | Function xsrf_form_html | resources/lib/python/lib/tornado/web.py:1367 | diff --git a/python/ql/test/library-tests/web/tornado/Methods.ql b/python/ql/test/library-tests/web/tornado/Methods.ql new file mode 100644 index 000000000000..96861c4bc0b2 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Methods.ql @@ -0,0 +1,12 @@ + +import python + +import semmle.python.TestUtils + +import semmle.python.web.tornado.Tornado + +from FunctionObject func, string name +where func = getTornadoRequestHandlerMethod(name) and +/* Compatibility hack to make tests pass on both 1.20 and 1.21 */ +not name = "_execute" +select name, func.toString(), remove_library_prefix(func.getFunction().getLocation()) diff --git a/python/ql/test/library-tests/web/tornado/Sinks.expected b/python/ql/test/library-tests/web/tornado/Sinks.expected new file mode 100644 index 000000000000..a44d48488cc2 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Sinks.expected @@ -0,0 +1,6 @@ +| resources/lib/python/lib/tornado/web.py:2316 | to_url | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2471 | chunk | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2597 | BinaryExpr | externally controlled string | +| test.py:6 | Attribute() | externally controlled string | +| test.py:12 | name | externally controlled string | +| test.py:20 | url | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Sinks.ql b/python/ql/test/library-tests/web/tornado/Sinks.ql new file mode 100644 index 000000000000..7d338fe63c6c --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Sinks.ql @@ -0,0 +1,11 @@ + +import python + +import semmle.python.web.HttpRequest +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted +import semmle.python.TestUtils + +from TaintSink sink, TaintKind kind +where sink.sinks(kind) +select remove_library_prefix(sink.getLocation()), sink.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/tornado/Sources.expected b/python/ql/test/library-tests/web/tornado/Sources.expected new file mode 100644 index 000000000000..a0e4a50bf9a1 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Sources.expected @@ -0,0 +1,15 @@ +| resources/lib/python/lib/tornado/web.py:406 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:449 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2313 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2315 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2421 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2476 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2522 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2527 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2596 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2597 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2728 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2826 | Attribute | tornado.request.HttpRequest | +| test.py:6 | Attribute() | externally controlled string | +| test.py:10 | Attribute() | [externally controlled string] | +| test.py:17 | Attribute | tornado.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/tornado/Sources.ql b/python/ql/test/library-tests/web/tornado/Sources.ql new file mode 100644 index 000000000000..164f45d627b5 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Sources.ql @@ -0,0 +1,13 @@ + +import python + +import semmle.python.TestUtils + +import semmle.python.web.HttpRequest +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + + +from TaintSource src, TaintKind kind +where src.isSourceOf(kind) +select remove_library_prefix(src.getLocation()), src.(ControlFlowNode).getNode().toString(), kind diff --git a/python/ql/test/library-tests/web/tornado/Taint.expected b/python/ql/test/library-tests/web/tornado/Taint.expected new file mode 100644 index 000000000000..11eb5ef7891f --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Taint.expected @@ -0,0 +1,38 @@ +| resources/lib/python/lib/tornado/web.py:406 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:406 | Attribute | {[externally controlled string]} | +| resources/lib/python/lib/tornado/web.py:449 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:449 | Attribute | {[externally controlled string]} | +| resources/lib/python/lib/tornado/web.py:2313 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2313 | Attribute | {[externally controlled string]} | +| resources/lib/python/lib/tornado/web.py:2315 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2315 | Attribute | {[externally controlled string]} | +| resources/lib/python/lib/tornado/web.py:2421 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2421 | Attribute | {externally controlled string} | +| resources/lib/python/lib/tornado/web.py:2421 | Attribute() | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2422 | range_header | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2425 | range_header | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2476 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2522 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2522 | Attribute | {externally controlled string} | +| resources/lib/python/lib/tornado/web.py:2522 | Attribute() | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2527 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2527 | Attribute | {externally controlled string} | +| resources/lib/python/lib/tornado/web.py:2527 | Attribute() | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2528 | ims_value | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2529 | ims_value | externally controlled string | +| resources/lib/python/lib/tornado/web.py:2596 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2597 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2728 | Attribute | tornado.request.HttpRequest | +| resources/lib/python/lib/tornado/web.py:2728 | Attribute | {[externally controlled string]} | +| resources/lib/python/lib/tornado/web.py:2826 | Attribute | tornado.request.HttpRequest | +| test.py:6 | Attribute() | externally controlled string | +| test.py:10 | Attribute() | [externally controlled string] | +| test.py:11 | Subscript | externally controlled string | +| test.py:11 | args | [externally controlled string] | +| test.py:12 | name | externally controlled string | +| test.py:17 | Attribute | tornado.request.HttpRequest | +| test.py:18 | Attribute | {externally controlled string} | +| test.py:18 | req | tornado.request.HttpRequest | +| test.py:19 | Subscript | externally controlled string | +| test.py:19 | h | {externally controlled string} | +| test.py:20 | url | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Taint.ql b/python/ql/test/library-tests/web/tornado/Taint.ql new file mode 100644 index 000000000000..d0b1d3273417 --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/Taint.ql @@ -0,0 +1,14 @@ + +import python + +import semmle.python.TestUtils + +import semmle.python.web.HttpRequest +import semmle.python.web.HttpResponse +import semmle.python.security.strings.Untrusted + +from TaintedNode node +// Add this restriction to keep Python2 and 3 results the same. +where not exists(node.getContext().getCaller()) +select remove_library_prefix(node.getLocation()), node.getAstNode().toString(), node.getTaintKind() + diff --git a/python/ql/test/library-tests/web/tornado/options b/python/ql/test/library-tests/web/tornado/options new file mode 100644 index 000000000000..bcb745ec528e --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/options @@ -0,0 +1,2 @@ +semmle-extractor-options: --max-import-depth=2 -p ../../../../../../../resources/lib/python/lib/ +optimize: true diff --git a/python/ql/test/library-tests/web/tornado/test.py b/python/ql/test/library-tests/web/tornado/test.py new file mode 100644 index 000000000000..151efd2166fc --- /dev/null +++ b/python/ql/test/library-tests/web/tornado/test.py @@ -0,0 +1,20 @@ + +import tornado.web + +class Handler1(tornado.web.RequestHandler): + def get(self): + self.write(self.get_argument("xss")) + +class Handler2(tornado.web.RequestHandler): + def get(self): + args = self.get_body_arguments() + name = args[0] + self.write(name) + +class Handler3(tornado.web.RequestHandler): + + def get(self): + req = self.request + h = req.headers + url = h["url"] + self.redirect(url) From bc50e90f5b45fd9ee6f20eb293c24f88e52a638b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Wed, 23 Oct 2019 16:53:30 +0200 Subject: [PATCH 0081/2538] Python: Use mock for tornado tests --- .../web/tornado/Classes.expected | 4 - .../web/tornado/Methods.expected | 76 ------------------- .../library-tests/web/tornado/Sinks.expected | 3 - .../web/tornado/Sources.expected | 12 --- .../library-tests/web/tornado/Taint.expected | 27 ------- .../ql/test/library-tests/web/tornado/options | 2 +- .../Security/lib/tornado/__init__.py | 0 .../query-tests/Security/lib/tornado/web.py | 2 + 8 files changed, 3 insertions(+), 123 deletions(-) create mode 100644 python/ql/test/query-tests/Security/lib/tornado/__init__.py create mode 100644 python/ql/test/query-tests/Security/lib/tornado/web.py diff --git a/python/ql/test/library-tests/web/tornado/Classes.expected b/python/ql/test/library-tests/web/tornado/Classes.expected index c303fda39e77..94a11c22065e 100644 --- a/python/ql/test/library-tests/web/tornado/Classes.expected +++ b/python/ql/test/library-tests/web/tornado/Classes.expected @@ -1,7 +1,3 @@ -| class ErrorHandler | resources/lib/python/lib/tornado/web.py:2260 | -| class FallbackHandler | resources/lib/python/lib/tornado/web.py:2806 | | class Handler1 | test.py:4 | | class Handler2 | test.py:8 | | class Handler3 | test.py:14 | -| class RedirectHandler | resources/lib/python/lib/tornado/web.py:2275 | -| class StaticFileHandler | resources/lib/python/lib/tornado/web.py:2319 | diff --git a/python/ql/test/library-tests/web/tornado/Methods.expected b/python/ql/test/library-tests/web/tornado/Methods.expected index 684d18ca9dab..e69de29bb2d1 100644 --- a/python/ql/test/library-tests/web/tornado/Methods.expected +++ b/python/ql/test/library-tests/web/tornado/Methods.expected @@ -1,76 +0,0 @@ -| __init__ | Function __init__ | resources/lib/python/lib/tornado/web.py:168 | -| _break_cycles | Function _break_cycles | resources/lib/python/lib/tornado/web.py:1025 | -| _clear_headers_for_304 | Function _clear_headers_for_304 | resources/lib/python/lib/tornado/web.py:1636 | -| _convert_header_value | Function _convert_header_value | resources/lib/python/lib/tornado/web.py:363 | -| _decode_xsrf_token | Function _decode_xsrf_token | resources/lib/python/lib/tornado/web.py:1294 | -| _get_argument | Function _get_argument | resources/lib/python/lib/tornado/web.py:479 | -| _get_arguments | Function _get_arguments | resources/lib/python/lib/tornado/web.py:487 | -| _get_raw_xsrf_token | Function _get_raw_xsrf_token | resources/lib/python/lib/tornado/web.py:1270 | -| _handle_request_exception | Function _handle_request_exception | resources/lib/python/lib/tornado/web.py:1581 | -| _log | Function _log | resources/lib/python/lib/tornado/web.py:1568 | -| _request_summary | Function _request_summary | resources/lib/python/lib/tornado/web.py:1577 | -| _stack_context_handle_exception | Function _stack_context_handle_exception | resources/lib/python/lib/tornado/web.py:1493 | -| _ui_method | Function _ui_method | resources/lib/python/lib/tornado/web.py:1633 | -| _ui_module | Function _ui_module | resources/lib/python/lib/tornado/web.py:1623 | -| add_header | Function add_header | resources/lib/python/lib/tornado/web.py:343 | -| check_etag_header | Function check_etag_header | resources/lib/python/lib/tornado/web.py:1452 | -| check_xsrf_cookie | Function check_xsrf_cookie | resources/lib/python/lib/tornado/web.py:1330 | -| clear | Function clear | resources/lib/python/lib/tornado/web.py:288 | -| clear_all_cookies | Function clear_all_cookies | resources/lib/python/lib/tornado/web.py:597 | -| clear_cookie | Function clear_cookie | resources/lib/python/lib/tornado/web.py:582 | -| clear_header | Function clear_header | resources/lib/python/lib/tornado/web.py:352 | -| compute_etag | Function compute_etag | resources/lib/python/lib/tornado/web.py:1428 | -| create_signed_value | Function create_signed_value | resources/lib/python/lib/tornado/web.py:642 | -| create_template_loader | Function create_template_loader | resources/lib/python/lib/tornado/web.py:916 | -| data_received | Function data_received | resources/lib/python/lib/tornado/web.py:1561 | -| decode_argument | Function decode_argument | resources/lib/python/lib/tornado/web.py:500 | -| delete | Function delete | resources/lib/python/lib/tornado/web.py:230 | -| finish | Function finish | resources/lib/python/lib/tornado/web.py:985 | -| flush | Function flush | resources/lib/python/lib/tornado/web.py:937 | -| get | Function get | resources/lib/python/lib/tornado/web.py:224 | -| get_argument | Function get_argument | resources/lib/python/lib/tornado/web.py:395 | -| get_arguments | Function get_arguments | resources/lib/python/lib/tornado/web.py:408 | -| get_body_argument | Function get_body_argument | resources/lib/python/lib/tornado/web.py:423 | -| get_body_arguments | Function get_body_arguments | resources/lib/python/lib/tornado/web.py:440 | -| get_browser_locale | Function get_browser_locale | resources/lib/python/lib/tornado/web.py:1127 | -| get_cookie | Function get_cookie | resources/lib/python/lib/tornado/web.py:525 | -| get_current_user | Function get_current_user | resources/lib/python/lib/tornado/web.py:1191 | -| get_login_url | Function get_login_url | resources/lib/python/lib/tornado/web.py:1198 | -| get_query_argument | Function get_query_argument | resources/lib/python/lib/tornado/web.py:451 | -| get_query_arguments | Function get_query_arguments | resources/lib/python/lib/tornado/web.py:468 | -| get_secure_cookie | Function get_secure_cookie | resources/lib/python/lib/tornado/web.py:665 | -| get_secure_cookie_key_version | Function get_secure_cookie_key_version | resources/lib/python/lib/tornado/web.py:688 | -| get_status | Function get_status | resources/lib/python/lib/tornado/web.py:329 | -| get_template_namespace | Function get_template_namespace | resources/lib/python/lib/tornado/web.py:893 | -| get_template_path | Function get_template_path | resources/lib/python/lib/tornado/web.py:1206 | -| get_user_locale | Function get_user_locale | resources/lib/python/lib/tornado/web.py:1117 | -| head | Function head | resources/lib/python/lib/tornado/web.py:221 | -| initialize | Function initialize | resources/lib/python/lib/tornado/web.py:195 | -| log_exception | Function log_exception | resources/lib/python/lib/tornado/web.py:1603 | -| on_connection_close | Function on_connection_close | resources/lib/python/lib/tornado/web.py:269 | -| on_finish | Function on_finish | resources/lib/python/lib/tornado/web.py:259 | -| options | Function options | resources/lib/python/lib/tornado/web.py:239 | -| patch | Function patch | resources/lib/python/lib/tornado/web.py:233 | -| post | Function post | resources/lib/python/lib/tornado/web.py:227 | -| prepare | Function prepare | resources/lib/python/lib/tornado/web.py:242 | -| put | Function put | resources/lib/python/lib/tornado/web.py:236 | -| redirect | Function redirect | resources/lib/python/lib/tornado/web.py:698 | -| render | Function render | resources/lib/python/lib/tornado/web.py:746 | -| render_embed_css | Function render_embed_css | resources/lib/python/lib/tornado/web.py:859 | -| render_embed_js | Function render_embed_js | resources/lib/python/lib/tornado/web.py:830 | -| render_linked_css | Function render_linked_css | resources/lib/python/lib/tornado/web.py:839 | -| render_linked_js | Function render_linked_js | resources/lib/python/lib/tornado/web.py:810 | -| render_string | Function render_string | resources/lib/python/lib/tornado/web.py:868 | -| require_setting | Function require_setting | resources/lib/python/lib/tornado/web.py:1418 | -| reverse_url | Function reverse_url | resources/lib/python/lib/tornado/web.py:1424 | -| send_error | Function send_error | resources/lib/python/lib/tornado/web.py:1030 | -| set_cookie | Function set_cookie | resources/lib/python/lib/tornado/web.py:538 | -| set_default_headers | Function set_default_headers | resources/lib/python/lib/tornado/web.py:300 | -| set_etag_header | Function set_etag_header | resources/lib/python/lib/tornado/web.py:1441 | -| set_header | Function set_header | resources/lib/python/lib/tornado/web.py:333 | -| set_secure_cookie | Function set_secure_cookie | resources/lib/python/lib/tornado/web.py:613 | -| set_status | Function set_status | resources/lib/python/lib/tornado/web.py:310 | -| static_url | Function static_url | resources/lib/python/lib/tornado/web.py:1383 | -| write | Function write | resources/lib/python/lib/tornado/web.py:716 | -| write_error | Function write_error | resources/lib/python/lib/tornado/web.py:1069 | -| xsrf_form_html | Function xsrf_form_html | resources/lib/python/lib/tornado/web.py:1367 | diff --git a/python/ql/test/library-tests/web/tornado/Sinks.expected b/python/ql/test/library-tests/web/tornado/Sinks.expected index a44d48488cc2..dfcd7e7fbcbd 100644 --- a/python/ql/test/library-tests/web/tornado/Sinks.expected +++ b/python/ql/test/library-tests/web/tornado/Sinks.expected @@ -1,6 +1,3 @@ -| resources/lib/python/lib/tornado/web.py:2316 | to_url | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2471 | chunk | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2597 | BinaryExpr | externally controlled string | | test.py:6 | Attribute() | externally controlled string | | test.py:12 | name | externally controlled string | | test.py:20 | url | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Sources.expected b/python/ql/test/library-tests/web/tornado/Sources.expected index a0e4a50bf9a1..b72ab2176049 100644 --- a/python/ql/test/library-tests/web/tornado/Sources.expected +++ b/python/ql/test/library-tests/web/tornado/Sources.expected @@ -1,15 +1,3 @@ -| resources/lib/python/lib/tornado/web.py:406 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:449 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2313 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2315 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2421 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2476 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2522 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2527 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2596 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2597 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2728 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2826 | Attribute | tornado.request.HttpRequest | | test.py:6 | Attribute() | externally controlled string | | test.py:10 | Attribute() | [externally controlled string] | | test.py:17 | Attribute | tornado.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/tornado/Taint.expected b/python/ql/test/library-tests/web/tornado/Taint.expected index 11eb5ef7891f..1a2a9a1d4a29 100644 --- a/python/ql/test/library-tests/web/tornado/Taint.expected +++ b/python/ql/test/library-tests/web/tornado/Taint.expected @@ -1,30 +1,3 @@ -| resources/lib/python/lib/tornado/web.py:406 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:406 | Attribute | {[externally controlled string]} | -| resources/lib/python/lib/tornado/web.py:449 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:449 | Attribute | {[externally controlled string]} | -| resources/lib/python/lib/tornado/web.py:2313 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2313 | Attribute | {[externally controlled string]} | -| resources/lib/python/lib/tornado/web.py:2315 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2315 | Attribute | {[externally controlled string]} | -| resources/lib/python/lib/tornado/web.py:2421 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2421 | Attribute | {externally controlled string} | -| resources/lib/python/lib/tornado/web.py:2421 | Attribute() | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2422 | range_header | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2425 | range_header | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2476 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2522 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2522 | Attribute | {externally controlled string} | -| resources/lib/python/lib/tornado/web.py:2522 | Attribute() | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2527 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2527 | Attribute | {externally controlled string} | -| resources/lib/python/lib/tornado/web.py:2527 | Attribute() | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2528 | ims_value | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2529 | ims_value | externally controlled string | -| resources/lib/python/lib/tornado/web.py:2596 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2597 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2728 | Attribute | tornado.request.HttpRequest | -| resources/lib/python/lib/tornado/web.py:2728 | Attribute | {[externally controlled string]} | -| resources/lib/python/lib/tornado/web.py:2826 | Attribute | tornado.request.HttpRequest | | test.py:6 | Attribute() | externally controlled string | | test.py:10 | Attribute() | [externally controlled string] | | test.py:11 | Subscript | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/options b/python/ql/test/library-tests/web/tornado/options index bcb745ec528e..0267f80a6d65 100644 --- a/python/ql/test/library-tests/web/tornado/options +++ b/python/ql/test/library-tests/web/tornado/options @@ -1,2 +1,2 @@ -semmle-extractor-options: --max-import-depth=2 -p ../../../../../../../resources/lib/python/lib/ +semmle-extractor-options: --max-import-depth=2 -p ../../../query-tests/Security/lib/ optimize: true diff --git a/python/ql/test/query-tests/Security/lib/tornado/__init__.py b/python/ql/test/query-tests/Security/lib/tornado/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/ql/test/query-tests/Security/lib/tornado/web.py b/python/ql/test/query-tests/Security/lib/tornado/web.py new file mode 100644 index 000000000000..41b918489929 --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/tornado/web.py @@ -0,0 +1,2 @@ +class RequestHandler(object): + pass From 3e3833927b084220861302e1e799a2fabda404c7 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 24 Oct 2019 14:05:45 +0200 Subject: [PATCH 0082/2538] Python: Remove unused getTornadoRequestHandlerMethod It was only used in a test, and with the mock, it gives no results anyway. --- python/ql/src/semmle/python/web/tornado/Tornado.qll | 4 ---- .../test/library-tests/web/tornado/Methods.expected | 0 python/ql/test/library-tests/web/tornado/Methods.ql | 12 ------------ 3 files changed, 16 deletions(-) delete mode 100644 python/ql/test/library-tests/web/tornado/Methods.expected delete mode 100644 python/ql/test/library-tests/web/tornado/Methods.ql diff --git a/python/ql/src/semmle/python/web/tornado/Tornado.qll b/python/ql/src/semmle/python/web/tornado/Tornado.qll index c9d8a2237e46..f138fee3b5c7 100644 --- a/python/ql/src/semmle/python/web/tornado/Tornado.qll +++ b/python/ql/src/semmle/python/web/tornado/Tornado.qll @@ -11,10 +11,6 @@ ClassObject aTornadoRequestHandlerClass() { result.getASuperType() = theTornadoRequestHandlerClass() } -FunctionObject getTornadoRequestHandlerMethod(string name) { - result = theTornadoRequestHandlerClass().declaredAttribute(name) -} - /** Holds if `node` is likely to refer to an instance of a tornado * `RequestHandler` class. */ diff --git a/python/ql/test/library-tests/web/tornado/Methods.expected b/python/ql/test/library-tests/web/tornado/Methods.expected deleted file mode 100644 index e69de29bb2d1..000000000000 diff --git a/python/ql/test/library-tests/web/tornado/Methods.ql b/python/ql/test/library-tests/web/tornado/Methods.ql deleted file mode 100644 index 96861c4bc0b2..000000000000 --- a/python/ql/test/library-tests/web/tornado/Methods.ql +++ /dev/null @@ -1,12 +0,0 @@ - -import python - -import semmle.python.TestUtils - -import semmle.python.web.tornado.Tornado - -from FunctionObject func, string name -where func = getTornadoRequestHandlerMethod(name) and -/* Compatibility hack to make tests pass on both 1.20 and 1.21 */ -not name = "_execute" -select name, func.toString(), remove_library_prefix(func.getFunction().getLocation()) From 2bb933fef0cf4bfeb6b8ca2b05b245daca269489 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 1 Oct 2019 16:04:54 +0200 Subject: [PATCH 0083/2538] Python: Modernise tornado library --- .../src/semmle/python/web/tornado/Tornado.qll | 19 +++++++++---------- .../web/tornado/Classes.expected | 1 + .../test/library-tests/web/tornado/Classes.ql | 4 ++-- .../library-tests/web/tornado/Sinks.expected | 1 + .../web/tornado/Sources.expected | 1 + .../library-tests/web/tornado/Taint.expected | 1 + .../ql/test/library-tests/web/tornado/test.py | 6 ++++++ 7 files changed, 21 insertions(+), 12 deletions(-) diff --git a/python/ql/src/semmle/python/web/tornado/Tornado.qll b/python/ql/src/semmle/python/web/tornado/Tornado.qll index f138fee3b5c7..f40537ae276c 100644 --- a/python/ql/src/semmle/python/web/tornado/Tornado.qll +++ b/python/ql/src/semmle/python/web/tornado/Tornado.qll @@ -3,26 +3,25 @@ import python import semmle.python.security.TaintTracking import semmle.python.web.Http -private ClassObject theTornadoRequestHandlerClass() { - result = ModuleObject::named("tornado.web").attr("RequestHandler") +private ClassValue theTornadoRequestHandlerClass() { + result = Value::named("tornado.web.RequestHandler") } -ClassObject aTornadoRequestHandlerClass() { - result.getASuperType() = theTornadoRequestHandlerClass() +ClassValue aTornadoRequestHandlerClass() { + result.getABaseType+() = theTornadoRequestHandlerClass() } -/** Holds if `node` is likely to refer to an instance of a tornado +/** Holds if `node` is likely to refer to an instance of a tornado * `RequestHandler` class. */ - predicate isTornadoRequestHandlerInstance(ControlFlowNode node) { - node.refersTo(_, aTornadoRequestHandlerClass(), _) + node.pointsTo().getClass() = aTornadoRequestHandlerClass() or /* In some cases, the points-to analysis won't capture all instances we care - * about. For these, we use the following syntactic check. First, that - * `node` appears inside a method of a subclass of + * about. For these, we use the following syntactic check. First, that + * `node` appears inside a method of a subclass of * `tornado.web.RequestHandler`:*/ - node.getScope().getEnclosingScope().(Class).getClassObject() = aTornadoRequestHandlerClass() and + node.getScope().getEnclosingScope() = aTornadoRequestHandlerClass().getScope() and /* Secondly, that `node` refers to the `self` argument: */ node.isLoad() and node.(NameNode).isSelf() } diff --git a/python/ql/test/library-tests/web/tornado/Classes.expected b/python/ql/test/library-tests/web/tornado/Classes.expected index 94a11c22065e..b9b39efbf6b0 100644 --- a/python/ql/test/library-tests/web/tornado/Classes.expected +++ b/python/ql/test/library-tests/web/tornado/Classes.expected @@ -1,3 +1,4 @@ +| class DeepInheritance | test.py:23 | | class Handler1 | test.py:4 | | class Handler2 | test.py:8 | | class Handler3 | test.py:14 | diff --git a/python/ql/test/library-tests/web/tornado/Classes.ql b/python/ql/test/library-tests/web/tornado/Classes.ql index a4915037ac3b..1246ccc7ab35 100644 --- a/python/ql/test/library-tests/web/tornado/Classes.ql +++ b/python/ql/test/library-tests/web/tornado/Classes.ql @@ -4,6 +4,6 @@ import python import semmle.python.TestUtils import semmle.python.web.tornado.Tornado -from ClassObject cls +from ClassValue cls where cls = aTornadoRequestHandlerClass() -select cls.toString(), remove_library_prefix(cls.getPyClass().getLocation()) +select cls.toString(), remove_library_prefix(cls.getScope().getLocation()) diff --git a/python/ql/test/library-tests/web/tornado/Sinks.expected b/python/ql/test/library-tests/web/tornado/Sinks.expected index dfcd7e7fbcbd..d493bb82ee3b 100644 --- a/python/ql/test/library-tests/web/tornado/Sinks.expected +++ b/python/ql/test/library-tests/web/tornado/Sinks.expected @@ -1,3 +1,4 @@ | test.py:6 | Attribute() | externally controlled string | | test.py:12 | name | externally controlled string | | test.py:20 | url | externally controlled string | +| test.py:26 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Sources.expected b/python/ql/test/library-tests/web/tornado/Sources.expected index b72ab2176049..78fb140df3c2 100644 --- a/python/ql/test/library-tests/web/tornado/Sources.expected +++ b/python/ql/test/library-tests/web/tornado/Sources.expected @@ -1,3 +1,4 @@ | test.py:6 | Attribute() | externally controlled string | | test.py:10 | Attribute() | [externally controlled string] | | test.py:17 | Attribute | tornado.request.HttpRequest | +| test.py:26 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/Taint.expected b/python/ql/test/library-tests/web/tornado/Taint.expected index 1a2a9a1d4a29..6028c194b944 100644 --- a/python/ql/test/library-tests/web/tornado/Taint.expected +++ b/python/ql/test/library-tests/web/tornado/Taint.expected @@ -9,3 +9,4 @@ | test.py:19 | Subscript | externally controlled string | | test.py:19 | h | {externally controlled string} | | test.py:20 | url | externally controlled string | +| test.py:26 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/tornado/test.py b/python/ql/test/library-tests/web/tornado/test.py index 151efd2166fc..a5a467a81ab1 100644 --- a/python/ql/test/library-tests/web/tornado/test.py +++ b/python/ql/test/library-tests/web/tornado/test.py @@ -18,3 +18,9 @@ def get(self): h = req.headers url = h["url"] self.redirect(url) + + +class DeepInheritance(Handler3): + + def get(self): + self.write(self.get_argument("also_xss")) From e7eaf2b7d9bf54c102375e7c22d73b7f9fbc1ae4 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 1 Oct 2019 16:06:33 +0200 Subject: [PATCH 0084/2538] Python: Autoformat (4 spaces) tornado library --- .../semmle/python/web/tornado/Redirect.qll | 12 ++-- .../src/semmle/python/web/tornado/Request.qll | 47 ++++------------ .../semmle/python/web/tornado/Response.qll | 55 ++++--------------- .../src/semmle/python/web/tornado/Tornado.qll | 21 +++---- 4 files changed, 36 insertions(+), 99 deletions(-) diff --git a/python/ql/src/semmle/python/web/tornado/Redirect.qll b/python/ql/src/semmle/python/web/tornado/Redirect.qll index f059560e23d9..cf213a5b044d 100644 --- a/python/ql/src/semmle/python/web/tornado/Redirect.qll +++ b/python/ql/src/semmle/python/web/tornado/Redirect.qll @@ -1,23 +1,20 @@ -/** Provides class representing the `tornado.redirect` function. +/** + * Provides class representing the `tornado.redirect` function. * This module is intended to be imported into a taint-tracking query * to extend `TaintSink`. */ -import python +import python import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic import semmle.python.web.Http import Tornado - /** * Represents an argument to the `tornado.redirect` function. */ class TornadoRedirect extends HttpRedirectTaintSink { - - override string toString() { - result = "tornado.redirect" - } + override string toString() { result = "tornado.redirect" } TornadoRedirect() { exists(CallNode call, ControlFlowNode node | @@ -26,5 +23,4 @@ class TornadoRedirect extends HttpRedirectTaintSink { this = call.getAnArg() ) } - } diff --git a/python/ql/src/semmle/python/web/tornado/Request.qll b/python/ql/src/semmle/python/web/tornado/Request.qll index ae19730e26e7..a5a6c752f8ed 100644 --- a/python/ql/src/semmle/python/web/tornado/Request.qll +++ b/python/ql/src/semmle/python/web/tornado/Request.qll @@ -1,15 +1,11 @@ import python - import semmle.python.security.TaintTracking import semmle.python.web.Http import Tornado /** A tornado.request.HttpRequest object */ class TornadoRequest extends TaintKind { - - TornadoRequest() { - this = "tornado.request.HttpRequest" - } + TornadoRequest() { this = "tornado.request.HttpRequest" } override TaintKind getTaintOfAttribute(string name) { result instanceof ExternalStringDictKind and @@ -32,68 +28,45 @@ class TornadoRequest extends TaintKind { name = "body_arguments" ) } - } - class TornadoRequestSource extends TaintSource { + TornadoRequestSource() { isTornadoRequestHandlerInstance(this.(AttrNode).getObject("request")) } - TornadoRequestSource() { - isTornadoRequestHandlerInstance(this.(AttrNode).getObject("request")) - } - - override string toString() { - result = "Tornado request source" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof TornadoRequest - } + override string toString() { result = "Tornado request source" } + override predicate isSourceOf(TaintKind kind) { kind instanceof TornadoRequest } } class TornadoExternalInputSource extends TaintSource { - TornadoExternalInputSource() { exists(string name | name = "get_argument" or name = "get_query_argument" or name = "get_body_argument" or name = "decode_argument" - | + | this = callToNamedTornadoRequestHandlerMethod(name) ) } - override string toString() { - result = "Tornado request method" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringKind - } + override string toString() { result = "Tornado request method" } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringKind } } class TornadoExternalInputListSource extends TaintSource { - TornadoExternalInputListSource() { exists(string name | name = "get_arguments" or name = "get_query_arguments" or name = "get_body_arguments" - | + | this = callToNamedTornadoRequestHandlerMethod(name) ) } - override string toString() { - result = "Tornado request method" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof ExternalStringSequenceKind - } + override string toString() { result = "Tornado request method" } + override predicate isSourceOf(TaintKind kind) { kind instanceof ExternalStringSequenceKind } } - diff --git a/python/ql/src/semmle/python/web/tornado/Response.qll b/python/ql/src/semmle/python/web/tornado/Response.qll index ebaae1414ea8..e6312c49549d 100644 --- a/python/ql/src/semmle/python/web/tornado/Response.qll +++ b/python/ql/src/semmle/python/web/tornado/Response.qll @@ -1,63 +1,42 @@ import python - - import semmle.python.security.TaintTracking import semmle.python.security.strings.Basic private import semmle.python.web.Http - import Tornado class TornadoConnection extends TaintKind { - - TornadoConnection() { - this = "tornado.http.connection" - } - + TornadoConnection() { this = "tornado.http.connection" } } class TornadoConnectionSource extends TaintSource { - TornadoConnectionSource() { isTornadoRequestHandlerInstance(this.(AttrNode).getObject("connection")) } - override string toString() { - result = "Tornado http connection source" - } - - override predicate isSourceOf(TaintKind kind) { - kind instanceof TornadoConnection - } + override string toString() { result = "Tornado http connection source" } + override predicate isSourceOf(TaintKind kind) { kind instanceof TornadoConnection } } class TornadoConnectionWrite extends HttpResponseTaintSink { - - override string toString() { - result = "tornado.connection.write" - } + override string toString() { result = "tornado.connection.write" } TornadoConnectionWrite() { exists(CallNode call, ControlFlowNode conn | conn = call.getFunction().(AttrNode).getObject("write") and - this = call.getAnArg() | + this = call.getAnArg() + | exists(TornadoConnection tc | tc.taints(conn)) or isTornadoRequestHandlerInstance(conn) ) } - override predicate sinks(TaintKind kind) { - kind instanceof StringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof StringKind } } class TornadoHttpRequestHandlerWrite extends HttpResponseTaintSink { - - override string toString() { - result = "tornado.HttpRequesHandler.write" - } + override string toString() { result = "tornado.HttpRequesHandler.write" } TornadoHttpRequestHandlerWrite() { exists(CallNode call, ControlFlowNode node | @@ -67,17 +46,11 @@ class TornadoHttpRequestHandlerWrite extends HttpResponseTaintSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof StringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof StringKind } } class TornadoHttpRequestHandlerRedirect extends HttpResponseTaintSink { - - override string toString() { - result = "tornado.HttpRequesHandler.redirect" - } + override string toString() { result = "tornado.HttpRequesHandler.redirect" } TornadoHttpRequestHandlerRedirect() { exists(CallNode call, ControlFlowNode node | @@ -87,11 +60,5 @@ class TornadoHttpRequestHandlerRedirect extends HttpResponseTaintSink { ) } - override predicate sinks(TaintKind kind) { - kind instanceof StringKind - } - + override predicate sinks(TaintKind kind) { kind instanceof StringKind } } - - - diff --git a/python/ql/src/semmle/python/web/tornado/Tornado.qll b/python/ql/src/semmle/python/web/tornado/Tornado.qll index f40537ae276c..bf2e0260428f 100644 --- a/python/ql/src/semmle/python/web/tornado/Tornado.qll +++ b/python/ql/src/semmle/python/web/tornado/Tornado.qll @@ -1,5 +1,4 @@ import python - import semmle.python.security.TaintTracking import semmle.python.web.Http @@ -11,28 +10,31 @@ ClassValue aTornadoRequestHandlerClass() { result.getABaseType+() = theTornadoRequestHandlerClass() } -/** Holds if `node` is likely to refer to an instance of a tornado +/** + * Holds if `node` is likely to refer to an instance of a tornado * `RequestHandler` class. */ predicate isTornadoRequestHandlerInstance(ControlFlowNode node) { node.pointsTo().getClass() = aTornadoRequestHandlerClass() or - /* In some cases, the points-to analysis won't capture all instances we care - * about. For these, we use the following syntactic check. First, that - * `node` appears inside a method of a subclass of - * `tornado.web.RequestHandler`:*/ + /* + * In some cases, the points-to analysis won't capture all instances we care + * about. For these, we use the following syntactic check. First, that + * `node` appears inside a method of a subclass of + * `tornado.web.RequestHandler`: + */ + node.getScope().getEnclosingScope() = aTornadoRequestHandlerClass().getScope() and /* Secondly, that `node` refers to the `self` argument: */ - node.isLoad() and node.(NameNode).isSelf() + node.isLoad() and + node.(NameNode).isSelf() } CallNode callToNamedTornadoRequestHandlerMethod(string name) { isTornadoRequestHandlerInstance(result.getFunction().(AttrNode).getObject(name)) } - class TornadoCookieSet extends CookieSet, CallNode { - TornadoCookieSet() { exists(ControlFlowNode f | f = this.getFunction().(AttrNode).getObject("set_cookie") and @@ -45,5 +47,4 @@ class TornadoCookieSet extends CookieSet, CallNode { override ControlFlowNode getKey() { result = this.getArg(0) } override ControlFlowNode getValue() { result = this.getArg(1) } - } From 5b6675aa71915e5e2f41596bb7c6d153b1c02de6 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 24 Oct 2019 14:57:21 +0200 Subject: [PATCH 0085/2538] Python: Select location first in tornado Classes test so it conforms with the general scheme in tests --- python/ql/test/library-tests/web/tornado/Classes.expected | 8 ++++---- python/ql/test/library-tests/web/tornado/Classes.ql | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/python/ql/test/library-tests/web/tornado/Classes.expected b/python/ql/test/library-tests/web/tornado/Classes.expected index b9b39efbf6b0..b9eb92a4cece 100644 --- a/python/ql/test/library-tests/web/tornado/Classes.expected +++ b/python/ql/test/library-tests/web/tornado/Classes.expected @@ -1,4 +1,4 @@ -| class DeepInheritance | test.py:23 | -| class Handler1 | test.py:4 | -| class Handler2 | test.py:8 | -| class Handler3 | test.py:14 | +| test.py:4 | class Handler1 | +| test.py:8 | class Handler2 | +| test.py:14 | class Handler3 | +| test.py:23 | class DeepInheritance | diff --git a/python/ql/test/library-tests/web/tornado/Classes.ql b/python/ql/test/library-tests/web/tornado/Classes.ql index 1246ccc7ab35..08346af0dcfe 100644 --- a/python/ql/test/library-tests/web/tornado/Classes.ql +++ b/python/ql/test/library-tests/web/tornado/Classes.ql @@ -6,4 +6,4 @@ import semmle.python.TestUtils import semmle.python.web.tornado.Tornado from ClassValue cls where cls = aTornadoRequestHandlerClass() -select cls.toString(), remove_library_prefix(cls.getScope().getLocation()) +select remove_library_prefix(cls.getScope().getLocation()), cls.toString() From 11da4a53285b6fc93afc6e9c8c88bdc6644118d4 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 24 Oct 2019 15:17:16 +0200 Subject: [PATCH 0086/2538] C++: Accept test results for GVN and sign analysis --- .../signanalysis/SignAnalysis.expected | 28 --- .../GlobalValueNumbering/ir_gvn.expected | 234 ++++++++---------- 2 files changed, 101 insertions(+), 161 deletions(-) diff --git a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected index 4dc280b6ca9b..0c8f9c1cff14 100644 --- a/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected +++ b/cpp/ql/test/library-tests/rangeanalysis/signanalysis/SignAnalysis.expected @@ -13,7 +13,6 @@ | bounded_bounds.c:16:12:16:12 | Load: x | negative strictlyNegative | | bounded_bounds.c:16:12:16:12 | Store: x | negative strictlyNegative | | inline_assembly.c:9:23:9:23 | Uninitialized: definition of y | positive | -| inline_assembly.c:10:3:10:7 | CopyValue: ... = ... | positive strictlyPositive | | inline_assembly.c:10:3:10:7 | Store: ... = ... | positive strictlyPositive | | inline_assembly.c:10:7:10:7 | Constant: (unsigned int)... | positive strictlyPositive | | inline_assembly.c:12:32:12:32 | Load: y | positive strictlyPositive | @@ -28,10 +27,8 @@ | minmax.c:18:37:18:37 | Load: x | positive strictlyPositive | | minmax.c:18:40:18:40 | Load: y | positive strictlyPositive | | minmax.c:18:43:18:43 | Load: z | positive strictlyPositive | -| minmax.c:20:2:24:3 | CopyValue: ... = ... | positive | | minmax.c:20:2:24:3 | Store: ... = ... | positive | | minmax.c:20:6:24:3 | CopyValue: (statement expression) | positive | -| minmax.c:22:18:22:22 | CopyValue: ... = ... | positive strictlyPositive | | minmax.c:22:18:22:22 | Store: ... = ... | positive strictlyPositive | | minmax.c:22:22:22:22 | Load: x | positive strictlyPositive | | minmax.c:23:3:23:3 | Load: t | positive | @@ -40,7 +37,6 @@ | minmax.c:26:40:26:40 | Load: y | positive strictlyPositive | | minmax.c:26:43:26:43 | Load: z | positive | | test.c:7:10:7:10 | Phi: p | positive | -| test.c:8:5:8:19 | CopyValue: ... = ... | positive strictlyPositive | | test.c:8:5:8:19 | Store: ... = ... | positive strictlyPositive | | test.c:8:13:8:17 | Load: count | positive | | test.c:8:13:8:19 | Add: ... + ... | positive strictlyPositive | @@ -48,7 +44,6 @@ | test.c:10:10:10:14 | Load: count | positive | | test.c:10:10:10:14 | Store: count | positive | | test.c:15:10:15:10 | Phi: p | positive | -| test.c:16:5:16:26 | CopyValue: ... = ... | positive | | test.c:16:5:16:26 | Store: ... = ... | positive | | test.c:16:13:16:26 | Rem: ... % ... | positive | | test.c:16:14:16:18 | Load: count | positive | @@ -62,7 +57,6 @@ | test.c:24:5:24:11 | Constant: ... ++ | positive strictlyPositive | | test.c:24:5:24:11 | Load: ... ++ | positive | | test.c:24:5:24:11 | Store: ... ++ | positive strictlyPositive | -| test.c:25:5:25:22 | CopyValue: ... = ... | positive | | test.c:25:5:25:22 | Store: ... = ... | positive | | test.c:25:13:25:17 | Load: count | positive strictlyPositive | | test.c:25:13:25:22 | Rem: ... % ... | positive | @@ -73,7 +67,6 @@ | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:15:33:15 | Phi: i | positive | | test.c:33:19:33:19 | Constant: 2 | positive strictlyPositive | -| test.c:33:22:33:28 | CopyValue: ... = ... | positive strictlyPositive | | test.c:33:22:33:28 | Store: ... = ... | positive strictlyPositive | | test.c:33:26:33:26 | Load: i | positive | | test.c:33:26:33:28 | Add: ... + ... | positive strictlyPositive | @@ -108,7 +101,6 @@ | test.c:51:15:51:17 | Add: ... + ... | positive strictlyPositive | | test.c:51:17:51:17 | Constant: 2 | positive strictlyPositive | | test.c:51:21:51:21 | Constant: 4 | positive strictlyPositive | -| test.c:51:24:51:30 | CopyValue: ... = ... | positive strictlyPositive | | test.c:51:24:51:30 | Store: ... = ... | positive strictlyPositive | | test.c:51:28:51:28 | Load: i | positive | | test.c:51:28:51:30 | Add: ... + ... | positive strictlyPositive | @@ -467,7 +459,6 @@ | test.c:343:5:343:7 | Constant: ... ++ | positive strictlyPositive | | test.c:343:5:343:7 | Load: ... ++ | positive | | test.c:343:5:343:7 | Store: ... ++ | positive strictlyPositive | -| test.c:345:3:345:7 | CopyValue: ... = ... | positive strictlyPositive | | test.c:345:3:345:7 | Store: ... = ... | positive strictlyPositive | | test.c:345:7:345:7 | Load: i | positive strictlyPositive | | test.c:346:7:346:7 | Load: x | positive | @@ -483,7 +474,6 @@ | test.c:356:36:356:37 | Uninitialized: definition of y6 | positive | | test.c:356:40:356:41 | Uninitialized: definition of y7 | positive | | test.c:356:44:356:45 | Uninitialized: definition of y8 | positive | -| test.c:357:3:357:23 | CopyValue: ... = ... | positive | | test.c:357:3:357:23 | Store: ... = ... | positive | | test.c:357:8:357:8 | Load: x | positive | | test.c:357:8:357:23 | Load: ... ? ... : ... | positive | @@ -493,7 +483,6 @@ | test.c:357:12:357:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:357:18:357:18 | Load: x | positive | | test.c:357:22:357:23 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:358:3:358:24 | CopyValue: ... = ... | positive | | test.c:358:3:358:24 | Store: ... = ... | positive | | test.c:358:8:358:8 | Load: x | positive | | test.c:358:8:358:24 | Load: ... ? ... : ... | positive | @@ -505,7 +494,6 @@ | test.c:358:24:358:24 | Load: x | positive | | test.c:365:7:365:7 | Load: x | positive | | test.c:365:11:365:13 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:366:5:366:15 | CopyValue: ... = ... | positive | | test.c:366:5:366:15 | Store: ... = ... | positive | | test.c:366:10:366:10 | Load: x | positive | | test.c:366:10:366:15 | Load: ... ? ... : ... | positive | @@ -513,7 +501,6 @@ | test.c:366:10:366:15 | Store: ... ? ... : ... | positive | | test.c:366:10:366:15 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:366:15:366:15 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:367:5:367:17 | CopyValue: ... = ... | positive | | test.c:367:5:367:17 | Store: ... = ... | positive | | test.c:367:10:367:10 | Load: x | positive | | test.c:367:10:367:17 | Load: ... ? ... : ... | positive | @@ -521,7 +508,6 @@ | test.c:367:10:367:17 | Store: ... ? ... : ... | positive | | test.c:367:10:367:17 | Store: ... ? ... : ... | positive strictlyPositive | | test.c:367:15:367:17 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:368:5:368:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:368:5:368:21 | Store: ... = ... | positive strictlyPositive | | test.c:368:10:368:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:368:10:368:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -529,7 +515,6 @@ | test.c:368:11:368:13 | Add: ... + ... | positive strictlyPositive | | test.c:368:13:368:13 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:368:19:368:21 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:369:5:369:36 | CopyValue: ... = ... | positive strictlyPositive | | test.c:369:5:369:36 | Store: ... = ... | positive strictlyPositive | | test.c:369:10:369:36 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:369:10:369:36 | Load: ... ? ... : ... | positive strictlyPositive | @@ -539,7 +524,6 @@ | test.c:369:27:369:29 | Add: ... + ... | positive strictlyPositive | | test.c:369:29:369:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:369:36:369:36 | Constant: 5 | positive strictlyPositive | -| test.c:370:5:370:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:370:5:370:38 | Store: ... = ... | positive strictlyPositive | | test.c:370:10:370:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:370:10:370:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -549,7 +533,6 @@ | test.c:370:27:370:29 | Add: ... + ... | positive strictlyPositive | | test.c:370:29:370:29 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:370:36:370:38 | Constant: 500 | positive strictlyPositive | -| test.c:371:5:371:39 | CopyValue: ... = ... | positive strictlyPositive | | test.c:371:5:371:39 | Store: ... = ... | positive strictlyPositive | | test.c:371:10:371:39 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:371:10:371:39 | Load: ... ? ... : ... | positive strictlyPositive | @@ -587,7 +570,6 @@ | test.c:378:24:378:25 | Uninitialized: definition of y3 | positive | | test.c:378:28:378:29 | Uninitialized: definition of y4 | positive | | test.c:378:32:378:33 | Uninitialized: definition of y5 | positive | -| test.c:379:3:379:24 | CopyValue: ... = ... | positive strictlyPositive | | test.c:379:3:379:24 | Store: ... = ... | positive strictlyPositive | | test.c:379:8:379:8 | Load: x | positive | | test.c:379:8:379:24 | Load: ... ? ... : ... | positive strictlyPositive | @@ -597,7 +579,6 @@ | test.c:379:12:379:14 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:379:18:379:18 | Load: x | positive strictlyPositive | | test.c:379:22:379:24 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:380:3:380:25 | CopyValue: ... = ... | positive strictlyPositive | | test.c:380:3:380:25 | Store: ... = ... | positive strictlyPositive | | test.c:380:8:380:8 | Load: x | positive | | test.c:380:8:380:25 | Load: ... ? ... : ... | positive strictlyPositive | @@ -607,18 +588,14 @@ | test.c:380:13:380:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:19:380:21 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:380:25:380:25 | Load: x | positive strictlyPositive | -| test.c:381:3:381:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:381:3:381:11 | Store: ... = ... | positive strictlyPositive | | test.c:381:8:381:11 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:382:3:382:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:382:3:382:11 | Store: ... = ... | positive strictlyPositive | | test.c:382:8:382:11 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:383:3:383:11 | CopyValue: ... = ... | positive strictlyPositive | | test.c:383:3:383:11 | Store: ... = ... | positive strictlyPositive | | test.c:383:8:383:11 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:384:7:384:7 | Load: x | positive | | test.c:384:12:384:14 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:385:5:385:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:385:5:385:21 | Store: ... = ... | positive strictlyPositive | | test.c:385:10:385:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:385:10:385:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -626,7 +603,6 @@ | test.c:385:11:385:15 | Sub: ... - ... | positive | | test.c:385:13:385:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:385:21:385:21 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:386:5:386:21 | CopyValue: ... = ... | positive strictlyPositive | | test.c:386:5:386:21 | Store: ... = ... | positive strictlyPositive | | test.c:386:10:386:21 | Load: ... ? ... : ... | positive strictlyPositive | | test.c:386:10:386:21 | Store: ... ? ... : ... | positive strictlyPositive | @@ -634,7 +610,6 @@ | test.c:386:11:386:15 | Sub: ... - ... | positive | | test.c:386:13:386:15 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:386:21:386:21 | Constant: (unsigned int)... | positive strictlyPositive | -| test.c:387:5:387:38 | CopyValue: ... = ... | positive strictlyPositive | | test.c:387:5:387:38 | Store: ... = ... | positive strictlyPositive | | test.c:387:10:387:38 | Convert: (unsigned int)... | positive strictlyPositive | | test.c:387:10:387:38 | Load: ... ? ... : ... | positive strictlyPositive | @@ -669,7 +644,6 @@ | test.c:394:34:394:36 | Constant: (unsigned int)... | positive strictlyPositive | | test.c:395:16:395:17 | Uninitialized: definition of y1 | positive | | test.c:396:16:396:17 | Uninitialized: definition of y2 | positive | -| test.c:397:3:397:15 | CopyValue: ... = ... | positive strictlyPositive | | test.c:397:3:397:15 | Store: ... = ... | positive strictlyPositive | | test.c:397:9:397:11 | Add: ++ ... | positive strictlyPositive | | test.c:397:9:397:11 | Constant: ++ ... | positive strictlyPositive | @@ -677,13 +651,11 @@ | test.c:397:9:397:11 | Store: ++ ... | positive strictlyPositive | | test.c:397:9:397:14 | CopyValue: ... , ... | positive strictlyPositive | | test.c:397:14:397:14 | Load: y | positive strictlyPositive | -| test.c:398:3:398:23 | CopyValue: ... = ... | positive strictlyPositive | | test.c:398:3:398:23 | Store: ... = ... | positive strictlyPositive | | test.c:398:9:398:11 | Add: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Constant: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Load: ... ++ | positive strictlyPositive | | test.c:398:9:398:11 | Store: ... ++ | positive strictlyPositive | -| test.c:398:9:398:19 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:9:398:22 | CopyValue: ... , ... | positive strictlyPositive | | test.c:398:14:398:19 | Add: ... += ... | positive strictlyPositive | | test.c:398:14:398:19 | Load: ... += ... | positive strictlyPositive | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 4bc9f90cc60e..ec6f300a9576 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -40,40 +40,34 @@ test.cpp: # 5| valnum = r0_7 # 5| m0_19(int) = Store : &:r0_18, r0_17 # 5| valnum = r0_17 -# 5| r0_20(glval) = CopyValue : r0_18 -# 5| valnum = r0_7 -# 6| r0_21(glval) = VariableAddress[p0] : +# 6| r0_20(glval) = VariableAddress[p0] : # 6| valnum = r0_3 -# 6| r0_22(int) = Load : &:r0_21, m0_4 +# 6| r0_21(int) = Load : &:r0_20, m0_4 # 6| valnum = m0_4 -# 6| r0_23(glval) = VariableAddress[p1] : +# 6| r0_22(glval) = VariableAddress[p1] : # 6| valnum = r0_5 -# 6| r0_24(int) = Load : &:r0_23, m0_6 +# 6| r0_23(int) = Load : &:r0_22, m0_6 # 6| valnum = m0_6 -# 6| r0_25(int) = Add : r0_22, r0_24 +# 6| r0_24(int) = Add : r0_21, r0_23 # 6| valnum = r0_17 -# 6| r0_26(glval) = VariableAddress[x] : +# 6| r0_25(glval) = VariableAddress[x] : # 6| valnum = r0_7 -# 6| m0_27(int) = Store : &:r0_26, r0_25 +# 6| m0_26(int) = Store : &:r0_25, r0_24 # 6| valnum = r0_17 -# 6| r0_28(glval) = CopyValue : r0_26 -# 6| valnum = r0_7 -# 7| r0_29(glval) = VariableAddress[x] : +# 7| r0_27(glval) = VariableAddress[x] : # 7| valnum = r0_7 -# 7| r0_30(int) = Load : &:r0_29, m0_27 +# 7| r0_28(int) = Load : &:r0_27, m0_26 # 7| valnum = r0_17 -# 7| r0_31(glval) = VariableAddress[y] : +# 7| r0_29(glval) = VariableAddress[y] : # 7| valnum = r0_9 -# 7| m0_32(int) = Store : &:r0_31, r0_30 +# 7| m0_30(int) = Store : &:r0_29, r0_28 # 7| valnum = r0_17 -# 7| r0_33(glval) = CopyValue : r0_31 -# 7| valnum = r0_9 -# 8| v0_34(void) = NoOp : -# 1| r0_35(glval) = VariableAddress[#return] : +# 8| v0_31(void) = NoOp : +# 1| r0_32(glval) = VariableAddress[#return] : # 1| valnum = unique -# 1| v0_36(void) = ReturnValue : &:r0_35 -# 1| v0_37(void) = UnmodeledUse : mu* -# 1| v0_38(void) = ExitFunction : +# 1| v0_33(void) = ReturnValue : &:r0_32 +# 1| v0_34(void) = UnmodeledUse : mu* +# 1| v0_35(void) = ExitFunction : # 12| int test01(int, int) # 12| Block 0 @@ -122,46 +116,40 @@ test.cpp: # 16| valnum = r0_7 # 16| m0_22(int) = Store : &:r0_21, r0_20 # 16| valnum = r0_20 -# 16| r0_23(glval) = CopyValue : r0_21 -# 16| valnum = r0_7 -# 17| r0_24(glval) = VariableAddress[p0] : +# 17| r0_23(glval) = VariableAddress[p0] : # 17| valnum = r0_3 -# 17| r0_25(int) = Load : &:r0_24, m0_4 +# 17| r0_24(int) = Load : &:r0_23, m0_4 # 17| valnum = m0_4 -# 17| r0_26(glval) = VariableAddress[p1] : +# 17| r0_25(glval) = VariableAddress[p1] : # 17| valnum = r0_5 -# 17| r0_27(int) = Load : &:r0_26, m0_6 +# 17| r0_26(int) = Load : &:r0_25, m0_6 # 17| valnum = m0_6 -# 17| r0_28(int) = Add : r0_25, r0_27 +# 17| r0_27(int) = Add : r0_24, r0_26 # 17| valnum = r0_17 -# 17| r0_29(glval) = VariableAddress[global01] : +# 17| r0_28(glval) = VariableAddress[global01] : # 17| valnum = r0_18 -# 17| r0_30(int) = Load : &:r0_29, ~m0_1 +# 17| r0_29(int) = Load : &:r0_28, ~m0_1 # 17| valnum = unique -# 17| r0_31(int) = Add : r0_28, r0_30 -# 17| valnum = r0_31 -# 17| r0_32(glval) = VariableAddress[x] : +# 17| r0_30(int) = Add : r0_27, r0_29 +# 17| valnum = r0_30 +# 17| r0_31(glval) = VariableAddress[x] : # 17| valnum = r0_7 -# 17| m0_33(int) = Store : &:r0_32, r0_31 -# 17| valnum = r0_31 -# 17| r0_34(glval) = CopyValue : r0_32 -# 17| valnum = r0_7 -# 18| r0_35(glval) = VariableAddress[x] : +# 17| m0_32(int) = Store : &:r0_31, r0_30 +# 17| valnum = r0_30 +# 18| r0_33(glval) = VariableAddress[x] : # 18| valnum = r0_7 -# 18| r0_36(int) = Load : &:r0_35, m0_33 -# 18| valnum = r0_31 -# 18| r0_37(glval) = VariableAddress[y] : -# 18| valnum = r0_9 -# 18| m0_38(int) = Store : &:r0_37, r0_36 -# 18| valnum = r0_31 -# 18| r0_39(glval) = CopyValue : r0_37 +# 18| r0_34(int) = Load : &:r0_33, m0_32 +# 18| valnum = r0_30 +# 18| r0_35(glval) = VariableAddress[y] : # 18| valnum = r0_9 -# 19| v0_40(void) = NoOp : -# 12| r0_41(glval) = VariableAddress[#return] : +# 18| m0_36(int) = Store : &:r0_35, r0_34 +# 18| valnum = r0_30 +# 19| v0_37(void) = NoOp : +# 12| r0_38(glval) = VariableAddress[#return] : # 12| valnum = unique -# 12| v0_42(void) = ReturnValue : &:r0_41 -# 12| v0_43(void) = UnmodeledUse : mu* -# 12| v0_44(void) = ExitFunction : +# 12| v0_39(void) = ReturnValue : &:r0_38 +# 12| v0_40(void) = UnmodeledUse : mu* +# 12| v0_41(void) = ExitFunction : # 25| int test02(int, int) # 25| Block 0 @@ -210,53 +198,47 @@ test.cpp: # 29| valnum = r0_7 # 29| m0_22(int) = Store : &:r0_21, r0_20 # 29| valnum = r0_20 -# 29| r0_23(glval) = CopyValue : r0_21 -# 29| valnum = r0_7 -# 30| r0_24(glval) = FunctionAddress[change_global02] : +# 30| r0_23(glval) = FunctionAddress[change_global02] : # 30| valnum = unique -# 30| v0_25(void) = Call : func:r0_24 -# 30| m0_26(unknown) = ^CallSideEffect : ~m0_1 +# 30| v0_24(void) = Call : func:r0_23 +# 30| m0_25(unknown) = ^CallSideEffect : ~m0_1 # 30| valnum = unique -# 30| m0_27(unknown) = Chi : total:m0_1, partial:m0_26 +# 30| m0_26(unknown) = Chi : total:m0_1, partial:m0_25 # 30| valnum = unique -# 31| r0_28(glval) = VariableAddress[p0] : +# 31| r0_27(glval) = VariableAddress[p0] : # 31| valnum = r0_3 -# 31| r0_29(int) = Load : &:r0_28, m0_4 +# 31| r0_28(int) = Load : &:r0_27, m0_4 # 31| valnum = m0_4 -# 31| r0_30(glval) = VariableAddress[p1] : +# 31| r0_29(glval) = VariableAddress[p1] : # 31| valnum = r0_5 -# 31| r0_31(int) = Load : &:r0_30, m0_6 +# 31| r0_30(int) = Load : &:r0_29, m0_6 # 31| valnum = m0_6 -# 31| r0_32(int) = Add : r0_29, r0_31 +# 31| r0_31(int) = Add : r0_28, r0_30 # 31| valnum = r0_17 -# 31| r0_33(glval) = VariableAddress[global02] : +# 31| r0_32(glval) = VariableAddress[global02] : # 31| valnum = r0_18 -# 31| r0_34(int) = Load : &:r0_33, ~m0_27 +# 31| r0_33(int) = Load : &:r0_32, ~m0_26 # 31| valnum = unique -# 31| r0_35(int) = Add : r0_32, r0_34 -# 31| valnum = r0_35 -# 31| r0_36(glval) = VariableAddress[x] : -# 31| valnum = r0_7 -# 31| m0_37(int) = Store : &:r0_36, r0_35 -# 31| valnum = r0_35 -# 31| r0_38(glval) = CopyValue : r0_36 +# 31| r0_34(int) = Add : r0_31, r0_33 +# 31| valnum = r0_34 +# 31| r0_35(glval) = VariableAddress[x] : # 31| valnum = r0_7 -# 32| r0_39(glval) = VariableAddress[x] : +# 31| m0_36(int) = Store : &:r0_35, r0_34 +# 31| valnum = r0_34 +# 32| r0_37(glval) = VariableAddress[x] : # 32| valnum = r0_7 -# 32| r0_40(int) = Load : &:r0_39, m0_37 -# 32| valnum = r0_35 -# 32| r0_41(glval) = VariableAddress[y] : +# 32| r0_38(int) = Load : &:r0_37, m0_36 +# 32| valnum = r0_34 +# 32| r0_39(glval) = VariableAddress[y] : # 32| valnum = r0_9 -# 32| m0_42(int) = Store : &:r0_41, r0_40 -# 32| valnum = r0_35 -# 32| r0_43(glval) = CopyValue : r0_41 -# 32| valnum = r0_9 -# 33| v0_44(void) = NoOp : -# 25| r0_45(glval) = VariableAddress[#return] : +# 32| m0_40(int) = Store : &:r0_39, r0_38 +# 32| valnum = r0_34 +# 33| v0_41(void) = NoOp : +# 25| r0_42(glval) = VariableAddress[#return] : # 25| valnum = unique -# 25| v0_46(void) = ReturnValue : &:r0_45 -# 25| v0_47(void) = UnmodeledUse : mu* -# 25| v0_48(void) = ExitFunction : +# 25| v0_43(void) = ReturnValue : &:r0_42 +# 25| v0_44(void) = UnmodeledUse : mu* +# 25| v0_45(void) = ExitFunction : # 39| int test03(int, int, int*) # 39| Block 0 @@ -309,60 +291,52 @@ test.cpp: # 43| valnum = r0_9 # 43| m0_24(int) = Store : &:r0_23, r0_22 # 43| valnum = r0_22 -# 43| r0_25(glval) = CopyValue : r0_23 -# 43| valnum = r0_9 -# 44| r0_26(int) = Constant[0] : -# 44| valnum = r0_26 -# 44| r0_27(glval) = VariableAddress[p2] : +# 44| r0_25(int) = Constant[0] : +# 44| valnum = r0_25 +# 44| r0_26(glval) = VariableAddress[p2] : # 44| valnum = r0_7 -# 44| r0_28(int *) = Load : &:r0_27, m0_8 +# 44| r0_27(int *) = Load : &:r0_26, m0_8 # 44| valnum = m0_8 -# 44| r0_29(glval) = CopyValue : r0_28 +# 44| r0_28(glval) = CopyValue : r0_27 # 44| valnum = m0_8 -# 44| m0_30(int) = Store : &:r0_29, r0_26 -# 44| valnum = r0_26 -# 44| m0_31(unknown) = Chi : total:m0_1, partial:m0_30 +# 44| m0_29(int) = Store : &:r0_28, r0_25 +# 44| valnum = r0_25 +# 44| m0_30(unknown) = Chi : total:m0_1, partial:m0_29 # 44| valnum = unique -# 44| r0_32(glval) = CopyValue : r0_29 -# 44| valnum = m0_8 -# 45| r0_33(glval) = VariableAddress[p0] : +# 45| r0_31(glval) = VariableAddress[p0] : # 45| valnum = r0_3 -# 45| r0_34(int) = Load : &:r0_33, m0_4 +# 45| r0_32(int) = Load : &:r0_31, m0_4 # 45| valnum = m0_4 -# 45| r0_35(glval) = VariableAddress[p1] : +# 45| r0_33(glval) = VariableAddress[p1] : # 45| valnum = r0_5 -# 45| r0_36(int) = Load : &:r0_35, m0_6 +# 45| r0_34(int) = Load : &:r0_33, m0_6 # 45| valnum = m0_6 -# 45| r0_37(int) = Add : r0_34, r0_36 +# 45| r0_35(int) = Add : r0_32, r0_34 # 45| valnum = r0_19 -# 45| r0_38(glval) = VariableAddress[global03] : +# 45| r0_36(glval) = VariableAddress[global03] : # 45| valnum = r0_20 -# 45| r0_39(int) = Load : &:r0_38, ~m0_31 +# 45| r0_37(int) = Load : &:r0_36, ~m0_30 # 45| valnum = unique -# 45| r0_40(int) = Add : r0_37, r0_39 -# 45| valnum = r0_40 -# 45| r0_41(glval) = VariableAddress[x] : -# 45| valnum = r0_9 -# 45| m0_42(int) = Store : &:r0_41, r0_40 -# 45| valnum = r0_40 -# 45| r0_43(glval) = CopyValue : r0_41 +# 45| r0_38(int) = Add : r0_35, r0_37 +# 45| valnum = r0_38 +# 45| r0_39(glval) = VariableAddress[x] : # 45| valnum = r0_9 -# 46| r0_44(glval) = VariableAddress[x] : +# 45| m0_40(int) = Store : &:r0_39, r0_38 +# 45| valnum = r0_38 +# 46| r0_41(glval) = VariableAddress[x] : # 46| valnum = r0_9 -# 46| r0_45(int) = Load : &:r0_44, m0_42 -# 46| valnum = r0_40 -# 46| r0_46(glval) = VariableAddress[y] : +# 46| r0_42(int) = Load : &:r0_41, m0_40 +# 46| valnum = r0_38 +# 46| r0_43(glval) = VariableAddress[y] : # 46| valnum = r0_11 -# 46| m0_47(int) = Store : &:r0_46, r0_45 -# 46| valnum = r0_40 -# 46| r0_48(glval) = CopyValue : r0_46 -# 46| valnum = r0_11 -# 47| v0_49(void) = NoOp : -# 39| r0_50(glval) = VariableAddress[#return] : +# 46| m0_44(int) = Store : &:r0_43, r0_42 +# 46| valnum = r0_38 +# 47| v0_45(void) = NoOp : +# 39| r0_46(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_51(void) = ReturnValue : &:r0_50 -# 39| v0_52(void) = UnmodeledUse : mu* -# 39| v0_53(void) = ExitFunction : +# 39| v0_47(void) = ReturnValue : &:r0_46 +# 39| v0_48(void) = UnmodeledUse : mu* +# 39| v0_49(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -419,8 +393,6 @@ test.cpp: # 55| valnum = r0_7 # 55| m2_3(char *) = Store : &:r2_2, r2_1 # 55| valnum = m0_6 -# 55| r2_4(glval) = CopyValue : r2_2 -# 55| valnum = r0_7 #-----| Goto -> Block 3 # 56| Block 3 @@ -602,8 +574,6 @@ test.cpp: # 80| valnum = r0_5 # 80| m1_6(signed short) = Store : &:r1_5, r1_4 # 80| valnum = r1_4 -# 80| r1_7(glval) = CopyValue : r1_5 -# 80| valnum = r0_5 #-----| Goto -> Block 2 # 82| Block 2 @@ -680,12 +650,10 @@ test.cpp: # 88| valnum = r0_9 # 88| m3_4(int) = Store : &:r3_3, r3_2 # 88| valnum = m3_0 -# 88| r3_5(glval) = CopyValue : r3_3 -# 88| valnum = r0_9 -# 89| v3_6(void) = NoOp : -# 84| v3_7(void) = ReturnVoid : -# 84| v3_8(void) = UnmodeledUse : mu* -# 84| v3_9(void) = ExitFunction : +# 89| v3_5(void) = NoOp : +# 84| v3_6(void) = ReturnVoid : +# 84| v3_7(void) = UnmodeledUse : mu* +# 84| v3_8(void) = ExitFunction : # 91| int regression_test00() # 91| Block 0 From 5c07750286a2bfa2c4bdffc35f4267e488d1f7f6 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 24 Oct 2019 11:28:42 +0200 Subject: [PATCH 0087/2538] simplify the heuristic for Deferred promises --- .../ql/src/semmle/javascript/Promises.qll | 48 ++++--------------- 1 file changed, 8 insertions(+), 40 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index 13eb1e8114e9..ae8554c1a0a3 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -36,35 +36,9 @@ module Bluebird { * Provides classes for working with various Deferred implementations */ module Deferred { - class DeferredClass extends DataFlow::SourceNode { - DeferredClass() { - exists(Variable var | - var.getName() = "Deferred" and - ( - var.getADeclaration() instanceof LocalNamespaceDecl or - var.getScope() instanceof GlobalScope - ) and - this = DataFlow::valueNode(var.getADefinition()) - ) - or - this.(DataFlow::ParameterNode).getName() = "Deferred" - or - exists(Function f | - f.getName() = "Deferred" and - this = DataFlow::valueNode(f) - ) - or - exists(ClassDefinition c | - c.getName() = "Deferred" and - this = DataFlow::valueNode(c) - ) - } - } - class DeferredInstance extends DataFlow::NewNode { - DeferredClass deferredClass; - - DeferredInstance() { this = deferredClass.getAnInstantiation() } + // Describes both `new Deferred()`, `new $.Deferred` and other variants. + DeferredInstance() { this.getCalleeName() = "Deferred" } private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { t.start() and @@ -72,23 +46,17 @@ module Deferred { or exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) } - - DeferredClass getDeferredClass() { result = deferredClass } - - DataFlow::CallNode getPromiseMemberCall(string methodName) { - result = ref(DataFlow::TypeTracker::end()).getAMemberCall(methodName) - } + + DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } } /** * A promise object created by a Deferred constructor */ private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { - DeferredPromiseDefinition() { - this = any(DeferredClass c | - exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("resolve")) and - exists(any(DeferredInstance i | i.getDeferredClass() = c).getPromiseMemberCall("reject")) - ).getAnInstantiation() + DeferredPromiseDefinition() { + // hardening of the "Deferred" heuristic: a method call to `resolve`. + exists(ref().getAMethodCall("resolve")) } override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } @@ -99,7 +67,7 @@ module Deferred { */ class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { ResolvedDeferredPromiseDefinition() { - this = any(DeferredPromiseDefinition def).getPromiseMemberCall("resolve") + this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") } override DataFlow::Node getValue() { result = getArgument(0) } From 5489a80372ab2fdbf1c30f7d3a5c0625a4ed9bf1 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 10 Oct 2019 16:20:27 +0200 Subject: [PATCH 0088/2538] add query for detecting ignored calls to Array.prototype.concat --- change-notes/1.23/analysis-javascript.md | 1 + .../src/Statements/IgnoreConcatReturn.qhelp | 44 +++++++++++++++++++ .../ql/src/Statements/IgnoreConcatReturn.ql | 42 ++++++++++++++++++ .../src/Statements/examples/IgnoreConcat.js | 5 +++ .../Statements/examples/IgnoreConcatFixed.js | 5 +++ .../IgnoreConcatReturn.expected | 2 + .../IgnoreConcatReturn.qlref | 1 + .../Statements/IgnoreConcatReturn/tst.js | 13 ++++++ 8 files changed, 113 insertions(+) create mode 100644 javascript/ql/src/Statements/IgnoreConcatReturn.qhelp create mode 100644 javascript/ql/src/Statements/IgnoreConcatReturn.ql create mode 100644 javascript/ql/src/Statements/examples/IgnoreConcat.js create mode 100644 javascript/ql/src/Statements/examples/IgnoreConcatFixed.js create mode 100644 javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected create mode 100644 javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref create mode 100644 javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 73bbf1247f7b..90f46403f26c 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -23,6 +23,7 @@ | Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. | | Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. | | Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. | +| Ignoring return from concat (`js/ignore-return-from-concat`) | maintainability, correctness | Highlights calls to the concat method on array where the return value is ignored. Results are shown on LGTM by default. | ## Changes to existing queries diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp b/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp new file mode 100644 index 000000000000..1b69a61b3a9a --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp @@ -0,0 +1,44 @@ + + + +

    +The concat method on is pure and does not modify any of the input +arrays. It is therefore generally an error to ignore the return value from a +call to concat. +

    + +
    + + +

    +Use the returned value from the call to concat. +

    + +
    + + +

    +In the following example a function extend is defined. The +function uses the concat method to add elements to the +arr array. However, the extend function has no +effect as the return value from concat is ignored. +

    + + + +

    +Assigning the returned value from the call to concat to the +arr variable fixes the error. +

    + + + +
    + + +
  • Mozilla Developer Network: Array concat.
  • + +
    + diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.ql b/javascript/ql/src/Statements/IgnoreConcatReturn.ql new file mode 100644 index 000000000000..65c379b3437f --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreConcatReturn.ql @@ -0,0 +1,42 @@ +/** + * @name Ignoring return from concat + * @description The concat method does not modify an array, ignoring the result of a call to concat is therefore generally an error. + * @kind problem + * @problem.severity warning + * @id js/ignore-result-from-concat + * @tags maintainability, + * correctness + * @precision high + */ + +import javascript +import Expressions.ExprHasNoEffect + +DataFlow::SourceNode array(DataFlow::TypeTracker t) { + t.start() and + result instanceof DataFlow::ArrayCreationNode + or + exists (DataFlow::TypeTracker t2 | + result = array(t2).track(t2, t) + ) +} + +DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } + +predicate isArrayMethod(DataFlow::MethodCallNode call) { + call.getReceiver().getALocalSource() = array() +} + +predicate isIncomplete(DataFlow::Node node) { + any(DataFlow::Incompleteness cause | node.analyze().getAValue().isIndefinite(cause)) != "global" +} + +from DataFlow::CallNode call +where + isArrayMethod(call) and + call.getCalleeName() = "concat" and + call.getNumArgument() = 1 and + (call.getArgument(0).getALocalSource() = array() or isIncomplete(call.getArgument(0))) and + not call.getArgument(0).asExpr().(ArrayExpr).getSize() = 0 and + inVoidContext(call.asExpr()) +select call, "Return value from call to concat ignored." diff --git a/javascript/ql/src/Statements/examples/IgnoreConcat.js b/javascript/ql/src/Statements/examples/IgnoreConcat.js new file mode 100644 index 000000000000..7137d5261a6b --- /dev/null +++ b/javascript/ql/src/Statements/examples/IgnoreConcat.js @@ -0,0 +1,5 @@ +var arr = [1,2,3]; + +function extend(others) { + arr.concat(others); +} \ No newline at end of file diff --git a/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js b/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js new file mode 100644 index 000000000000..1c7977e9ef06 --- /dev/null +++ b/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js @@ -0,0 +1,5 @@ +var arr = [1,2,3]; + +function extend(others) { + arr = arr.concat(others); +} \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected new file mode 100644 index 000000000000..1ae8b59226a3 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected @@ -0,0 +1,2 @@ +| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Return value from call to concat ignored. | +| tst.js:5:1:5:15 | arr.concat(arr) | Return value from call to concat ignored. | diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref new file mode 100644 index 000000000000..485692fff076 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref @@ -0,0 +1 @@ +Statements/IgnoreConcatReturn.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js new file mode 100644 index 000000000000..f2c5f34cc601 --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js @@ -0,0 +1,13 @@ +var arr = [1,2,3]; + +arr.concat([1,2,3]); // NOT OK! + +arr.concat(arr); // NOT OK! + +console.log(arr.concat([1,2,3])); + +arr.concat(null); +arr.concat(); +arr.concat([]); + +({concat: Array.prototype.concat}.concat(arr)); \ No newline at end of file From 5b26d03f1ca2dba1a91e86f363dd855e09529230 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 25 Oct 2019 15:45:35 +0200 Subject: [PATCH 0089/2538] introduce backtracking, and also marking join/slice calls --- ...atReturn.qhelp => IgnoreArrayResult.qhelp} | 16 ++++--- .../ql/src/Statements/IgnoreArrayResult.ql | 45 +++++++++++++++++++ .../ql/src/Statements/IgnoreConcatReturn.ql | 42 ----------------- .../{IgnoreConcat.js => IgnoreArrayResult.js} | 0 ...ncatFixed.js => IgnoreArrayResultFixed.js} | 0 .../IgnoreArrayResult.expected} | 0 .../IgnoreArrayResult.qlref} | 0 .../tst.js | 0 8 files changed, 55 insertions(+), 48 deletions(-) rename javascript/ql/src/Statements/{IgnoreConcatReturn.qhelp => IgnoreArrayResult.qhelp} (50%) create mode 100644 javascript/ql/src/Statements/IgnoreArrayResult.ql delete mode 100644 javascript/ql/src/Statements/IgnoreConcatReturn.ql rename javascript/ql/src/Statements/examples/{IgnoreConcat.js => IgnoreArrayResult.js} (100%) rename javascript/ql/src/Statements/examples/{IgnoreConcatFixed.js => IgnoreArrayResultFixed.js} (100%) rename javascript/ql/test/query-tests/Statements/{IgnoreConcatReturn/IgnoreConcatReturn.expected => IgnoreArrayResult/IgnoreArrayResult.expected} (100%) rename javascript/ql/test/query-tests/Statements/{IgnoreConcatReturn/IgnoreConcatReturn.qlref => IgnoreArrayResult/IgnoreArrayResult.qlref} (100%) rename javascript/ql/test/query-tests/Statements/{IgnoreConcatReturn => IgnoreArrayResult}/tst.js (100%) diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp similarity index 50% rename from javascript/ql/src/Statements/IgnoreConcatReturn.qhelp rename to javascript/ql/src/Statements/IgnoreArrayResult.qhelp index 1b69a61b3a9a..b70ff1f1b32a 100644 --- a/javascript/ql/src/Statements/IgnoreConcatReturn.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -4,16 +4,18 @@

    -The concat method on is pure and does not modify any of the input -arrays. It is therefore generally an error to ignore the return value from a -call to concat. +The concat, join and slice methods are +pure and does not modify any of the inputs or the array the method was called +on. It is therefore generally an error to ignore the return value from a call +to one of these methods.

    -Use the returned value from the call to concat. +Use the returned value from the calls to concat, join +or slice.

    @@ -26,19 +28,21 @@ function uses the concat method to add elements to the effect as the return value from concat is ignored.

    - +

    Assigning the returned value from the call to concat to the arr variable fixes the error.

    - +
  • Mozilla Developer Network: Array concat.
  • +
  • Mozilla Developer Network: Array slice.
  • +
  • Mozilla Developer Network: Array join.
  • diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql new file mode 100644 index 000000000000..b3703c6992d5 --- /dev/null +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -0,0 +1,45 @@ +/** + * @name Ignoring result from pure array method + * @description The array methods do not modify the array, ignoring the result of such a call is therefore generally an error. + * @kind problem + * @problem.severity warning + * @id js/ignore-array-result + * @tags maintainability, + * correctness + * @precision high + */ + +import javascript +import Expressions.ExprHasNoEffect + +DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) { + isIgnoredPureArrayCall(call) and + ( + t.start() and + result = call.getReceiver() + or + exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) + ) +} + +DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) { + result = callsArray(DataFlow::TypeBackTracker::end(), call) +} + +predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) { + inVoidContext(call.asExpr()) and + ( + call.getMethodName() = "concat" and + call.getNumArgument() = 1 + or + call.getMethodName() = "join" and + call.getNumArgument() < 2 + or + call.getMethodName() = "slice" and + call.getNumArgument() < 3 + ) +} + +from DataFlow::MethodCallNode call +where callsArray(call) instanceof DataFlow::ArrayCreationNode +select call, "Result from call to " + call.getMethodName() + " ignored." diff --git a/javascript/ql/src/Statements/IgnoreConcatReturn.ql b/javascript/ql/src/Statements/IgnoreConcatReturn.ql deleted file mode 100644 index 65c379b3437f..000000000000 --- a/javascript/ql/src/Statements/IgnoreConcatReturn.ql +++ /dev/null @@ -1,42 +0,0 @@ -/** - * @name Ignoring return from concat - * @description The concat method does not modify an array, ignoring the result of a call to concat is therefore generally an error. - * @kind problem - * @problem.severity warning - * @id js/ignore-result-from-concat - * @tags maintainability, - * correctness - * @precision high - */ - -import javascript -import Expressions.ExprHasNoEffect - -DataFlow::SourceNode array(DataFlow::TypeTracker t) { - t.start() and - result instanceof DataFlow::ArrayCreationNode - or - exists (DataFlow::TypeTracker t2 | - result = array(t2).track(t2, t) - ) -} - -DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } - -predicate isArrayMethod(DataFlow::MethodCallNode call) { - call.getReceiver().getALocalSource() = array() -} - -predicate isIncomplete(DataFlow::Node node) { - any(DataFlow::Incompleteness cause | node.analyze().getAValue().isIndefinite(cause)) != "global" -} - -from DataFlow::CallNode call -where - isArrayMethod(call) and - call.getCalleeName() = "concat" and - call.getNumArgument() = 1 and - (call.getArgument(0).getALocalSource() = array() or isIncomplete(call.getArgument(0))) and - not call.getArgument(0).asExpr().(ArrayExpr).getSize() = 0 and - inVoidContext(call.asExpr()) -select call, "Return value from call to concat ignored." diff --git a/javascript/ql/src/Statements/examples/IgnoreConcat.js b/javascript/ql/src/Statements/examples/IgnoreArrayResult.js similarity index 100% rename from javascript/ql/src/Statements/examples/IgnoreConcat.js rename to javascript/ql/src/Statements/examples/IgnoreArrayResult.js diff --git a/javascript/ql/src/Statements/examples/IgnoreConcatFixed.js b/javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js similarity index 100% rename from javascript/ql/src/Statements/examples/IgnoreConcatFixed.js rename to javascript/ql/src/Statements/examples/IgnoreArrayResultFixed.js diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected similarity index 100% rename from javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.expected rename to javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref similarity index 100% rename from javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/IgnoreConcatReturn.qlref rename to javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref diff --git a/javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js similarity index 100% rename from javascript/ql/test/query-tests/Statements/IgnoreConcatReturn/tst.js rename to javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js From 841dac1abad86183a0c590fbe45eb486efd81039 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Fri, 25 Oct 2019 17:46:55 +0200 Subject: [PATCH 0090/2538] address review feedback --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 2fc3f01a560f..c01c6b5e3ebf 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -127,8 +127,10 @@ DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } */ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { hasNonVoidCallbackMethod(call.getCalleeName()) and - func = call.getAnArgument().getALocalSource().asExpr() and - 1 = count(DataFlow::Node arg | arg = call.getAnArgument() and arg.getALocalSource().asExpr() instanceof Function) and + exists(int index | + index = min(int i | exists(call.getCallback(i))) and + func = call.getCallback(index).getFunction() + ) and returnsVoid(func) and not isStub(func) and not alwaysThrows(func) and From 1d052a8e6256aaa7aca937e77bc25a399e160f7f Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 13:07:54 -0700 Subject: [PATCH 0091/2538] [CPP-434] Address comments re change notes. --- change-notes/1.23/analysis-cpp.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 24fa06e9bbfe..b3e16dcc29a3 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,7 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | -| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | This query checks for when two signed values are added together to test for overflow (`a + b < a`), which is undefined behavior. | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which is undefined behavior. Example: `a + b < a`. | ## Changes to existing queries From f964fe8b0ee99ebc568fad54ea4c59038ab2ba23 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 14:08:30 -0700 Subject: [PATCH 0092/2538] [CPP-434] Address comments regarding .ql and .qhelp. --- .../Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 12 ++++++------ .../Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 9b9d358dea2b..df48af7056d9 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -4,16 +4,16 @@

    -Testing for signed integer overflow by adding a -value to a variable and then comparing the result to that variable -is not defined by the C or C++ standards. The comparison may -produce an unintended result, or may be deleted by the compiler -entirely. +Testing for signed integer overflow by adding a +two signed values together and then comparing the result to one +of the values is ill-formed since the overflow check is undefined. +The comparison may produce an unintended result, or may be deleted +by the compiler entirely.

    -Make sure that the comparison in question uses unsigned values. +When checking for overflow, make sure that unsigned values are used.

    diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index f1b65dd4a967..7ea5df5da641 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -2,7 +2,7 @@ * @name Undefined result of signed test for overflow * @description Testing for overflow by adding a value to a variable * to see if it "wraps around" works only for - * `unsigned` integer values. + * unsigned integer values. * @kind problem * @problem.severity warning * @precision high @@ -15,12 +15,12 @@ import cpp private import semmle.code.cpp.valuenumbering.GlobalValueNumbering private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis -from RelationalOperation ro, AddExpr add, VariableAccess va1, VariableAccess va2 +from RelationalOperation ro, AddExpr add, Expr expr1, Expr expr2 where ro.getAnOperand() = add and - add.getAnOperand() = va1 and - ro.getAnOperand() = va2 and - globalValueNumber(va1) = globalValueNumber(va2) and - add.getType().getUnspecifiedType().(IntegralType).isSigned() and + add.getAnOperand() = expr1 and + ro.getAnOperand() = expr2 and + globalValueNumber(expr1) = globalValueNumber(expr2) and + add.getUnspecifiedType().(IntegralType).isSigned() and exprMightOverflowPositively(add) select ro, "Testing for signed overflow may produce undefined results." From 7204e137467f25d317194eab9805a846b320f3de Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 14:37:28 -0700 Subject: [PATCH 0093/2538] [CPP-434] Address comments re .cpp test cases. --- .../SignedOverflowCheck.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 72767c54aab5..273c84ae73b8 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -29,10 +29,10 @@ bool cannotHoldAnotherUInt(int n1, unsigned int delta) { } bool shortShort1(unsigned short n1, unsigned short delta) { - // clang 8.0.0 -O2: deleted - // gcc 9.2 -O2: deleted - // msvc 19.22 /O2: not deleted - return n1 + delta < n1; // GOOD: always false, but will never overflow + + // BAD [BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return n1 + delta < n1; } bool shortShort2(unsigned short n1, unsigned short delta) { @@ -107,10 +107,10 @@ bool multipleCasts(char x) { } bool multipleCasts2(char x) { - // clang 9.0.0 -O2: not deleted - // gcc 9.2 -O2: not deleted - // msvc 19.22 /O2: not deleted - return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; // GOOD: cannot overflow + + // BAD [BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. + return (int)(unsigned short)(x + '1') < (int)(unsigned short)x; } int does_it_overflow(int n1, unsigned short delta) { From 6ee3d7d788fe5e990b27309b2dcf4dd79f3d9d80 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 25 Oct 2019 15:50:00 -0700 Subject: [PATCH 0094/2538] [CPP-434] Address more comments re .cpp test cases. --- .../BadAdditionOverflowCheck/SignedOverflowCheck.cpp | 12 ++++++------ .../SignedOverflowCheck.expected | 1 + 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index 273c84ae73b8..bbfb1c3fad82 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -44,7 +44,7 @@ bool shortShort2(unsigned short n1, unsigned short delta) { /* Distinguish `varname` from `ptr->varname` and `obj.varname` */ struct N { - unsigned short n1; + int n1; } n, *np; bool shortStruct1(unsigned short n1, unsigned short delta) { @@ -60,7 +60,7 @@ bool shortStruct2(unsigned short n1, unsigned short delta) { } struct se { - short xPos; + int xPos; short yPos; short xSize; short ySize; @@ -70,7 +70,7 @@ extern se *getSo(void); bool func1(se *so) { se *o = getSo(); - if (so->xPos + so->xSize < o->xPos // GOOD + if (so->xPos + so->xSize < so->xPos // BAD || so->xPos > o->xPos + o->xSize) { // GOOD // clang 8.0.0 -O2: not deleted // gcc 9.2 -O2: not deleted @@ -100,9 +100,9 @@ int overflow12(int n) { } bool multipleCasts(char x) { - // clang 9.0.0 -O2: deleted - // gcc 9.2 -O2: deleted - // msvc 19.22 /O2: deleted + + // BAD [UNDETECTED - BadAdditionOverflowCheck.ql] + // GOOD [SigneOverflowCheck.ql]: Test always fails, but will never overflow. return (int)(unsigned short)x + 2 < (int)(unsigned short)x; // GOOD: cannot overflow } diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected index eaf6a7ac1e4d..414bc74f99e6 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.expected @@ -1,4 +1,5 @@ | SignedOverflowCheck.cpp:8:12:8:22 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:18:12:18:26 | ... < ... | Testing for signed overflow may produce undefined results. | +| SignedOverflowCheck.cpp:73:6:73:36 | ... < ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:99:10:99:30 | ... <= ... | Testing for signed overflow may produce undefined results. | | SignedOverflowCheck.cpp:122:10:122:42 | ... <= ... | Testing for signed overflow may produce undefined results. | From da23898ebae5e0701ba1aa40783401e232619c16 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sat, 26 Oct 2019 23:26:45 +0200 Subject: [PATCH 0095/2538] update tests --- .../Statements/IgnoreArrayResult/IgnoreArrayResult.expected | 4 ++-- .../Statements/IgnoreArrayResult/IgnoreArrayResult.qlref | 2 +- .../ql/test/query-tests/Statements/IgnoreArrayResult/tst.js | 4 ---- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected index 1ae8b59226a3..9f5c5a0b0829 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.expected @@ -1,2 +1,2 @@ -| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Return value from call to concat ignored. | -| tst.js:5:1:5:15 | arr.concat(arr) | Return value from call to concat ignored. | +| tst.js:3:1:3:19 | arr.concat([1,2,3]) | Result from call to concat ignored. | +| tst.js:5:1:5:15 | arr.concat(arr) | Result from call to concat ignored. | diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref index 485692fff076..2cbc7e722a5c 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/IgnoreArrayResult.qlref @@ -1 +1 @@ -Statements/IgnoreConcatReturn.ql \ No newline at end of file +Statements/IgnoreArrayResult.ql \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js index f2c5f34cc601..fc00470c8e19 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js @@ -6,8 +6,4 @@ arr.concat(arr); // NOT OK! console.log(arr.concat([1,2,3])); -arr.concat(null); -arr.concat(); -arr.concat([]); - ({concat: Array.prototype.concat}.concat(arr)); \ No newline at end of file From c6f53199d400c11c4ad71f75e44484bef81a6e18 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 27 Oct 2019 00:24:38 +0200 Subject: [PATCH 0096/2538] ignore when the reciever is the empty array --- javascript/ql/src/Statements/IgnoreArrayResult.ql | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql index b3703c6992d5..b6137e664d79 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.ql +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -41,5 +41,7 @@ predicate isIgnoredPureArrayCall(DataFlow::MethodCallNode call) { } from DataFlow::MethodCallNode call -where callsArray(call) instanceof DataFlow::ArrayCreationNode +where + callsArray(call) instanceof DataFlow::ArrayCreationNode and + not call.getReceiver().asExpr().(ArrayExpr).getSize() = 0 select call, "Result from call to " + call.getMethodName() + " ignored." From 92cebea235d6906a18e818c5234696fae2e58965 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 27 Oct 2019 00:25:59 +0200 Subject: [PATCH 0097/2538] update tests to include empty reciever case --- .../ql/test/query-tests/Statements/IgnoreArrayResult/tst.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js index fc00470c8e19..47efe8c1cb6c 100644 --- a/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js +++ b/javascript/ql/test/query-tests/Statements/IgnoreArrayResult/tst.js @@ -6,4 +6,6 @@ arr.concat(arr); // NOT OK! console.log(arr.concat([1,2,3])); -({concat: Array.prototype.concat}.concat(arr)); \ No newline at end of file +({concat: Array.prototype.concat}.concat(arr)); + +[].concat([1,2,3]); \ No newline at end of file From b2c31701f3cf6dfdfb900fdaeba38b5e0ced2444 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Sun, 27 Oct 2019 09:07:45 +0100 Subject: [PATCH 0098/2538] add documentation to two predicates --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index c01c6b5e3ebf..77ec29ba9ee7 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -89,6 +89,9 @@ predicate lastStatementHasNoEffect(Function f) { hasNoEffect(f.getExit().getAPredecessor()) } +/** + * Holds if `func` is a callee of `call`, and all possible callees of `call` never return a value. + */ predicate callToVoidFunction(DataFlow::CallNode call, Function func) { not call.isIncomplete() and func = call.getACallee() and @@ -97,6 +100,11 @@ predicate callToVoidFunction(DataFlow::CallNode call, Function func) { ) } +/** + * Holds if `name` is the name of a method from `Array.prototype` or Lodash, + * where that method takes a callback as parameter, + * and the callback is expected to return a value. + */ predicate hasNonVoidCallbackMethod(string name) { name = "every" or name = "filter" or From 1500148c765438be0170777a7c6bcd79e71b0872 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Sun, 27 Oct 2019 11:23:54 -0700 Subject: [PATCH 0099/2538] [CPP-434] Clarify Qhelp. --- .../Arithmetic/SignedOverflowCheck-good1.cpp | 2 +- .../Arithmetic/SignedOverflowCheck-good2.cpp | 4 +- .../Arithmetic/SignedOverflowCheck.qhelp | 48 +++++++++++-------- 3 files changed, 30 insertions(+), 24 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp index d79d3ccbe93a..2209b8bff711 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -1,3 +1,3 @@ bool baf(unsigned short n1, unsigned short delta) { - return n1 + (unsigned)delta < n1; // GOOD + return (unsigned short)(n1 + delta) < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp index 2670a4371f6c..cccc66b71f80 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp @@ -1,3 +1,3 @@ -bool baz(int n1, unsigned int delta) { - return n1 + delta < n1; // GOOD +bool baz(int n1, int delta) { + return (unsigned)n1 + delta < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index df48af7056d9..ae4dae550165 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -4,16 +4,22 @@

    -Testing for signed integer overflow by adding a -two signed values together and then comparing the result to one -of the values is ill-formed since the overflow check is undefined. -The comparison may produce an unintended result, or may be deleted -by the compiler entirely. +When checking for integer overflow, one often writes tests like +a + b < a. This works fine if a or +b are unsigned integers, since any overflow in the addition +will cause the value to simply "wrap around". However, using +signed integers is problematic because signed overflows have undefined +behavior according to the C and C++ standards. If the addition overflows +and has an undefined result, the comparison will likewise be undefined; +it may produce an unintended result, or may be deleted entirely by an +optimizing compiler.

    -When checking for overflow, make sure that unsigned values are used. +When checking for overflow by adding two values, first make sure that a +or b are (converted into) unsigned values, unless it is +certain that the signed addition cannot overflow.

    @@ -21,9 +27,10 @@ When checking for overflow, make sure that unsigned values are used In the following example, even though delta has been declared unsigned short, C/C++ type promotion rules require that its type is promoted to the larger type used in the addition and comparison, -namely a signed int. As a result, the entire expression is -evaluated using signed integers and may overflow, and hence -is undefined. +namely a signed int. Addition is performed on +signed integers, and may have undefined behavior if an overflow occurs. +As a result, the entire (comparison) expression may also have an undefined +result.

    @@ -39,21 +46,20 @@ hold true, which likely is not what the programmer intended. (see also the

    The following example builds upon the previous one. Again, we have two -unsigned short values getting promoted to a wider type. However, -since delta is explicitly cast to an unsigned type, -n1 (on both sides of the comparison) is promoted to -unsigned int as well. Since we are now operating on -unsigned values, the overflow check is defined and supported by -standard C/C++. +unsigned short values getting promoted to a wider type, resulting +in a comparison that always succeeds (since there is no overflow). To +test whether we have an unsigned short overflow, we cast the +left-hand side to it, causing the right-hand side to remain an unsigned +short as well.

    -In the next example, a value of type signed int is -added to a value of type unsigned int. Because -the types are of the same size, C/C++ conversion rules dictate that -unsigned int is chosen as the overall type of the addition -operation. The entire expression is evaluated using unsigned -values, which is allowed and defined behavior per the C/C++ standard. +In the next example, we have two signed int values that we +wish to add together. Adding them "as-is" opens the possibility of +a signed integer overflow, the results of which are undefined. +By casting one of the operands to unsigned, the entire +expression is evaluated using unsigned +values, which is defined behavior per the C/C++ standard.

    From 379ef1d2f94ddd38d2b383fcedaa7760b310faad Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 28 Oct 2019 10:40:06 +0100 Subject: [PATCH 0100/2538] Java: Fix bad magic and join-order. --- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll | 2 +- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll | 2 +- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll | 2 +- cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll | 2 +- .../src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll | 2 +- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll | 2 +- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll | 2 +- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll | 2 +- .../src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll | 2 +- .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll | 2 +- .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll | 2 +- .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll | 2 +- .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll | 2 +- .../src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll | 2 +- java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll | 2 +- .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll | 2 +- .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll | 2 +- .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll | 2 +- .../ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll | 2 +- 19 files changed, 19 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index 7858d7711128..c7ab550dd731 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index 7858d7711128..c7ab550dd731 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index 7858d7711128..c7ab550dd731 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index 7858d7711128..c7ab550dd731 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index 7858d7711128..c7ab550dd731 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index 7858d7711128..c7ab550dd731 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index 7858d7711128..c7ab550dd731 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index 7858d7711128..c7ab550dd731 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index 7858d7711128..c7ab550dd731 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index 7858d7711128..c7ab550dd731 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index 7858d7711128..c7ab550dd731 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -1785,7 +1785,7 @@ private predicate pathOutOfCallable0(PathNodeMid mid, ReturnPosition pos, CallCo not innercc instanceof CallContextCall } -pragma[noinline] +pragma[nomagic] private predicate pathOutOfCallable1( PathNodeMid mid, DataFlowCall call, ReturnKindExt kind, CallContext cc ) { From b0cf7cb39a9f04648fc98f796ee2c9a444d63d74 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 28 Oct 2019 13:38:53 +0100 Subject: [PATCH 0101/2538] C#: Move `UnsafeDeserialization.qll` --- .../ql/src/Security Features/CWE-502/UnsafeDeserialization.ql | 2 +- .../CWE-502/UnsafeDeserializationUntrustedInput.ql | 2 +- .../code/csharp/security/dataflow}/UnsafeDeserialization.qll | 0 3 files changed, 2 insertions(+), 2 deletions(-) rename csharp/ql/src/{Security Features/CWE-502 => semmle/code/csharp/security/dataflow}/UnsafeDeserialization.qll (100%) diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index edd0e15c2477..d0ab23560a1f 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -14,7 +14,7 @@ */ import csharp -import UnsafeDeserialization::UnsafeDeserialization +import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization from Call deserializeCall, Sink sink where deserializeCall.getAnArgument() = sink.asExpr() diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index b0b659857ab3..fb4011ec8465 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -14,7 +14,7 @@ */ import csharp -import UnsafeDeserialization::UnsafeDeserialization +import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph from TaintTrackingConfig config, DataFlow::PathNode source, DataFlow::PathNode sink diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll similarity index 100% rename from csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qll rename to csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll From eb990525d740a3744dcb2781d5466ed00140c2c3 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 28 Oct 2019 14:19:40 +0100 Subject: [PATCH 0102/2538] C#: Add precision tags to `UnsafeDeserialization[UntrustedInput].ql` --- .../CWE-502/UnsafeDeserialization.ql | 5 +-- .../UnsafeDeserializationUntrustedInput.ql | 5 +-- .../dataflow/UnsafeDeserialization.qll | 1 - .../UnsafeDeserialization/ExtractorOptions.cs | 2 +- .../UnsafeDeserialization/SystemWebStub.cs | 34 -------------- .../ExtractorOptions.cs | 2 +- .../SystemWebStub.cs | 45 ------------------- csharp/ql/test/resources/stubs/System.Web.cs | 22 +++++++++ 8 files changed, 26 insertions(+), 90 deletions(-) delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs delete mode 100644 csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql index d0ab23560a1f..40022d405732 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.ql @@ -5,14 +5,11 @@ * @kind problem * @id cs/unsafe-deserialization * @problem.severity warning + * @precision low * @tags security * external/cwe/cwe-502 */ -/* - * consider: @precision low - */ - import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql index fb4011ec8465..80a3762a8bc3 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.ql @@ -5,14 +5,11 @@ * @kind path-problem * @id cs/unsafe-deserialization-untrusted-input * @problem.severity error + * @precision high * @tags security * external/cwe/cwe-502 */ -/* - * consider: @precision high - */ - import csharp import semmle.code.csharp.security.dataflow.UnsafeDeserialization::UnsafeDeserialization import DataFlow::PathGraph diff --git a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll index 4e401eb48040..57b3a78485bf 100644 --- a/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll +++ b/csharp/ql/src/semmle/code/csharp/security/dataflow/UnsafeDeserialization.qll @@ -6,7 +6,6 @@ import csharp module UnsafeDeserialization { - private import semmle.code.csharp.dataflow.flowsources.Remote private import semmle.code.csharp.dataflow.flowsources.Remote private import semmle.code.csharp.serialization.Deserializers diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs index 11f05a14a00e..bd796aa9f519 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs deleted file mode 100644 index 48c74335f6fd..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserialization/SystemWebStub.cs +++ /dev/null @@ -1,34 +0,0 @@ -// This file contains auto-generated code. -// original-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll - -namespace System -{ - namespace Web - { - namespace Script - { - namespace Serialization - { - // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class JavaScriptSerializer - { - public JavaScriptSerializer() => throw null; - public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; - public object DeserializeObject(string input) => throw null; - } - - // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - abstract public class JavaScriptTypeResolver - { - } - - // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver - { - public SimpleTypeResolver() => throw null; - } - - } - } - } -} diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs index 11f05a14a00e..bd796aa9f519 100644 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs +++ b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/ExtractorOptions.cs @@ -1 +1 @@ -// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll +// semmle-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll /r:System.Collections.Specialized.dll ${testdir}/../../../../resources/stubs/System.Web.cs diff --git a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs b/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs deleted file mode 100644 index 293c0cdf3551..000000000000 --- a/csharp/ql/test/query-tests/Security Features/CWE-502/UnsafeDeserializationUntrustedInput/SystemWebStub.cs +++ /dev/null @@ -1,45 +0,0 @@ -// This file contains auto-generated code. -// original-extractor-options: /r:System.Runtime.Extensions.dll /r:System.IO.FileSystem.dll - -namespace System -{ - namespace Web - { - namespace UI - { - namespace WebControls - { - public class TextBox - { - public string Text { get; set; } - } - } - } - - namespace Script - { - namespace Serialization - { - // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class JavaScriptSerializer - { - public JavaScriptSerializer() => throw null; - public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; - public object DeserializeObject(string input) => throw null; - } - - // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - abstract public class JavaScriptTypeResolver - { - } - - // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` - public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver - { - public SimpleTypeResolver() => throw null; - } - - } - } - } -} diff --git a/csharp/ql/test/resources/stubs/System.Web.cs b/csharp/ql/test/resources/stubs/System.Web.cs index eb08326b7948..13ebaf316d75 100644 --- a/csharp/ql/test/resources/stubs/System.Web.cs +++ b/csharp/ql/test/resources/stubs/System.Web.cs @@ -346,3 +346,25 @@ public static class AntiForgery public static void Validate() { } } } + +namespace System.Web.Script.Serialization +{ + // Generated from `System.Web.Script.Serialization.JavaScriptSerializer` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + public class JavaScriptSerializer + { + public JavaScriptSerializer() => throw null; + public JavaScriptSerializer(System.Web.Script.Serialization.JavaScriptTypeResolver resolver) => throw null; + public object DeserializeObject(string input) => throw null; + } + + // Generated from `System.Web.Script.Serialization.JavaScriptTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + abstract public class JavaScriptTypeResolver + { + } + + // Generated from `System.Web.Script.Serialization.SimpleTypeResolver` in `System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35` + public class SimpleTypeResolver : System.Web.Script.Serialization.JavaScriptTypeResolver + { + public SimpleTypeResolver() => throw null; + } +} From 3f5ee5138b99d52ae2146e8ceddc96b628d9e331 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 28 Oct 2019 14:22:59 +0100 Subject: [PATCH 0103/2538] C#: Add change notes --- change-notes/1.23/analysis-csharp.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index 7ec412a0eb23..786c35ffbaeb 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -8,7 +8,9 @@ The following changes in version 1.23 affect C# analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| +| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security | Finds flow of untrusted input to calls to unsafe deserializers. | | Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. | +| Unsafe deserializer (`cs/unsafe-deserialization`) | security | Finds calls to unsafe deserializers. | | Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. | ## Changes to existing queries From d0842fc35d69cfa6d09b971990c97b39b6b5895a Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Mon, 28 Oct 2019 16:31:22 +0100 Subject: [PATCH 0104/2538] Java/C++/C#: Minor refactor following review comment. --- .../cpp/dataflow/internal/DataFlowImpl.qll | 16 +++++++------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 16 +++++++------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 16 +++++++------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 16 +++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 21 +++++++++++-------- .../dataflow/internal/DataFlowImplLocal.qll | 16 +++++++------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 16 +++++++------- .../ir/dataflow/internal/DataFlowImpl2.qll | 16 +++++++------- .../ir/dataflow/internal/DataFlowImpl3.qll | 16 +++++++------- .../ir/dataflow/internal/DataFlowImpl4.qll | 16 +++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 21 +++++++++++-------- .../csharp/dataflow/internal/DataFlowImpl.qll | 16 +++++++------- .../dataflow/internal/DataFlowImpl2.qll | 16 +++++++------- .../dataflow/internal/DataFlowImpl3.qll | 16 +++++++------- .../dataflow/internal/DataFlowImpl4.qll | 16 +++++++------- .../dataflow/internal/DataFlowImpl5.qll | 16 +++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 21 +++++++++++-------- .../java/dataflow/internal/DataFlowImpl.qll | 16 +++++++------- .../java/dataflow/internal/DataFlowImpl2.qll | 16 +++++++------- .../java/dataflow/internal/DataFlowImpl3.qll | 16 +++++++------- .../java/dataflow/internal/DataFlowImpl4.qll | 16 +++++++------- .../java/dataflow/internal/DataFlowImpl5.qll | 16 +++++++------- .../dataflow/internal/DataFlowImplCommon.qll | 21 +++++++++++-------- 23 files changed, 200 insertions(+), 188 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll index b9ed7d5e07e2..8b9c8f5abd3a 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll @@ -772,6 +772,9 @@ private module ImplCommon { abstract class ReturnKindExt extends TReturnKindExt { /** Gets a textual representation of this return kind. */ abstract string toString(); + + /** Gets a node corresponding to data flow out of `call`. */ + abstract Node getAnOutNode(DataFlowCall call); } class ValueReturnKind extends ReturnKindExt, TValueReturn { @@ -782,6 +785,8 @@ private module ImplCommon { ReturnKind getKind() { result = kind } override string toString() { result = kind.toString() } + + override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) } } class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { @@ -792,6 +797,13 @@ private module ImplCommon { int getPosition() { result = pos } override string toString() { result = "param update " + pos } + + override Node getAnOutNode(DataFlowCall call) { + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, this.getPosition()) + ) + } } /** A callable tagged with a relevant return kind. */ @@ -823,15 +835,6 @@ private module ImplCommon { ) } - Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { - result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) - or - exists(ArgumentNode arg | - result.(PostUpdateNode).getPreUpdateNode() = arg and - arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) - ) - } - bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll index b9ed7d5e07e2..8b9c8f5abd3a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll @@ -772,6 +772,9 @@ private module ImplCommon { abstract class ReturnKindExt extends TReturnKindExt { /** Gets a textual representation of this return kind. */ abstract string toString(); + + /** Gets a node corresponding to data flow out of `call`. */ + abstract Node getAnOutNode(DataFlowCall call); } class ValueReturnKind extends ReturnKindExt, TValueReturn { @@ -782,6 +785,8 @@ private module ImplCommon { ReturnKind getKind() { result = kind } override string toString() { result = kind.toString() } + + override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) } } class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { @@ -792,6 +797,13 @@ private module ImplCommon { int getPosition() { result = pos } override string toString() { result = "param update " + pos } + + override Node getAnOutNode(DataFlowCall call) { + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, this.getPosition()) + ) + } } /** A callable tagged with a relevant return kind. */ @@ -823,15 +835,6 @@ private module ImplCommon { ) } - Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { - result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) - or - exists(ArgumentNode arg | - result.(PostUpdateNode).getPreUpdateNode() = arg and - arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) - ) - } - bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll index b9ed7d5e07e2..8b9c8f5abd3a 100644 --- a/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll +++ b/csharp/ql/src/semmle/code/csharp/dataflow/internal/DataFlowImplCommon.qll @@ -772,6 +772,9 @@ private module ImplCommon { abstract class ReturnKindExt extends TReturnKindExt { /** Gets a textual representation of this return kind. */ abstract string toString(); + + /** Gets a node corresponding to data flow out of `call`. */ + abstract Node getAnOutNode(DataFlowCall call); } class ValueReturnKind extends ReturnKindExt, TValueReturn { @@ -782,6 +785,8 @@ private module ImplCommon { ReturnKind getKind() { result = kind } override string toString() { result = kind.toString() } + + override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) } } class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { @@ -792,6 +797,13 @@ private module ImplCommon { int getPosition() { result = pos } override string toString() { result = "param update " + pos } + + override Node getAnOutNode(DataFlowCall call) { + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, this.getPosition()) + ) + } } /** A callable tagged with a relevant return kind. */ @@ -823,15 +835,6 @@ private module ImplCommon { ) } - Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { - result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) - or - exists(ArgumentNode arg | - result.(PostUpdateNode).getPreUpdateNode() = arg and - arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) - ) - } - bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index c7ab550dd731..c5b1a0beb279 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -317,7 +317,7 @@ private predicate nodeCandFwd1(Node node, Configuration config) { exists(DataFlowCall call, ReturnNodeExt ret, ReturnKindExt kind | nodeCandFwd1(ret, config) and getReturnPosition(ret) = viableReturnPos(call, kind) and - node = getAnOutNodeExt(call, kind) + node = kind.getAnOutNode(call) ) ) } @@ -409,7 +409,7 @@ private predicate nodeCand1ReturnPosition(ReturnPosition pos, Configuration conf exists(DataFlowCall call, ReturnKindExt kind, Node out | nodeCand1(out, config) and pos = viableReturnPos(call, kind) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -576,7 +576,7 @@ private predicate flowOutOfCallable(Node node1, Node node2, Configuration config not inBarrier(node2, config) and exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition1(node1, unbind(config)) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) } @@ -1806,7 +1806,7 @@ private predicate pathOutOfCallable1( pragma[noinline] private predicate pathOutOfCallable(PathNodeMid mid, Node out, CallContext cc) { exists(ReturnKindExt kind, DataFlowCall call | pathOutOfCallable1(mid, call, kind, cc) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1905,7 +1905,7 @@ pragma[noinline] private predicate pathThroughCallable(PathNodeMid mid, Node out, CallContext cc, AccessPathNil apnil) { exists(DataFlowCall call, ReturnKindExt kind | pathThroughCallable0(call, mid, kind, cc, apnil) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -1965,7 +1965,7 @@ private module FlowExploration { // flow out of a callable exists(DataFlowCall call, ReturnKindExt kind | getReturnPosition(node1) = viableReturnPos(call, kind) and - node2 = getAnOutNodeExt(call, kind) + node2 = kind.getAnOutNode(call) ) | c1 = node1.getEnclosingCallable() and @@ -2287,7 +2287,7 @@ private module FlowExploration { exists(ReturnKindExt kind, DataFlowCall call | partialPathOutOfCallable1(mid, call, kind, cc, ap, config) | - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } @@ -2370,7 +2370,7 @@ private module FlowExploration { ) { exists(DataFlowCall call, ReturnKindExt kind | partialPathThroughCallable0(call, mid, kind, cc, apnil, config) and - out = getAnOutNodeExt(call, kind) + out = kind.getAnOutNode(call) ) } diff --git a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll index b9ed7d5e07e2..8b9c8f5abd3a 100644 --- a/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll +++ b/java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll @@ -772,6 +772,9 @@ private module ImplCommon { abstract class ReturnKindExt extends TReturnKindExt { /** Gets a textual representation of this return kind. */ abstract string toString(); + + /** Gets a node corresponding to data flow out of `call`. */ + abstract Node getAnOutNode(DataFlowCall call); } class ValueReturnKind extends ReturnKindExt, TValueReturn { @@ -782,6 +785,8 @@ private module ImplCommon { ReturnKind getKind() { result = kind } override string toString() { result = kind.toString() } + + override Node getAnOutNode(DataFlowCall call) { result = getAnOutNode(call, this.getKind()) } } class ParamUpdateReturnKind extends ReturnKindExt, TParamUpdate { @@ -792,6 +797,13 @@ private module ImplCommon { int getPosition() { result = pos } override string toString() { result = "param update " + pos } + + override Node getAnOutNode(DataFlowCall call) { + exists(ArgumentNode arg | + result.(PostUpdateNode).getPreUpdateNode() = arg and + arg.argumentOf(call, this.getPosition()) + ) + } } /** A callable tagged with a relevant return kind. */ @@ -823,15 +835,6 @@ private module ImplCommon { ) } - Node getAnOutNodeExt(DataFlowCall call, ReturnKindExt kind) { - result = getAnOutNode(call, kind.(ValueReturnKind).getKind()) - or - exists(ArgumentNode arg | - result.(PostUpdateNode).getPreUpdateNode() = arg and - arg.argumentOf(call, kind.(ParamUpdateReturnKind).getPosition()) - ) - } - bindingset[cc, callable] predicate resolveReturn(CallContext cc, DataFlowCallable callable, DataFlowCall call) { cc instanceof CallContextAny and callable = viableCallable(call) From d693eb8c20a147a927ae2e5dda179d9233cde6b9 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Oct 2019 17:39:45 +0000 Subject: [PATCH 0105/2538] CPP: Correct the ConditionallyUninitializedVariable examples. --- .../CWE/CWE-457/ConditionallyUninitializedVariableBad.c | 6 +++--- .../CWE/CWE-457/ConditionallyUninitializedVariableGood.c | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c index 1f281f3cfd9c..73a01c2d9003 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableBad.c @@ -19,7 +19,7 @@ int notify(int deviceNumber) { DeviceConfig config; initDeviceConfig(&config, deviceNumber); // BAD: Using config without checking the status code that is returned - if (config->isEnabled) { - notifyChannel(config->channel); + if (config.isEnabled) { + notifyChannel(config.channel); } -} \ No newline at end of file +} diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c index a9dcc06c9a59..ced43a66cfc5 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariableGood.c @@ -20,8 +20,8 @@ void notify(int deviceNumber) { int statusCode = initDeviceConfig(&config, deviceNumber); if (statusCode == 0) { // GOOD: Status code returned by initialization function is checked, so this is safe - if (config->isEnabled) { - notifyChannel(config->channel); + if (config.isEnabled) { + notifyChannel(config.channel); } } -} \ No newline at end of file +} From c40c88ec4bfd2ddd5e79ed48fb1c955e23bf2a7b Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Mon, 28 Oct 2019 18:43:00 +0000 Subject: [PATCH 0106/2538] CPP: Add test cases for ConditionallyUninitializedVariables.ql. --- ...onditionallyUninitializedVariable.expected | 3 + .../ConditionallyUninitializedVariable.qlref | 1 + .../examples.cpp | 43 +++++++++ .../test.cpp | 96 +++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp create mode 100644 cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected new file mode 100644 index 000000000000..60964c8f178f --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.expected @@ -0,0 +1,3 @@ +| examples.cpp:38:3:38:18 | call to initDeviceConfig | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | examples.cpp:13:5:13:20 | initDeviceConfig | initDeviceConfig | examples.cpp:37:16:37:21 | config | config | +| test.cpp:22:2:22:17 | call to maybeInitialize1 | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | test.cpp:4:5:4:20 | maybeInitialize1 | maybeInitialize1 | test.cpp:19:6:19:6 | a | a | +| test.cpp:68:2:68:17 | call to maybeInitialize2 | The status of this call to $@ is not checked, potentially leaving $@ uninitialized. | test.cpp:51:6:51:21 | maybeInitialize2 | maybeInitialize2 | test.cpp:66:6:66:6 | a | a | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref new file mode 100644 index 000000000000..5150d627257c --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/ConditionallyUninitializedVariable.qlref @@ -0,0 +1 @@ +Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp new file mode 100644 index 000000000000..ccb15904d025 --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/examples.cpp @@ -0,0 +1,43 @@ +// based on the qhelp + +int getMaxDevices(); +bool fetchIsDeviceEnabled(int deviceNumber); +int fetchDeviceChannel(int deviceNumber); +void notifyChannel(int channel); + +struct DeviceConfig { + bool isEnabled; + int channel; +}; + +int initDeviceConfig(DeviceConfig *ref, int deviceNumber) { + if (deviceNumber >= getMaxDevices()) { + // No device with that number, return -1 to indicate failure + return -1; + } + // Device with that number, fetch parameters and initialize struct + ref->isEnabled = fetchIsDeviceEnabled(deviceNumber); + ref->channel = fetchDeviceChannel(deviceNumber); + // Return 0 to indicate success + return 0; +} + +void notifyGood(int deviceNumber) { + DeviceConfig config; + int statusCode = initDeviceConfig(&config, deviceNumber); + if (statusCode == 0) { + // GOOD: Status code returned by initialization function is checked, so this is safe + if (config.isEnabled) { + notifyChannel(config.channel); + } + } +} + +int notifyBad(int deviceNumber) { + DeviceConfig config; + initDeviceConfig(&config, deviceNumber); + // BAD: Using config without checking the status code that is returned + if (config.isEnabled) { + notifyChannel(config.channel); + } +} \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp new file mode 100644 index 000000000000..a3c9b0a24aaa --- /dev/null +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-457/semmle/ConditionallyUninitializedVariable/test.cpp @@ -0,0 +1,96 @@ + +void use(int i); + +int maybeInitialize1(int *v) +{ + static int resources = 100; + + if (resources == 0) + { + return 0; // FAIL + } + + *v = resources--; + return 1; // SUCCESS +} + +void test1() +{ + int a, b, c, d, e, f; + int result1, result2; + + maybeInitialize1(&a); // BAD (initialization not checked) + use(a); + + if (maybeInitialize1(&b) == 1) // GOOD + { + use(b); + } + + if (maybeInitialize1(&c) == 0) // BAD (initialization check is wrong) [NOT DETECTED] + { + use(c); + } + + result1 = maybeInitialize1(&d); // BAD (initialization stored but not checked) [NOT DETECTED] + use(d); + + result2 = maybeInitialize1(&e); // GOOD + if (result2 == 1) + { + use(e); + } + + if (maybeInitialize1(&f) == 0) // GOOD + { + return; + } + use(f); +} + +bool maybeInitialize2(int *v) +{ + static int resources = 100; + + if (resources > 0) + { + *v = resources--; + return true; // SUCCESS + } + + return false; // FAIL +} + +void test2() +{ + int a, b; + + maybeInitialize2(&a); // BAD (initialization not checked) + use(a); + + if (maybeInitialize2(&b)) // GOOD + { + use(b); + } +} + +int alwaysInitialize(int *v) +{ + static int resources = 0; + + *v = resources++; + return 1; // SUCCESS +} + +void test3() +{ + int a, b; + + alwaysInitialize(&a); // GOOD (initialization never fails) + use(a); + + if (alwaysInitialize(&b) == 1) // GOOD + { + use(b); + } +} From 2d64fedeb021db7fa0a919bad6f189ae4805907f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Oct 2019 11:19:31 +0100 Subject: [PATCH 0107/2538] CPP: Speed up VirtualDispatch.qll's getAViableTarget. --- .../code/cpp/dispatch/VirtualDispatch.qll | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll index 2fa9322843e6..1113fc430e73 100644 --- a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll @@ -28,6 +28,19 @@ module VirtualDispatch { not result.hasName("IUnknown") } + /** + * Helper predicate for `getAViableTarget`, which computes the viable targets for + * virtual calls based on the qualifier type. + */ + private Function getAViableVirtualCallTarget(Class qualifierType, MemberFunction staticTarget) { + exists(Class qualifierSubType | + result = getAPossibleImplementation(staticTarget) and + qualifierType = qualifierSubType.getABaseClass*() and + mayInherit(qualifierSubType, result) and + not cannotInherit(qualifierSubType, result) + ) + } + /** * Gets a viable target for the given function call. * @@ -42,18 +55,9 @@ module VirtualDispatch { * If `c` is not a virtual call, the result will be `c.getTarget()`. */ Function getAViableTarget(Call c) { - exists(Function staticTarget | staticTarget = c.getTarget() | - if c.(FunctionCall).isVirtual() and staticTarget instanceof MemberFunction - then - exists(Class qualifierType, Class qualifierSubType | - result = getAPossibleImplementation(staticTarget) and - qualifierType = getCallQualifierType(c) and - qualifierType = qualifierSubType.getABaseClass*() and - mayInherit(qualifierSubType, result) and - not cannotInherit(qualifierSubType, result) - ) - else result = staticTarget - ) + if c.(FunctionCall).isVirtual() and c.getTarget() instanceof MemberFunction + then result = getAViableVirtualCallTarget(getCallQualifierType(c), c.getTarget()) + else result = c.getTarget() } /** Holds if `f` is declared in `c` or a transitive base class of `c`. */ From 3584c0b2e5ae646b0e4c53d4d80810e84ed5c780 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 25 Oct 2019 11:22:42 +0100 Subject: [PATCH 0108/2538] CPP: Speed up InitializationFunctions.qll's getTarget. --- .../CWE/CWE-457/InitializationFunctions.qll | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 240bd7aa25e3..720cf11950b4 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -618,6 +618,33 @@ Function getAPossibleDefinition(Function undefinedFunction) { ) and result.isDefined() } + +private Function getTarget1(Call c) { + /* + * If there is at least one defined target after performing some simple virtual dispatch + * resolution, then the result is all the defined targets. + */ + + result = VirtualDispatch::getAViableTarget(c) and + result.isDefined() +} + +private Function getTarget2(Call c) { + /* + * If we can use the heuristic matching of functions to find definitions for some of the viable + * targets, return those. + */ + + not exists(getTarget1(c)) and + result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) +} + +private Function getTarget3(Call c) { + not exists(getTarget1(c)) and + not exists(getTarget2(c)) and + // Otherwise, the result is the undefined `Function` instances. + result = VirtualDispatch::getAViableTarget(c) +} /** * Gets a possible target for the Call, using the name and parameter matching if we did not associate @@ -625,27 +652,9 @@ Function getAPossibleDefinition(Function undefinedFunction) { * dispatch resolution. */ Function getTarget(Call c) { - if VirtualDispatch::getAViableTarget(c).isDefined() - then - /* - * If there is at least one defined target after performing some simple virtual dispatch - * resolution, then the result is all the defined targets. - */ - - result = VirtualDispatch::getAViableTarget(c) and - result.isDefined() - else - if exists(getAPossibleDefinition(VirtualDispatch::getAViableTarget(c))) - then - /* - * If we can use the heuristic matching of functions to find definitions for some of the viable - * targets, return those. - */ - - result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) - else - // Otherwise, the result is the undefined `Function` instances - result = VirtualDispatch::getAViableTarget(c) + result = getTarget1(c) or + result = getTarget2(c) or + result = getTarget3(c) } /** From 5e946cc9f3dc7b5daaeac3d34961dfac69eacced Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 23 Oct 2019 15:07:41 -0700 Subject: [PATCH 0109/2538] C++: add param read side effects to IR exit blocks --- .../code/cpp/ir/implementation/Opcode.qll | 5 + .../aliased_ssa/Instruction.qll | 15 +- .../cpp/ir/implementation/raw/Instruction.qll | 15 +- .../raw/internal/TranslatedElement.qll | 10 + .../raw/internal/TranslatedFunction.qll | 107 ++++- .../unaliased_ssa/Instruction.qll | 15 +- .../test/library-tests/ir/ir/raw_ir.expected | 418 ++++++++++-------- .../ir/ssa/aliased_ssa_ir.expected | 47 +- .../ir/ssa/unaliased_ssa_ir.expected | 47 +- 9 files changed, 441 insertions(+), 238 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll index 67507fce11d6..713893f52f7a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/Opcode.qll @@ -9,6 +9,7 @@ private newtype TOpcode = TExitFunction() or TReturnValue() or TReturnVoid() or + TReturnIndirection() or TCopyValue() or TLoad() or TStore() or @@ -202,6 +203,10 @@ module Opcode { final override string toString() { result = "ReturnVoid" } } + class ReturnIndirection extends MemoryAccessOpcode, TReturnIndirection { + final override string toString() { result = "ReturnIndirection" } + } + class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue { final override string toString() { result = "CopyValue" } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index f0a9c0e698ae..d710515bc06a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index f0a9c0e698ae..d710515bc06a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll index 01ed6a4d5911..6e8651230696 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll @@ -346,6 +346,16 @@ newtype TTranslatedElement = translateFunction(func) ) } or + TTranslatedReadEffects(Function func) { translateFunction(func) } or + // The read side effects in a function's return block + TTranslatedReadEffect(Parameter param) { + translateFunction(param.getFunction()) and + exists(Type t | t = param.getUnspecifiedType() | + t instanceof ArrayType or + t instanceof PointerType or + t instanceof ReferenceType + ) + } or // A local declaration TTranslatedDeclarationEntry(DeclarationEntry entry) { exists(DeclStmt declStmt | diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll index c4e4f5c02d22..6ef3113dd7c7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedFunction.qll @@ -34,6 +34,8 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { final override Function getFunction() { result = func } final override TranslatedElement getChild(int id) { + id = -4 and result = getReadEffects() + or id = -3 and result = getConstructorInitList() or id = -2 and result = getBody() @@ -53,6 +55,8 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { final private TranslatedStmt getBody() { result = getTranslatedStmt(func.getEntryPoint()) } + final private TranslatedReadEffects getReadEffects() { result = getTranslatedReadEffects(func) } + final private TranslatedParameter getParameter(int index) { result = getTranslatedParameter(func.getParameter(index)) } @@ -113,8 +117,11 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction { child = getBody() and result = getReturnSuccessorInstruction() or + child = getDestructorDestructionList() and + result = getReadEffects().getFirstInstruction() + or ( - child = getDestructorDestructionList() and + child = getReadEffects() and if getReturnType() instanceof VoidType then result = getInstruction(ReturnTag()) else result = getInstruction(ReturnValueAddressTag()) @@ -531,3 +538,101 @@ class TranslatedDestructorDestructionList extends TranslatedElement, ) } } + +TranslatedReadEffects getTranslatedReadEffects(Function func) { result.getAST() = func } + +class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects { + Function func; + + TranslatedReadEffects() { this = TTranslatedReadEffects(func) } + + override Locatable getAST() { result = func } + + override Function getFunction() { result = func } + + override string toString() { result = "read effects: " + func.toString() } + + override TranslatedElement getChild(int id) { + result = getTranslatedReadEffect(func.getParameter(id)) + } + + override Instruction getFirstInstruction() { + if exists(getAChild()) + then + result = min(TranslatedReadEffect child, int id | child = getChild(id) | child order by id) + .getFirstInstruction() + else result = getParent().getChildSuccessor(this) + } + + override Instruction getChildSuccessor(TranslatedElement child) { + exists(int id | child = getChild(id) | + if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = getChild(id2)) + then + result = min(TranslatedReadEffect child2, int id2 | + child2 = getChild(id2) and id2 > id + | + child2 order by id2 + ).getFirstInstruction() + else result = getParent().getChildSuccessor(this) + ) + } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + none() + } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() } +} + +private TranslatedReadEffect getTranslatedReadEffect(Parameter param) { result.getAST() = param } + +class TranslatedReadEffect extends TranslatedElement, TTranslatedReadEffect { + Parameter param; + + TranslatedReadEffect() { this = TTranslatedReadEffect(param) } + + override Locatable getAST() { result = param } + + override string toString() { result = "read effect: " + param.toString() } + + override TranslatedElement getChild(int id) { none() } + + override Instruction getChildSuccessor(TranslatedElement child) { none() } + + override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind edge) { + tag = OnlyInstructionTag() and + edge = gotoEdge() and + result = getParent().getChildSuccessor(this) + } + + override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) } + + override Function getFunction() { result = param.getFunction() } + + override predicate hasInstruction( + Opcode opcode, InstructionTag tag, Type resultType, boolean isGLValue + ) { + opcode instanceof Opcode::ReturnIndirection and + tag = OnlyInstructionTag() and + resultType instanceof VoidType and + isGLValue = false + } + + final override Instruction getInstructionOperand(InstructionTag tag, OperandTag operandTag) { + tag = OnlyInstructionTag() and + operandTag = sideEffectOperand() and + result = getTranslatedFunction(getFunction()).getUnmodeledDefinitionInstruction() + or + tag = OnlyInstructionTag() and + operandTag = addressOperand() and + result = getTranslatedParameter(param).getInstruction(InitializerIndirectAddressTag()) + } + + final override Type getInstructionOperandType(InstructionTag tag, TypedOperandTag operandTag) { + tag = OnlyInstructionTag() and + operandTag = sideEffectOperand() and + result instanceof UnknownType + } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index f0a9c0e698ae..d710515bc06a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 4cc0d7bb8a89..819928c82323 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -48,9 +48,10 @@ bad_asts.cpp: # 27| r0_11(Point) = Load : &:r0_10, ~mu0_2 # 27| mu0_12(Point) = Store : &:r0_7, r0_11 # 28| v0_13(void) = NoOp : -# 26| v0_14(void) = ReturnVoid : -# 26| v0_15(void) = UnmodeledUse : mu* -# 26| v0_16(void) = ExitFunction : +# 26| v0_14(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 26| v0_15(void) = ReturnVoid : +# 26| v0_16(void) = UnmodeledUse : mu* +# 26| v0_17(void) = ExitFunction : # 30| void Bad::errorExpr() # 30| Block 0 @@ -771,9 +772,10 @@ ir.cpp: # 168| r0_69(glval) = VariableAddress[b] : # 168| mu0_70(bool) = Store : &:r0_69, r0_68 # 169| v0_71(void) = NoOp : -# 153| v0_72(void) = ReturnVoid : -# 153| v0_73(void) = UnmodeledUse : mu* -# 153| v0_74(void) = ExitFunction : +# 153| v0_72(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 153| v0_73(void) = ReturnVoid : +# 153| v0_74(void) = UnmodeledUse : mu* +# 153| v0_75(void) = ExitFunction : # 171| void ArrayAccess(int*, int) # 171| Block 0 @@ -855,9 +857,10 @@ ir.cpp: # 184| r0_75(glval) = PointerAdd[4] : r0_72, r0_74 # 184| mu0_76(int) = Store : &:r0_75, r0_70 # 185| v0_77(void) = NoOp : -# 171| v0_78(void) = ReturnVoid : -# 171| v0_79(void) = UnmodeledUse : mu* -# 171| v0_80(void) = ExitFunction : +# 171| v0_78(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 171| v0_79(void) = ReturnVoid : +# 171| v0_80(void) = UnmodeledUse : mu* +# 171| v0_81(void) = ExitFunction : # 187| void StringLiteral(int) # 187| Block 0 @@ -950,9 +953,11 @@ ir.cpp: # 201| r0_53(glval) = VariableAddress[b] : # 201| mu0_54(bool) = Store : &:r0_53, r0_52 # 202| v0_55(void) = NoOp : -# 193| v0_56(void) = ReturnVoid : -# 193| v0_57(void) = UnmodeledUse : mu* -# 193| v0_58(void) = ExitFunction : +# 193| v0_56(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 193| v0_57(void) = ReturnIndirection : &:r0_9, ~mu0_2 +# 193| v0_58(void) = ReturnVoid : +# 193| v0_59(void) = UnmodeledUse : mu* +# 193| v0_60(void) = ExitFunction : # 204| void PointerCrement(int*) # 204| Block 0 @@ -994,9 +999,10 @@ ir.cpp: # 210| r0_35(glval) = VariableAddress[q] : # 210| mu0_36(int *) = Store : &:r0_35, r0_31 # 211| v0_37(void) = NoOp : -# 204| v0_38(void) = ReturnVoid : -# 204| v0_39(void) = UnmodeledUse : mu* -# 204| v0_40(void) = ExitFunction : +# 204| v0_38(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 204| v0_39(void) = ReturnVoid : +# 204| v0_40(void) = UnmodeledUse : mu* +# 204| v0_41(void) = ExitFunction : # 213| void CompoundAssignment() # 213| Block 0 @@ -1567,10 +1573,11 @@ ir.cpp: # 343| r0_13(int *) = Load : &:r0_12, ~mu0_2 # 343| r0_14(int) = Load : &:r0_13, ~mu0_2 # 343| mu0_15(int) = Store : &:r0_11, r0_14 -# 341| r0_16(glval) = VariableAddress[#return] : -# 341| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 -# 341| v0_18(void) = UnmodeledUse : mu* -# 341| v0_19(void) = ExitFunction : +# 341| v0_16(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 341| r0_17(glval) = VariableAddress[#return] : +# 341| v0_18(void) = ReturnValue : &:r0_17, ~mu0_2 +# 341| v0_19(void) = UnmodeledUse : mu* +# 341| v0_20(void) = ExitFunction : # 348| int* AddressOf() # 348| Block 0 @@ -2238,26 +2245,26 @@ ir.cpp: # 493| r0_5(glval) = VariableAddress[a] : # 493| r0_6(bool) = Load : &:r0_5, ~mu0_2 # 493| v0_7(void) = ConditionalBranch : r0_6 -#-----| False -> Block 3 -#-----| True -> Block 2 +#-----| False -> Block 1 +#-----| True -> Block 3 -# 494| Block 1 -# 494| v1_0(void) = NoOp : -# 492| v1_1(void) = ReturnVoid : -# 492| v1_2(void) = UnmodeledUse : mu* -# 492| v1_3(void) = ExitFunction : +# 493| Block 1 +# 493| r1_0(glval) = FunctionAddress[VoidFunc] : +# 493| v1_1(void) = Call : func:r1_0 +# 493| mu1_2(unknown) = ^CallSideEffect : ~mu0_2 +#-----| Goto -> Block 2 -# 493| Block 2 -# 493| r2_0(glval) = FunctionAddress[VoidFunc] : -# 493| v2_1(void) = Call : func:r2_0 -# 493| mu2_2(unknown) = ^CallSideEffect : ~mu0_2 -#-----| Goto -> Block 1 +# 494| Block 2 +# 494| v2_0(void) = NoOp : +# 492| v2_1(void) = ReturnVoid : +# 492| v2_2(void) = UnmodeledUse : mu* +# 492| v2_3(void) = ExitFunction : # 493| Block 3 # 493| r3_0(glval) = FunctionAddress[VoidFunc] : # 493| v3_1(void) = Call : func:r3_0 # 493| mu3_2(unknown) = ^CallSideEffect : ~mu0_2 -#-----| Goto -> Block 1 +#-----| Goto -> Block 2 # 496| void Nullptr() # 496| Block 0 @@ -2794,9 +2801,11 @@ ir.cpp: # 625| v0_34(void) = ^IndirectReadSideEffect[-1] : &:r0_30, ~mu0_2 # 625| mu0_35(String) = ^IndirectMayWriteSideEffect[-1] : &:r0_30 # 626| v0_36(void) = NoOp : -# 622| v0_37(void) = ReturnVoid : -# 622| v0_38(void) = UnmodeledUse : mu* -# 622| v0_39(void) = ExitFunction : +# 622| v0_37(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 622| v0_38(void) = ReturnIndirection : &:r0_9, ~mu0_2 +# 622| v0_39(void) = ReturnVoid : +# 622| v0_40(void) = UnmodeledUse : mu* +# 622| v0_41(void) = ExitFunction : # 630| int C::StaticMemberFunction(int) # 630| Block 0 @@ -2966,10 +2975,11 @@ ir.cpp: # 676| r0_9(int &) = Load : &:r0_8, ~mu0_2 # 676| r0_10(int) = Load : &:r0_9, ~mu0_2 # 676| mu0_11(int) = Store : &:r0_7, r0_10 -# 675| r0_12(glval) = VariableAddress[#return] : -# 675| v0_13(void) = ReturnValue : &:r0_12, ~mu0_2 -# 675| v0_14(void) = UnmodeledUse : mu* -# 675| v0_15(void) = ExitFunction : +# 675| v0_12(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 675| r0_13(glval) = VariableAddress[#return] : +# 675| v0_14(void) = ReturnValue : &:r0_13, ~mu0_2 +# 675| v0_15(void) = UnmodeledUse : mu* +# 675| v0_16(void) = ExitFunction : # 679| int& TakeReference() # 679| Block 0 @@ -3133,10 +3143,11 @@ ir.cpp: # 716| r0_9(glval) = VariableAddress[#return] : # 716| r0_10(long) = Constant[0] : # 716| mu0_11(long) = Store : &:r0_9, r0_10 -# 715| r0_12(glval) = VariableAddress[#return] : -# 715| v0_13(void) = ReturnValue : &:r0_12, ~mu0_2 -# 715| v0_14(void) = UnmodeledUse : mu* -# 715| v0_15(void) = ExitFunction : +# 715| v0_12(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 715| r0_13(glval) = VariableAddress[#return] : +# 715| v0_14(void) = ReturnValue : &:r0_13, ~mu0_2 +# 715| v0_15(void) = UnmodeledUse : mu* +# 715| v0_16(void) = ExitFunction : # 720| double CallNestedTemplateFunc() # 720| Block 0 @@ -3303,10 +3314,11 @@ ir.cpp: #-----| r0_20(glval) = VariableAddress[#return] : #-----| r0_21(Base *) = CopyValue : r0_3 #-----| mu0_22(Base &) = Store : &:r0_20, r0_21 -# 745| r0_23(glval) = VariableAddress[#return] : -# 745| v0_24(void) = ReturnValue : &:r0_23, ~mu0_2 -# 745| v0_25(void) = UnmodeledUse : mu* -# 745| v0_26(void) = ExitFunction : +#-----| v0_23(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 745| r0_24(glval) = VariableAddress[#return] : +# 745| v0_25(void) = ReturnValue : &:r0_24, ~mu0_2 +# 745| v0_26(void) = UnmodeledUse : mu* +# 745| v0_27(void) = ExitFunction : # 745| void Base::Base(Base const&) # 745| Block 0 @@ -3323,9 +3335,10 @@ ir.cpp: # 745| v0_10(void) = Call : func:r0_9, this:r0_8 # 745| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 # 745| v0_12(void) = NoOp : -# 745| v0_13(void) = ReturnVoid : -# 745| v0_14(void) = UnmodeledUse : mu* -# 745| v0_15(void) = ExitFunction : +#-----| v0_13(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 745| v0_14(void) = ReturnVoid : +# 745| v0_15(void) = UnmodeledUse : mu* +# 745| v0_16(void) = ExitFunction : # 748| void Base::Base() # 748| Block 0 @@ -3394,10 +3407,11 @@ ir.cpp: #-----| r0_32(glval) = VariableAddress[#return] : #-----| r0_33(Middle *) = CopyValue : r0_3 #-----| mu0_34(Middle &) = Store : &:r0_32, r0_33 -# 754| r0_35(glval) = VariableAddress[#return] : -# 754| v0_36(void) = ReturnValue : &:r0_35, ~mu0_2 -# 754| v0_37(void) = UnmodeledUse : mu* -# 754| v0_38(void) = ExitFunction : +#-----| v0_35(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 754| r0_36(glval) = VariableAddress[#return] : +# 754| v0_37(void) = ReturnValue : &:r0_36, ~mu0_2 +# 754| v0_38(void) = UnmodeledUse : mu* +# 754| v0_39(void) = ExitFunction : # 757| void Middle::Middle() # 757| Block 0 @@ -3474,10 +3488,11 @@ ir.cpp: #-----| r0_32(glval) = VariableAddress[#return] : #-----| r0_33(Derived *) = CopyValue : r0_3 #-----| mu0_34(Derived &) = Store : &:r0_32, r0_33 -# 763| r0_35(glval) = VariableAddress[#return] : -# 763| v0_36(void) = ReturnValue : &:r0_35, ~mu0_2 -# 763| v0_37(void) = UnmodeledUse : mu* -# 763| v0_38(void) = ExitFunction : +#-----| v0_35(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 763| r0_36(glval) = VariableAddress[#return] : +# 763| v0_37(void) = ReturnValue : &:r0_36, ~mu0_2 +# 763| v0_38(void) = UnmodeledUse : mu* +# 763| v0_39(void) = ExitFunction : # 766| void Derived::Derived() # 766| Block 0 @@ -4082,9 +4097,10 @@ ir.cpp: # 885| r0_17(glval<..(*)(..)>) = VariableAddress[pfn] : # 885| mu0_18(..(*)(..)) = Store : &:r0_17, r0_16 # 886| v0_19(void) = NoOp : -# 883| v0_20(void) = ReturnVoid : -# 883| v0_21(void) = UnmodeledUse : mu* -# 883| v0_22(void) = ExitFunction : +# 883| v0_20(void) = ReturnIndirection : &:r0_7, ~mu0_2 +# 883| v0_21(void) = ReturnVoid : +# 883| v0_22(void) = UnmodeledUse : mu* +# 883| v0_23(void) = ExitFunction : # 888| void VarArgUsage(int) # 888| Block 0 @@ -4536,10 +4552,11 @@ ir.cpp: # 988| mu0_19(unknown) = ^CallSideEffect : ~mu0_2 # 988| r0_20(int) = Add : r0_14, r0_18 # 988| mu0_21(int) = Store : &:r0_9, r0_20 -# 987| r0_22(glval) = VariableAddress[#return] : -# 987| v0_23(void) = ReturnValue : &:r0_22, ~mu0_2 -# 987| v0_24(void) = UnmodeledUse : mu* -# 987| v0_25(void) = ExitFunction : +# 987| v0_22(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 987| r0_23(glval) = VariableAddress[#return] : +# 987| v0_24(void) = ReturnValue : &:r0_23, ~mu0_2 +# 987| v0_25(void) = UnmodeledUse : mu* +# 987| v0_26(void) = ExitFunction : # 991| int ExprStmt(int, int, int) # 991| Block 0 @@ -4655,9 +4672,10 @@ ir.cpp: #-----| r0_6(lambda [] type at line 1029, col. 12 &&) = Load : &:r0_4, ~mu0_5 #-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 # 1029| v0_8(void) = NoOp : -# 1029| v0_9(void) = ReturnVoid : -# 1029| v0_10(void) = UnmodeledUse : mu* -# 1029| v0_11(void) = ExitFunction : +#-----| v0_9(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 1029| v0_10(void) = ReturnVoid : +# 1029| v0_11(void) = UnmodeledUse : mu* +# 1029| v0_12(void) = ExitFunction : # 1029| void (lambda [] type at line 1029, col. 12)::operator()() const # 1029| Block 0 @@ -4842,9 +4860,10 @@ ir.cpp: # 1046| v0_153(void) = ^IndirectReadSideEffect[-1] : &:r0_148, ~mu0_2 # 1046| mu0_154(decltype([...](...){...})) = ^IndirectMayWriteSideEffect[-1] : &:r0_148 # 1047| v0_155(void) = NoOp : -# 1031| v0_156(void) = ReturnVoid : -# 1031| v0_157(void) = UnmodeledUse : mu* -# 1031| v0_158(void) = ExitFunction : +# 1031| v0_156(void) = ReturnIndirection : &:r0_7, ~mu0_2 +# 1031| v0_157(void) = ReturnVoid : +# 1031| v0_158(void) = UnmodeledUse : mu* +# 1031| v0_159(void) = ExitFunction : # 1032| void (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)&&) # 1032| Block 0 @@ -4857,9 +4876,10 @@ ir.cpp: #-----| r0_6(lambda [] type at line 1032, col. 23 &&) = Load : &:r0_4, ~mu0_5 #-----| mu0_7(unknown) = InitializeIndirection[p#0] : &:r0_6 # 1032| v0_8(void) = NoOp : -# 1032| v0_9(void) = ReturnVoid : -# 1032| v0_10(void) = UnmodeledUse : mu* -# 1032| v0_11(void) = ExitFunction : +#-----| v0_9(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 1032| v0_10(void) = ReturnVoid : +# 1032| v0_11(void) = UnmodeledUse : mu* +# 1032| v0_12(void) = ExitFunction : # 1032| char (void Lambda(int, String const&))::(lambda [] type at line 1032, col. 23)::operator()(float) const # 1032| Block 0 @@ -5003,9 +5023,10 @@ ir.cpp: # 1040| v0_10(void) = Call : func:r0_9, this:r0_8 # 1040| mu0_11(unknown) = ^CallSideEffect : ~mu0_2 # 1040| v0_12(void) = NoOp : -# 1040| v0_13(void) = ReturnVoid : -# 1040| v0_14(void) = UnmodeledUse : mu* -# 1040| v0_15(void) = ExitFunction : +#-----| v0_13(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 1040| v0_14(void) = ReturnVoid : +# 1040| v0_15(void) = UnmodeledUse : mu* +# 1040| v0_16(void) = ExitFunction : # 1040| void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::~() # 1040| Block 0 @@ -5143,133 +5164,134 @@ ir.cpp: #-----| v0_26(void) = ^IndirectReadSideEffect[-1] : &:r0_22, ~mu0_2 #-----| mu0_27(vector) = ^IndirectMayWriteSideEffect[-1] : &:r0_22 # 1069| mu0_28(iterator) = Store : &:r0_20, r0_24 -#-----| Goto -> Block 4 - -# 1075| Block 1 -# 1075| r1_0(glval) = VariableAddress[e] : -#-----| r1_1(glval) = VariableAddress[(__begin)] : -#-----| r1_2(glval) = Convert : r1_1 -# 1075| r1_3(glval) = FunctionAddress[operator*] : -# 1075| r1_4(int &) = Call : func:r1_3, this:r1_2 -# 1075| mu1_5(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v1_6(void) = ^IndirectReadSideEffect[-1] : &:r1_2, ~mu0_2 -#-----| mu1_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1_2 -# 1075| r1_8(glval) = Convert : r1_4 -# 1075| mu1_9(int &) = Store : &:r1_0, r1_8 -# 1076| r1_10(glval) = VariableAddress[e] : -# 1076| r1_11(int &) = Load : &:r1_10, ~mu0_2 -# 1076| r1_12(int) = Load : &:r1_11, ~mu0_2 -# 1076| r1_13(int) = Constant[5] : -# 1076| r1_14(bool) = CompareLT : r1_12, r1_13 -# 1076| v1_15(void) = ConditionalBranch : r1_14 -#-----| False -> Block 10 -#-----| True -> Block 2 +#-----| Goto -> Block 5 -# 1077| Block 2 -# 1077| v2_0(void) = NoOp : -#-----| Goto -> Block 3 +#-----| Block 1 +#-----| r1_0(glval) = VariableAddress[(__begin)] : +# 1075| r1_1(glval) = FunctionAddress[operator++] : +# 1075| r1_2(iterator &) = Call : func:r1_1, this:r1_0 +# 1075| mu1_3(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v1_4(void) = ^IndirectReadSideEffect[-1] : &:r1_0, ~mu0_2 +#-----| mu1_5(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r1_0 +#-----| Goto (back edge) -> Block 10 + +# 1075| Block 2 +# 1075| r2_0(glval) = VariableAddress[e] : +#-----| r2_1(glval) = VariableAddress[(__begin)] : +#-----| r2_2(glval) = Convert : r2_1 +# 1075| r2_3(glval) = FunctionAddress[operator*] : +# 1075| r2_4(int &) = Call : func:r2_3, this:r2_2 +# 1075| mu2_5(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v2_6(void) = ^IndirectReadSideEffect[-1] : &:r2_2, ~mu0_2 +#-----| mu2_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r2_2 +# 1075| r2_8(glval) = Convert : r2_4 +# 1075| mu2_9(int &) = Store : &:r2_0, r2_8 +# 1076| r2_10(glval) = VariableAddress[e] : +# 1076| r2_11(int &) = Load : &:r2_10, ~mu0_2 +# 1076| r2_12(int) = Load : &:r2_11, ~mu0_2 +# 1076| r2_13(int) = Constant[5] : +# 1076| r2_14(bool) = CompareLT : r2_12, r2_13 +# 1076| v2_15(void) = ConditionalBranch : r2_14 +#-----| False -> Block 1 +#-----| True -> Block 3 -# 1079| Block 3 -# 1079| v3_0(void) = NoOp : -# 1080| v3_1(void) = NoOp : -# 1068| v3_2(void) = ReturnVoid : -# 1068| v3_3(void) = UnmodeledUse : mu* -# 1068| v3_4(void) = ExitFunction : - -#-----| Block 4 -#-----| r4_0(glval) = VariableAddress[(__begin)] : -#-----| r4_1(glval) = Convert : r4_0 -# 1069| r4_2(glval) = FunctionAddress[operator!=] : -#-----| r4_3(glval) = VariableAddress[(__end)] : -#-----| r4_4(iterator) = Load : &:r4_3, ~mu0_2 -# 1069| r4_5(bool) = Call : func:r4_2, this:r4_1, 0:r4_4 -# 1069| mu4_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v4_7(void) = ^IndirectReadSideEffect[-1] : &:r4_1, ~mu0_2 -#-----| mu4_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r4_1 -# 1069| v4_9(void) = ConditionalBranch : r4_5 -#-----| False -> Block 8 -#-----| True -> Block 5 +# 1077| Block 3 +# 1077| v3_0(void) = NoOp : +#-----| Goto -> Block 4 -# 1069| Block 5 -# 1069| r5_0(glval) = VariableAddress[e] : -#-----| r5_1(glval) = VariableAddress[(__begin)] : -#-----| r5_2(glval) = Convert : r5_1 -# 1069| r5_3(glval) = FunctionAddress[operator*] : -# 1069| r5_4(int &) = Call : func:r5_3, this:r5_2 -# 1069| mu5_5(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v5_6(void) = ^IndirectReadSideEffect[-1] : &:r5_2, ~mu0_2 -#-----| mu5_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r5_2 -# 1069| r5_8(int) = Load : &:r5_4, ~mu0_2 -# 1069| mu5_9(int) = Store : &:r5_0, r5_8 -# 1070| r5_10(glval) = VariableAddress[e] : -# 1070| r5_11(int) = Load : &:r5_10, ~mu0_2 -# 1070| r5_12(int) = Constant[0] : -# 1070| r5_13(bool) = CompareGT : r5_11, r5_12 -# 1070| v5_14(void) = ConditionalBranch : r5_13 -#-----| False -> Block 7 +# 1079| Block 4 +# 1079| v4_0(void) = NoOp : +# 1080| v4_1(void) = NoOp : +# 1068| v4_2(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 1068| v4_3(void) = ReturnVoid : +# 1068| v4_4(void) = UnmodeledUse : mu* +# 1068| v4_5(void) = ExitFunction : + +#-----| Block 5 +#-----| r5_0(glval) = VariableAddress[(__begin)] : +#-----| r5_1(glval) = Convert : r5_0 +# 1069| r5_2(glval) = FunctionAddress[operator!=] : +#-----| r5_3(glval) = VariableAddress[(__end)] : +#-----| r5_4(iterator) = Load : &:r5_3, ~mu0_2 +# 1069| r5_5(bool) = Call : func:r5_2, this:r5_1, 0:r5_4 +# 1069| mu5_6(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v5_7(void) = ^IndirectReadSideEffect[-1] : &:r5_1, ~mu0_2 +#-----| mu5_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r5_1 +# 1069| v5_9(void) = ConditionalBranch : r5_5 +#-----| False -> Block 9 #-----| True -> Block 6 -# 1071| Block 6 -# 1071| v6_0(void) = NoOp : -#-----| Goto -> Block 7 +# 1069| Block 6 +# 1069| r6_0(glval) = VariableAddress[e] : +#-----| r6_1(glval) = VariableAddress[(__begin)] : +#-----| r6_2(glval) = Convert : r6_1 +# 1069| r6_3(glval) = FunctionAddress[operator*] : +# 1069| r6_4(int &) = Call : func:r6_3, this:r6_2 +# 1069| mu6_5(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v6_6(void) = ^IndirectReadSideEffect[-1] : &:r6_2, ~mu0_2 +#-----| mu6_7(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r6_2 +# 1069| r6_8(int) = Load : &:r6_4, ~mu0_2 +# 1069| mu6_9(int) = Store : &:r6_0, r6_8 +# 1070| r6_10(glval) = VariableAddress[e] : +# 1070| r6_11(int) = Load : &:r6_10, ~mu0_2 +# 1070| r6_12(int) = Constant[0] : +# 1070| r6_13(bool) = CompareGT : r6_11, r6_12 +# 1070| v6_14(void) = ConditionalBranch : r6_13 +#-----| False -> Block 8 +#-----| True -> Block 7 -# 1069| Block 7 -# 1069| v7_0(void) = NoOp : -#-----| r7_1(glval) = VariableAddress[(__begin)] : -# 1069| r7_2(glval) = FunctionAddress[operator++] : -# 1069| r7_3(iterator &) = Call : func:r7_2, this:r7_1 -# 1069| mu7_4(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v7_5(void) = ^IndirectReadSideEffect[-1] : &:r7_1, ~mu0_2 -#-----| mu7_6(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r7_1 -#-----| Goto (back edge) -> Block 4 +# 1071| Block 7 +# 1071| v7_0(void) = NoOp : +#-----| Goto -> Block 8 -# 1075| Block 8 -# 1075| r8_0(glval &>) = VariableAddress[(__range)] : -# 1075| r8_1(glval &>) = VariableAddress[v] : -# 1075| r8_2(vector &) = Load : &:r8_1, ~mu0_2 -# 1075| mu8_3(vector &) = Store : &:r8_0, r8_2 -# 1075| r8_4(glval) = VariableAddress[(__begin)] : -#-----| r8_5(glval &>) = VariableAddress[(__range)] : -#-----| r8_6(vector &) = Load : &:r8_5, ~mu0_2 -# 1075| r8_7(glval) = FunctionAddress[begin] : -# 1075| r8_8(iterator) = Call : func:r8_7, this:r8_6 -# 1075| mu8_9(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v8_10(void) = ^IndirectReadSideEffect[-1] : &:r8_6, ~mu0_2 -#-----| mu8_11(vector) = ^IndirectMayWriteSideEffect[-1] : &:r8_6 -# 1075| mu8_12(iterator) = Store : &:r8_4, r8_8 -# 1075| r8_13(glval) = VariableAddress[(__end)] : -#-----| r8_14(glval &>) = VariableAddress[(__range)] : -#-----| r8_15(vector &) = Load : &:r8_14, ~mu0_2 -# 1075| r8_16(glval) = FunctionAddress[end] : -# 1075| r8_17(iterator) = Call : func:r8_16, this:r8_15 -# 1075| mu8_18(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v8_19(void) = ^IndirectReadSideEffect[-1] : &:r8_15, ~mu0_2 -#-----| mu8_20(vector) = ^IndirectMayWriteSideEffect[-1] : &:r8_15 -# 1075| mu8_21(iterator) = Store : &:r8_13, r8_17 -#-----| Goto -> Block 9 +# 1069| Block 8 +# 1069| v8_0(void) = NoOp : +#-----| r8_1(glval) = VariableAddress[(__begin)] : +# 1069| r8_2(glval) = FunctionAddress[operator++] : +# 1069| r8_3(iterator &) = Call : func:r8_2, this:r8_1 +# 1069| mu8_4(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v8_5(void) = ^IndirectReadSideEffect[-1] : &:r8_1, ~mu0_2 +#-----| mu8_6(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r8_1 +#-----| Goto (back edge) -> Block 5 -#-----| Block 9 -#-----| r9_0(glval) = VariableAddress[(__begin)] : -#-----| r9_1(glval) = Convert : r9_0 -# 1075| r9_2(glval) = FunctionAddress[operator!=] : -#-----| r9_3(glval) = VariableAddress[(__end)] : -#-----| r9_4(iterator) = Load : &:r9_3, ~mu0_2 -# 1075| r9_5(bool) = Call : func:r9_2, this:r9_1, 0:r9_4 -# 1075| mu9_6(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v9_7(void) = ^IndirectReadSideEffect[-1] : &:r9_1, ~mu0_2 -#-----| mu9_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r9_1 -# 1075| v9_9(void) = ConditionalBranch : r9_5 -#-----| False -> Block 3 -#-----| True -> Block 1 +# 1075| Block 9 +# 1075| r9_0(glval &>) = VariableAddress[(__range)] : +# 1075| r9_1(glval &>) = VariableAddress[v] : +# 1075| r9_2(vector &) = Load : &:r9_1, ~mu0_2 +# 1075| mu9_3(vector &) = Store : &:r9_0, r9_2 +# 1075| r9_4(glval) = VariableAddress[(__begin)] : +#-----| r9_5(glval &>) = VariableAddress[(__range)] : +#-----| r9_6(vector &) = Load : &:r9_5, ~mu0_2 +# 1075| r9_7(glval) = FunctionAddress[begin] : +# 1075| r9_8(iterator) = Call : func:r9_7, this:r9_6 +# 1075| mu9_9(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v9_10(void) = ^IndirectReadSideEffect[-1] : &:r9_6, ~mu0_2 +#-----| mu9_11(vector) = ^IndirectMayWriteSideEffect[-1] : &:r9_6 +# 1075| mu9_12(iterator) = Store : &:r9_4, r9_8 +# 1075| r9_13(glval) = VariableAddress[(__end)] : +#-----| r9_14(glval &>) = VariableAddress[(__range)] : +#-----| r9_15(vector &) = Load : &:r9_14, ~mu0_2 +# 1075| r9_16(glval) = FunctionAddress[end] : +# 1075| r9_17(iterator) = Call : func:r9_16, this:r9_15 +# 1075| mu9_18(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v9_19(void) = ^IndirectReadSideEffect[-1] : &:r9_15, ~mu0_2 +#-----| mu9_20(vector) = ^IndirectMayWriteSideEffect[-1] : &:r9_15 +# 1075| mu9_21(iterator) = Store : &:r9_13, r9_17 +#-----| Goto -> Block 10 #-----| Block 10 #-----| r10_0(glval) = VariableAddress[(__begin)] : -# 1075| r10_1(glval) = FunctionAddress[operator++] : -# 1075| r10_2(iterator &) = Call : func:r10_1, this:r10_0 -# 1075| mu10_3(unknown) = ^CallSideEffect : ~mu0_2 -#-----| v10_4(void) = ^IndirectReadSideEffect[-1] : &:r10_0, ~mu0_2 -#-----| mu10_5(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r10_0 -#-----| Goto (back edge) -> Block 9 +#-----| r10_1(glval) = Convert : r10_0 +# 1075| r10_2(glval) = FunctionAddress[operator!=] : +#-----| r10_3(glval) = VariableAddress[(__end)] : +#-----| r10_4(iterator) = Load : &:r10_3, ~mu0_2 +# 1075| r10_5(bool) = Call : func:r10_2, this:r10_1, 0:r10_4 +# 1075| mu10_6(unknown) = ^CallSideEffect : ~mu0_2 +#-----| v10_7(void) = ^IndirectReadSideEffect[-1] : &:r10_1, ~mu0_2 +#-----| mu10_8(iterator) = ^IndirectMayWriteSideEffect[-1] : &:r10_1 +# 1075| v10_9(void) = ConditionalBranch : r10_5 +#-----| False -> Block 4 +#-----| True -> Block 2 # 1099| int AsmStmt(int) # 1099| Block 0 @@ -5315,9 +5337,13 @@ ir.cpp: # 1106| r0_22(glval) = VariableAddress[d] : # 1106| mu0_23(unknown) = InlineAsm : ~mu0_2, 0:r0_19, 1:r0_20, 2:r0_21, 3:r0_22 # 1111| v0_24(void) = NoOp : -# 1104| v0_25(void) = ReturnVoid : -# 1104| v0_26(void) = UnmodeledUse : mu* -# 1104| v0_27(void) = ExitFunction : +# 1104| v0_25(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 1104| v0_26(void) = ReturnIndirection : &:r0_9, ~mu0_2 +# 1104| v0_27(void) = ReturnIndirection : &:r0_13, ~mu0_2 +# 1104| v0_28(void) = ReturnIndirection : &:r0_17, ~mu0_2 +# 1104| v0_29(void) = ReturnVoid : +# 1104| v0_30(void) = UnmodeledUse : mu* +# 1104| v0_31(void) = ExitFunction : # 1113| void ExternDeclarations() # 1113| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index dadbfdea9e13..a7925db2a469 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -84,10 +84,11 @@ ssa.cpp: # 28| r6_9(int) = Load : &:r6_8, ~m6_0 # 28| r6_10(int) = Add : r6_5, r6_9 # 28| m6_11(int) = Store : &:r6_1, r6_10 -# 13| r6_12(glval) = VariableAddress[#return] : -# 13| v6_13(void) = ReturnValue : &:r6_12, m6_11 -# 13| v6_14(void) = UnmodeledUse : mu* -# 13| v6_15(void) = ExitFunction : +# 13| v6_12(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 13| r6_13(glval) = VariableAddress[#return] : +# 13| v6_14(void) = ReturnValue : &:r6_13, m6_11 +# 13| v6_15(void) = UnmodeledUse : mu* +# 13| v6_16(void) = ExitFunction : # 31| int UnreachableViaGoto() # 31| Block 0 @@ -222,10 +223,11 @@ ssa.cpp: #-----| Goto (back edge) -> Block 3 # 71| Block 2 -# 71| v2_0(void) = NoOp : -# 68| v2_1(void) = ReturnVoid : -# 68| v2_2(void) = UnmodeledUse : mu* -# 68| v2_3(void) = ExitFunction : +# 71| v2_0(void) = NoOp : +# 68| v2_1(void) = ReturnIndirection : &:r0_7, ~mu0_2 +# 68| v2_2(void) = ReturnVoid : +# 68| v2_3(void) = UnmodeledUse : mu* +# 68| v2_4(void) = ExitFunction : # 69| Block 3 # 69| m3_0(unknown) = Phi : from 0:~m0_9, from 1:~m1_7 @@ -744,10 +746,11 @@ ssa.cpp: # 181| r0_12(int *) = Load : &:r0_11, m0_4 # 181| r0_13(int) = Load : &:r0_12, ~m0_9 # 181| m0_14(int) = Store : &:r0_10, r0_13 -# 179| r0_15(glval) = VariableAddress[#return] : -# 179| v0_16(void) = ReturnValue : &:r0_15, m0_14 -# 179| v0_17(void) = UnmodeledUse : mu* -# 179| v0_18(void) = ExitFunction : +# 179| v0_15(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 179| r0_16(glval) = VariableAddress[#return] : +# 179| v0_17(void) = ReturnValue : &:r0_16, m0_14 +# 179| v0_18(void) = UnmodeledUse : mu* +# 179| v0_19(void) = ExitFunction : # 184| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&) # 184| Block 0 @@ -785,9 +788,13 @@ ssa.cpp: # 186| m0_31(unknown) = InlineAsm : ~mu0_2, 0:r0_27, 1:r0_28, 2:r0_29, 3:r0_30 # 186| m0_32(unknown) = Chi : total:m0_26, partial:m0_31 # 192| v0_33(void) = NoOp : -# 184| v0_34(void) = ReturnVoid : -# 184| v0_35(void) = UnmodeledUse : mu* -# 184| v0_36(void) = ExitFunction : +# 184| v0_34(void) = ReturnIndirection : &:r0_6, ~mu0_2 +# 184| v0_35(void) = ReturnIndirection : &:r0_12, ~mu0_2 +# 184| v0_36(void) = ReturnIndirection : &:r0_18, ~mu0_2 +# 184| v0_37(void) = ReturnIndirection : &:r0_24, ~mu0_2 +# 184| v0_38(void) = ReturnVoid : +# 184| v0_39(void) = UnmodeledUse : mu* +# 184| v0_40(void) = ExitFunction : # 198| int PureFunctions(char*, char*, int) # 198| Block 0 @@ -839,10 +846,12 @@ ssa.cpp: # 202| r0_45(glval) = VariableAddress[ret] : # 202| r0_46(int) = Load : &:r0_45, m0_43 # 202| m0_47(int) = Store : &:r0_44, r0_46 -# 198| r0_48(glval) = VariableAddress[#return] : -# 198| v0_49(void) = ReturnValue : &:r0_48, m0_47 -# 198| v0_50(void) = UnmodeledUse : mu* -# 198| v0_51(void) = ExitFunction : +# 198| v0_48(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 198| v0_49(void) = ReturnIndirection : &:r0_10, ~mu0_2 +# 198| r0_50(glval) = VariableAddress[#return] : +# 198| v0_51(void) = ReturnValue : &:r0_50, m0_47 +# 198| v0_52(void) = UnmodeledUse : mu* +# 198| v0_53(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 66b377adf505..957a4b3a2271 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -77,10 +77,11 @@ ssa.cpp: # 28| r6_8(int) = Load : &:r6_7, ~mu0_2 # 28| r6_9(int) = Add : r6_4, r6_8 # 28| m6_10(int) = Store : &:r6_0, r6_9 -# 13| r6_11(glval) = VariableAddress[#return] : -# 13| v6_12(void) = ReturnValue : &:r6_11, m6_10 -# 13| v6_13(void) = UnmodeledUse : mu* -# 13| v6_14(void) = ExitFunction : +# 13| v6_11(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 13| r6_12(glval) = VariableAddress[#return] : +# 13| v6_13(void) = ReturnValue : &:r6_12, m6_10 +# 13| v6_14(void) = UnmodeledUse : mu* +# 13| v6_15(void) = ExitFunction : # 31| int UnreachableViaGoto() # 31| Block 0 @@ -222,10 +223,11 @@ ssa.cpp: #-----| Goto (back edge) -> Block 3 # 71| Block 2 -# 71| v2_0(void) = NoOp : -# 68| v2_1(void) = ReturnVoid : -# 68| v2_2(void) = UnmodeledUse : mu* -# 68| v2_3(void) = ExitFunction : +# 71| v2_0(void) = NoOp : +# 68| v2_1(void) = ReturnIndirection : &:r0_7, ~mu0_2 +# 68| v2_2(void) = ReturnVoid : +# 68| v2_3(void) = UnmodeledUse : mu* +# 68| v2_4(void) = ExitFunction : # 69| Block 3 # 69| m3_0(int) = Phi : from 0:m0_4, from 1:m3_6 @@ -709,10 +711,11 @@ ssa.cpp: # 181| r0_10(int *) = Load : &:r0_9, m0_4 # 181| r0_11(int) = Load : &:r0_10, ~mu0_2 # 181| m0_12(int) = Store : &:r0_8, r0_11 -# 179| r0_13(glval) = VariableAddress[#return] : -# 179| v0_14(void) = ReturnValue : &:r0_13, m0_12 -# 179| v0_15(void) = UnmodeledUse : mu* -# 179| v0_16(void) = ExitFunction : +# 179| v0_13(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 179| r0_14(glval) = VariableAddress[#return] : +# 179| v0_15(void) = ReturnValue : &:r0_14, m0_12 +# 179| v0_16(void) = UnmodeledUse : mu* +# 179| v0_17(void) = ExitFunction : # 184| void AsmStmtWithOutputs(unsigned int&, unsigned int&, unsigned int&, unsigned int&) # 184| Block 0 @@ -741,9 +744,13 @@ ssa.cpp: # 186| r0_22(glval) = VariableAddress[d] : # 186| mu0_23(unknown) = InlineAsm : ~mu0_2, 0:r0_19, 1:r0_20, 2:r0_21, 3:r0_22 # 192| v0_24(void) = NoOp : -# 184| v0_25(void) = ReturnVoid : -# 184| v0_26(void) = UnmodeledUse : mu* -# 184| v0_27(void) = ExitFunction : +# 184| v0_25(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 184| v0_26(void) = ReturnIndirection : &:r0_9, ~mu0_2 +# 184| v0_27(void) = ReturnIndirection : &:r0_13, ~mu0_2 +# 184| v0_28(void) = ReturnIndirection : &:r0_17, ~mu0_2 +# 184| v0_29(void) = ReturnVoid : +# 184| v0_30(void) = UnmodeledUse : mu* +# 184| v0_31(void) = ExitFunction : # 198| int PureFunctions(char*, char*, int) # 198| Block 0 @@ -793,10 +800,12 @@ ssa.cpp: # 202| r0_43(glval) = VariableAddress[ret] : # 202| r0_44(int) = Load : &:r0_43, m0_41 # 202| m0_45(int) = Store : &:r0_42, r0_44 -# 198| r0_46(glval) = VariableAddress[#return] : -# 198| v0_47(void) = ReturnValue : &:r0_46, m0_45 -# 198| v0_48(void) = UnmodeledUse : mu* -# 198| v0_49(void) = ExitFunction : +# 198| v0_46(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 198| v0_47(void) = ReturnIndirection : &:r0_9, ~mu0_2 +# 198| r0_48(glval) = VariableAddress[#return] : +# 198| v0_49(void) = ReturnValue : &:r0_48, m0_45 +# 198| v0_50(void) = UnmodeledUse : mu* +# 198| v0_51(void) = ExitFunction : # 207| int ModeledCallTarget(int) # 207| Block 0 From 120fa6c330b52d03e49064f9a3535de323fd3888 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Mon, 28 Oct 2019 11:54:59 -0700 Subject: [PATCH 0110/2538] C++: alias fixes for ReturnIndirection --- .../ir/implementation/aliased_ssa/Operand.qll | 3 + .../aliased_ssa/internal/AliasAnalysis.qll | 1 + .../cpp/ir/implementation/raw/Operand.qll | 3 + .../implementation/unaliased_ssa/Operand.qll | 3 + .../unaliased_ssa/internal/AliasAnalysis.qll | 1 + .../ir/ssa/aliased_ssa_ir.expected | 18 ++-- .../syntax-zoo/raw_sanity.expected | 6 ++ .../GlobalValueNumbering/ir_gvn.expected | 102 ++++++++++-------- .../code/csharp/ir/implementation/Opcode.qll | 5 + .../ir/implementation/raw/Instruction.qll | 15 ++- .../csharp/ir/implementation/raw/Operand.qll | 3 + .../unaliased_ssa/Instruction.qll | 15 ++- .../implementation/unaliased_ssa/Operand.qll | 3 + 13 files changed, 120 insertions(+), 58 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll index a23fb081afed..4e1dd07a3506 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b367..74c288d34681 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -69,6 +69,7 @@ private predicate operandEscapesDomain(Operand operand) { not isArgumentForParameter(_, operand, _) and not isOnlyEscapesViaReturnArgument(operand) and not operand.getUse() instanceof ReturnValueInstruction and + not operand.getUse() instanceof ReturnIndirectionInstruction and not operand instanceof PhiInputOperand } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll index a23fb081afed..4e1dd07a3506 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll index a23fb081afed..4e1dd07a3506 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b367..74c288d34681 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -69,6 +69,7 @@ private predicate operandEscapesDomain(Operand operand) { not isArgumentForParameter(_, operand, _) and not isOnlyEscapesViaReturnArgument(operand) and not operand.getUse() instanceof ReturnValueInstruction and + not operand.getUse() instanceof ReturnIndirectionInstruction and not operand instanceof PhiInputOperand } diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index a7925db2a469..bcaf356c8fe1 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -84,7 +84,7 @@ ssa.cpp: # 28| r6_9(int) = Load : &:r6_8, ~m6_0 # 28| r6_10(int) = Add : r6_5, r6_9 # 28| m6_11(int) = Store : &:r6_1, r6_10 -# 13| v6_12(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 13| v6_12(void) = ReturnIndirection : &:r0_5, ~m6_0 # 13| r6_13(glval) = VariableAddress[#return] : # 13| v6_14(void) = ReturnValue : &:r6_13, m6_11 # 13| v6_15(void) = UnmodeledUse : mu* @@ -224,7 +224,7 @@ ssa.cpp: # 71| Block 2 # 71| v2_0(void) = NoOp : -# 68| v2_1(void) = ReturnIndirection : &:r0_7, ~mu0_2 +# 68| v2_1(void) = ReturnIndirection : &:r0_7, ~m3_0 # 68| v2_2(void) = ReturnVoid : # 68| v2_3(void) = UnmodeledUse : mu* # 68| v2_4(void) = ExitFunction : @@ -746,7 +746,7 @@ ssa.cpp: # 181| r0_12(int *) = Load : &:r0_11, m0_4 # 181| r0_13(int) = Load : &:r0_12, ~m0_9 # 181| m0_14(int) = Store : &:r0_10, r0_13 -# 179| v0_15(void) = ReturnIndirection : &:r0_5, ~mu0_2 +# 179| v0_15(void) = ReturnIndirection : &:r0_5, ~m0_9 # 179| r0_16(glval) = VariableAddress[#return] : # 179| v0_17(void) = ReturnValue : &:r0_16, m0_14 # 179| v0_18(void) = UnmodeledUse : mu* @@ -788,10 +788,10 @@ ssa.cpp: # 186| m0_31(unknown) = InlineAsm : ~mu0_2, 0:r0_27, 1:r0_28, 2:r0_29, 3:r0_30 # 186| m0_32(unknown) = Chi : total:m0_26, partial:m0_31 # 192| v0_33(void) = NoOp : -# 184| v0_34(void) = ReturnIndirection : &:r0_6, ~mu0_2 -# 184| v0_35(void) = ReturnIndirection : &:r0_12, ~mu0_2 -# 184| v0_36(void) = ReturnIndirection : &:r0_18, ~mu0_2 -# 184| v0_37(void) = ReturnIndirection : &:r0_24, ~mu0_2 +# 184| v0_34(void) = ReturnIndirection : &:r0_6, ~m0_32 +# 184| v0_35(void) = ReturnIndirection : &:r0_12, ~m0_32 +# 184| v0_36(void) = ReturnIndirection : &:r0_18, ~m0_32 +# 184| v0_37(void) = ReturnIndirection : &:r0_24, ~m0_32 # 184| v0_38(void) = ReturnVoid : # 184| v0_39(void) = UnmodeledUse : mu* # 184| v0_40(void) = ExitFunction : @@ -846,8 +846,8 @@ ssa.cpp: # 202| r0_45(glval) = VariableAddress[ret] : # 202| r0_46(int) = Load : &:r0_45, m0_43 # 202| m0_47(int) = Store : &:r0_44, r0_46 -# 198| v0_48(void) = ReturnIndirection : &:r0_5, ~mu0_2 -# 198| v0_49(void) = ReturnIndirection : &:r0_10, ~mu0_2 +# 198| v0_48(void) = ReturnIndirection : &:r0_5, ~m0_12 +# 198| v0_49(void) = ReturnIndirection : &:r0_10, ~m0_12 # 198| r0_50(glval) = VariableAddress[#return] : # 198| v0_51(void) = ReturnValue : &:r0_50, m0_47 # 198| v0_52(void) = UnmodeledUse : mu* diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 5d7c44473026..2e5973b06802 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -610,6 +610,8 @@ lostReachability | range_analysis.c:371:37:371:39 | Constant: 500 | backEdgeCountMismatch useNotDominatedByDefinition +| VacuousDestructorCall.cpp:2:29:2:29 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor(int, int*) | +| VacuousDestructorCall.cpp:2:29:2:29 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor(int, int*) | | VacuousDestructorCall.cpp:4:3:4:3 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | VacuousDestructorCall.cpp:2:6:2:6 | IR: CallDestructor | void CallDestructor(int, int*) | | assume0.cpp:11:2:11:2 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | assume0.cpp:5:6:5:6 | IR: h | void h() | | condition_decls.cpp:16:15:16:15 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | @@ -662,6 +664,8 @@ useNotDominatedByDefinition | misc.c:174:17:174:22 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | misc.c:168:6:168:8 | IR: vla | void vla() | | misc.c:174:30:174:35 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | misc.c:168:6:168:8 | IR: vla | void vla() | | misc.c:219:5:219:26 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | +| misc.c:219:47:219:48 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | +| misc.c:219:47:219:48 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | misc.c:220:4:220:5 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | misc.c:219:5:219:26 | IR: assign_designated_init | int assign_designated_init(someStruct*) | | ms_try_except.cpp:9:19:9:19 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | IR: ms_try_except | void ms_try_except(int) | | ms_try_except.cpp:19:17:19:17 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | ms_try_except.cpp:2:6:2:18 | IR: ms_try_except | void ms_try_except(int) | @@ -684,6 +688,8 @@ useNotDominatedByDefinition | stmt_expr.cpp:31:16:31:18 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) | | try_catch.cpp:21:13:21:24 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | try_catch.cpp:19:6:19:23 | IR: throw_from_nonstmt | void throw_from_nonstmt(int) | | vla.c:3:5:3:8 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | +| vla.c:3:27:3:30 | Address | Operand 'Address' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | +| vla.c:3:27:3:30 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | | vla.c:5:16:5:19 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | | vla.c:5:22:5:25 | Operand | Operand 'Operand' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | | vla.c:5:27:5:30 | Load | Operand 'Load' is not dominated by its definition in function '$@'. | vla.c:3:5:3:8 | IR: main | int main(int, char**) | diff --git a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected index 3b386c2c1ec8..77754d317d90 100644 --- a/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected +++ b/cpp/ql/test/library-tests/valuenumbering/GlobalValueNumbering/ir_gvn.expected @@ -336,11 +336,12 @@ test.cpp: # 46| m0_46(int) = Store : &:r0_45, r0_44 # 46| valnum = r0_40 # 47| v0_47(void) = NoOp : -# 39| r0_48(glval) = VariableAddress[#return] : +# 39| v0_48(void) = ReturnIndirection : &:r0_9, ~m0_32 +# 39| r0_49(glval) = VariableAddress[#return] : # 39| valnum = unique -# 39| v0_49(void) = ReturnValue : &:r0_48 -# 39| v0_50(void) = UnmodeledUse : mu* -# 39| v0_51(void) = ExitFunction : +# 39| v0_50(void) = ReturnValue : &:r0_49 +# 39| v0_51(void) = UnmodeledUse : mu* +# 39| v0_52(void) = ExitFunction : # 49| unsigned int my_strspn(char const*, char const*) # 49| Block 0 @@ -510,11 +511,13 @@ test.cpp: # 65| valnum = m1_0 # 65| m9_4(unsigned int) = Store : &:r9_1, r9_3 # 65| valnum = m1_0 -# 49| r9_5(glval) = VariableAddress[#return] : +# 49| v9_5(void) = ReturnIndirection : &:r0_5, ~m0_12 +# 49| v9_6(void) = ReturnIndirection : &:r0_10, ~m0_12 +# 49| r9_7(glval) = VariableAddress[#return] : # 49| valnum = r9_1 -# 49| v9_6(void) = ReturnValue : &:r9_5, m9_4 -# 49| v9_7(void) = UnmodeledUse : mu* -# 49| v9_8(void) = ExitFunction : +# 49| v9_8(void) = ReturnValue : &:r9_7, m9_4 +# 49| v9_9(void) = UnmodeledUse : mu* +# 49| v9_10(void) = ExitFunction : # 75| void test04(two_values*) # 75| Block 0 @@ -599,10 +602,13 @@ test.cpp: #-----| Goto -> Block 2 # 82| Block 2 -# 82| v2_0(void) = NoOp : -# 75| v2_1(void) = ReturnVoid : -# 75| v2_2(void) = UnmodeledUse : mu* -# 75| v2_3(void) = ExitFunction : +# 82| m2_0(unknown) = Phi : from 0:~m0_12, from 1:~m1_3 +# 82| valnum = unique +# 82| v2_1(void) = NoOp : +# 75| v2_2(void) = ReturnIndirection : &:r0_5, ~m2_0 +# 75| v2_3(void) = ReturnVoid : +# 75| v2_4(void) = UnmodeledUse : mu* +# 75| v2_5(void) = ExitFunction : # 84| void test05(int, int, void*) # 84| Block 0 @@ -642,46 +648,47 @@ test.cpp: # 88| r0_17(bool) = CompareNE : r0_15, r0_16 # 88| valnum = unique # 88| v0_18(void) = ConditionalBranch : r0_17 -#-----| False -> Block 2 -#-----| True -> Block 1 +#-----| False -> Block 3 +#-----| True -> Block 2 # 88| Block 1 -# 88| r1_0(glval) = VariableAddress[x] : +# 88| m1_0(int) = Phi : from 2:m2_3, from 3:m3_3 +# 88| valnum = m1_0 +# 88| r1_1(glval) = VariableAddress[#temp88:7] : +# 88| valnum = r1_1 +# 88| r1_2(int) = Load : &:r1_1, m1_0 +# 88| valnum = m1_0 +# 88| r1_3(glval) = VariableAddress[v] : +# 88| valnum = r0_12 +# 88| m1_4(int) = Store : &:r1_3, r1_2 +# 88| valnum = m1_0 +# 89| v1_5(void) = NoOp : +# 84| v1_6(void) = ReturnIndirection : &:r0_9, ~m0_11 +# 84| v1_7(void) = ReturnVoid : +# 84| v1_8(void) = UnmodeledUse : mu* +# 84| v1_9(void) = ExitFunction : + +# 88| Block 2 +# 88| r2_0(glval) = VariableAddress[x] : # 88| valnum = r0_3 -# 88| r1_1(int) = Load : &:r1_0, m0_4 +# 88| r2_1(int) = Load : &:r2_0, m0_4 # 88| valnum = m0_4 -# 88| r1_2(glval) = VariableAddress[#temp88:7] : -# 88| valnum = r1_2 -# 88| m1_3(int) = Store : &:r1_2, r1_1 +# 88| r2_2(glval) = VariableAddress[#temp88:7] : +# 88| valnum = r1_1 +# 88| m2_3(int) = Store : &:r2_2, r2_1 # 88| valnum = m0_4 -#-----| Goto -> Block 3 +#-----| Goto -> Block 1 -# 88| Block 2 -# 88| r2_0(glval) = VariableAddress[y] : +# 88| Block 3 +# 88| r3_0(glval) = VariableAddress[y] : # 88| valnum = r0_5 -# 88| r2_1(int) = Load : &:r2_0, m0_6 +# 88| r3_1(int) = Load : &:r3_0, m0_6 # 88| valnum = m0_6 -# 88| r2_2(glval) = VariableAddress[#temp88:7] : -# 88| valnum = r1_2 -# 88| m2_3(int) = Store : &:r2_2, r2_1 +# 88| r3_2(glval) = VariableAddress[#temp88:7] : +# 88| valnum = r1_1 +# 88| m3_3(int) = Store : &:r3_2, r3_1 # 88| valnum = m0_6 -#-----| Goto -> Block 3 - -# 88| Block 3 -# 88| m3_0(int) = Phi : from 1:m1_3, from 2:m2_3 -# 88| valnum = m3_0 -# 88| r3_1(glval) = VariableAddress[#temp88:7] : -# 88| valnum = r1_2 -# 88| r3_2(int) = Load : &:r3_1, m3_0 -# 88| valnum = m3_0 -# 88| r3_3(glval) = VariableAddress[v] : -# 88| valnum = r0_12 -# 88| m3_4(int) = Store : &:r3_3, r3_2 -# 88| valnum = m3_0 -# 89| v3_5(void) = NoOp : -# 84| v3_6(void) = ReturnVoid : -# 84| v3_7(void) = UnmodeledUse : mu* -# 84| v3_8(void) = ExitFunction : +#-----| Goto -> Block 1 # 91| int regression_test00() # 91| Block 0 @@ -775,11 +782,12 @@ test.cpp: # 109| valnum = r0_24 # 109| m0_29(int) = Store : &:r0_26, r0_28 # 109| valnum = r0_24 -# 104| r0_30(glval) = VariableAddress[#return] : +# 104| v0_30(void) = ReturnIndirection : &:r0_5, ~m0_7 +# 104| r0_31(glval) = VariableAddress[#return] : # 104| valnum = r0_26 -# 104| v0_31(void) = ReturnValue : &:r0_30, m0_29 -# 104| v0_32(void) = UnmodeledUse : mu* -# 104| v0_33(void) = ExitFunction : +# 104| v0_32(void) = ReturnValue : &:r0_31, m0_29 +# 104| v0_33(void) = UnmodeledUse : mu* +# 104| v0_34(void) = ExitFunction : # 112| void test06() # 112| Block 0 diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll index 67507fce11d6..713893f52f7a 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/Opcode.qll @@ -9,6 +9,7 @@ private newtype TOpcode = TExitFunction() or TReturnValue() or TReturnVoid() or + TReturnIndirection() or TCopyValue() or TLoad() or TStore() or @@ -202,6 +203,10 @@ module Opcode { final override string toString() { result = "ReturnVoid" } } + class ReturnIndirection extends MemoryAccessOpcode, TReturnIndirection { + final override string toString() { result = "ReturnIndirection" } + } + class CopyValue extends UnaryOpcode, CopyOpcode, TCopyValue { final override string toString() { result = "CopyValue" } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index f0a9c0e698ae..d710515bc06a 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll index a23fb081afed..4e1dd07a3506 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index f0a9c0e698ae..d710515bc06a 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -49,7 +49,8 @@ module InstructionSanity { ( opcode instanceof ReadSideEffectOpcode or opcode instanceof Opcode::InlineAsm or - opcode instanceof Opcode::CallSideEffect + opcode instanceof Opcode::CallSideEffect or + opcode instanceof Opcode::ReturnIndirection ) and tag instanceof SideEffectOperandTag ) @@ -743,6 +744,18 @@ class ReturnValueInstruction extends ReturnInstruction { final Instruction getReturnValue() { result = getReturnValueOperand().getDef() } } +class ReturnIndirectionInstruction extends Instruction { + ReturnIndirectionInstruction() { getOpcode() instanceof Opcode::ReturnIndirection } + + final SideEffectOperand getSideEffectOperand() { result = getAnOperand() } + + final Instruction getSideEffect() { result = getSideEffectOperand().getDef() } + + final AddressOperand getSourceAddressOperand() { result = getAnOperand() } + + final Instruction getSourceAddress() { result = getSourceAddressOperand().getDef() } +} + class CopyInstruction extends Instruction { CopyInstruction() { getOpcode() instanceof CopyOpcode } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll index a23fb081afed..4e1dd07a3506 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Operand.qll @@ -411,6 +411,9 @@ class SideEffectOperand extends TypedOperand { or useInstr instanceof BufferMayWriteSideEffectInstruction and result instanceof BufferMayMemoryAccess + or + useInstr instanceof ReturnIndirectionInstruction and + result instanceof BufferMemoryAccess } } From 563f32193cfbb747c19c0b28884be70264a6296c Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Oct 2019 12:10:12 +0100 Subject: [PATCH 0111/2538] suggestions from @max-schaefer Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/Statements/IgnoreArrayResult.qhelp | 2 +- javascript/ql/src/Statements/IgnoreArrayResult.ql | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp index b70ff1f1b32a..2232784d881e 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -5,7 +5,7 @@

    The concat, join and slice methods are -pure and does not modify any of the inputs or the array the method was called +pure and do not modify any of the inputs or the array the method was called on. It is therefore generally an error to ignore the return value from a call to one of these methods.

    diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql index b6137e664d79..5ab778ed95bf 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.ql +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -1,10 +1,10 @@ /** * @name Ignoring result from pure array method - * @description The array methods do not modify the array, ignoring the result of such a call is therefore generally an error. + * @description Ignoring the result of an array method that does not modify its receiver is generally an error. * @kind problem * @problem.severity warning * @id js/ignore-array-result - * @tags maintainability, + * @tags maintainability * correctness * @precision high */ @@ -16,7 +16,7 @@ DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCal isIgnoredPureArrayCall(call) and ( t.start() and - result = call.getReceiver() + result = call.getReceiver().getALocalSource() or exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) ) From 2d01e7c5ed97392e55db948755d445dc8337a68a Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 29 Oct 2019 12:13:01 +0100 Subject: [PATCH 0112/2538] simplify the callsArray predicate --- javascript/ql/src/Statements/IgnoreArrayResult.ql | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.ql b/javascript/ql/src/Statements/IgnoreArrayResult.ql index 5ab778ed95bf..6f6698797f1c 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.ql +++ b/javascript/ql/src/Statements/IgnoreArrayResult.ql @@ -13,13 +13,11 @@ import javascript import Expressions.ExprHasNoEffect DataFlow::SourceNode callsArray(DataFlow::TypeBackTracker t, DataFlow::MethodCallNode call) { - isIgnoredPureArrayCall(call) and - ( - t.start() and - result = call.getReceiver().getALocalSource() - or - exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) - ) + isIgnoredPureArrayCall(call) and + t.start() and + result = call.getReceiver().getALocalSource() + or + exists(DataFlow::TypeBackTracker t2 | result = callsArray(t2, call).backtrack(t2, t)) } DataFlow::SourceNode callsArray(DataFlow::MethodCallNode call) { From 49dd2216a65e55824bb0371d8d476eebae1c241b Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 10 Oct 2019 16:14:12 +0200 Subject: [PATCH 0113/2538] Python: Refactor django library Use General.qll for routing, like in other web libraries --- .../src/semmle/python/web/django/General.qll | 28 +++++++++++++ .../src/semmle/python/web/django/Request.qll | 41 ++++--------------- 2 files changed, 35 insertions(+), 34 deletions(-) create mode 100644 python/ql/src/semmle/python/web/django/General.qll diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll new file mode 100644 index 000000000000..954df1892e88 --- /dev/null +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -0,0 +1,28 @@ +import python +import semmle.python.regex +import semmle.python.web.Http + +predicate django_route(CallNode call, ControlFlowNode regex, FunctionValue view) { + exists(FunctionValue url | + Value::named("django.conf.urls.url") = url and + url.getArgumentForCall(call, 0) = regex and + url.getArgumentForCall(call, 1).pointsTo(view) + ) +} + +class DjangoRouteRegex extends RegexString { + DjangoRouteRegex() { django_route(_, this.getAFlowNode(), _) } +} + +class DjangoRoute extends CallNode { + DjangoRoute() { django_route(this, _, _) } + + FunctionValue getViewFunction() { django_route(this, _, result) } + + string getNamedArgument() { + exists(DjangoRouteRegex regex | + django_route(this, regex.getAFlowNode(), _) and + regex.getGroupName(_, _) = result + ) + } +} diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index d2ad2ff30d3e..71da78f9b43e 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -1,7 +1,7 @@ import python -import semmle.python.regex import semmle.python.security.TaintTracking import semmle.python.web.Http +import semmle.python.web.django.General /** A django.request.HttpRequest object */ class DjangoRequest extends TaintKind { @@ -52,7 +52,7 @@ abstract class DjangoRequestSource extends HttpRequestTaintSource { private class DjangoFunctionBasedViewRequestArgument extends DjangoRequestSource { DjangoFunctionBasedViewRequestArgument() { exists(FunctionValue view | - url_dispatch(_, _, view) and + django_route(_, _, view) and this = view.getScope().getArg(0).asName().getAFlowNode() ) } @@ -76,41 +76,14 @@ class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { } } -/* *********** Routing ********* */ -/* Function based views */ -predicate url_dispatch(CallNode call, ControlFlowNode regex, FunctionValue view) { - exists(FunctionValue url | - Value::named("django.conf.urls.url") = url and - url.getArgumentForCall(call, 0) = regex and - url.getArgumentForCall(call, 1).pointsTo(view) - ) -} - -class UrlRegex extends RegexString { - UrlRegex() { url_dispatch(_, this.getAFlowNode(), _) } -} - -class UrlRouting extends CallNode { - UrlRouting() { url_dispatch(this, _, _) } - - FunctionValue getViewFunction() { url_dispatch(this, _, result) } - - string getNamedArgument() { - exists(UrlRegex regex | - url_dispatch(this, regex.getAFlowNode(), _) and - regex.getGroupName(_, _) = result - ) - } -} - /** An argument specified in a url routing table */ -class HttpRequestParameter extends HttpRequestTaintSource { - HttpRequestParameter() { - exists(UrlRouting url | - this.(ControlFlowNode).getNode() = url +class DjangoRequestParameter extends HttpRequestTaintSource { + DjangoRequestParameter() { + exists(DjangoRoute route | + this.(ControlFlowNode).getNode() = route .getViewFunction() .getScope() - .getArgByName(url.getNamedArgument()) + .getArgByName(route.getNamedArgument()) ) } From afe7a0536cc0ad3cc93b396c0d3ed40bb1c5502c Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Thu, 10 Oct 2019 17:25:09 +0200 Subject: [PATCH 0114/2538] Python: Support positional arguments in Django routes --- change-notes/1.23/analysis-python.md | 5 +++ .../src/semmle/python/web/django/General.qll | 12 +++++++ .../src/semmle/python/web/django/Request.qll | 14 +++++--- .../library-tests/web/django/Sinks.expected | 4 +++ .../library-tests/web/django/Sources.expected | 9 +++++ .../ql/test/library-tests/web/django/test.py | 33 ++++++++++++++++++- 6 files changed, 71 insertions(+), 6 deletions(-) diff --git a/change-notes/1.23/analysis-python.md b/change-notes/1.23/analysis-python.md index 00fab13e098e..6cea1745284a 100644 --- a/change-notes/1.23/analysis-python.md +++ b/change-notes/1.23/analysis-python.md @@ -20,3 +20,8 @@ |----------------------------|------------------------|------------| | Unreachable code | Fewer false positives | Analysis now accounts for uses of `contextlib.suppress` to suppress exceptions. | | `__iter__` method returns a non-iterator | Better alert message | Alert now highlights which class is expected to be an iterator. | + + +## Changes to QL libraries + +* Django library now recognizes positional arguments from a `django.conf.urls.url` regex (Django version 1.x) diff --git a/python/ql/src/semmle/python/web/django/General.qll b/python/ql/src/semmle/python/web/django/General.qll index 954df1892e88..423d853cdad6 100644 --- a/python/ql/src/semmle/python/web/django/General.qll +++ b/python/ql/src/semmle/python/web/django/General.qll @@ -25,4 +25,16 @@ class DjangoRoute extends CallNode { regex.getGroupName(_, _) = result ) } + + /** + * Get the number of positional arguments that will be passed to the view. + * Will only return a result if there are no named arguments. + */ + int getNumPositionalArguments() { + exists(DjangoRouteRegex regex | + django_route(this, regex.getAFlowNode(), _) and + not exists(string s | s = regex.getGroupName(_, _)) and + result = count(regex.getGroupNumber(_, _)) + ) + } } diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index 71da78f9b43e..15ea032e6d72 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -79,11 +79,15 @@ class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { /** An argument specified in a url routing table */ class DjangoRequestParameter extends HttpRequestTaintSource { DjangoRequestParameter() { - exists(DjangoRoute route | - this.(ControlFlowNode).getNode() = route - .getViewFunction() - .getScope() - .getArgByName(route.getNamedArgument()) + exists(DjangoRoute route, Function f | + f = route.getViewFunction().getScope() | + this.(ControlFlowNode).getNode() = f.getArgByName(route.getNamedArgument()) + or + exists(int i | i >= 0 | + i < route.getNumPositionalArguments() and + // +1 because first argument is always the request + this.(ControlFlowNode).getNode() = f.getArg(i+1) + ) ) } diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 82d1b71e53a6..7201a7a20a94 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -4,3 +4,7 @@ | test.py:25 | BinaryExpr | externally controlled string | | test.py:26 | BinaryExpr | externally controlled string | | test.py:34 | BinaryExpr | externally controlled string | +| test.py:46 | Attribute() | externally controlled string | +| test.py:57 | Attribute() | externally controlled string | +| test.py:60 | Attribute() | externally controlled string | +| test.py:63 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 8f421a2d1694..7482f21cddab 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,2 +1,11 @@ | test.py:11 | request | django.request.HttpRequest | | test.py:31 | request | django.request.HttpRequest | +| test.py:56 | arg0 | externally controlled string | +| test.py:56 | request | django.request.HttpRequest | +| test.py:59 | arg0 | externally controlled string | +| test.py:59 | arg1 | externally controlled string | +| test.py:59 | arg2 | externally controlled string | +| test.py:59 | request | django.request.HttpRequest | +| test.py:62 | arg0 | externally controlled string | +| test.py:62 | arg1 | externally controlled string | +| test.py:62 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index e6c39c30a32d..3cabac0e5c55 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -34,7 +34,38 @@ def maybe_xss(request): resp.write("first name is " + first_name) return resp -urlpatterns2 = [ +urlpatterns = [ # Route to code_execution url(r'^maybe_xss$', maybe_xss, name='maybe_xss') ] + + +# Non capturing group (we correctly identify page_number as a request parameter) + +def show_articles(request, page_number=1): + return HttpResponse('articles page: {}'.format(page_number)) + +urlpatterns = [ + # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 + url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), +] + + +# Positional arguments + +def xxs_positional_arg1(request, arg0): + return HttpResponse('xxs_positional_arg1: {}'.format(arg0)) + +def xxs_positional_arg2(request, arg0, arg1, arg2): + return HttpResponse('xxs_positional_arg2: {} {} {}'.format(arg0, arg1, arg2)) + +def xxs_positional_arg3(request, arg0, arg1): + return HttpResponse('xxs_positional_arg3: {} {}'.format(arg0, arg1)) + +urlpatterns = [ + # passing as positional argument is not the recommended way of doing things, + # but it is certainly possible + url(r'^(.+)$', xxs_positional_arg1, name='xxs_positional_arg1'), + url(r'^([^/]+)/([^/]+)/([^/]+)$', xxs_positional_arg2, name='xxs_positional_arg2'), + url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg3, name='xxs_positional_arg3'), +] From 471318369b4fee5c66239a5f33c91d9410df8f76 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 14 Oct 2019 16:51:50 +0200 Subject: [PATCH 0115/2538] Python: Don't quote %s in django example This is vulnerable to SQL injection because of the quotes around %s -- added some code that highlights this in test.py Since our examples did this in the safe query, I ended up rewriting them completely, causing a lot of trouble for myself :D --- .../src/Security/CWE-089/SqlInjection.qhelp | 17 ++++-- .../CWE-089/examples/sql_injection.py | 28 +++++---- .../library-tests/web/django/Sinks.expected | 21 ++++--- .../library-tests/web/django/Sources.expected | 26 +++++---- .../ql/test/library-tests/web/django/test.py | 57 ++++++++++++------- .../Security/CWE-089/SqlInjection.expected | 27 ++++----- .../Security/CWE-089/sql_injection.py | 48 ++++++++++------ 7 files changed, 131 insertions(+), 93 deletions(-) diff --git a/python/ql/src/Security/CWE-089/SqlInjection.qhelp b/python/ql/src/Security/CWE-089/SqlInjection.qhelp index e976401a6b5f..286b71a60475 100644 --- a/python/ql/src/Security/CWE-089/SqlInjection.qhelp +++ b/python/ql/src/Security/CWE-089/SqlInjection.qhelp @@ -21,20 +21,29 @@ or prepared statements.

    -In the following snippet, from an example django app, -a name is stored in the database using two different queries. +In the following snippet, a user is fetched from the database using three +different queries.

    In the first case, the query string is built by -directly using string formatting from a user-supplied request attribute. +directly using string formatting from a user-supplied request parameter. The parameter may include quote characters, so this code is vulnerable to a SQL injection attack.

    In the second case, the user-supplied request attribute is passed -to the database using query parameters. +to the database using query parameters. The database connector library will +take care of escaping and inserting quotes as needed. +

    + +

    +In the third case, the placeholder in the SQL string has been manually quoted. Since most +databaseconnector libraries will insert their own quotes, doing so yourself will make the code +vulnerable to SQL injection attacks. In this example, if username was +; DROP ALL TABLES -- , the final SQL query would be +SELECT * FROM users WHERE username = ''; DROP ALL TABLES -- ''

    diff --git a/python/ql/src/Security/CWE-089/examples/sql_injection.py b/python/ql/src/Security/CWE-089/examples/sql_injection.py index 541c580f7127..fe6dbc50c010 100644 --- a/python/ql/src/Security/CWE-089/examples/sql_injection.py +++ b/python/ql/src/Security/CWE-089/examples/sql_injection.py @@ -1,21 +1,19 @@ - -from django.conf.urls import patterns, url +from django.conf.urls import url from django.db import connection -def save_name(request): - - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) +def show_user(request, username): + with connection.cursor() as cursor: + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + user = cursor.fetchone() + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + user = cursor.fetchone() -urlpatterns = patterns(url(r'^save_name/$', - upload, name='save_name')) + # BAD -- Manually quoting placeholder (%s) + cursor.execute("SELECT * FROM users WHERE username = '%s'", username) + user = cursor.fetchone() +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 7201a7a20a94..31a42364762d 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -1,10 +1,13 @@ -| test.py:18 | Str | externally controlled string | +| test.py:14 | Str | externally controlled string | +| test.py:15 | Str | externally controlled string | +| test.py:18 | BinaryExpr | externally controlled string | | test.py:21 | BinaryExpr | externally controlled string | -| test.py:24 | BinaryExpr | externally controlled string | -| test.py:25 | BinaryExpr | externally controlled string | -| test.py:26 | BinaryExpr | externally controlled string | -| test.py:34 | BinaryExpr | externally controlled string | -| test.py:46 | Attribute() | externally controlled string | -| test.py:57 | Attribute() | externally controlled string | -| test.py:60 | Attribute() | externally controlled string | -| test.py:63 | Attribute() | externally controlled string | +| test.py:22 | BinaryExpr | externally controlled string | +| test.py:23 | BinaryExpr | externally controlled string | +| test.py:37 | Str | externally controlled string | +| test.py:44 | BinaryExpr | externally controlled string | +| test.py:48 | Attribute() | externally controlled string | +| test.py:59 | Attribute() | externally controlled string | +| test.py:70 | Attribute() | externally controlled string | +| test.py:73 | Attribute() | externally controlled string | +| test.py:76 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 7482f21cddab..371b1e7cb6f1 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,11 +1,17 @@ | test.py:11 | request | django.request.HttpRequest | -| test.py:31 | request | django.request.HttpRequest | -| test.py:56 | arg0 | externally controlled string | -| test.py:56 | request | django.request.HttpRequest | -| test.py:59 | arg0 | externally controlled string | -| test.py:59 | arg1 | externally controlled string | -| test.py:59 | arg2 | externally controlled string | -| test.py:59 | request | django.request.HttpRequest | -| test.py:62 | arg0 | externally controlled string | -| test.py:62 | arg1 | externally controlled string | -| test.py:62 | request | django.request.HttpRequest | +| test.py:11 | username | externally controlled string | +| test.py:41 | request | django.request.HttpRequest | +| test.py:47 | bar | externally controlled string | +| test.py:47 | foo | externally controlled string | +| test.py:47 | request | django.request.HttpRequest | +| test.py:58 | page_number | externally controlled string | +| test.py:58 | request | django.request.HttpRequest | +| test.py:69 | arg0 | externally controlled string | +| test.py:69 | request | django.request.HttpRequest | +| test.py:72 | arg0 | externally controlled string | +| test.py:72 | arg1 | externally controlled string | +| test.py:72 | arg2 | externally controlled string | +| test.py:72 | request | django.request.HttpRequest | +| test.py:75 | arg0 | externally controlled string | +| test.py:75 | arg1 | externally controlled string | +| test.py:75 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index 3cabac0e5c55..1240b9ae5a1b 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -5,28 +5,38 @@ from django.http.response import HttpResponse import base64 -class Name(models.Model): +class User(models.Model): pass -def save_name(request): - - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) - - #BAD -- other ways of executing raw SQL code with string interpolation - Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name)) - Name.objects.raw("insert into names_file ('name') values ('%s')" % name) - Name.objects.extra("insert into names_file ('name') values ('%s')" % name) - -urlpatterns1 = patterns(url(r'^save_name/$', - save_name, name='save_name')) +def show_user(request, username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) + + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) + + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) + +urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) def maybe_xss(request): first_name = request.POST.get('first_name', '') @@ -34,9 +44,12 @@ def maybe_xss(request): resp.write("first name is " + first_name) return resp +def xss_kwargs(request, foo, bar, baz=None): + return HttpResponse('xss_kwargs: {} {}'.format(foo, bar)) + urlpatterns = [ - # Route to code_execution - url(r'^maybe_xss$', maybe_xss, name='maybe_xss') + url(r'^maybe_xss$', maybe_xss, name='maybe_xss'), + url(r'^bar/(?P[^/]+)/foo/(?P[^/]+)', xss_kwargs, name='xss_kwargs'), ] diff --git a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected b/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected index 9c00ffdb2dba..461d42fccf12 100644 --- a/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected +++ b/python/ql/test/query-tests/Security/CWE-089/SqlInjection.expected @@ -1,17 +1,14 @@ edges -| sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:12:16:12:22 | django.request.HttpRequest | -| sql_injection.py:12:16:12:22 | django.request.HttpRequest | sql_injection.py:12:16:12:27 | django.http.request.QueryDict | -| sql_injection.py:12:16:12:27 | django.http.request.QueryDict | sql_injection.py:12:16:12:39 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:19:63:19:66 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:22:88:22:91 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:23:76:23:79 | externally controlled string | -| sql_injection.py:12:16:12:39 | externally controlled string | sql_injection.py:24:78:24:81 | externally controlled string | -| sql_injection.py:19:63:19:66 | externally controlled string | sql_injection.py:19:13:19:66 | externally controlled string | -| sql_injection.py:22:88:22:91 | externally controlled string | sql_injection.py:22:38:22:91 | externally controlled string | -| sql_injection.py:23:76:23:79 | externally controlled string | sql_injection.py:23:26:23:79 | externally controlled string | -| sql_injection.py:24:78:24:81 | externally controlled string | sql_injection.py:24:28:24:81 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:70:19:77 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:88:22:95 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:76:23:83 | externally controlled string | +| sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:78:24:85 | externally controlled string | +| sql_injection.py:19:70:19:77 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | +| sql_injection.py:22:88:22:95 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | +| sql_injection.py:23:76:23:83 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | +| sql_injection.py:24:78:24:85 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | #select -| sql_injection.py:19:13:19:66 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:19:13:19:66 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:22:38:22:91 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:22:38:22:91 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:23:26:23:79 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:23:26:23:79 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | -| sql_injection.py:24:28:24:81 | BinaryExpr | sql_injection.py:9:15:9:21 | django.request.HttpRequest | sql_injection.py:24:28:24:81 | externally controlled string | This SQL query depends on $@. | sql_injection.py:9:15:9:21 | request | a user-provided value | +| sql_injection.py:19:24:19:77 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:19:24:19:77 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:22:38:22:95 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:22:38:22:95 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:23:26:23:83 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:23:26:23:83 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | +| sql_injection.py:24:28:24:85 | BinaryExpr | sql_injection.py:12:24:12:31 | externally controlled string | sql_injection.py:24:28:24:85 | externally controlled string | This SQL query depends on $@. | sql_injection.py:12:24:12:31 | username | a user-provided value | diff --git a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py b/python/ql/test/query-tests/Security/CWE-089/sql_injection.py index b312241b8099..9ccca7503bdf 100644 --- a/python/ql/test/query-tests/Security/CWE-089/sql_injection.py +++ b/python/ql/test/query-tests/Security/CWE-089/sql_injection.py @@ -1,28 +1,40 @@ +"""This is copied from ql/python/ql/test/library-tests/web/django/test.py +and a only a slight extension of ql/python/ql/src/Security/CWE-089/examples/sql_injection.py +""" -from django.conf.urls import patterns, url +from django.conf.urls import url from django.db import connection, models from django.db.models.expressions import RawSQL -class Name(models.Model): +class User(models.Model): pass -def save_name(request): +def show_user(request, username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) - if request.method == 'POST': - name = request.POST.get('name') - curs = connection.cursor() - #GOOD -- Using parameters - curs.execute( - "insert into names_file ('name') values ('%s')", name) - #BAD -- Using string formatting - curs.execute( - "insert into names_file ('name') values ('%s')" % name) + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) - #BAD -- other ways of executing raw SQL code with string interpolation - Name.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % name)) - Name.objects.raw("insert into names_file ('name') values ('%s')" % name) - Name.objects.extra("insert into names_file ('name') values ('%s')" % name) + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) -urlpatterns = patterns(url(r'^save_name/$', - save_name, name='save_name')) + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) +urlpatterns = [url(r'^users/(?P[^/]+)$', show_user)] From 91f269ed7b873cc7fc329f562a99552297467a0e Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Tue, 15 Oct 2019 16:44:26 +0200 Subject: [PATCH 0116/2538] Python: Remove unused django sinks This would find instances of `thing = MyThing.objects.get(field=userinput)`, and what seems to be a query that wants to match on `thing = MyThing(); thing.field=userinput`. Both are not vulnerable to user-input, due to the build-in escaping by django. The DjangoModelFieldWrite actually matches on `MyThing.field=userinput` and not `thing.field=userinput`. I suspect this to be a mistake. Matching on `thing.field=userinput`, would require this CodeQL: attr.getObject(_).pointsTo().getClass() = model --- .../ql/src/semmle/python/web/django/Model.qll | 27 ------------------- 1 file changed, 27 deletions(-) diff --git a/python/ql/src/semmle/python/web/django/Model.qll b/python/ql/src/semmle/python/web/django/Model.qll index 34cf58568021..b8f47b64bdf4 100644 --- a/python/ql/src/semmle/python/web/django/Model.qll +++ b/python/ql/src/semmle/python/web/django/Model.qll @@ -54,33 +54,6 @@ class DjangoModelObjects extends TaintSource { override string toString() { result = "django.db.models.Model.objects" } } -/** A write to a field of a django model, which is a vulnerable to external data. */ -class DjangoModelFieldWrite extends SqlInjectionSink { - DjangoModelFieldWrite() { - exists(AttrNode attr, DjangoModel model | - this = attr and attr.isStore() and attr.getObject(_).pointsTo(model) - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } - - override string toString() { result = "django model field write" } -} - -/** A direct reference to a django model object, which is vulnerable to external data. */ -class DjangoModelDirectObjectReference extends TaintSink { - DjangoModelDirectObjectReference() { - exists(CallNode objects_get_call, ControlFlowNode objects | this = objects_get_call.getAnArg() | - objects_get_call.getFunction().(AttrNode).getObject("get") = objects and - any(DjangoDbTableObjects objs).taints(objects) - ) - } - - override predicate sinks(TaintKind kind) { kind instanceof ExternalStringKind } - - override string toString() { result = "django model object reference" } -} - /** * A call to the `raw` method on a django model. This allows a raw SQL query * to be sent to the database, which is a security risk. From fb864b7262ec63ed695edf8fd084f6eb1b124da1 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 21 Oct 2019 16:39:55 +0200 Subject: [PATCH 0117/2538] Python: Consolidate tests for django The tests in 3/ was not Python 3 specific anymore --- .../3/library-tests/web/django/Sinks.expected | 6 -- .../test/3/library-tests/web/django/Sinks.ql | 13 --- .../library-tests/web/django/Sources.expected | 8 -- .../3/library-tests/web/django/Sources.ql | 12 --- .../3/library-tests/web/django/Taint.expected | 24 ------ .../test/3/library-tests/web/django/Taint.ql | 14 --- .../web/django/django/__init__.py | 1 - .../web/django/django/conf/__init__.py | 1 - .../web/django/django/conf/urls.py | 3 - .../web/django/django/db/__init__.py | 1 - .../web/django/django/db/models/__init__.py | 2 - .../django/django/db/models/expressions.py | 2 - .../web/django/django/http/__init__.py | 2 - .../web/django/django/http/response.py | 5 -- .../test/3/library-tests/web/django/models.py | 10 --- .../test/3/library-tests/web/django/rawsql.py | 23 ----- .../test/3/library-tests/web/django/urls.py | 9 -- .../test/3/library-tests/web/django/views.py | 19 ---- python/ql/test/3/library-tests/web/options | 1 - .../library-tests/web/django/Sinks.expected | 28 +++--- .../library-tests/web/django/Sources.expected | 32 +++---- .../ql/test/library-tests/web/django/sql.py | 53 ++++++++++++ .../ql/test/library-tests/web/django/test.py | 86 +++---------------- .../ql/test/library-tests/web/django/views.py | 65 ++++++++++++++ .../Security/lib/django/conf/urls.py | 5 +- 25 files changed, 161 insertions(+), 264 deletions(-) delete mode 100644 python/ql/test/3/library-tests/web/django/Sinks.expected delete mode 100644 python/ql/test/3/library-tests/web/django/Sinks.ql delete mode 100644 python/ql/test/3/library-tests/web/django/Sources.expected delete mode 100644 python/ql/test/3/library-tests/web/django/Sources.ql delete mode 100644 python/ql/test/3/library-tests/web/django/Taint.expected delete mode 100644 python/ql/test/3/library-tests/web/django/Taint.ql delete mode 100644 python/ql/test/3/library-tests/web/django/django/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/conf/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/conf/urls.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/db/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/db/models/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/db/models/expressions.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/http/__init__.py delete mode 100644 python/ql/test/3/library-tests/web/django/django/http/response.py delete mode 100644 python/ql/test/3/library-tests/web/django/models.py delete mode 100644 python/ql/test/3/library-tests/web/django/rawsql.py delete mode 100644 python/ql/test/3/library-tests/web/django/urls.py delete mode 100644 python/ql/test/3/library-tests/web/django/views.py delete mode 100644 python/ql/test/3/library-tests/web/options create mode 100644 python/ql/test/library-tests/web/django/sql.py create mode 100644 python/ql/test/library-tests/web/django/views.py diff --git a/python/ql/test/3/library-tests/web/django/Sinks.expected b/python/ql/test/3/library-tests/web/django/Sinks.expected deleted file mode 100644 index b4142a2d82a0..000000000000 --- a/python/ql/test/3/library-tests/web/django/Sinks.expected +++ /dev/null @@ -1,6 +0,0 @@ -| models.py:9 | key | externally controlled string | -| rawsql.py:4 | BinaryExpr | externally controlled string | -| rawsql.py:13 | BinaryExpr | externally controlled string | -| rawsql.py:18 | BinaryExpr | externally controlled string | -| rawsql.py:22 | BinaryExpr | externally controlled string | -| views.py:8 | Attribute() | externally controlled string | diff --git a/python/ql/test/3/library-tests/web/django/Sinks.ql b/python/ql/test/3/library-tests/web/django/Sinks.ql deleted file mode 100644 index db9b6a89b937..000000000000 --- a/python/ql/test/3/library-tests/web/django/Sinks.ql +++ /dev/null @@ -1,13 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Db -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - -from TaintSink sink, TaintKind kind -where sink.sinks(kind) -select sink.getLocation().toString(), sink.(ControlFlowNode).getNode().toString(), kind.toString() diff --git a/python/ql/test/3/library-tests/web/django/Sources.expected b/python/ql/test/3/library-tests/web/django/Sources.expected deleted file mode 100644 index 965142343dcf..000000000000 --- a/python/ql/test/3/library-tests/web/django/Sources.expected +++ /dev/null @@ -1,8 +0,0 @@ -| models.py:9 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute | django.db.models.Model.objects | -| rawsql.py:16 | Attribute | django.db.models.Model.objects | -| rawsql.py:21 | Attribute | django.db.models.Model.objects | -| views.py:6 | request | django.request.HttpRequest | -| views.py:8 | HttpResponse() | django.response.HttpResponse | -| views.py:11 | path | externally controlled string | -| views.py:11 | request | django.request.HttpRequest | diff --git a/python/ql/test/3/library-tests/web/django/Sources.ql b/python/ql/test/3/library-tests/web/django/Sources.ql deleted file mode 100644 index 60d42cb2ac1b..000000000000 --- a/python/ql/test/3/library-tests/web/django/Sources.ql +++ /dev/null @@ -1,12 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - -from TaintSource src, TaintKind kind -where src.isSourceOf(kind) -select src.getLocation().toString(), src.(ControlFlowNode).getNode().toString(), kind.toString() diff --git a/python/ql/test/3/library-tests/web/django/Taint.expected b/python/ql/test/3/library-tests/web/django/Taint.expected deleted file mode 100644 index 3f40979c8a29..000000000000 --- a/python/ql/test/3/library-tests/web/django/Taint.expected +++ /dev/null @@ -1,24 +0,0 @@ -| models.py:9 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute | django.db.models.Model.objects | -| rawsql.py:13 | Attribute() | django.db.models.Model.objects | -| rawsql.py:16 | Attribute | django.db.models.Model.objects | -| rawsql.py:16 | Attribute() | django.db.models.Model.objects | -| rawsql.py:17 | Attribute() | django.db.models.Model.objects | -| rawsql.py:17 | m | django.db.models.Model.objects | -| rawsql.py:18 | Attribute() | django.db.models.Model.objects | -| rawsql.py:18 | m | django.db.models.Model.objects | -| rawsql.py:21 | Attribute | django.db.models.Model.objects | -| rawsql.py:21 | Attribute() | django.db.models.Model.objects | -| rawsql.py:22 | Attribute() | django.db.models.Model.objects | -| rawsql.py:22 | m | django.db.models.Model.objects | -| views.py:6 | request | django.request.HttpRequest | -| views.py:8 | Attribute | django.http.request.QueryDict | -| views.py:8 | Attribute() | externally controlled string | -| views.py:8 | HttpResponse() | django.response.HttpResponse | -| views.py:8 | request | django.request.HttpRequest | -| views.py:11 | path | externally controlled string | -| views.py:11 | request | django.request.HttpRequest | -| views.py:12 | Dict | {externally controlled string} | -| views.py:12 | path | externally controlled string | -| views.py:13 | env | {externally controlled string} | -| views.py:13 | request | django.request.HttpRequest | diff --git a/python/ql/test/3/library-tests/web/django/Taint.ql b/python/ql/test/3/library-tests/web/django/Taint.ql deleted file mode 100644 index b12a6560125d..000000000000 --- a/python/ql/test/3/library-tests/web/django/Taint.ql +++ /dev/null @@ -1,14 +0,0 @@ - -import python - - -import semmle.python.web.django.Request -import semmle.python.web.django.Model -import semmle.python.web.django.Response -import semmle.python.security.strings.Untrusted - - -from TaintedNode node - -select node.getLocation().toString(), node.getAstNode().toString(), node.getTaintKind().toString() - diff --git a/python/ql/test/3/library-tests/web/django/django/__init__.py b/python/ql/test/3/library-tests/web/django/django/__init__.py deleted file mode 100644 index fc8d5b8c09bc..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/conf/__init__.py b/python/ql/test/3/library-tests/web/django/django/conf/__init__.py deleted file mode 100644 index fc8d5b8c09bc..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/conf/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/conf/urls.py b/python/ql/test/3/library-tests/web/django/django/conf/urls.py deleted file mode 100644 index 580cc063d996..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/conf/urls.py +++ /dev/null @@ -1,3 +0,0 @@ - -def url(regex, view): - pass \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/db/__init__.py b/python/ql/test/3/library-tests/web/django/django/db/__init__.py deleted file mode 100644 index fc8d5b8c09bc..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/__init__.py +++ /dev/null @@ -1 +0,0 @@ -#Fake django package \ No newline at end of file diff --git a/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py b/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py deleted file mode 100644 index eb9c72adc45b..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/models/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -class Model: - pass diff --git a/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py b/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py deleted file mode 100644 index d7e0d1c27b6c..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/db/models/expressions.py +++ /dev/null @@ -1,2 +0,0 @@ -class RawSQL: - pass diff --git a/python/ql/test/3/library-tests/web/django/django/http/__init__.py b/python/ql/test/3/library-tests/web/django/django/http/__init__.py deleted file mode 100644 index e1a02f873cb1..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/http/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ - -from .response import HttpResponse diff --git a/python/ql/test/3/library-tests/web/django/django/http/response.py b/python/ql/test/3/library-tests/web/django/django/http/response.py deleted file mode 100644 index f3dd53d15b0e..000000000000 --- a/python/ql/test/3/library-tests/web/django/django/http/response.py +++ /dev/null @@ -1,5 +0,0 @@ - -class HttpResponse: - - def __init__(self, *args): - pass diff --git a/python/ql/test/3/library-tests/web/django/models.py b/python/ql/test/3/library-tests/web/django/models.py deleted file mode 100644 index 571c594d0553..000000000000 --- a/python/ql/test/3/library-tests/web/django/models.py +++ /dev/null @@ -1,10 +0,0 @@ - -from django.db import models - -class MyModel(models.Model): - title = models.CharField(max_length=500) - summary = models.TextField(blank=True) - -def update_my_model(key, title): - item = MyModel.objects.get(pk=key) - item.title = title diff --git a/python/ql/test/3/library-tests/web/django/rawsql.py b/python/ql/test/3/library-tests/web/django/rawsql.py deleted file mode 100644 index c6c82909c2d3..000000000000 --- a/python/ql/test/3/library-tests/web/django/rawsql.py +++ /dev/null @@ -1,23 +0,0 @@ -from django.db.models.expressions import RawSQL - -def raw1(arg): - return RawSQL("select foo from bar where baz = %s" % arg, "") - - -from django.db import models - -class MyModel(models.Model): - pass - -def raw2(arg): - MyModel.objects.raw("select foo from bar where baz = %s" % arg) - -def raw3(arg): - m = MyModel.objects.filter('foo') - m = m.filter('bar') - m.raw("select foo from bar where baz = %s" % arg) - -def raw4(arg): - m = MyModel.objects.filter('foo') - m.extra("select foo from bar where baz = %s" % arg) - diff --git a/python/ql/test/3/library-tests/web/django/urls.py b/python/ql/test/3/library-tests/web/django/urls.py deleted file mode 100644 index d5a941ae519d..000000000000 --- a/python/ql/test/3/library-tests/web/django/urls.py +++ /dev/null @@ -1,9 +0,0 @@ -from django.conf.urls import url -import views - -urlpatterns = [ - - url(r'^route1$', views.view_func1), - url(r'^(?P.*)$', views.view_func2), - url(r'^route2$', views.ClassView.as_view()) -] diff --git a/python/ql/test/3/library-tests/web/django/views.py b/python/ql/test/3/library-tests/web/django/views.py deleted file mode 100644 index f7de60a23f6b..000000000000 --- a/python/ql/test/3/library-tests/web/django/views.py +++ /dev/null @@ -1,19 +0,0 @@ - -from django.http import HttpResponse -from django.shortcuts import redirect, render -from django.views.generic import View - -def view_func1(request): - # Whether this is safe depends on template.html -- annoyingly - return HttpResponse(request.GET.get("untrusted")) - - -def view_func2(request, path='default'): - env = {'path': path} - return render(request, 'vulnerable-path.html', env) - - -class ClassView(View): - - def get(self, request): - pass diff --git a/python/ql/test/3/library-tests/web/options b/python/ql/test/3/library-tests/web/options deleted file mode 100644 index f2d60a4bc3c4..000000000000 --- a/python/ql/test/3/library-tests/web/options +++ /dev/null @@ -1 +0,0 @@ -semmle-extractor-options: --max-import-depth=3 --lang=3 diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 31a42364762d..86e05bca6dc6 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -1,13 +1,15 @@ -| test.py:14 | Str | externally controlled string | -| test.py:15 | Str | externally controlled string | -| test.py:18 | BinaryExpr | externally controlled string | -| test.py:21 | BinaryExpr | externally controlled string | -| test.py:22 | BinaryExpr | externally controlled string | -| test.py:23 | BinaryExpr | externally controlled string | -| test.py:37 | Str | externally controlled string | -| test.py:44 | BinaryExpr | externally controlled string | -| test.py:48 | Attribute() | externally controlled string | -| test.py:59 | Attribute() | externally controlled string | -| test.py:70 | Attribute() | externally controlled string | -| test.py:73 | Attribute() | externally controlled string | -| test.py:76 | Attribute() | externally controlled string | +| sql.py:13 | Str | externally controlled string | +| sql.py:14 | Str | externally controlled string | +| sql.py:17 | BinaryExpr | externally controlled string | +| sql.py:20 | BinaryExpr | externally controlled string | +| sql.py:21 | BinaryExpr | externally controlled string | +| sql.py:22 | BinaryExpr | externally controlled string | +| sql.py:36 | Str | externally controlled string | +| sql.py:42 | BinaryExpr | externally controlled string | +| sql.py:47 | BinaryExpr | externally controlled string | +| views.py:7 | Attribute() | externally controlled string | +| views.py:11 | Attribute() | externally controlled string | +| views.py:15 | Attribute() | externally controlled string | +| views.py:22 | Attribute() | externally controlled string | +| views.py:27 | Attribute() | externally controlled string | +| views.py:31 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index 371b1e7cb6f1..a0c253b27c54 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -1,17 +1,17 @@ +| test.py:5 | path | externally controlled string | +| test.py:5 | request | django.request.HttpRequest | +| test.py:11 | path | externally controlled string | | test.py:11 | request | django.request.HttpRequest | -| test.py:11 | username | externally controlled string | -| test.py:41 | request | django.request.HttpRequest | -| test.py:47 | bar | externally controlled string | -| test.py:47 | foo | externally controlled string | -| test.py:47 | request | django.request.HttpRequest | -| test.py:58 | page_number | externally controlled string | -| test.py:58 | request | django.request.HttpRequest | -| test.py:69 | arg0 | externally controlled string | -| test.py:69 | request | django.request.HttpRequest | -| test.py:72 | arg0 | externally controlled string | -| test.py:72 | arg1 | externally controlled string | -| test.py:72 | arg2 | externally controlled string | -| test.py:72 | request | django.request.HttpRequest | -| test.py:75 | arg0 | externally controlled string | -| test.py:75 | arg1 | externally controlled string | -| test.py:75 | request | django.request.HttpRequest | +| views.py:6 | bar | externally controlled string | +| views.py:6 | foo | externally controlled string | +| views.py:6 | request | django.request.HttpRequest | +| views.py:10 | request | django.request.HttpRequest | +| views.py:14 | request | django.request.HttpRequest | +| views.py:25 | page_number | externally controlled string | +| views.py:25 | request | django.request.HttpRequest | +| views.py:30 | arg0 | externally controlled string | +| views.py:30 | arg1 | externally controlled string | +| views.py:30 | request | django.request.HttpRequest | +| views.py:50 | request | django.request.HttpRequest | +| views.py:50 | username | externally controlled string | +| views.py:59 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/sql.py b/python/ql/test/library-tests/web/django/sql.py new file mode 100644 index 000000000000..7809c24edc16 --- /dev/null +++ b/python/ql/test/library-tests/web/django/sql.py @@ -0,0 +1,53 @@ +from django.db import connection, models +from django.db.models.expressions import RawSQL + + +class User(models.Model): + username = models.CharField(max_length=100) + description = models.TextField(blank=True) + + +def show_user(username): + with connection.cursor() as cursor: + # GOOD -- Using parameters + cursor.execute("SELECT * FROM users WHERE username = %s", username) + User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) + + # BAD -- Using string formatting + cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) + + # BAD -- other ways of executing raw SQL code with string interpolation + User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) + User.objects.raw("insert into names_file ('name') values ('%s')" % username) + User.objects.extra("insert into names_file ('name') values ('%s')" % username) + + # BAD (but currently no custom query to find this) + # + # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) + # For example, using name = "; DROP ALL TABLES -- " + # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' + # + # This shouldn't be very widespread, since using a normal string will result in invalid SQL + # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' + # which in MySQL will give a syntax error + # + # When testing this out locally, none of the queries worked against SQLite3, but I could use + # the SQL injection against MySQL. + User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) + + +def raw3(arg): + m = User.objects.filter('foo') + m = m.filter('bar') + m.raw("select foo from bar where baz = %s" % arg) + + +def raw4(arg): + m = User.objects.filter('foo') + m.extra("select foo from bar where baz = %s" % arg) + + +def update_user(key, description1): + # Neither of these are exposed to sql-injections + user = User.objects.get(pk=key) + item.description = description diff --git a/python/ql/test/library-tests/web/django/test.py b/python/ql/test/library-tests/web/django/test.py index 1240b9ae5a1b..5664647c3a78 100644 --- a/python/ql/test/library-tests/web/django/test.py +++ b/python/ql/test/library-tests/web/django/test.py @@ -1,84 +1,18 @@ +from django.conf.urls import url +from django.shortcuts import redirect, render -from django.conf.urls import patterns, url -from django.db import connection, models -from django.db.models.expressions import RawSQL -from django.http.response import HttpResponse -import base64 -class User(models.Model): - pass +def with_template(request, path='default'): + env = {'path': path} + # We would need to understand django templates to know if this is safe or not + return render(request, 'possibly-vulnerable-template.html', env) -def show_user(request, username): - with connection.cursor() as cursor: - # GOOD -- Using parameters - cursor.execute("SELECT * FROM users WHERE username = %s", username) - User.objects.raw("SELECT * FROM users WHERE username = %s", (username,)) - # BAD -- Using string formatting - cursor.execute("SELECT * FROM users WHERE username = '%s'" % username) +def vuln_redirect(request, path): + return redirect(path) - # BAD -- other ways of executing raw SQL code with string interpolation - User.objects.annotate(RawSQL("insert into names_file ('name') values ('%s')" % username)) - User.objects.raw("insert into names_file ('name') values ('%s')" % username) - User.objects.extra("insert into names_file ('name') values ('%s')" % username) - - # BAD (but currently no custom query to find this) - # - # It is exposed to SQL injection (https://docs.djangoproject.com/en/2.2/ref/models/querysets/#extra) - # For example, using name = "; DROP ALL TABLES -- " - # will result in SQL: SELECT * FROM name WHERE name = ''; DROP ALL TABLES -- '' - # - # This shouldn't be very widespread, since using a normal string will result in invalid SQL - # Using name = "example", will result in SQL: SELECT * FROM name WHERE name = ''example'' - # which in MySQL will give a syntax error - # - # When testing this out locally, none of the queries worked against SQLite3, but I could use - # the SQL injection against MySQL. - User.objects.raw("SELECT * FROM users WHERE username = '%s'", (username,)) - -urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) - -def maybe_xss(request): - first_name = request.POST.get('first_name', '') - resp = HttpResponse() - resp.write("first name is " + first_name) - return resp - -def xss_kwargs(request, foo, bar, baz=None): - return HttpResponse('xss_kwargs: {} {}'.format(foo, bar)) - -urlpatterns = [ - url(r'^maybe_xss$', maybe_xss, name='maybe_xss'), - url(r'^bar/(?P[^/]+)/foo/(?P[^/]+)', xss_kwargs, name='xss_kwargs'), -] - - -# Non capturing group (we correctly identify page_number as a request parameter) - -def show_articles(request, page_number=1): - return HttpResponse('articles page: {}'.format(page_number)) - -urlpatterns = [ - # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 - url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), -] - - -# Positional arguments - -def xxs_positional_arg1(request, arg0): - return HttpResponse('xxs_positional_arg1: {}'.format(arg0)) - -def xxs_positional_arg2(request, arg0, arg1, arg2): - return HttpResponse('xxs_positional_arg2: {} {} {}'.format(arg0, arg1, arg2)) - -def xxs_positional_arg3(request, arg0, arg1): - return HttpResponse('xxs_positional_arg3: {} {}'.format(arg0, arg1)) urlpatterns = [ - # passing as positional argument is not the recommended way of doing things, - # but it is certainly possible - url(r'^(.+)$', xxs_positional_arg1, name='xxs_positional_arg1'), - url(r'^([^/]+)/([^/]+)/([^/]+)$', xxs_positional_arg2, name='xxs_positional_arg2'), - url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg3, name='xxs_positional_arg3'), + url(r'^(?P.*)$', with_template), + url(r'^redirect/(?P.*)$', vuln_redirect), ] diff --git a/python/ql/test/library-tests/web/django/views.py b/python/ql/test/library-tests/web/django/views.py new file mode 100644 index 000000000000..ffa491187853 --- /dev/null +++ b/python/ql/test/library-tests/web/django/views.py @@ -0,0 +1,65 @@ +from django.conf.urls import patterns, url +from django.http.response import HttpResponse +from django.views.generic import View + + +def url_match_xss(request, foo, bar, no_taint=None): + return HttpResponse('url_match_xss: {} {}'.format(foo, bar)) + + +def get_params_xss(request): + return HttpResponse(request.GET.get("untrusted")) + + +def post_params_xss(request): + return HttpResponse(request.POST.get("untrusted")) + + +class ClassView(View): + + # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter + def get(self, request, untrusted): + return HttpResponse('ClassView: {}'.format(untrusted)) + + +def show_articles(request, page_number=1): + page_number = int(page_number) + return HttpResponse('articles page: {}'.format(page_number)) + + +def xxs_positional_arg(request, arg0, arg1, no_taint=None): + return HttpResponse('xxs_positional_arg: {} {}'.format(arg0, arg1)) + + +urlpatterns = [ + url(r'^url_match/(?P[^/]+)/(?P[^/]+)$', url_match_xss), + url(r'^get_params$', get_params_xss), + url(r'^post_params$', post_params_xss), + url(r'^class_view/(?P.+)$', ClassView.as_view()), + + # one pattern to support `articles/page-` and ensuring that articles/ goes to page-1 + url(r'articles/^(?:page-(?P\d+)/)?$', show_articles), + # passing as positional argument is not the recommended way of doing things, but it is certainly + # possible + url(r'^([^/]+)/(?:foo|bar)/([^/]+)$', xxs_positional_arg, name='xxs_positional_arg'), +] + + +# Using patterns() for routing + +def show_user(request, username): + pass + + +urlpatterns = patterns(url(r'^users/(?P[^/]+)$', show_user)) + + +# Show we understand the keyword arguments to django.conf.urls.url + +def we_understand_url_kwargs(request): + pass + + +urlpatterns = [ + url(view=we_understand_url_kwargs, regex=r'^specifying-as-kwargs-is-not-a-problem$') +] diff --git a/python/ql/test/query-tests/Security/lib/django/conf/urls.py b/python/ql/test/query-tests/Security/lib/django/conf/urls.py index cf65525e893c..6c1a83baf0b5 100644 --- a/python/ql/test/query-tests/Security/lib/django/conf/urls.py +++ b/python/ql/test/query-tests/Security/lib/django/conf/urls.py @@ -1,7 +1,6 @@ - -def url(pattern, *args): +# https://docs.djangoproject.com/en/1.11/_modules/django/conf/urls/#url +def url(regex, view, kwargs=None, name=None): pass def patterns(*urls): pass - From fc851b46c3d41cda88ecfecd8c35821d96ac7222 Mon Sep 17 00:00:00 2001 From: Rasmus Wriedt Larsen Date: Mon, 21 Oct 2019 16:44:35 +0200 Subject: [PATCH 0118/2538] Python: Fix Django class-based views --- .../src/semmle/python/web/django/Request.qll | 2 +- .../library-tests/web/django/Sinks.expected | 7 ++++--- .../library-tests/web/django/Sources.expected | 18 ++++++++++-------- .../ql/test/library-tests/web/django/views.py | 11 +++++++++-- .../Security/lib/django/views/__init__.py | 0 .../Security/lib/django/views/generic.py | 2 ++ 6 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 python/ql/test/query-tests/Security/lib/django/views/__init__.py create mode 100644 python/ql/test/query-tests/Security/lib/django/views/generic.py diff --git a/python/ql/src/semmle/python/web/django/Request.qll b/python/ql/src/semmle/python/web/django/Request.qll index 15ea032e6d72..24a29ea45425 100644 --- a/python/ql/src/semmle/python/web/django/Request.qll +++ b/python/ql/src/semmle/python/web/django/Request.qll @@ -67,7 +67,7 @@ private class DjangoView extends ClassValue { } private FunctionValue djangoViewHttpMethod() { - exists(DjangoView view | view.attr(httpVerbLower()) = result) + exists(DjangoView view | view.lookup(httpVerbLower()) = result) } class DjangoClassBasedViewRequestArgument extends DjangoRequestSource { diff --git a/python/ql/test/library-tests/web/django/Sinks.expected b/python/ql/test/library-tests/web/django/Sinks.expected index 86e05bca6dc6..e3d233c99901 100644 --- a/python/ql/test/library-tests/web/django/Sinks.expected +++ b/python/ql/test/library-tests/web/django/Sinks.expected @@ -10,6 +10,7 @@ | views.py:7 | Attribute() | externally controlled string | | views.py:11 | Attribute() | externally controlled string | | views.py:15 | Attribute() | externally controlled string | -| views.py:22 | Attribute() | externally controlled string | -| views.py:27 | Attribute() | externally controlled string | -| views.py:31 | Attribute() | externally controlled string | +| views.py:23 | Attribute() | externally controlled string | +| views.py:29 | Attribute() | externally controlled string | +| views.py:34 | Attribute() | externally controlled string | +| views.py:38 | Attribute() | externally controlled string | diff --git a/python/ql/test/library-tests/web/django/Sources.expected b/python/ql/test/library-tests/web/django/Sources.expected index a0c253b27c54..35e0d3d8cede 100644 --- a/python/ql/test/library-tests/web/django/Sources.expected +++ b/python/ql/test/library-tests/web/django/Sources.expected @@ -7,11 +7,13 @@ | views.py:6 | request | django.request.HttpRequest | | views.py:10 | request | django.request.HttpRequest | | views.py:14 | request | django.request.HttpRequest | -| views.py:25 | page_number | externally controlled string | -| views.py:25 | request | django.request.HttpRequest | -| views.py:30 | arg0 | externally controlled string | -| views.py:30 | arg1 | externally controlled string | -| views.py:30 | request | django.request.HttpRequest | -| views.py:50 | request | django.request.HttpRequest | -| views.py:50 | username | externally controlled string | -| views.py:59 | request | django.request.HttpRequest | +| views.py:22 | request | django.request.HttpRequest | +| views.py:28 | request | django.request.HttpRequest | +| views.py:32 | page_number | externally controlled string | +| views.py:32 | request | django.request.HttpRequest | +| views.py:37 | arg0 | externally controlled string | +| views.py:37 | arg1 | externally controlled string | +| views.py:37 | request | django.request.HttpRequest | +| views.py:57 | request | django.request.HttpRequest | +| views.py:57 | username | externally controlled string | +| views.py:66 | request | django.request.HttpRequest | diff --git a/python/ql/test/library-tests/web/django/views.py b/python/ql/test/library-tests/web/django/views.py index ffa491187853..57d1ea5460c9 100644 --- a/python/ql/test/library-tests/web/django/views.py +++ b/python/ql/test/library-tests/web/django/views.py @@ -15,11 +15,18 @@ def post_params_xss(request): return HttpResponse(request.POST.get("untrusted")) -class ClassView(View): +class Foo(object): + # Note: since Foo is used as the super type in a class view, it will be able to handle requests. + # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter + def post(self, request, untrusted): + return HttpResponse('Foo post: {}'.format(untrusted)) + + +class ClassView(View, Foo): # TODO: Currently we don't flag `untrusted` as a DjangoRequestParameter def get(self, request, untrusted): - return HttpResponse('ClassView: {}'.format(untrusted)) + return HttpResponse('ClassView get: {}'.format(untrusted)) def show_articles(request, page_number=1): diff --git a/python/ql/test/query-tests/Security/lib/django/views/__init__.py b/python/ql/test/query-tests/Security/lib/django/views/__init__.py new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/python/ql/test/query-tests/Security/lib/django/views/generic.py b/python/ql/test/query-tests/Security/lib/django/views/generic.py new file mode 100644 index 000000000000..d924b03d062a --- /dev/null +++ b/python/ql/test/query-tests/Security/lib/django/views/generic.py @@ -0,0 +1,2 @@ +class View: + pass From 924d23f657fedab6cb16d3d8c9fba071014953a9 Mon Sep 17 00:00:00 2001 From: alexet Date: Fri, 25 Oct 2019 14:31:32 +0100 Subject: [PATCH 0119/2538] Cache the computation of core toString predicates. --- cpp/ql/src/semmle/code/cpp/Element.qll | 1 + csharp/ql/src/semmle/code/dotnet/Element.qll | 1 + java/ql/src/semmle/code/Location.qll | 1 + 3 files changed, 3 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Element.qll b/cpp/ql/src/semmle/code/cpp/Element.qll index 7d7f95272d99..2b2361474845 100644 --- a/cpp/ql/src/semmle/code/cpp/Element.qll +++ b/cpp/ql/src/semmle/code/cpp/Element.qll @@ -47,6 +47,7 @@ pragma[inline] */ class ElementBase extends @element { /** Gets a textual representation of this element. */ + cached string toString() { none() } /** diff --git a/csharp/ql/src/semmle/code/dotnet/Element.qll b/csharp/ql/src/semmle/code/dotnet/Element.qll index c06e78551139..9d8b35023aad 100644 --- a/csharp/ql/src/semmle/code/dotnet/Element.qll +++ b/csharp/ql/src/semmle/code/dotnet/Element.qll @@ -10,6 +10,7 @@ import semmle.code.csharp.Location */ class Element extends @dotnet_element { /** Gets a textual representation of this element. */ + cached string toString() { none() } /** Gets the location of this element. */ diff --git a/java/ql/src/semmle/code/Location.qll b/java/ql/src/semmle/code/Location.qll index 92b92fc69edb..a34bba9ddc7c 100755 --- a/java/ql/src/semmle/code/Location.qll +++ b/java/ql/src/semmle/code/Location.qll @@ -84,6 +84,7 @@ class Top extends @top { int getNumberOfCommentLines() { numlines(this, _, _, result) } /** Gets a textual representation of this element. */ + cached string toString() { hasName(this, result) } } From 84202ff2e135ceaabfef72cdbaffd6fc0b887e5b Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 24 Oct 2019 16:15:50 +0100 Subject: [PATCH 0120/2538] Java: Respect Hamcrest assertThat(X, notNullValue()) --- .../semmle/code/java/dataflow/Nullness.qll | 7 ++++- .../code/java/frameworks/Assertions.qll | 18 +++++++++++- java/ql/test/query-tests/Nullness/A.java | 8 ++++++ .../query-tests/Nullness/NullAlways.expected | 28 +++++++++---------- .../query-tests/Nullness/NullMaybe.expected | 12 ++++---- java/ql/test/query-tests/Nullness/options | 2 +- java/ql/test/stubs/hamcrest-2.2/LICENSE.txt | 27 ++++++++++++++++++ .../org/hamcrest/MatcherAssert.java | 14 ++++++++++ .../org/hamcrest/core/IsNull.java | 13 +++++++++ 9 files changed, 106 insertions(+), 23 deletions(-) create mode 100644 java/ql/test/stubs/hamcrest-2.2/LICENSE.txt create mode 100644 java/ql/test/stubs/hamcrest-2.2/org/hamcrest/MatcherAssert.java create mode 100644 java/ql/test/stubs/hamcrest-2.2/org/hamcrest/core/IsNull.java diff --git a/java/ql/src/semmle/code/java/dataflow/Nullness.qll b/java/ql/src/semmle/code/java/dataflow/Nullness.qll index 8dbac1520ba0..af8e323521c8 100644 --- a/java/ql/src/semmle/code/java/dataflow/Nullness.qll +++ b/java/ql/src/semmle/code/java/dataflow/Nullness.qll @@ -147,7 +147,12 @@ private ControlFlowNode ensureNotNull(SsaVariable v) { result.(AssertStmt).getExpr() = nullGuard(v, true, false) or exists(AssertTrueMethod m | result = m.getACheck(nullGuard(v, true, false))) or exists(AssertFalseMethod m | result = m.getACheck(nullGuard(v, false, false))) or - exists(AssertNotNullMethod m | result = m.getACheck(v.getAUse())) + exists(AssertNotNullMethod m | result = m.getACheck(v.getAUse())) or + exists(AssertThatMethod m, MethodAccess ma | + result = m.getACheck(v.getAUse()) and ma.getControlFlowNode() = result + | + ma.getAnArgument().(MethodAccess).getMethod().getName() = "notNullValue" + ) } /** diff --git a/java/ql/src/semmle/code/java/frameworks/Assertions.qll b/java/ql/src/semmle/code/java/frameworks/Assertions.qll index e2276ccb3b34..aac514a26bd4 100644 --- a/java/ql/src/semmle/code/java/frameworks/Assertions.qll +++ b/java/ql/src/semmle/code/java/frameworks/Assertions.qll @@ -11,7 +11,8 @@ newtype AssertKind = AssertKindTrue() or AssertKindFalse() or AssertKindNotNull() or - AssertKindFail() + AssertKindFail() or + AssertKindThat() private predicate assertionMethod(Method m, AssertKind kind) { exists(RefType junit | @@ -27,6 +28,13 @@ private predicate assertionMethod(Method m, AssertKind kind) { m.hasName("fail") and kind = AssertKindFail() ) or + exists(RefType hamcrest | + m.getDeclaringType() = hamcrest and + hamcrest.hasQualifiedName("org.hamcrest", "MatcherAssert") // TODO: Check some older versions of hamcrest + | + m.hasName("assertThat") and kind = AssertKindThat() + ) + or exists(RefType objects | m.getDeclaringType() = objects and objects.hasQualifiedName("java.util", "Objects") @@ -82,6 +90,14 @@ class AssertFailMethod extends AssertionMethod { AssertFailMethod() { assertionMethod(this, AssertKindFail()) } } +/** + * A method that asserts that its first argument has a property + * given by its second argument. + */ +class AssertThatMethod extends AssertionMethod { + AssertThatMethod() { assertionMethod(this, AssertKindThat()) } +} + /** A trivially failing assertion. That is, `assert false` or its equivalents. */ predicate assertFail(BasicBlock bb, ControlFlowNode n) { bb = n.getBasicBlock() and diff --git a/java/ql/test/query-tests/Nullness/A.java b/java/ql/test/query-tests/Nullness/A.java index 0dcb5304b77a..2a3f36da4b1e 100644 --- a/java/ql/test/query-tests/Nullness/A.java +++ b/java/ql/test/query-tests/Nullness/A.java @@ -1,6 +1,8 @@ import java.util.Iterator; import java.util.List; import static org.junit.Assert.*; +import static org.hamcrest.core.IsNull.*; +import static org.hamcrest.MatcherAssert.*; public class A { public void notTest() { @@ -296,6 +298,12 @@ public void testForLoopCondition(Iterable iter) { for (it = iter.iterator(); !!it.hasNext(); ) {} } + public void assertThatTest() { + Object assertThat_ok1 = maybe() ? null : new Object(); + assertThat(assertThat_ok1, notNullValue()); + assertThat_ok1.toString(); + } + private boolean m; A(boolean m) { this.m = m; diff --git a/java/ql/test/query-tests/Nullness/NullAlways.expected b/java/ql/test/query-tests/Nullness/NullAlways.expected index 31feb5ad4470..2344f849ab3f 100644 --- a/java/ql/test/query-tests/Nullness/NullAlways.expected +++ b/java/ql/test/query-tests/Nullness/NullAlways.expected @@ -1,15 +1,15 @@ -| A.java:13:7:13:9 | not | Variable $@ is always null here. | A.java:11:5:11:22 | Object not | not | -| A.java:95:18:95:36 | synchronized_always | Variable $@ is always null here. | A.java:94:5:94:38 | Object synchronized_always | synchronized_always | -| A.java:159:26:159:34 | do_always | Variable $@ is always null here. | A.java:157:5:157:28 | String do_always | do_always | -| A.java:165:26:165:34 | do_maybe1 | Variable $@ is always null here. | A.java:163:5:163:28 | String do_maybe1 | do_maybe1 | -| A.java:185:26:185:37 | while_always | Variable $@ is always null here. | A.java:183:5:183:31 | String while_always | while_always | -| A.java:205:26:205:34 | if_always | Variable $@ is always null here. | A.java:203:5:203:28 | String if_always | if_always | -| A.java:221:24:221:29 | for_ok | Variable $@ is always null here. | A.java:217:5:217:19 | String for_ok | for_ok | -| A.java:224:26:224:35 | for_always | Variable $@ is always null here. | A.java:223:10:223:33 | String for_always | for_always | -| A.java:234:5:234:14 | array_null | Variable $@ is always null here. | A.java:233:5:233:28 | int[] array_null | array_null | -| A.java:246:24:246:34 | arrayaccess | Variable $@ is always null here. | A.java:242:5:242:29 | int[] arrayaccess | arrayaccess | -| A.java:247:24:247:34 | fieldaccess | Variable $@ is always null here. | A.java:243:5:243:32 | String[] fieldaccess | fieldaccess | -| A.java:248:24:248:35 | methodaccess | Variable $@ is always null here. | A.java:244:5:244:31 | Object methodaccess | methodaccess | -| A.java:262:21:262:30 | for_always | Variable $@ is always null here. | A.java:261:5:261:35 | List for_always | for_always | -| A.java:264:24:264:33 | for_always | Variable $@ is always null here. | A.java:261:5:261:35 | List for_always | for_always | +| A.java:15:7:15:9 | not | Variable $@ is always null here. | A.java:13:5:13:22 | Object not | not | +| A.java:97:18:97:36 | synchronized_always | Variable $@ is always null here. | A.java:96:5:96:38 | Object synchronized_always | synchronized_always | +| A.java:161:26:161:34 | do_always | Variable $@ is always null here. | A.java:159:5:159:28 | String do_always | do_always | +| A.java:167:26:167:34 | do_maybe1 | Variable $@ is always null here. | A.java:165:5:165:28 | String do_maybe1 | do_maybe1 | +| A.java:187:26:187:37 | while_always | Variable $@ is always null here. | A.java:185:5:185:31 | String while_always | while_always | +| A.java:207:26:207:34 | if_always | Variable $@ is always null here. | A.java:205:5:205:28 | String if_always | if_always | +| A.java:223:24:223:29 | for_ok | Variable $@ is always null here. | A.java:219:5:219:19 | String for_ok | for_ok | +| A.java:226:26:226:35 | for_always | Variable $@ is always null here. | A.java:225:10:225:33 | String for_always | for_always | +| A.java:236:5:236:14 | array_null | Variable $@ is always null here. | A.java:235:5:235:28 | int[] array_null | array_null | +| A.java:248:24:248:34 | arrayaccess | Variable $@ is always null here. | A.java:244:5:244:29 | int[] arrayaccess | arrayaccess | +| A.java:249:24:249:34 | fieldaccess | Variable $@ is always null here. | A.java:245:5:245:32 | String[] fieldaccess | fieldaccess | +| A.java:250:24:250:35 | methodaccess | Variable $@ is always null here. | A.java:246:5:246:31 | Object methodaccess | methodaccess | +| A.java:264:21:264:30 | for_always | Variable $@ is always null here. | A.java:263:5:263:35 | List for_always | for_always | +| A.java:266:24:266:33 | for_always | Variable $@ is always null here. | A.java:263:5:263:35 | List for_always | for_always | | B.java:304:7:304:9 | ioe | Variable $@ is always null here. | B.java:297:5:297:25 | Exception ioe | ioe | diff --git a/java/ql/test/query-tests/Nullness/NullMaybe.expected b/java/ql/test/query-tests/Nullness/NullMaybe.expected index 4a21a3f2f667..5d50a47b9d80 100644 --- a/java/ql/test/query-tests/Nullness/NullMaybe.expected +++ b/java/ql/test/query-tests/Nullness/NullMaybe.expected @@ -1,9 +1,9 @@ -| A.java:46:5:46:21 | assertNotNull_ok3 | Variable $@ may be null here because of $@ assignment. | A.java:44:5:44:61 | Object assertNotNull_ok3 | assertNotNull_ok3 | A.java:44:12:44:60 | assertNotNull_ok3 | this | -| A.java:170:26:170:33 | do_maybe | Variable $@ may be null here because of $@ assignment. | A.java:168:5:168:25 | String do_maybe | do_maybe | A.java:171:7:171:21 | ...=... | this | -| A.java:191:26:191:36 | while_maybe | Variable $@ may be null here because of $@ assignment. | A.java:189:5:189:28 | String while_maybe | while_maybe | A.java:192:7:192:24 | ...=... | this | -| A.java:213:24:213:31 | if_maybe | Variable $@ may be null here because of $@ assignment. | A.java:209:5:209:25 | String if_maybe | if_maybe | A.java:211:7:211:21 | ...=... | this | -| A.java:228:26:228:34 | for_maybe | Variable $@ may be null here because of $@ assignment. | A.java:227:10:227:30 | String for_maybe | for_maybe | A.java:227:35:227:50 | ...=... | this | -| A.java:271:24:271:32 | for_maybe | Variable $@ may be null here because of $@ assignment. | A.java:266:5:266:63 | List for_maybe | for_maybe | A.java:269:7:269:22 | ...=... | this | +| A.java:48:5:48:21 | assertNotNull_ok3 | Variable $@ may be null here because of $@ assignment. | A.java:46:5:46:61 | Object assertNotNull_ok3 | assertNotNull_ok3 | A.java:46:12:46:60 | assertNotNull_ok3 | this | +| A.java:172:26:172:33 | do_maybe | Variable $@ may be null here because of $@ assignment. | A.java:170:5:170:25 | String do_maybe | do_maybe | A.java:173:7:173:21 | ...=... | this | +| A.java:193:26:193:36 | while_maybe | Variable $@ may be null here because of $@ assignment. | A.java:191:5:191:28 | String while_maybe | while_maybe | A.java:194:7:194:24 | ...=... | this | +| A.java:215:24:215:31 | if_maybe | Variable $@ may be null here because of $@ assignment. | A.java:211:5:211:25 | String if_maybe | if_maybe | A.java:213:7:213:21 | ...=... | this | +| A.java:230:26:230:34 | for_maybe | Variable $@ may be null here because of $@ assignment. | A.java:229:10:229:30 | String for_maybe | for_maybe | A.java:229:35:229:50 | ...=... | this | +| A.java:273:24:273:32 | for_maybe | Variable $@ may be null here because of $@ assignment. | A.java:268:5:268:63 | List for_maybe | for_maybe | A.java:271:7:271:22 | ...=... | this | | B.java:16:5:16:9 | param | Variable $@ may be null here because of $@ null argument. | B.java:15:23:15:34 | param | param | B.java:11:13:11:16 | null | this | | B.java:23:5:23:9 | param | Variable $@ may be null here as suggested by $@ null guard. | B.java:19:23:19:34 | param | param | B.java:20:9:20:21 | ... != ... | this | | B.java:57:7:57:8 | o7 | Variable $@ may be null here because of $@ assignment. | B.java:52:5:52:34 | Object o7 | o7 | B.java:52:12:52:33 | o7 | this | diff --git a/java/ql/test/query-tests/Nullness/options b/java/ql/test/query-tests/Nullness/options index e33d1dca688a..b996e88e0b0f 100644 --- a/java/ql/test/query-tests/Nullness/options +++ b/java/ql/test/query-tests/Nullness/options @@ -1 +1 @@ -//semmle-extractor-options: --javac-args -cp ${testdir}/../../stubs/junit-4.11:${testdir}/../../stubs/junit-jupiter-api-5.2.0 +//semmle-extractor-options: --javac-args -cp ${testdir}/../../stubs/junit-4.11:${testdir}/../../stubs/hamcrest-2.2:${testdir}/../../stubs/junit-jupiter-api-5.2.0 diff --git a/java/ql/test/stubs/hamcrest-2.2/LICENSE.txt b/java/ql/test/stubs/hamcrest-2.2/LICENSE.txt new file mode 100644 index 000000000000..4933bda5bac2 --- /dev/null +++ b/java/ql/test/stubs/hamcrest-2.2/LICENSE.txt @@ -0,0 +1,27 @@ +BSD License + +Copyright (c) 2000-2015 www.hamcrest.org +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +Redistributions of source code must retain the above copyright notice, this list of +conditions and the following disclaimer. Redistributions in binary form must reproduce +the above copyright notice, this list of conditions and the following disclaimer in +the documentation and/or other materials provided with the distribution. + +Neither the name of Hamcrest nor the names of its contributors may be used to endorse +or promote products derived from this software without specific prior written +permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED +TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY +WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. diff --git a/java/ql/test/stubs/hamcrest-2.2/org/hamcrest/MatcherAssert.java b/java/ql/test/stubs/hamcrest-2.2/org/hamcrest/MatcherAssert.java new file mode 100644 index 000000000000..b6deec029c67 --- /dev/null +++ b/java/ql/test/stubs/hamcrest-2.2/org/hamcrest/MatcherAssert.java @@ -0,0 +1,14 @@ +package org.hamcrest; + + +public class MatcherAssert { + public static void assertThat(T actual, Object matcher) { + assertThat("", actual, matcher); + } + + public static void assertThat(String reason, T actual, Object matcher) { + } + + public static void assertThat(String reason, boolean assertion) { + } +} diff --git a/java/ql/test/stubs/hamcrest-2.2/org/hamcrest/core/IsNull.java b/java/ql/test/stubs/hamcrest-2.2/org/hamcrest/core/IsNull.java new file mode 100644 index 000000000000..3bb6a3457349 --- /dev/null +++ b/java/ql/test/stubs/hamcrest-2.2/org/hamcrest/core/IsNull.java @@ -0,0 +1,13 @@ +package org.hamcrest.core; + +public class IsNull { + + public static Object notNullValue() { + return new String(); + } + + public static Object notNullValue(Class type) { + return new String(); + } +} + From 96f9a01355ec42d066599f8863d919c2e91168f9 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Fri, 25 Oct 2019 14:58:52 +0100 Subject: [PATCH 0121/2538] Correct minor compilation errors in test code --- java/ql/test/query-tests/Nullness/B.java | 6 +++--- java/ql/test/query-tests/Nullness/C.java | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/test/query-tests/Nullness/B.java b/java/ql/test/query-tests/Nullness/B.java index 6605a9c84e31..c0d9171041bd 100644 --- a/java/ql/test/query-tests/Nullness/B.java +++ b/java/ql/test/query-tests/Nullness/B.java @@ -120,7 +120,7 @@ public void missedGuard(Object obj) { } private Object mkMaybe() { - if (maybe) throw new Exception(); + if (maybe) throw new RuntimeException(); return new Object(); } @@ -267,7 +267,7 @@ else if(obj.hashCode() > 7) { // OK } if(msg != null) { msg += "foobar"; - throw new Exception(msg); + throw new RuntimeException(msg); } obj.hashCode(); // OK } @@ -286,7 +286,7 @@ public void loopCorr(int iters) { int[] b = maybe ? null : new int[iters]; if (iters > 0 && (b == null || b.length < iters)) { - throw new Exception(); + throw new RuntimeException(); } for (int i = 0; i < iters; ++i) { b[i] = 0; // NPE - false positive diff --git a/java/ql/test/query-tests/Nullness/C.java b/java/ql/test/query-tests/Nullness/C.java index 10c9a21c6856..1eaad10e6b1c 100644 --- a/java/ql/test/query-tests/Nullness/C.java +++ b/java/ql/test/query-tests/Nullness/C.java @@ -87,7 +87,7 @@ public void ex6(int[] vals, boolean b1, boolean b2) { vals[0] = 0; // OK break; default: - throw new Exception(); + throw new RuntimeException(); } } From 63f24476e96771b0d557d3b7c2c01c547068d511 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 08:29:10 +0000 Subject: [PATCH 0122/2538] JavaScript: Refactor `DoubleEscaping.ql`. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 60 ++++++++++++------- 1 file changed, 40 insertions(+), 20 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index a150a2d7a7a7..124dcf304aa8 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -62,30 +62,23 @@ predicate escapingScheme(string metachar, string regex) { } /** - * A call to `String.prototype.replace` that replaces all instances of a pattern. + * A method call that performs string replacement. */ -class Replacement extends DataFlow::Node { - RegExpLiteral pattern; +abstract class Replacement extends DataFlow::Node { + /** + * Holds if this replacement replaces the string `input` with `output`. + */ + abstract predicate replaces(string input, string output); - Replacement() { - exists(DataFlow::MethodCallNode mcn | this = mcn | - mcn.getMethodName() = "replace" and - pattern.flow().(DataFlow::SourceNode).flowsTo(mcn.getArgument(0)) and - mcn.getNumArgument() = 2 and - pattern.isGlobal() - ) - } + /** + * Gets the input of this replacement. + */ + abstract DataFlow::Node getInput(); /** - * Holds if this replacement replaces the string `input` with `output`. + * Gets the output of this replacement. */ - predicate replaces(string input, string output) { - exists(DataFlow::MethodCallNode mcn | - mcn = this and - input = getStringValue(pattern) and - output = mcn.getArgument(1).getStringValue() - ) - } + abstract DataFlow::SourceNode getOutput(); /** * Holds if this replacement escapes `char` using `metachar`. @@ -119,7 +112,7 @@ class Replacement extends DataFlow::Node { * Gets the previous replacement in this chain of replacements. */ Replacement getPreviousReplacement() { - result = getASimplePredecessor*(this.(DataFlow::MethodCallNode).getReceiver()) + result.getOutput() = getASimplePredecessor*(getInput()) } /** @@ -147,6 +140,33 @@ class Replacement extends DataFlow::Node { } } +/** + * A call to `String.prototype.replace` that replaces all instances of a pattern. + */ +class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { + RegExpLiteral pattern; + + GlobalStringReplacement() { + this.getMethodName() = "replace" and + pattern.flow().(DataFlow::SourceNode).flowsTo(this.getArgument(0)) and + this.getNumArgument() = 2 and + pattern.isGlobal() + } + + override predicate replaces(string input, string output) { + input = getStringValue(pattern) and + output = this.getArgument(1).getStringValue() + } + + override DataFlow::Node getInput() { + result = this.getReceiver() + } + + override DataFlow::SourceNode getOutput() { + result = this + } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and From bd1c99d8a428770a12c90450ce3518854427b352 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 09:35:49 +0000 Subject: [PATCH 0123/2538] JavaScript: Recognise `JSON.stringify` and `JSON.parse` as escaper/unescaper. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 46 +++++++++++++++++++ .../DoubleEscaping/DoubleEscaping.expected | 2 + .../Security/CWE-116/DoubleEscaping/tst.js | 20 ++++++++ 3 files changed, 68 insertions(+) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 124dcf304aa8..589a935d5fec 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -167,6 +167,52 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { } } +/** + * A call to `JSON.stringify`, viewed as a string replacement. + */ +class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { + JsonStringifyReplacement() { + this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") + } + + override predicate replaces(string input, string output) { + input = "\\" and output = "\\\\" + // the other replacements are not relevant for this query + } + + override DataFlow::Node getInput() { + result = this.getArgument(0) + } + + override DataFlow::SourceNode getOutput() { + result = this + } +} + +/** + * A call to `JSON.parse`, viewed as a string replacement. + */ +class JsonParseReplacement extends Replacement { + JsonParserCall self; + + JsonParseReplacement() { + this = self + } + + override predicate replaces(string input, string output) { + input = "\\\\" and output = "\\" + // the other replacements are not relevant for this query + } + + override DataFlow::Node getInput() { + result = self.getInput() + } + + override DataFlow::SourceNode getOutput() { + result = self.getOutput() + } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d4930ad07cfd..e3d5a9a42522 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -5,3 +5,5 @@ | tst.js:53:10:53:33 | s.repla ... , '\\\\') | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:53:10:54:33 | s.repla ... , '\\'') | here | | tst.js:60:7:60:28 | s.repla ... '%25') | This replacement may double-escape '%' characters from $@. | tst.js:59:7:59:28 | s.repla ... '%26') | here | | tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here | +| tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | +| tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 19ab94d26911..ee9cd930b6fd 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -69,3 +69,23 @@ function badEncode(s) { .replace(indirect2, "'") .replace(indirect3, "&"); } + +function badEscape1(s) { + return JSON.stringify( + s.replace(//g, "\\u003E") + ); +} + +function goodEscape1(s) { + return JSON.stringify(s) + .replace(//g, "\\u003E"); +} + +function badUnescape2(s) { + return JSON.parse(s).replace(/\\u003C/g, "<").replace(/\\u003E/g, ">"); +} + +function goodUnescape2(s) { + return JSON.parse(s.replace(/\\u003C/g, "<").replace(/\\u003E/g, ">")); +} From aaeca325193deedc7ac8ea163cbe574514d44b94 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 09:55:28 +0000 Subject: [PATCH 0124/2538] JavaScript: Recognize string escaping using `.replace` with a callback. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 8 ++++++++ .../CWE-116/DoubleEscaping/DoubleEscaping.expected | 1 + .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 9 +++++++++ 3 files changed, 18 insertions(+) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 589a935d5fec..4e6969e54c34 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -156,6 +156,14 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { override predicate replaces(string input, string output) { input = getStringValue(pattern) and output = this.getArgument(1).getStringValue() + or + exists(DataFlow::FunctionNode replacer, DataFlow::PropRead pr, DataFlow::ObjectLiteralNode map | + replacer = getCallback(1) and + replacer.getParameter(0).flowsToExpr(pr.getPropertyNameExpr()) and + pr = map.getAPropertyRead() and + pr.flowsTo(replacer.getAReturn()) and + map.asExpr().(ObjectExpr).getPropertyByName(input).getInit().getStringValue() = output + ) } override DataFlow::Node getInput() { diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index e3d5a9a42522..d7e2b558a069 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -7,3 +7,4 @@ | tst.js:68:10:70:38 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:68:10:69:39 | s.repla ... apos;") | here | | tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | | tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | +| tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index ee9cd930b6fd..78c73ce95844 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -89,3 +89,12 @@ function badUnescape2(s) { function goodUnescape2(s) { return JSON.parse(s.replace(/\\u003C/g, "<").replace(/\\u003E/g, ">")); } + +function badEncodeWithReplacer(s) { + var repl = { + '"': """, + "'": "'", + "&": "&" + }; + return s.replace(/["']/g, (c) => repl[c]).replace(/&/g, "&"); +} From 02d16b1dc99ddbcb3b2c8148b0cb53731214b039 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 10:59:04 +0000 Subject: [PATCH 0125/2538] JavaScript: Recognise wrapped string replacement functions. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 28 +++++++++++++++++++ .../DoubleEscaping/DoubleEscaping.expected | 1 + .../Security/CWE-116/DoubleEscaping/tst.js | 8 ++++++ 3 files changed, 37 insertions(+) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 4e6969e54c34..733afad0b067 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -221,6 +221,34 @@ class JsonParseReplacement extends Replacement { } } +/** + * A string replacement wrapped in a utility function. + */ +class WrappedReplacement extends Replacement, DataFlow::CallNode { + int i; + + Replacement inner; + + WrappedReplacement() { + exists(DataFlow::FunctionNode wrapped | wrapped.getFunction() = getACallee() | + wrapped.getParameter(i).flowsTo(inner.getInput()) and + inner.getOutput().flowsTo(wrapped.getAReturn()) + ) + } + + override predicate replaces(string input, string output) { + inner.replaces(input, output) + } + + override DataFlow::Node getInput() { + result = getArgument(i) + } + + override DataFlow::SourceNode getOutput() { + result = this + } +} + from Replacement primary, Replacement supplementary, string message, string metachar where primary.escapes(metachar, _) and diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d7e2b558a069..d0747087d123 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -8,3 +8,4 @@ | tst.js:74:10:77:10 | JSON.st ... ) | This replacement may double-escape '\\' characters from $@. | tst.js:75:12:76:37 | s.repla ... u003E") | here | | tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | | tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | +| tst.js:107:10:107:53 | encodeD ... &") | This replacement may double-escape '&' characters from $@. | tst.js:107:10:107:30 | encodeD ... otes(s) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 78c73ce95844..d88422e74a4c 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -98,3 +98,11 @@ function badEncodeWithReplacer(s) { }; return s.replace(/["']/g, (c) => repl[c]).replace(/&/g, "&"); } + +function encodeDoubleQuotes(s) { + return s.replace(/"/g, """); +} + +function badWrappedEncode(s) { + return encodeDoubleQuotes(s).replace(/&/g, "&"); +} From 5349e0f88142ae4e7a63038fa3238b5001e0972d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 13:02:59 +0000 Subject: [PATCH 0126/2538] JavaScript: Recognise wrapped chains of replacements. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 11 +++++++++-- .../CWE-116/DoubleEscaping/DoubleEscaping.expected | 1 + .../Security/CWE-116/DoubleEscaping/tst.js | 8 ++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 733afad0b067..2fc91a9854d7 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -115,6 +115,13 @@ abstract class Replacement extends DataFlow::Node { result.getOutput() = getASimplePredecessor*(getInput()) } + /** + * Gets the next replacement in this chain of replacements. + */ + Replacement getNextReplacement() { + this = result.getPreviousReplacement() + } + /** * Gets an earlier replacement in this chain of replacements that * performs an escaping. @@ -231,8 +238,8 @@ class WrappedReplacement extends Replacement, DataFlow::CallNode { WrappedReplacement() { exists(DataFlow::FunctionNode wrapped | wrapped.getFunction() = getACallee() | - wrapped.getParameter(i).flowsTo(inner.getInput()) and - inner.getOutput().flowsTo(wrapped.getAReturn()) + wrapped.getParameter(i).flowsTo(inner.getPreviousReplacement*().getInput()) and + inner.getNextReplacement*().getOutput().flowsTo(wrapped.getAReturn()) ) } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected index d0747087d123..23e5a4a6b050 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/DoubleEscaping.expected @@ -9,3 +9,4 @@ | tst.js:86:10:86:22 | JSON.parse(s) | This replacement may produce '\\' characters that are double-unescaped $@. | tst.js:86:10:86:47 | JSON.pa ... g, "<") | here | | tst.js:99:10:99:66 | s.repla ... &") | This replacement may double-escape '&' characters from $@. | tst.js:99:10:99:43 | s.repla ... epl[c]) | here | | tst.js:107:10:107:53 | encodeD ... &") | This replacement may double-escape '&' characters from $@. | tst.js:107:10:107:30 | encodeD ... otes(s) | here | +| tst.js:115:10:115:47 | encodeQ ... &") | This replacement may double-escape '&' characters from $@. | tst.js:115:10:115:24 | encodeQuotes(s) | here | diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index d88422e74a4c..628166ed04ac 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -106,3 +106,11 @@ function encodeDoubleQuotes(s) { function badWrappedEncode(s) { return encodeDoubleQuotes(s).replace(/&/g, "&"); } + +function encodeQuotes(s) { + return s.replace(/"/g, """).replace(/'/g, "'"); +} + +function badWrappedEncode2(s) { + return encodeQuotes(s).replace(/&/g, "&"); +} From a8214ce7ee070ad082430a6ea0140548ea1b0799 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:15:59 +0000 Subject: [PATCH 0127/2538] JavaScript: Fix regexes for escaping schemes. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 6 +++--- .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 9 +++++++++ 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 2fc91a9854d7..5d5157bafb3c 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -54,11 +54,11 @@ DataFlow::Node getASimplePredecessor(DataFlow::Node nd) { * into a form described by regular expression `regex`. */ predicate escapingScheme(string metachar, string regex) { - metachar = "&" and regex = "&.*;" + metachar = "&" and regex = "&.+;" or - metachar = "%" and regex = "%.*" + metachar = "%" and regex = "%.+" or - metachar = "\\" and regex = "\\\\.*" + metachar = "\\" and regex = "\\\\.+" } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 628166ed04ac..e05779eeb7af 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -114,3 +114,12 @@ function encodeQuotes(s) { function badWrappedEncode2(s) { return encodeQuotes(s).replace(/&/g, "&"); } + +function roundtrip(s) { + return JSON.parse(JSON.stringify(s)); +} + +// dubious, but out of scope for this query +function badRoundtrip(s) { + return s.replace(/\\\\/g, "\\").replace(/\\/g, "\\\\"); +} From 8c133ff61d873b574ff0fef778f5248f8c4b11d9 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:46:50 +0000 Subject: [PATCH 0128/2538] JavaScript: Deal with (un-)escaping on captured variables. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 7 ++++++- .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 7 +++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index 5d5157bafb3c..b6d769566301 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -46,7 +46,12 @@ string getStringValue(RegExpLiteral rl) { */ DataFlow::Node getASimplePredecessor(DataFlow::Node nd) { result = nd.getAPredecessor() and - not nd.(DataFlow::SsaDefinitionNode).getSsaVariable().getDefinition() instanceof SsaPhiNode + not exists(SsaDefinition ssa | + ssa = nd.(DataFlow::SsaDefinitionNode).getSsaVariable().getDefinition() + | + ssa instanceof SsaPhiNode or + ssa instanceof SsaVariableCapture + ) } /** diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index e05779eeb7af..7b840e2be084 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -123,3 +123,10 @@ function roundtrip(s) { function badRoundtrip(s) { return s.replace(/\\\\/g, "\\").replace(/\\/g, "\\\\"); } + +function testWithCapturedVar(x) { + var captured = x; + (function() { + captured = captured.replace(/\\/g, "\\\\"); + })(); +} From bb0771b36c3065c60dd4aa3f04a481b241ff9c86 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:49:01 +0000 Subject: [PATCH 0129/2538] JavaScript: Deal with escape-unescape-escape (and similar) chains. --- javascript/ql/src/Security/CWE-116/DoubleEscaping.ql | 8 ++++++-- .../query-tests/Security/CWE-116/DoubleEscaping/tst.js | 4 ++++ 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index b6d769566301..db8624458b79 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -135,7 +135,9 @@ abstract class Replacement extends DataFlow::Node { exists(Replacement pred | pred = this.getPreviousReplacement() | if pred.escapes(_, metachar) then result = pred - else result = pred.getAnEarlierEscaping(metachar) + else ( + not pred.unescapes(metachar, _) and result = pred.getAnEarlierEscaping(metachar) + ) ) } @@ -147,7 +149,9 @@ abstract class Replacement extends DataFlow::Node { exists(Replacement succ | this = succ.getPreviousReplacement() | if succ.unescapes(metachar, _) then result = succ - else result = succ.getALaterUnescaping(metachar) + else ( + not succ.escapes(_, metachar) and result = succ.getALaterUnescaping(metachar) + ) ) } } diff --git a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js index 7b840e2be084..9c69c837f6bd 100644 --- a/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-116/DoubleEscaping/tst.js @@ -130,3 +130,7 @@ function testWithCapturedVar(x) { captured = captured.replace(/\\/g, "\\\\"); })(); } + +function cloneAndStringify(s) { + return JSON.stringify(JSON.parse(JSON.stringify(s))); +} From 3bbded57d3c45c1adc1056d23c3c74f0ffb38568 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 30 Oct 2019 14:49:18 +0000 Subject: [PATCH 0130/2538] JavaScript: Autoformat. --- .../ql/src/Security/CWE-116/DoubleEscaping.ql | 52 +++++-------------- 1 file changed, 13 insertions(+), 39 deletions(-) diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql index db8624458b79..6340a2fcedc8 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.ql @@ -116,16 +116,12 @@ abstract class Replacement extends DataFlow::Node { /** * Gets the previous replacement in this chain of replacements. */ - Replacement getPreviousReplacement() { - result.getOutput() = getASimplePredecessor*(getInput()) - } + Replacement getPreviousReplacement() { result.getOutput() = getASimplePredecessor*(getInput()) } /** * Gets the next replacement in this chain of replacements. */ - Replacement getNextReplacement() { - this = result.getPreviousReplacement() - } + Replacement getNextReplacement() { this = result.getPreviousReplacement() } /** * Gets an earlier replacement in this chain of replacements that @@ -182,35 +178,25 @@ class GlobalStringReplacement extends Replacement, DataFlow::MethodCallNode { ) } - override DataFlow::Node getInput() { - result = this.getReceiver() - } + override DataFlow::Node getInput() { result = this.getReceiver() } - override DataFlow::SourceNode getOutput() { - result = this - } + override DataFlow::SourceNode getOutput() { result = this } } /** * A call to `JSON.stringify`, viewed as a string replacement. */ class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { - JsonStringifyReplacement() { - this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") - } + JsonStringifyReplacement() { this = DataFlow::globalVarRef("JSON").getAMemberCall("stringify") } override predicate replaces(string input, string output) { input = "\\" and output = "\\\\" // the other replacements are not relevant for this query } - override DataFlow::Node getInput() { - result = this.getArgument(0) - } + override DataFlow::Node getInput() { result = this.getArgument(0) } - override DataFlow::SourceNode getOutput() { - result = this - } + override DataFlow::SourceNode getOutput() { result = this } } /** @@ -219,22 +205,16 @@ class JsonStringifyReplacement extends Replacement, DataFlow::CallNode { class JsonParseReplacement extends Replacement { JsonParserCall self; - JsonParseReplacement() { - this = self - } + JsonParseReplacement() { this = self } override predicate replaces(string input, string output) { input = "\\\\" and output = "\\" // the other replacements are not relevant for this query } - override DataFlow::Node getInput() { - result = self.getInput() - } + override DataFlow::Node getInput() { result = self.getInput() } - override DataFlow::SourceNode getOutput() { - result = self.getOutput() - } + override DataFlow::SourceNode getOutput() { result = self.getOutput() } } /** @@ -252,17 +232,11 @@ class WrappedReplacement extends Replacement, DataFlow::CallNode { ) } - override predicate replaces(string input, string output) { - inner.replaces(input, output) - } + override predicate replaces(string input, string output) { inner.replaces(input, output) } - override DataFlow::Node getInput() { - result = getArgument(i) - } + override DataFlow::Node getInput() { result = getArgument(i) } - override DataFlow::SourceNode getOutput() { - result = this - } + override DataFlow::SourceNode getOutput() { result = this } } from Replacement primary, Replacement supplementary, string message, string metachar From 8620b0513efa171a2713c08f8fdde5576b73078a Mon Sep 17 00:00:00 2001 From: yh-semmle Date: Wed, 30 Oct 2019 11:18:36 -0400 Subject: [PATCH 0131/2538] Java: move `UnsafeDeserialization.qll` to standard library location --- java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql | 2 +- .../code/java/security}/UnsafeDeserialization.qll | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename java/ql/src/{Security/CWE/CWE-502 => semmle/code/java/security}/UnsafeDeserialization.qll (100%) diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql index 18cf624375fc..bb4df03cd4fa 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql @@ -12,7 +12,7 @@ import java import semmle.code.java.dataflow.FlowSources -import UnsafeDeserialization +import semmle.code.java.security.UnsafeDeserialization import DataFlow::PathGraph class UnsafeDeserializationConfig extends TaintTracking::Configuration { diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qll b/java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll similarity index 100% rename from java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qll rename to java/ql/src/semmle/code/java/security/UnsafeDeserialization.qll From 27d0b51c6b4eabc891c71eb8952874c07932c7e3 Mon Sep 17 00:00:00 2001 From: alistair Date: Wed, 30 Oct 2019 16:10:03 +0000 Subject: [PATCH 0132/2538] CPP & C#: Review of qhelp PR #2151 got merged without a review of the qhelp by a technical writer. The current PR makes changes I would have suggested on that PR. --- .../NtohlArrayNoBoundOpenSource.qhelp | 2 +- .../ConditionallyUninitializedVariable.qhelp | 2 +- .../ConditionallyUninitializedVariable.ql | 2 +- .../CWE-091/XMLInjection.qhelp | 4 ++-- .../CWE-114/AssemblyPathInjection.qhelp | 6 ++--- .../CWE-321/HardcodedEncryptionKey.ql | 4 ++-- .../CWE-327/InsecureSQLConnection.qhelp | 22 +++++++++---------- .../CWE-327/InsecureSQLConnection.ql | 2 +- 8 files changed, 21 insertions(+), 23 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp index 522d6cde74c8..fc8f309f73a0 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.qhelp @@ -14,7 +14,7 @@ byte order function, such as ntohl. The use of a network-to-host byte order function is therefore a good indicator that the returned value is unvalidated data retrieved from the network, and should not be used without further validation. In particular, the returned value should not be used as an array index or array length -value without validation, which may result in a buffer overflow vulnerability. +value without validation, as this could result in a buffer overflow vulnerability.

    diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp index b9118edc7361..8e6a89034838 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.qhelp @@ -37,7 +37,7 @@ which is then subsequently accessed to fetch properties of the device. However, check the return value from the function call to initDeviceConfig. If the device number passed to the notify function was invalid, the initDeviceConfig function will leave the config variable uninitialized, -which would result in the notify function accessing uninitialized memory.

    +which will result in the notify function accessing uninitialized memory.

    diff --git a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql index eb00fb9ea106..f9eb2fe5400f 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql +++ b/cpp/ql/src/Security/CWE/CWE-457/ConditionallyUninitializedVariable.ql @@ -2,7 +2,7 @@ * @name Conditionally uninitialized variable * @description When an initialization function is used to initialize a local variable, but the * returned status code is not checked, the variable may be left in an uninitialized - * state, and reading the variable may result in undefined behaviour. + * state, and reading the variable may result in undefined behavior. * @kind problem * @problem.severity warning * @opaque-id SM02313 diff --git a/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp b/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp index 4e70b06531ae..3aff9901bfce 100644 --- a/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-091/XMLInjection.qhelp @@ -36,10 +36,10 @@ which ensures the content is appropriately escaped.

  • - XML Injection (The Web Application Security Consortium). + Web Application Security Consortium: XML Injection.
  • - WriteRaw (Microsoft documentation). + Microsoft Docs: WriteRaw.
  • diff --git a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp index 5f95181c092e..e1dbe9c1bd0a 100644 --- a/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-114/AssemblyPathInjection.qhelp @@ -14,7 +14,7 @@ was not intended to be loaded, and executing arbitrary code.

    Avoid loading assemblies based on user provided input. If this is not possible, ensure that the path is validated before being used with Assembly. For example, compare the provided input -against a whitelist of known safe assemblies, or confirm that path is restricted to a single +against a whitelist of known safe assemblies, or confirm that the path is restricted to a single directory which only contains safe assemblies.

    @@ -30,8 +30,8 @@ is only loaded if the user input matches one of those options.

    -
  • - System.Reflection.Assembly (Microsoft documentation). +
  • Microsoft: + System.Reflection.Assembly.
  • diff --git a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql index c09a67d756c6..cce122ffa62d 100644 --- a/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql +++ b/csharp/ql/src/Security Features/CWE-321/HardcodedEncryptionKey.ql @@ -1,6 +1,6 @@ /** - * @name Do not use hard-coded encryption keys. - * @description The .Key property or rgbKey parameter of a SymmetricAlgorithm should never be a hardcoded value. + * @name Hard-coded encryption key + * @description The .Key property or rgbKey parameter of a SymmetricAlgorithm should never be a hard-coded value. * @kind problem * @id cs/hardcoded-key * @problem.severity error diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp index ae69402eb7e1..c59feeed61c5 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.qhelp @@ -3,7 +3,6 @@ "qhelp.dtd"> -

    Finds uses of insecure SQL Connections string by not enabling the Encrypt option.

    SQL Server connections where the client is not enforcing the encryption in transit are susceptible to multiple attacks, including a man-in-the-middle, that would potentially compromise the user credentials and/or the TDS session. @@ -29,18 +28,17 @@ - -

  • - Selectively using secure connection to SQL Server +
  • Microsoft, SQL Protocols blog: + Selectively using secure connection to SQL Server. +
  • +
  • Microsoft: + SqlConnection.ConnectionString Property. +
  • +
  • Microsoft: + Using Connection String Keywords with SQL Server Native Client.
  • -
  • - Net SqlClient (ADO .Net) +
  • Microsoft: + Setting the connection properties.
  • -
  • SQL native driver (SNAC) -
  • -
  • - JDBC driver -
  • -
    diff --git a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql index 0f855150aa98..78bcc1c19e5f 100644 --- a/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql +++ b/csharp/ql/src/Security Features/CWE-327/InsecureSQLConnection.ql @@ -1,6 +1,6 @@ /** * @name Insecure SQL connection - * @description TODO. + * @description Using an SQL Server connection without enforcing encryption is a security vulnerability. * @kind path-problem * @id cs/insecure-sql-connection * @problem.severity error From d3016e5b9898605d1babb05dfa7067401fa836dc Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Thu, 31 Oct 2019 11:21:57 +0000 Subject: [PATCH 0133/2538] Run autoformatter --- .../ql/src/semmle/code/java/dataflow/Nullness.qll | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/java/ql/src/semmle/code/java/dataflow/Nullness.qll b/java/ql/src/semmle/code/java/dataflow/Nullness.qll index af8e323521c8..d7da85832ae7 100644 --- a/java/ql/src/semmle/code/java/dataflow/Nullness.qll +++ b/java/ql/src/semmle/code/java/dataflow/Nullness.qll @@ -143,11 +143,16 @@ private ControlFlowNode varDereference(SsaVariable v, VarAccess va) { * subsequent use, either by dereferencing it or by an assertion. */ private ControlFlowNode ensureNotNull(SsaVariable v) { - result = varDereference(v, _) or - result.(AssertStmt).getExpr() = nullGuard(v, true, false) or - exists(AssertTrueMethod m | result = m.getACheck(nullGuard(v, true, false))) or - exists(AssertFalseMethod m | result = m.getACheck(nullGuard(v, false, false))) or - exists(AssertNotNullMethod m | result = m.getACheck(v.getAUse())) or + result = varDereference(v, _) + or + result.(AssertStmt).getExpr() = nullGuard(v, true, false) + or + exists(AssertTrueMethod m | result = m.getACheck(nullGuard(v, true, false))) + or + exists(AssertFalseMethod m | result = m.getACheck(nullGuard(v, false, false))) + or + exists(AssertNotNullMethod m | result = m.getACheck(v.getAUse())) + or exists(AssertThatMethod m, MethodAccess ma | result = m.getACheck(v.getAUse()) and ma.getControlFlowNode() = result | From 03c9a40ba35db5be5e635703db8b2ab82beca909 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 22 Oct 2019 09:32:51 +0100 Subject: [PATCH 0134/2538] JavaScript: Add libraries for forward and backward data-flow exploration. --- .../dataflow/BackwardExploration.qll | 44 +++++++++++++++++++ .../dataflow/ForwardExploration.qll | 42 ++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll create mode 100644 javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll diff --git a/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll b/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll new file mode 100644 index 000000000000..caf67e6db7fd --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/BackwardExploration.qll @@ -0,0 +1,44 @@ +/** + * Provides machinery for performing backward data-flow exploration. + * + * Importing this module effectively makes all data-flow and taint-tracking configurations + * ignore their `isSource` predicate. Instead, flow is tracked from any _initial node_ (that is, + * a node without incoming flow) to a sink node. All initial nodes are then treated as source + * nodes. + * + * Data-flow exploration cannot be used with configurations depending on other configurations. + * + * NOTE: This library should only be used for debugging, not in production code. Backward + * exploration in particular does not scale on non-trivial code bases and hence is of limited + * usefulness as it stands. + */ + +import javascript + +private class BackwardExploringConfiguration extends DataFlow::Configuration { + DataFlow::Configuration cfg; + + BackwardExploringConfiguration() { + this = cfg + } + + override predicate isSource(DataFlow::Node node) { any() } + + override predicate isSource(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } + + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | + source = src.getNode() and + sink = snk.getNode() + ) + } + + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + exists(DataFlow::MidPathNode first | + source.getConfiguration() = this and + source.getASuccessor() = first and + not exists(DataFlow::MidPathNode mid | mid.getASuccessor() = first) and + first.getASuccessor*() = sink + ) + } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll b/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll new file mode 100644 index 000000000000..0e3a7ae91c2f --- /dev/null +++ b/javascript/ql/src/semmle/javascript/dataflow/ForwardExploration.qll @@ -0,0 +1,42 @@ +/** + * Provides machinery for performing forward data-flow exploration. + * + * Importing this module effectively makes all data-flow and taint-tracking configurations + * ignore their `isSink` predicate. Instead, flow is tracked from source nodes as far as + * possible, until a _terminal node_ (that is, a node without any outgoing flow) is reached. + * All terminal nodes are then treated as sink nodes. + * + * Data-flow exploration cannot be used with configurations depending on other configurations. + * + * NOTE: This library should only be used for debugging, not in production code. + */ + +import javascript + +private class ForwardExploringConfiguration extends DataFlow::Configuration { + DataFlow::Configuration cfg; + + ForwardExploringConfiguration() { + this = cfg + } + + override predicate isSink(DataFlow::Node node) { any() } + + override predicate isSink(DataFlow::Node node, DataFlow::FlowLabel lbl) { any() } + + override predicate hasFlow(DataFlow::Node source, DataFlow::Node sink) { + exists(DataFlow::PathNode src, DataFlow::PathNode snk | hasFlowPath(src, snk) | + source = src.getNode() and + sink = snk.getNode() + ) + } + + override predicate hasFlowPath(DataFlow::SourcePathNode source, DataFlow::SinkPathNode sink) { + exists(DataFlow::MidPathNode last | + source.getConfiguration() = this and + source.getASuccessor*() = last and + not last.getASuccessor() instanceof DataFlow::MidPathNode and + last.getASuccessor() = sink + ) + } +} From 31f25c8cfc07d02e9cf25995f6039e5fd18555fb Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 31 Oct 2019 11:43:47 -0700 Subject: [PATCH 0135/2538] C++: primary instrs for constructor side effects --- .../raw/internal/TranslatedCall.qll | 6 + .../ir/ir/aliased_ssa_sanity.expected | 40 ------ .../library-tests/ir/ir/raw_sanity.expected | 42 ------ .../ir/ir/unaliased_ssa_sanity.expected | 42 ------ .../ir/ssa/aliased_ssa_sanity.expected | 2 - .../ir/ssa/unaliased_ssa_sanity.expected | 2 - .../syntax-zoo/aliased_ssa_sanity.expected | 117 ---------------- .../syntax-zoo/raw_sanity.expected | 127 ------------------ .../syntax-zoo/unaliased_ssa_sanity.expected | 118 ---------------- 9 files changed, 6 insertions(+), 490 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll index 1a6c3fe80c80..4dab4ca33547 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedCall.qll @@ -352,6 +352,12 @@ class TranslatedSideEffects extends TranslatedElement, TTranslatedSideEffects { none() } + override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) { + tag = OnlyInstructionTag() and + result = getTranslatedExpr(expr).getInstruction(CallTag()) + } + + /** * Gets the `TranslatedFunction` containing this expression. */ diff --git a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected index c92478927534..e5e666c020b1 100644 --- a/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/aliased_ssa_sanity.expected @@ -9,46 +9,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:616:12:616:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:617:15:617:22 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:619:16:619:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:662:9:662:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:663:5:663:5 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:736:5:736:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:745:8:745:8 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:745:8:745:8 | IR: Base | void Base::Base(Base const&) | -| ir.cpp:748:10:748:10 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:748:3:748:6 | IR: Base | void Base::Base() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB1 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB2 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:800:8:800:8 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:801:10:801:10 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:802:11:802:11 | IndirectMayWriteSideEffect: call to Derived | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:846:8:846:8 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:846:8:846:8 | IR: PolymorphicDerived | void PolymorphicDerived::PolymorphicDerived() | -| ir.cpp:851:22:851:22 | IndirectMayWriteSideEffect: call to PolymorphicDerived | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| ir.cpp:868:3:868:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:867:1:867:14 | IR: String | void String::String() | -| ir.cpp:944:3:944:14 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:945:3:945:27 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:1036:20:1036:57 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:1040:29:1040:66 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:1040:30:1040:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1040:30:1040:30 | IR: (constructor) | void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) | -| ir.cpp:1145:5:1145:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1133:6:1133:23 | IR: TryCatchNoCatchAny | void TryCatchNoCatchAny(bool) | -| perf-regression.cpp:10:14:10:20 | IndirectMayWriteSideEffect: call to Big | Side effect instruction missing primary instruction in function $@ | perf-regression.cpp:9:5:9:8 | IR: main | int main() | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected index db12cd98a4c8..e5e666c020b1 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_sanity.expected @@ -9,48 +9,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:616:12:616:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:617:15:617:22 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:619:16:619:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:662:9:662:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:663:5:663:5 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:731:19:731:47 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:736:5:736:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:745:8:745:8 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:745:8:745:8 | IR: Base | void Base::Base(Base const&) | -| ir.cpp:748:10:748:10 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:748:3:748:6 | IR: Base | void Base::Base() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB1 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB2 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:800:8:800:8 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:801:10:801:10 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:802:11:802:11 | IndirectMayWriteSideEffect: call to Derived | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:846:8:846:8 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:846:8:846:8 | IR: PolymorphicDerived | void PolymorphicDerived::PolymorphicDerived() | -| ir.cpp:851:22:851:22 | IndirectMayWriteSideEffect: call to PolymorphicDerived | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| ir.cpp:868:3:868:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:867:1:867:14 | IR: String | void String::String() | -| ir.cpp:944:3:944:14 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:945:3:945:27 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:1036:20:1036:57 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:1040:29:1040:66 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:1040:30:1040:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1040:30:1040:30 | IR: (constructor) | void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) | -| ir.cpp:1140:19:1140:47 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1133:6:1133:23 | IR: TryCatchNoCatchAny | void TryCatchNoCatchAny(bool) | -| ir.cpp:1145:5:1145:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1133:6:1133:23 | IR: TryCatchNoCatchAny | void TryCatchNoCatchAny(bool) | -| perf-regression.cpp:10:14:10:20 | IndirectMayWriteSideEffect: call to Big | Side effect instruction missing primary instruction in function $@ | perf-regression.cpp:9:5:9:8 | IR: main | int main() | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected index db12cd98a4c8..e5e666c020b1 100644 --- a/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ir/unaliased_ssa_sanity.expected @@ -9,48 +9,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:616:12:616:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:617:15:617:22 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:619:16:619:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:662:9:662:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:663:5:663:5 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:731:19:731:47 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:736:5:736:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:745:8:745:8 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:745:8:745:8 | IR: Base | void Base::Base(Base const&) | -| ir.cpp:748:10:748:10 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:748:3:748:6 | IR: Base | void Base::Base() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB1 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB2 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:800:8:800:8 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:801:10:801:10 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:802:11:802:11 | IndirectMayWriteSideEffect: call to Derived | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:846:8:846:8 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:846:8:846:8 | IR: PolymorphicDerived | void PolymorphicDerived::PolymorphicDerived() | -| ir.cpp:851:22:851:22 | IndirectMayWriteSideEffect: call to PolymorphicDerived | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| ir.cpp:868:3:868:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:867:1:867:14 | IR: String | void String::String() | -| ir.cpp:944:3:944:14 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:945:3:945:27 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:1036:20:1036:57 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:1040:29:1040:66 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | ir.cpp:1031:6:1031:11 | IR: Lambda | void Lambda(int, String const&) | -| ir.cpp:1040:30:1040:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1040:30:1040:30 | IR: (constructor) | void (void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)::(constructor)((void Lambda(int, String const&))::(lambda [] type at line 1040, col. 30)&&) | -| ir.cpp:1140:19:1140:47 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1133:6:1133:23 | IR: TryCatchNoCatchAny | void TryCatchNoCatchAny(bool) | -| ir.cpp:1145:5:1145:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:1133:6:1133:23 | IR: TryCatchNoCatchAny | void TryCatchNoCatchAny(bool) | -| perf-regression.cpp:10:14:10:20 | IndirectMayWriteSideEffect: call to Big | Side effect instruction missing primary instruction in function $@ | perf-regression.cpp:9:5:9:8 | IR: main | int main() | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected index ed015868f1b7..9769ee11f99f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_sanity.expected @@ -5,8 +5,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| ssa.cpp:220:19:220:20 | IndirectMayWriteSideEffect: call to Constructible | Side effect instruction missing primary instruction in function $@ | ssa.cpp:219:6:219:29 | IR: ExplicitConstructorCalls | void ExplicitConstructorCalls() | -| ssa.cpp:223:21:223:37 | IndirectMayWriteSideEffect: call to Constructible | Side effect instruction missing primary instruction in function $@ | ssa.cpp:219:6:219:29 | IR: ExplicitConstructorCalls | void ExplicitConstructorCalls() | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected index ed015868f1b7..9769ee11f99f 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_sanity.expected @@ -5,8 +5,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| ssa.cpp:220:19:220:20 | IndirectMayWriteSideEffect: call to Constructible | Side effect instruction missing primary instruction in function $@ | ssa.cpp:219:6:219:29 | IR: ExplicitConstructorCalls | void ExplicitConstructorCalls() | -| ssa.cpp:223:21:223:37 | IndirectMayWriteSideEffect: call to Constructible | Side effect instruction missing primary instruction in function $@ | ssa.cpp:219:6:219:29 | IR: ExplicitConstructorCalls | void ExplicitConstructorCalls() | instructionWithoutSuccessor ambiguousSuccessors unexplainedLoop diff --git a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected index d8bdade48cc2..b19ec3d04b92 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/aliased_ssa_sanity.expected @@ -36,123 +36,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | allocators.cpp:14:5:14:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | -| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | -| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | -| condition_decls.cpp:48:22:48:24 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| condition_decls.cpp:48:34:48:36 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | array_delete.cpp:5:6:5:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | assignexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constmemberaccess.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constructorinitializer.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defconstructornewexpr.cpp:3:6:3:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defdestructordeleteexpr.cpp:3:6:3:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | deleteexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | fieldaccess.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | newexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | pmcallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | -| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp11.cpp:88:33:88:38 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp17.cpp:15:5:15:45 | IndirectMayWriteSideEffect: call to HasTwoArgCtor | Side effect instruction missing primary instruction in function $@ | cpp17.cpp:14:8:14:8 | IR: make | void placement_new::make(placement_new::HasTwoArgCtor*, int&&, int&&) | -| destructors.cpp:50:9:50:13 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| destructors.cpp:51:36:51:38 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticlocals.cpp:25:6:25:7 | IR: f2 | void staticlocals::f2() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| ir.cpp:616:12:616:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:617:15:617:22 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:619:16:619:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:662:9:662:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:663:5:663:5 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:736:5:736:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:745:8:745:8 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:745:8:745:8 | IR: Base | void Base::Base(Base const&) | -| ir.cpp:748:10:748:10 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:748:3:748:6 | IR: Base | void Base::Base() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB1 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB2 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:800:8:800:8 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:801:10:801:10 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:802:11:802:11 | IndirectMayWriteSideEffect: call to Derived | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:846:8:846:8 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:846:8:846:8 | IR: PolymorphicDerived | void PolymorphicDerived::PolymorphicDerived() | -| ir.cpp:851:22:851:22 | IndirectMayWriteSideEffect: call to PolymorphicDerived | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| ir.cpp:868:3:868:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:867:1:867:14 | IR: String | void String::String() | -| ir.cpp:944:3:944:14 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:945:3:945:27 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | array_delete.cpp:5:6:5:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | assignexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constmemberaccess.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constructorinitializer.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defconstructornewexpr.cpp:3:6:3:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defdestructordeleteexpr.cpp:3:6:3:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | deleteexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | fieldaccess.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | newexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | pmcallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| ops.cpp:26:31:26:53 | IndirectMayWriteSideEffect: call to C_with_constr_destr | Side effect instruction missing primary instruction in function $@ | ops.cpp:18:6:18:14 | IR: f_with_op | void f_with_op(int) | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | allocators.cpp:14:5:14:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| static_init_templates.cpp:31:10:31:11 | IndirectMayWriteSideEffect: call to MyClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:29:6:29:9 | IR: test | void test() | -| static_init_templates.cpp:236:7:236:7 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:236:7:236:7 | IR: MyDerivedClass | void MyDerivedClass::MyDerivedClass() | -| static_init_templates.cpp:240:7:240:7 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:240:7:240:7 | IR: MyContainingClass | void MyContainingClass::MyContainingClass() | -| static_init_templates.cpp:249:21:249:23 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| static_init_templates.cpp:250:17:250:19 | IndirectMayWriteSideEffect: call to MyDerivedClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| static_init_templates.cpp:251:20:251:23 | IndirectMayWriteSideEffect: call to MyContainingClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| stmt_expr.cpp:13:18:13:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | stmt_expr.cpp:9:6:9:6 | IR: f | void stmtexpr::f(int) | -| try_catch.cpp:7:8:7:8 | IndirectMayWriteSideEffect: call to exception | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:7:8:7:8 | IR: exn1 | void exn1::exn1() | -| try_catch.cpp:7:8:7:8 | IndirectMayWriteSideEffect: call to exception | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:7:8:7:8 | IR: exn1 | void exn1::exn1(exn1&&) | -| try_catch.cpp:13:5:13:16 | IndirectMayWriteSideEffect: call to exn1 | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() | instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | condition_decls.cpp:16:19:16:20 | Chi: call to BoxedInt | diff --git a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected index 2facee3f9bc2..4d110ac2522b 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/raw_sanity.expected @@ -51,133 +51,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | allocators.cpp:14:5:14:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | -| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | -| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | -| condition_decls.cpp:48:22:48:24 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| condition_decls.cpp:48:34:48:36 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | array_delete.cpp:5:6:5:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | assignexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constmemberaccess.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constructorinitializer.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defconstructornewexpr.cpp:3:6:3:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defdestructordeleteexpr.cpp:3:6:3:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | deleteexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | fieldaccess.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | newexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | pmcallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | -| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp11.cpp:88:33:88:38 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp17.cpp:15:5:15:45 | IndirectMayWriteSideEffect: call to HasTwoArgCtor | Side effect instruction missing primary instruction in function $@ | cpp17.cpp:14:8:14:8 | IR: make | void placement_new::make(placement_new::HasTwoArgCtor*, int&&, int&&) | -| destructors.cpp:50:9:50:13 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| destructors.cpp:51:36:51:38 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticlocals.cpp:25:6:25:7 | IR: f2 | void staticlocals::f2() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| ir.cpp:616:12:616:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:617:15:617:22 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:619:16:619:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:662:9:662:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:663:5:663:5 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:731:19:731:47 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:736:5:736:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:745:8:745:8 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:745:8:745:8 | IR: Base | void Base::Base(Base const&) | -| ir.cpp:748:10:748:10 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:748:3:748:6 | IR: Base | void Base::Base() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB1 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB2 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:800:8:800:8 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:801:10:801:10 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:802:11:802:11 | IndirectMayWriteSideEffect: call to Derived | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:846:8:846:8 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:846:8:846:8 | IR: PolymorphicDerived | void PolymorphicDerived::PolymorphicDerived() | -| ir.cpp:851:22:851:22 | IndirectMayWriteSideEffect: call to PolymorphicDerived | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| ir.cpp:868:3:868:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:867:1:867:14 | IR: String | void String::String() | -| ir.cpp:944:3:944:14 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:945:3:945:27 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:14:16:14:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:18:16:18:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:21:16:21:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:24:12:24:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:31:16:31:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:35:16:35:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:38:16:38:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:41:12:41:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | array_delete.cpp:5:6:5:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | assignexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constmemberaccess.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constructorinitializer.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defconstructornewexpr.cpp:3:6:3:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defdestructordeleteexpr.cpp:3:6:3:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | deleteexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | fieldaccess.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | newexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | pmcallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| ops.cpp:26:31:26:53 | IndirectMayWriteSideEffect: call to C_with_constr_destr | Side effect instruction missing primary instruction in function $@ | ops.cpp:18:6:18:14 | IR: f_with_op | void f_with_op(int) | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | allocators.cpp:14:5:14:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| static_init_templates.cpp:31:10:31:11 | IndirectMayWriteSideEffect: call to MyClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:29:6:29:9 | IR: test | void test() | -| static_init_templates.cpp:236:7:236:7 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:236:7:236:7 | IR: MyDerivedClass | void MyDerivedClass::MyDerivedClass() | -| static_init_templates.cpp:240:7:240:7 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:240:7:240:7 | IR: MyContainingClass | void MyContainingClass::MyContainingClass() | -| static_init_templates.cpp:249:21:249:23 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| static_init_templates.cpp:250:17:250:19 | IndirectMayWriteSideEffect: call to MyDerivedClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| static_init_templates.cpp:251:20:251:23 | IndirectMayWriteSideEffect: call to MyContainingClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| stmt_expr.cpp:13:18:13:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | stmt_expr.cpp:9:6:9:6 | IR: f | void stmtexpr::f(int) | -| stmt_expr.cpp:30:20:30:21 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | stmt_expr.cpp:21:6:21:6 | IR: g | void stmtexpr::g(int) | -| try_catch.cpp:7:8:7:8 | IndirectMayWriteSideEffect: call to exception | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:7:8:7:8 | IR: exn1 | void exn1::exn1() | -| try_catch.cpp:7:8:7:8 | IndirectMayWriteSideEffect: call to exception | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:7:8:7:8 | IR: exn1 | void exn1::exn1(exn1&&) | -| try_catch.cpp:13:5:13:16 | IndirectMayWriteSideEffect: call to exn1 | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() | instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | VacuousDestructorCall.cpp:3:3:3:3 | VariableAddress: x | diff --git a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected index f237d8dd692c..092d229974b9 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/unaliased_ssa_sanity.expected @@ -44,124 +44,6 @@ missingPhiOperand missingOperandType duplicateChiOperand sideEffectWithoutPrimary -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | allocators.cpp:14:5:14:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| allocators.cpp:16:14:16:36 | IndirectMayWriteSideEffect: call to Foo | Side effect instruction missing primary instruction in function $@ | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:15:6:15:17 | IR: if_decl_bind | void if_decl_bind(int) | -| condition_decls.cpp:26:23:26:24 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:25:6:25:21 | IR: switch_decl_bind | void switch_decl_bind(int) | -| condition_decls.cpp:41:22:41:23 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:40:6:40:20 | IR: while_decl_bind | void while_decl_bind(int) | -| condition_decls.cpp:48:22:48:24 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| condition_decls.cpp:48:34:48:36 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| condition_decls.cpp:48:52:48:53 | IndirectMayWriteSideEffect: call to BoxedInt | Side effect instruction missing primary instruction in function $@ | condition_decls.cpp:47:6:47:18 | IR: for_decl_bind | void for_decl_bind(int) | -| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:9:30:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:30:18:30:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:9:33:13 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:29:6:29:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:33:18:33:22 | IndirectMayWriteSideEffect: call to C1 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:1:6:1:7 | IR: f1 | void f1() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:9:39:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:39:18:39:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:9:42:13 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | conditional_destructors.cpp:38:6:38:7 | IR: f2 | void f2() | -| conditional_destructors.cpp:42:18:42:22 | IndirectMayWriteSideEffect: call to C2 | Side effect instruction missing primary instruction in function $@ | forstmt.cpp:8:6:8:7 | IR: f2 | void f2() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | array_delete.cpp:5:6:5:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | assignexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constmemberaccess.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constructorinitializer.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defconstructornewexpr.cpp:3:6:3:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defdestructordeleteexpr.cpp:3:6:3:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | deleteexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | fieldaccess.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | newexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | pmcallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| constructorinitializer.cpp:8:6:8:18 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| cpp11.cpp:77:19:77:21 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:76:8:76:8 | IR: apply | void lambda::apply<(void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)>(lambda::Val, (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)) | -| cpp11.cpp:82:11:82:14 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:17:82:55 | IndirectMayWriteSideEffect: call to (constructor) | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| cpp11.cpp:82:45:82:48 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:82:51:82:51 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:82:20:82:20 | IR: operator() | void (void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val))::(lambda [] type at line 82, col. 17)::operator()(lambda::Val) const | -| cpp11.cpp:88:25:88:30 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp11.cpp:88:33:88:38 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:87:8:87:11 | IR: main | void lambda::main() | -| cpp17.cpp:15:5:15:45 | IndirectMayWriteSideEffect: call to HasTwoArgCtor | Side effect instruction missing primary instruction in function $@ | cpp17.cpp:14:8:14:8 | IR: make | void placement_new::make(placement_new::HasTwoArgCtor*, int&&, int&&) | -| destructors.cpp:50:9:50:13 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| destructors.cpp:51:36:51:38 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | destructors.cpp:49:7:49:7 | IR: f | int cond_destruct::f(int) | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticlocals.cpp:25:6:25:7 | IR: f2 | void staticlocals::f2() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| file://:0:0:0:0 | IndirectMayWriteSideEffect: call to Val | Side effect instruction missing primary instruction in function $@ | cpp11.cpp:81:8:81:8 | IR: apply2 | void lambda::apply2(int(*)(lambda::Val, lambda::Val), lambda::Val, lambda::Val) | -| ir.cpp:616:12:616:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:617:15:617:22 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:619:16:619:30 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:615:6:615:18 | IR: DeclareObject | void DeclareObject() | -| ir.cpp:662:9:662:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:663:5:663:5 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:658:5:658:5 | IR: C | void C::C() | -| ir.cpp:731:19:731:47 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:736:5:736:19 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:724:6:724:13 | IR: TryCatch | void TryCatch(bool) | -| ir.cpp:745:8:745:8 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:745:8:745:8 | IR: Base | void Base::Base(Base const&) | -| ir.cpp:748:10:748:10 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:748:3:748:6 | IR: Base | void Base::Base() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:757:12:757:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:757:3:757:8 | IR: Middle | void Middle::Middle() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:766:13:766:13 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:766:3:766:9 | IR: Derived | void Derived::Derived() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:775:15:775:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:775:3:775:11 | IR: MiddleVB1 | void MiddleVB1::MiddleVB1() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:784:15:784:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:784:3:784:11 | IR: MiddleVB2 | void MiddleVB2::MiddleVB2() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB1 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to MiddleVB2 | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:793:15:793:15 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:793:3:793:11 | IR: DerivedVB | void DerivedVB::DerivedVB() | -| ir.cpp:800:8:800:8 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:801:10:801:10 | IndirectMayWriteSideEffect: call to Middle | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:802:11:802:11 | IndirectMayWriteSideEffect: call to Derived | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:809:7:809:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:810:7:810:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:823:7:823:13 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:824:7:824:26 | IndirectMayWriteSideEffect: call to Base | Side effect instruction missing primary instruction in function $@ | ir.cpp:799:6:799:25 | IR: HierarchyConversions | void HierarchyConversions() | -| ir.cpp:846:8:846:8 | IndirectMayWriteSideEffect: call to PolymorphicBase | Side effect instruction missing primary instruction in function $@ | ir.cpp:846:8:846:8 | IR: PolymorphicDerived | void PolymorphicDerived::PolymorphicDerived() | -| ir.cpp:851:22:851:22 | IndirectMayWriteSideEffect: call to PolymorphicDerived | Side effect instruction missing primary instruction in function $@ | ir.cpp:849:6:849:16 | IR: DynamicCast | void DynamicCast() | -| ir.cpp:868:3:868:12 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:867:1:867:14 | IR: String | void String::String() | -| ir.cpp:944:3:944:14 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ir.cpp:945:3:945:27 | IndirectMayWriteSideEffect: call to String | Side effect instruction missing primary instruction in function $@ | ir.cpp:940:6:940:16 | IR: OperatorNew | void OperatorNew() | -| ms_try_mix.cpp:11:12:11:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:10:6:10:18 | IR: ms_except_mix | void ms_except_mix(int) | -| ms_try_mix.cpp:28:12:28:15 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:27:6:27:19 | IR: ms_finally_mix | void ms_finally_mix(int) | -| ms_try_mix.cpp:48:10:48:13 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | ms_try_mix.cpp:47:6:47:28 | IR: ms_empty_finally_at_end | void ms_empty_finally_at_end() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | array_delete.cpp:5:6:5:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | assignexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constmemberaccess.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | constructorinitializer.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defconstructornewexpr.cpp:3:6:3:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | defdestructordeleteexpr.cpp:3:6:3:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | deleteexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | fieldaccess.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | membercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | newexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | pmcallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr.cpp:6:6:6:6 | IR: f | void f() | -| newexpr.cpp:8:2:8:20 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | staticmembercallexpr_args.cpp:7:6:7:6 | IR: f | void f() | -| ops.cpp:26:31:26:53 | IndirectMayWriteSideEffect: call to C_with_constr_destr | Side effect instruction missing primary instruction in function $@ | ops.cpp:18:6:18:14 | IR: f_with_op | void f_with_op(int) | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | allocators.cpp:14:5:14:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | no_dynamic_init.cpp:9:5:9:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | parameterinitializer.cpp:18:5:18:8 | IR: main | int main() | -| parameterinitializer.cpp:25:5:25:8 | IndirectMayWriteSideEffect: call to c | Side effect instruction missing primary instruction in function $@ | stream_it.cpp:16:5:16:8 | IR: main | int main() | -| static_init_templates.cpp:31:10:31:11 | IndirectMayWriteSideEffect: call to MyClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:29:6:29:9 | IR: test | void test() | -| static_init_templates.cpp:236:7:236:7 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:236:7:236:7 | IR: MyDerivedClass | void MyDerivedClass::MyDerivedClass() | -| static_init_templates.cpp:240:7:240:7 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:240:7:240:7 | IR: MyContainingClass | void MyContainingClass::MyContainingClass() | -| static_init_templates.cpp:249:21:249:23 | IndirectMayWriteSideEffect: call to MyConstructorClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| static_init_templates.cpp:250:17:250:19 | IndirectMayWriteSideEffect: call to MyDerivedClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| static_init_templates.cpp:251:20:251:23 | IndirectMayWriteSideEffect: call to MyContainingClass | Side effect instruction missing primary instruction in function $@ | static_init_templates.cpp:246:6:246:17 | IR: testFunction | void testFunction() | -| stmt_expr.cpp:13:18:13:19 | IndirectMayWriteSideEffect: call to C | Side effect instruction missing primary instruction in function $@ | stmt_expr.cpp:9:6:9:6 | IR: f | void stmtexpr::f(int) | -| try_catch.cpp:7:8:7:8 | IndirectMayWriteSideEffect: call to exception | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:7:8:7:8 | IR: exn1 | void exn1::exn1() | -| try_catch.cpp:7:8:7:8 | IndirectMayWriteSideEffect: call to exception | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:7:8:7:8 | IR: exn1 | void exn1::exn1(exn1&&) | -| try_catch.cpp:13:5:13:16 | IndirectMayWriteSideEffect: call to exn1 | Side effect instruction missing primary instruction in function $@ | try_catch.cpp:11:6:11:17 | IR: bypass_catch | void bypass_catch() | instructionWithoutSuccessor | VacuousDestructorCall.cpp:2:29:2:29 | InitializeParameter: y | | condition_decls.cpp:16:19:16:20 | IndirectMayWriteSideEffect: call to BoxedInt | From 3e1fd4a737549a47d322a47a3bf28720989ffceb Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 31 Oct 2019 18:03:34 -0700 Subject: [PATCH 0136/2538] [CPP-434] Add table of constructs to Qhelp. Rewrite examples section. --- change-notes/1.23/analysis-cpp.md | 2 +- .../Arithmetic/SignedOverflowCheck-bad2.cpp | 2 +- .../Arithmetic/SignedOverflowCheck-good1.cpp | 5 +- .../Arithmetic/SignedOverflowCheck-good2.cpp | 4 +- .../Arithmetic/SignedOverflowCheck.qhelp | 124 +++++++++++++++--- 5 files changed, 110 insertions(+), 27 deletions(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index b3e16dcc29a3..f98e3c7fef1b 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -9,7 +9,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Hard-coded Japanese era start date (`cpp/japanese-era/exact-era-date`) | reliability, japanese-era | This query is a combination of two old queries that were identical in purpose but separate as an implementation detail. This new query replaces Hard-coded Japanese era start date in call (`cpp/japanese-era/constructor-or-method-with-exact-era-date`) and Hard-coded Japanese era start date in struct (`cpp/japanese-era/struct-with-exact-era-date`). | -| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which is undefined behavior. Example: `a + b < a`. | +| Signed overflow check (`cpp/signed-overflow-check`) | correctness, reliability | Finds overflow checks that rely on signed integer addition to overflow, which has undefined behavior. Example: `a + b < a`. | ## Changes to existing queries diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp index d4d9cd75393b..7f69e374ed1c 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-bad2.cpp @@ -1,4 +1,4 @@ bool bar(unsigned short n1, unsigned short delta) { // NB: Comparison is always false - return n1 + delta < n1; // GOOD + return n1 + delta < n1; // GOOD (but misleading) } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp index 2209b8bff711..424684ee2ec9 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good1.cpp @@ -1,3 +1,4 @@ -bool baf(unsigned short n1, unsigned short delta) { - return (unsigned short)(n1 + delta) < n1; // GOOD +#include +bool foo(int n1, unsigned short delta) { + return n1 > INT_MAX - delta; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp index cccc66b71f80..de8de2b98470 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck-good2.cpp @@ -1,3 +1,3 @@ -bool baz(int n1, int delta) { - return (unsigned)n1 + delta < n1; // GOOD +bool bar(unsigned short n1, unsigned short delta) { + return (unsigned short)(n1 + delta) < n1; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index ae4dae550165..da7f86f021ba 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -4,11 +4,11 @@

    -When checking for integer overflow, one often writes tests like +When checking for integer overflow, you may often write tests like a + b < a. This works fine if a or b are unsigned integers, since any overflow in the addition -will cause the value to simply "wrap around". However, using -signed integers is problematic because signed overflows have undefined +will cause the value to simply "wrap around." However, using +signed integers is problematic because signed overflow has undefined behavior according to the C and C++ standards. If the addition overflows and has an undefined result, the comparison will likewise be undefined; it may produce an unintended result, or may be deleted entirely by an @@ -17,10 +17,89 @@ optimizing compiler.

    -When checking for overflow by adding two values, first make sure that a -or b are (converted into) unsigned values, unless it is -certain that the signed addition cannot overflow. +Solutions to this problem can be thought of as falling into one of two +categories: (1) rewrite the signed expression so that overflow cannot occur +but the signedness remains, or (2) rewrite (or cast) the signed expression +into unsigned form. + +The table below lists various expressions where signed overflow may +occur, along with proposed rewritings. It should not be +considered as exhaustive.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Original ConstructAlternate Construct(s)Notes
    + + + + + +
    unsigned short i, delta;
    i + delta < i
    + + + + + +
    unsigned short i, delta;
    (unsigned short)(i + delta) < i
    i + deltadoes not actually overflow due to int promotion
      + + + + + +
    unsigned short i, delta;
    i > USHORT_MAX - delta
    Must include limits.h or climits
    + + + + + +
    int i, delta;
    i + delta < i
    + + + + + +
    int i, delta;
    i > INT_MAX - delta
    Must include limits.h or climits
      + + + + + +
    int i, delta;
    (unsigned)i + delta < i
    Change in program semantics
      + + + + + +
    unsigned int i, delta;
    i + delta < i
    Change in program semantics

    @@ -34,6 +113,17 @@ result.

    +The following example builds upon the previous one. Instead of +performing an addition (which could overflow), we have re-framed the +solution so that a subtraction is used instead. Since delta +is promoted to a signed int and INT_MAX denotes +the largest possible positive value for an signed int, +the expression INT_MAX - delta can never be less than zero +or more than INT_MAX. Hence, any overflow and underflow +are avoided. +

    + +

    In the following example, even though both n and delta have been declared unsigned short, both are promoted to signed int prior to addition. Because we started out with the @@ -45,26 +135,18 @@ hold true, which likely is not what the programmer intended. (see also the

    -The following example builds upon the previous one. Again, we have two -unsigned short values getting promoted to a wider type, resulting -in a comparison that always succeeds (since there is no overflow). To -test whether we have an unsigned short overflow, we cast the -left-hand side to it, causing the right-hand side to remain an unsigned -short as well. -

    - -

    -In the next example, we have two signed int values that we -wish to add together. Adding them "as-is" opens the possibility of -a signed integer overflow, the results of which are undefined. -By casting one of the operands to unsigned, the entire -expression is evaluated using unsigned -values, which is defined behavior per the C/C++ standard. +The next example provides a solution to the previous one. Even though +i + delta does not overflow, casting it to an +unsigned short truncates the addition modulo 2^16, +so that unsigned short "wrap around" may now be observed. +Furthermore, since the left-hand side is now of type unsigned short, +the right-hand side does not need to be promoted to a signed int.

  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • +
  • W. Dietz,∗ P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • From 02bb142e7c6b3d8df058b60139504c1ead6b39e7 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 12:05:13 +0000 Subject: [PATCH 0137/2538] Update repository artifacts for name change --- CONTRIBUTING.md | 14 +++++++------- README.md | 12 ++++++------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 6c0714571fca..e074b1c2079d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,4 +1,4 @@ -# Contributing to QL +# Contributing to CodeQL We welcome contributions to our standard library and standard checks. Got an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! @@ -9,13 +9,13 @@ Before we accept your pull request, we require that you have agreed to our Contr If you have an idea for a query that you would like to share with other Semmle users, please open a pull request to add it to this repository. Follow the steps below to help other users understand what your query does, and to ensure that your query is consistent with the other Semmle queries. -1. **Consult the QL documentation for query writers** +1. **Consult the documentation for query writers** - There is lots of useful documentation to help you write QL, ranging from information about query file structure to language-specific tutorials. For more information on the documentation available, see [Writing QL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). + There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/writing-queries/writing-queries.html) on [help.semmle.com](https://help.semmle.com). -2. **Format your QL correctly** +2. **Format your code correctly** - All of Semmle's standard QL queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all QL contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md). + All of Semmle's standard queries and libraries are uniformly formatted for clarity and consistency, so we strongly recommend that all contributions follow the same formatting guidelines. If you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). For more information, see the [CodeQL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md). 3. **Make sure your query has the correct metadata** @@ -29,7 +29,7 @@ Follow the steps below to help other users understand what your query does, and The `select` statement of your query must be compatible with the query type (determined by the `@kind` metadata property) for alert or path results to be displayed correctly in LGTM and QL for Eclipse. For more information on `select` statement format, see [Introduction to query files](https://help.semmle.com/QL/learn-ql/writing-queries/introduction-to-queries.html#select-clause) on help.semmle.com. -5. **Save your query in a `.ql` file in correct language directory in this repository** +5. **Save your query in a `.ql` file in the correct language directory in this repository** There are five language-specific directories in this repository: @@ -54,7 +54,7 @@ repositories, which might be made public. We might also use this information to contact you in relation to your contributions, as well as in the normal course of software development. We also store records of your CLA agreements. Under GDPR legislation, we do this -on the basis of our legitimate interest in creating the QL product. +on the basis of our legitimate interest in creating the CodeQL product. Please do get in touch (privacy@semmle.com) if you have any questions about this or our data protection policies. diff --git a/README.md b/README.md index b483d29cae2c..a6aa5e38f1a3 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,16 @@ -# Semmle QL +# CodeQL -This open source repository contains the standard QL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide. +This open source repository contains the standard CodeQL libraries and queries that power [LGTM](https://lgtm.com), and the other products that [Semmle](https://semmle.com) makes available to its customers worldwide. -## How do I learn QL and run queries? +## How do I learn CodeQL and run queries? -There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing QL. +There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL. You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open-source project that's currently being analyzed. ## Contributing -We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your QL for consistency and clarity, how to write query metadata, and how to write query help documentation for your query. +We welcome contributions to our standard library and standard checks. Do you have an idea for a new check, or how to improve an existing query? Then please go ahead and open a pull request! Before you do, though, please take the time to read our [contributing guidelines](CONTRIBUTING.md). You can also consult our [style guides](https://github.com/Semmle/ql/tree/master/docs) to learn how to format your code for consistency and clarity, how to write query metadata, and how to write query help documentation for your query. ## License -The QL queries in this repository are licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com). +The code in this repository is licensed under [Apache License 2.0](LICENSE) by [Semmle](https://semmle.com). From 570e55190dda6e94d8080760f0987f6f6271becb Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 12:20:45 +0000 Subject: [PATCH 0138/2538] Update style guides for name change --- docs/ql-style-guide.md | 4 ++-- docs/query-metadata-style-guide.md | 7 +++---- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/docs/ql-style-guide.md b/docs/ql-style-guide.md index 7b6ee9caf948..9e926c0b07ed 100644 --- a/docs/ql-style-guide.md +++ b/docs/ql-style-guide.md @@ -1,8 +1,8 @@ -# QL Style Guide +# CodeQL style guide ## Introduction -This document describes how to format the QL code you contribute to this repository. It covers aspects such as layout, white-space, naming, and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code. +This document describes how to format the code you contribute to this repository. It covers aspects such as layout, white-space, naming, and documentation. Adhering to consistent standards makes code easier to read and maintain. Of course, these are only guidelines, and can be overridden as the need arises on a case-by-case basis. Where existing code deviates from these guidelines, prefer consistency with the surrounding code. Note, if you use QL for Eclipse, you can auto-format your query in the [QL editor](https://help.semmle.com/ql-for-eclipse/Content/WebHelp/ql-editor.html). Words in *italic* are defined in the [Glossary](#glossary). diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index 979594eb9252..aab4365c4453 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -1,6 +1,5 @@ # Query file metadata and alert message style guide - ## Introduction This document outlines the structure of Semmle query files. You should adopt this structure when contributing custom queries to this repository, in order to ensure that new queries are consistent with the standard Semmle queries. @@ -11,13 +10,13 @@ Query files have the extension `.ql`. Each file has two distinct areas: * Metadata area–displayed at the top of the file, contains the metadata that defines how results for the query are interpreted and gives a brief description of the purpose of the query. * Query definition–defined using QL. The query includes a select statement, which defines the content and format of the results. For further information about writing QL, see the following topics: - * [Learning QL](https://help.semmle.com/QL/learn-ql/index.html) + * [Learning CodeQL](https://help.semmle.com/QL/learn-ql/index.html) * [QL language handbook](https://help.semmle.com/QL/ql-handbook/index.html) * [QL language specification](https://help.semmle.com/QL/ql-spec/language.html) * [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md) -For examples of query files for the languages supported by Semmle, visit the following links: +For examples of query files for the languages supported by CodeQL, visit the following links: * [C/C++ queries](https://help.semmle.com/wiki/display/CCPPOBJ/) * [C# queries](https://help.semmle.com/wiki/display/CSHARP/) @@ -178,4 +177,4 @@ For examples of select clauses and alert messages, see the query source files at * [JavaScript queries](https://help.semmle.com/wiki/display/JS/) * [Python queries](https://help.semmle.com/wiki/display/PYTHON/) -For further information on query writing, see [Writing QL queries](https://help.semmle.com/QL/learn-ql/ql/writing-queries/writing-queries.html). For more information on learning QL, see [Learning QL](https://help.semmle.com/QL/learn-ql/index.html). +For further information on query writing, see [Writing CodeQL queries](https://help.semmle.com/QL/learn-ql/ql/writing-queries/writing-queries.html). For more information on learning CodeQL, see [Learning CodeQL](https://help.semmle.com/QL/learn-ql/index.html). From 236e1f7955a66a94562aa003253dd8d43093e7fd Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 12:27:43 +0000 Subject: [PATCH 0139/2538] Update change notes for name change --- change-notes/1.23/analysis-cpp.md | 2 +- change-notes/1.23/analysis-csharp.md | 2 +- change-notes/1.23/analysis-java.md | 2 +- change-notes/1.23/analysis-javascript.md | 2 +- change-notes/support/README.md | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index 64e9b98fcfb6..a24559dc5d03 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -24,7 +24,7 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. | Unclear comparison precedence (`cpp/comparison-precedence`) | Fewer false positive results | False positives involving template classes and functions have been fixed. | | Comparison of narrow type with wide type in loop condition (`cpp/comparison-with-wider-type`) | Higher precision | The precision of this query has been increased to "high" as the alerts from this query have proved to be valuable on real-world projects. With this precision, results are now displayed by default in LGTM. | -## Changes to QL libraries +## Changes to libraries * The data-flow library has been extended with a new feature to aid debugging. Instead of specifying `isSink(Node n) { any() }` on a configuration to diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index 7ec412a0eb23..1b9b70f9172e 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -24,7 +24,7 @@ The following changes in version 1.23 affect C# analysis in all applications. * `nameof` expressions are now extracted correctly when the name is a namespace. -## Changes to QL libraries +## Changes to libraries * The new class `NamespaceAccess` models accesses to namespaces, for example in `nameof` expressions. * The data-flow library now makes it easier to specify barriers/sanitizers diff --git a/change-notes/1.23/analysis-java.md b/change-notes/1.23/analysis-java.md index b81b681aac54..8c38f57e9d21 100644 --- a/change-notes/1.23/analysis-java.md +++ b/change-notes/1.23/analysis-java.md @@ -19,7 +19,7 @@ The following changes in version 1.23 affect Java analysis in all applications. | Query built without neutralizing special characters (`java/concatenated-sql-query`) | More results | The query now identifies arguments to `Statement.executeLargeUpdate` and `Connection.prepareCall` as SQL expressions sinks. | | Useless comparison test (`java/constant-comparison`) | Fewer false positives | Additional overflow check patterns are now recognized and no longer reported. | -## Changes to QL libraries +## Changes to libraries * The data-flow library has been extended with a new feature to aid debugging. Instead of specifying `isSink(Node n) { any() }` on a configuration to diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 20f9ad1df875..cc349113468e 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -46,7 +46,7 @@ | Uncontrolled data used in path expression (`js/path-injection`) | Fewer false-positive results | This query now recognizes calls to Express `sendFile` as safe in some cases. | | Unknown directive (`js/unknown-directive`) | Fewer false positive results | This query no longer flags uses of ":", which is sometimes used like a directive. | -## Changes to QL libraries +## Changes to libraries * `Expr.getDocumentation()` now handles chain assignments. diff --git a/change-notes/support/README.md b/change-notes/support/README.md index 7813c69523d7..f111a4371832 100644 --- a/change-notes/support/README.md +++ b/change-notes/support/README.md @@ -1,6 +1,6 @@ # Files moved to ``docs`` directory -Now that all of the QL documentation is in this repository, +Now that all of the CodeQL documentation is in this repository, notes on the languages, compilers, and frameworks supported have moved. They're now stored as part of the Sphinx ``support`` project with the other documentation: ``docs/language/support``. From 692e977a7148da6c6dc13a38c258b9034ae84bf7 Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 13:44:23 +0000 Subject: [PATCH 0140/2538] Update docs/query-metadata-style-guide.md Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/query-metadata-style-guide.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/query-metadata-style-guide.md b/docs/query-metadata-style-guide.md index aab4365c4453..d5f5606002c3 100644 --- a/docs/query-metadata-style-guide.md +++ b/docs/query-metadata-style-guide.md @@ -13,7 +13,7 @@ Query files have the extension `.ql`. Each file has two distinct areas: * [Learning CodeQL](https://help.semmle.com/QL/learn-ql/index.html) * [QL language handbook](https://help.semmle.com/QL/ql-handbook/index.html) * [QL language specification](https://help.semmle.com/QL/ql-spec/language.html) - * [QL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md) + * [CodeQL style guide](https://github.com/Semmle/ql/blob/master/docs/ql-style-guide.md) For examples of query files for the languages supported by CodeQL, visit the following links: From 458108f66b7fc5848ff3cffb7477efd4817e7fca Mon Sep 17 00:00:00 2001 From: Felicity Chapman Date: Fri, 1 Nov 2019 14:08:50 +0000 Subject: [PATCH 0141/2538] Make 'open source' consistent on the page and with other docs --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a6aa5e38f1a3..3c73253b6dfe 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ This open source repository contains the standard CodeQL libraries and queries t ## How do I learn CodeQL and run queries? There is [extensive documentation](https://help.semmle.com/QL/learn-ql/) on getting started with writing CodeQL. -You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open-source project that's currently being analyzed. +You can use the [interactive query console](https://lgtm.com/help/lgtm/using-query-console) on LGTM.com or the [QL for Eclipse](https://lgtm.com/help/lgtm/running-queries-ide) plugin to try out your queries on any open source project that's currently being analyzed. ## Contributing From e2b0ec5696111ab5183d291de61dbd5b81b5ce3e Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 16:17:17 +0000 Subject: [PATCH 0142/2538] JS: Handle multiple and/or operators in SanitizerFunction --- .../javascript/dataflow/TaintTracking.qll | 24 +++++++++++-- .../TaintTracking/BasicTaintTracking.expected | 2 ++ .../TaintTracking/DataFlowTracking.expected | 5 +++ .../TaintTracking/sanitizer-function.js | 35 +++++++++++++++++++ 4 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 06a0d9042613..41afdb653f75 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -846,6 +846,26 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } + /** + * Gets an operand of the given `&&` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ + private Expr getALogicalAndOperand(LogAndExpr e) { + result = e.getAnOperand() + } + + /** + * Gets an operand of the given `||` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ + private Expr getALogicalOrOperand(LogOrExpr e) { + result = e.getAnOperand() + } + /** * A function that returns the result of a sanitizer check. */ @@ -860,10 +880,10 @@ module TaintTracking { returnExpr = sanitizer.asExpr() or // ad hoc support for conjunctions: - returnExpr.(LogAndExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = true + getALogicalAndOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = true or // ad hoc support for disjunctions: - returnExpr.(LogOrExpr).getAnOperand() = sanitizer.asExpr() and sanitizerOutcome = false + getALogicalOrOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = false | exists(SsaExplicitDefinition ssa | ssa.getDef().getSource() = returnExpr and diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 2722f67d6fdf..df1d6306feb8 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,6 +69,8 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index 6a589e3e0d93..f3023ad44daa 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -41,6 +41,11 @@ | partialCalls.js:4:17:4:24 | source() | partialCalls.js:30:14:30:20 | x.value | | partialCalls.js:4:17:4:24 | source() | partialCalls.js:41:10:41:18 | id(taint) | | partialCalls.js:4:17:4:24 | source() | partialCalls.js:51:14:51:14 | x | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:14:10:14:14 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:17:14:17:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:21:14:21:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:25:14:25:18 | taint | +| sanitizer-function.js:12:17:12:24 | source() | sanitizer-function.js:33:14:33:18 | taint | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js b/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js new file mode 100644 index 000000000000..6df74cf29eec --- /dev/null +++ b/javascript/ql/test/library-tests/TaintTracking/sanitizer-function.js @@ -0,0 +1,35 @@ +function test() { + function myCheck1(x) { + return x === "a" && something() && somethingElse(); + } + function myCheck2(x) { + return something() && x === "a" && somethingElse(); + } + function myCheck3(x) { + return something() && somethingElse() && x === "a"; + } + + let taint = source(); + + sink(taint); // NOT OK + + if (myCheck1(taint)) { + sink(taint); // OK + } + + if (myCheck2(taint)) { + sink(taint); // OK + } + + if (myCheck3(taint)) { + sink(taint); // OK + } + + function badCheck(x) { + return something && x + isSafe(x) != null; + } + + if (badCheck(taint)) { + sink(taint); // NOT OK + } +} From d6158427c5cdecea8569441c71c59bb892304380 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 22:33:36 +0000 Subject: [PATCH 0143/2538] JS: Generalize SanitizerFunction to data flow configs and flow labels --- .../javascript/dataflow/Configuration.qll | 169 +++++++++++++++--- .../javascript/dataflow/TaintTracking.qll | 89 +-------- 2 files changed, 145 insertions(+), 113 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 568c1c92eab6..68771406006e 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -147,7 +147,7 @@ abstract class Configuration extends string { */ predicate isBarrier(DataFlow::Node node) { exists(BarrierGuardNode guard | - isBarrierGuard(guard) and + isBarrierGuardInternal(guard) and guard.internalBlocks(node, "") ) } @@ -181,7 +181,7 @@ abstract class Configuration extends string { */ predicate isLabeledBarrier(DataFlow::Node node, FlowLabel lbl) { exists(BarrierGuardNode guard | - isBarrierGuard(guard) and + isBarrierGuardInternal(guard) and guard.internalBlocks(node, lbl) ) or @@ -198,6 +198,12 @@ abstract class Configuration extends string { */ predicate isBarrierGuard(BarrierGuardNode guard) { none() } + private predicate isBarrierGuardInternal(BarrierGuardNode guard) { + isBarrierGuard(guard) + or + guard.(AdditionalBarrierGuardNode).appliesTo(this) + } + /** * Holds if data may flow from `source` to `sink` for this configuration. */ @@ -304,7 +310,7 @@ abstract class BarrierGuardNode extends DataFlow::Node { forex(SsaVariable input | input = ref.getAnInput() | asExpr() = ref.getGuard().getTest() and outcome = ref.getGuard().(ConditionGuardNode).getOutcome() and - internalBlocksExpr(outcome, input.getAUse(), label) + barrierGuardBlocksExpr(this, outcome, input.getAUse(), label) ) ) or @@ -313,33 +319,11 @@ abstract class BarrierGuardNode extends DataFlow::Node { nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and asExpr() = cond.getTest() and outcome = cond.getOutcome() and - internalBlocksAccessPath(outcome, p, label) and + barrierGuardBlocksAccessPath(this, outcome, p, label) and cond.dominates(bb) ) } - /** - * Holds if data flow node `nd` acts as a barrier for data flow. - * - * `label` is bound to the blocked label, or the empty string if all labels should be blocked. - */ - private predicate internalBlocksExpr(boolean outcome, Expr test, string label) { - blocks(outcome, test) and label = "" - or - blocks(outcome, test, label) - } - - /** - * Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through - * an access path. - * - * `label` is bound to the blocked label, or the empty string if all labels should be blocked. - */ - pragma[noinline] - private predicate internalBlocksAccessPath(boolean outcome, AccessPath ap, string label) { - internalBlocksExpr(outcome, ap.getAnInstance(), label) - } - /** * Holds if this node blocks expression `e` provided it evaluates to `outcome`. * @@ -353,6 +337,32 @@ abstract class BarrierGuardNode extends DataFlow::Node { predicate blocks(boolean outcome, Expr e, FlowLabel label) { none() } } +/** + * Holds if data flow node `nd` acts as a barrier for data flow. + * + * `label` is bound to the blocked label, or the empty string if all labels should be blocked. + */ +private predicate barrierGuardBlocksExpr(BarrierGuardNode guard, boolean outcome, Expr test, string label) { + guard.blocks(outcome, test) and label = "" + or + guard.blocks(outcome, test, label) + or + // Handle labelled barrier guard functions specially, to avoid negative recursion + // through the non-abstract 3-argument version of blocks(). + guard.(AdditionalBarrierGuardCall).internalBlocksLabel(outcome, test, label) +} + +/** + * Holds if data flow node `nd` acts as a barrier for data flow due to aliasing through + * an access path. + * + * `label` is bound to the blocked label, or the empty string if all labels should be blocked. + */ +pragma[noinline] +private predicate barrierGuardBlocksAccessPath(BarrierGuardNode guard, boolean outcome, AccessPath ap, string label) { + barrierGuardBlocksExpr(guard, outcome, ap.getAnInstance(), label) +} + /** * A guard node that only blocks specific labels. */ @@ -1186,3 +1196,110 @@ module PathGraph { not pred = finalMidNode(succ) } } + + + +/** + * Gets an operand of the given `&&` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ +private Expr getALogicalAndOperand(LogAndExpr e) { + result = e.getAnOperand() +} + +/** + * Gets an operand of the given `||` operator. + * + * We use this to construct the transitive closure over a relation + * that does not include all of `BinaryExpr.getAnOperand`. + */ +private Expr getALogicalOrOperand(LogOrExpr e) { + result = e.getAnOperand() +} + +/** + * A `BarrierGuardNode` that controls which data flow + * configurations it is used in. + * + * Note: For performance reasons, all subclasses of this class should be part + * of the standard library. Override `Configuration::isBarrierGuard` + * for analysis-specific barrier guards. + */ +abstract class AdditionalBarrierGuardNode extends BarrierGuardNode { + abstract predicate appliesTo(Configuration cfg); +} + +/** + * A function that returns the result of a barrier guard. + */ +private class BarrierGuardFunction extends Function { + DataFlow::ParameterNode sanitizedParameter; + BarrierGuardNode guard; + boolean guardOutcome; + string label; + + BarrierGuardFunction() { + exists(Expr e | + exists(Expr returnExpr | + returnExpr = guard.asExpr() + or + // ad hoc support for conjunctions: + getALogicalAndOperand+(returnExpr) = guard.asExpr() and guardOutcome = true + or + // ad hoc support for disjunctions: + getALogicalOrOperand+(returnExpr) = guard.asExpr() and guardOutcome = false + | + exists(SsaExplicitDefinition ssa | + ssa.getDef().getSource() = returnExpr and + ssa.getVariable().getAUse() = getAReturnedExpr() + ) + or + returnExpr = getAReturnedExpr() + ) and + sanitizedParameter.flowsToExpr(e) and + barrierGuardBlocksExpr(guard, guardOutcome, e, label) + ) and + getNumParameter() = 1 and + sanitizedParameter.getParameter() = getParameter(0) + } + + /** + * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`. + */ + predicate isBarrierCall(DataFlow::CallNode call, Expr e, boolean outcome, string lbl) { + exists(DataFlow::Node arg | + arg.asExpr() = e and + arg = call.getArgument(0) and + call.getNumArgument() = 1 and + argumentPassing(call, arg, this, sanitizedParameter) and + outcome = guardOutcome and + lbl = label + ) + } + + /** + * Holds if this function applies to the flow in `cfg`. + */ + predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(guard) } +} + +/** + * A call that sanitizes an argument. + */ +private class AdditionalBarrierGuardCall extends AdditionalBarrierGuardNode, DataFlow::CallNode { + BarrierGuardFunction f; + + AdditionalBarrierGuardCall() { f.isBarrierCall(this, _, _, _) } + + override predicate blocks(boolean outcome, Expr e) { + f.isBarrierCall(this, e, outcome, "") + } + + predicate internalBlocksLabel(boolean outcome, Expr e, DataFlow::FlowLabel label) { + f.isBarrierCall(this, e, outcome, label) + } + + override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } +} diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 41afdb653f75..43a04c553632 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -133,8 +133,8 @@ module TaintTracking { * configurations it is used in. * * Note: For performance reasons, all subclasses of this class should be part - * of the standard library. Override `Configuration::isSanitizer` - * for analysis-specific taint steps. + * of the standard library. Override `Configuration::isSanitizerGuard` + * for analysis-specific taint sanitizer guards. */ abstract class AdditionalSanitizerGuardNode extends SanitizerGuardNode { /** @@ -846,91 +846,6 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } - /** - * Gets an operand of the given `&&` operator. - * - * We use this to construct the transitive closure over a relation - * that does not include all of `BinaryExpr.getAnOperand`. - */ - private Expr getALogicalAndOperand(LogAndExpr e) { - result = e.getAnOperand() - } - - /** - * Gets an operand of the given `||` operator. - * - * We use this to construct the transitive closure over a relation - * that does not include all of `BinaryExpr.getAnOperand`. - */ - private Expr getALogicalOrOperand(LogOrExpr e) { - result = e.getAnOperand() - } - - /** - * A function that returns the result of a sanitizer check. - */ - private class SanitizingFunction extends Function { - DataFlow::ParameterNode sanitizedParameter; - SanitizerGuardNode sanitizer; - boolean sanitizerOutcome; - - SanitizingFunction() { - exists(Expr e | - exists(Expr returnExpr | - returnExpr = sanitizer.asExpr() - or - // ad hoc support for conjunctions: - getALogicalAndOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = true - or - // ad hoc support for disjunctions: - getALogicalOrOperand+(returnExpr) = sanitizer.asExpr() and sanitizerOutcome = false - | - exists(SsaExplicitDefinition ssa | - ssa.getDef().getSource() = returnExpr and - ssa.getVariable().getAUse() = getAReturnedExpr() - ) - or - returnExpr = getAReturnedExpr() - ) and - sanitizedParameter.flowsToExpr(e) and - sanitizer.sanitizes(sanitizerOutcome, e) - ) and - getNumParameter() = 1 and - sanitizedParameter.getParameter() = getParameter(0) - } - - /** - * Holds if this function sanitizes argument `e` of call `call`, provided the call evaluates to `outcome`. - */ - predicate isSanitizingCall(DataFlow::CallNode call, Expr e, boolean outcome) { - exists(DataFlow::Node arg | - arg.asExpr() = e and - arg = call.getArgument(0) and - call.getNumArgument() = 1 and - FlowSteps::argumentPassing(call, arg, this, sanitizedParameter) and - outcome = sanitizerOutcome - ) - } - - /** - * Holds if this function applies to the flow in `cfg`. - */ - predicate appliesTo(Configuration cfg) { cfg.isBarrierGuard(sanitizer) } - } - - /** - * A call that sanitizes an argument. - */ - private class AdditionalSanitizingCall extends AdditionalSanitizerGuardNode, DataFlow::CallNode { - SanitizingFunction f; - - AdditionalSanitizingCall() { f.isSanitizingCall(this, _, _) } - - override predicate sanitizes(boolean outcome, Expr e) { f.isSanitizingCall(this, e, outcome) } - - override predicate appliesTo(Configuration cfg) { f.appliesTo(cfg) } - } - /** * An equality test on `e.origin` or `e.source` where `e` is a `postMessage` event object, * considered as a sanitizer for `e`. From f48d16fcb7450579e4e36e6eaa1a1d8547eed4ef Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 1 Nov 2019 15:22:03 +0000 Subject: [PATCH 0144/2538] JS: Support barrier guards that are reflective calls --- .../semmle/javascript/dataflow/Configuration.qll | 11 +++++++++-- .../ql/src/semmle/javascript/dataflow/DataFlow.qll | 9 +++++++++ .../TaintTracking/BasicTaintTracking.expected | 2 ++ .../TaintTracking/BasicTaintTracking.ql | 6 +++++- .../TaintTracking/DataFlowTracking.expected | 3 +++ .../TaintTracking/sanitizer-guards.js | 14 ++++++++++++++ 6 files changed, 42 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll index 68771406006e..11cfb24376e6 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Configuration.qll @@ -308,7 +308,7 @@ abstract class BarrierGuardNode extends DataFlow::Node { exists(SsaRefinementNode ref, boolean outcome | nd = DataFlow::ssaDefinitionNode(ref) and forex(SsaVariable input | input = ref.getAnInput() | - asExpr() = ref.getGuard().getTest() and + getExpr() = ref.getGuard().getTest() and outcome = ref.getGuard().(ConditionGuardNode).getOutcome() and barrierGuardBlocksExpr(this, outcome, input.getAUse(), label) ) @@ -317,13 +317,20 @@ abstract class BarrierGuardNode extends DataFlow::Node { // 2) `nd` is an instance of an access path `p`, and dominated by a barrier for `p` exists(AccessPath p, BasicBlock bb, ConditionGuardNode cond, boolean outcome | nd = DataFlow::valueNode(p.getAnInstanceIn(bb)) and - asExpr() = cond.getTest() and + getExpr() = cond.getTest() and outcome = cond.getOutcome() and barrierGuardBlocksAccessPath(this, outcome, p, label) and cond.dominates(bb) ) } + /** Gets the corresponding expression, including that of reflective calls. */ + private Expr getExpr() { + result = asExpr() + or + this = DataFlow::reflectiveCallNode(result) + } + /** * Holds if this node blocks expression `e` provided it evaluates to `outcome`. * diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37c..0faecc011095 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -932,6 +932,15 @@ module DataFlow { */ DataFlow::Node globalAccessPathRootPseudoNode() { result instanceof TGlobalAccessPathRoot } + /** + * Gets a data flow node representing the underlying call performed by the given + * call to `Function.prototype.call` or `Function.prototype.apply`. + * + * For example, for an expression `fn.call(x, y)`, this gets a call node with `fn` as the + * callee, `x` as the receiver, and `y` as the first argument. + */ + DataFlow::InvokeNode reflectiveCallNode(InvokeExpr expr) { result = TReflectiveCallNode(expr, _) } + /** * Provides classes representing various kinds of calls. * diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index df1d6306feb8..93dc5e6e200c 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -75,6 +75,8 @@ typeInferenceMismatch | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x | | spread.js:2:15:2:22 | source() | spread.js:4:8:4:19 | { ...taint } | | spread.js:2:15:2:22 | source() | spread.js:5:8:5:43 | { f: 'h ... orld' } | | spread.js:2:15:2:22 | source() | spread.js:7:8:7:19 | [ ...taint ] | diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql index 0b1d5d9da84b..26c66a1b4fe0 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.ql @@ -1,7 +1,11 @@ import javascript import semmle.javascript.dataflow.InferredTypes -DataFlow::CallNode getACall(string name) { result.getCalleeName() = name } +DataFlow::CallNode getACall(string name) { + result.getCalleeName() = name + or + result.getCalleeNode().getALocalSource() = DataFlow::globalVarRef(name) +} class Sink extends DataFlow::Node { Sink() { this = getACall("sink").getAnArgument() } diff --git a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected index f3023ad44daa..f2799d763fdc 100644 --- a/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/DataFlowTracking.expected @@ -50,6 +50,9 @@ | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:26:9:26:14 | this.x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:45:8:45:8 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:48:10:48:10 | x | +| sanitizer-guards.js:43:11:43:18 | source() | sanitizer-guards.js:52:10:52:10 | x | | thisAssignments.js:4:17:4:24 | source() | thisAssignments.js:5:10:5:18 | obj.field | | thisAssignments.js:7:19:7:26 | source() | thisAssignments.js:8:10:8:20 | this.field2 | | tst.js:2:13:2:20 | source() | tst.js:4:10:4:10 | x | diff --git a/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js b/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js index 494e828460d3..03d6a9aedd74 100644 --- a/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js +++ b/javascript/ql/test/library-tests/TaintTracking/sanitizer-guards.js @@ -38,3 +38,17 @@ class C { }); } } + +function reflective() { + let x = source(); + + sink(x); // NOT OK + + if (isSafe.call(x)) { + sink(x); // NOT OK - `isSafe` does not sanitize the receiver + } + + if (isSafe.call(null, x)) { + sink(x); // OK + } +} From fa203254ce09661d52db689e4f5a388f0acf69b7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:09:42 +0000 Subject: [PATCH 0145/2538] CPP: Add test cases. --- .../TlsSettingsMisconfiguration.expected | 11 ++++ .../Likely Bugs/Protocols/boostorg/test2.cpp | 55 +++++++++++++++++++ 2 files changed, 66 insertions(+) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected index 8a3acb1aeb52..c6883e156d1f 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.expected @@ -1,3 +1,14 @@ +| test2.cpp:15:32:15:33 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:15:32:15:33 | call to context | boost::asio::ssl::context::context | test2.cpp:14:40:14:72 | sslv23 | sslv23 | test2.cpp:15:32:15:33 | call to context | no_sslv3 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_sslv3 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:23:32:23:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:23:32:23:65 | call to context | boost::asio::ssl::context::context | test2.cpp:23:32:23:64 | sslv23 | sslv23 | test2.cpp:23:32:23:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test2.cpp:31:32:31:64 | sslv23 | sslv23 | test2.cpp:31:32:31:65 | call to context | no_tlsv1_1 has not been set | +| test2.cpp:45:35:45:98 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:45:35:45:98 | call to context | boost::asio::ssl::context::context | test2.cpp:45:65:45:97 | sslv23 | sslv23 | test2.cpp:45:35:45:98 | call to context | no_sslv3 has not been set | +| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_sslv3 has not been set | +| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1 has not been set | +| test2.cpp:52:32:52:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test2.cpp:52:32:52:65 | call to context | boost::asio::ssl::context::context | test2.cpp:52:32:52:64 | sslv23 | sslv23 | test2.cpp:52:32:52:65 | call to context | no_tlsv1_1 has not been set | | test.cpp:25:32:25:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:25:32:25:65 | call to context | boost::asio::ssl::context::context | test.cpp:25:32:25:64 | sslv23 | sslv23 | test.cpp:25:32:25:65 | call to context | no_sslv3 has not been set | | test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_sslv3 has not been set | | test.cpp:31:32:31:65 | call to context | Usage of $@ with protocol $@ is not configured correctly: The option $@. | test.cpp:31:32:31:65 | call to context | boost::asio::ssl::context::context | test.cpp:31:32:31:64 | sslv23 | sslv23 | test.cpp:31:32:31:65 | call to context | no_tlsv1 has not been set | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp new file mode 100644 index 000000000000..5679cee8b0f8 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Protocols/boostorg/test2.cpp @@ -0,0 +1,55 @@ +#include "asio/boost_simulation.hpp" + +void good1() +{ + // GOOD + boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; + boost::asio::ssl::context ctx(m); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); +} + +void bad1() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context::method m = boost::asio::ssl::context::sslv23; + boost::asio::ssl::context ctx(m); + ctx.set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); +} + +void good2() +{ + // GOOD [FALSE POSITIVE x 3] + boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3; + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(opts); +} + +void bad2() +{ + // BAD: missing disable SSLv3 [WITH FALSE POSITIVE x 2] + boost::asio::ssl::context::options opts = boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1; + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); + ctx.set_options(opts); +} + +void good3() +{ + // GOOD + boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1 | boost::asio::ssl::context::no_sslv3); +} + +void bad3() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context *ctx = new boost::asio::ssl::context(boost::asio::ssl::context::sslv23); + ctx->set_options(boost::asio::ssl::context::no_tlsv1 | boost::asio::ssl::context::no_tlsv1_1); +} + +void bad4() +{ + // BAD: missing disable SSLv3 + boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); +} + + From 6a865ed580c3dfdfedb0236f9067206421b37d4c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 15:03:10 +0000 Subject: [PATCH 0146/2538] CPP: De-duplicate TlsSettingsMisconfiguration.ql. --- .../boostorg/TlsSettingsMisconfiguration.ql | 25 ++----------------- 1 file changed, 2 insertions(+), 23 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 83ed90bafab1..0089221799cb 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -46,29 +46,8 @@ predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { bindingset[flag] predicate isOptionNotSet(ConstructorCall cc, int flag) { - not exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, - Expr optionsSink - | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and - exists(VariableAccess contextSetOptions | - testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and - exists(FunctionCall fcSetOptions, BoostorgAsio::SslSetOptionsFunction f | - f.getACallToThisFunction() = fcSetOptions - | - contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | - optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) - | - optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag - ) - ) - ) + not exists(FunctionCall fcSetOptions | + isOptionSet(cc, flag, fcSetOptions) ) } From c08493670b56d1ac019161e676f766c930942df7 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 15:09:25 +0000 Subject: [PATCH 0147/2538] CPP: Speed up ExistsAnyFlowConfig. --- .../Protocols/boostorg/TlsSettingsMisconfiguration.ql | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 0089221799cb..1a5dbfb74fcb 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -13,7 +13,9 @@ import semmle.code.cpp.security.boostorg.asio.protocols class ExistsAnyFlowConfig extends DataFlow::Configuration { ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } - override predicate isSource(DataFlow::Node source) { any() } + override predicate isSource(DataFlow::Node source) { + source.asExpr() instanceof ConstructorCall + } override predicate isSink(DataFlow::Node sink) { any() } } @@ -21,12 +23,12 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig testConfig, + BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig anyFlowConfig, Expr optionsSink | config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and exists(VariableAccess contextSetOptions | - testConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | contextSetOptions = fcSetOptions.getQualifier() and forall( From 98b9afd83f772e45f9c3c44cdb8211eef0d01446 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 15:19:36 +0000 Subject: [PATCH 0148/2538] CPP: Remove apparently irrelevant parts of the query. This is not strictly behaviour preserving, but I believe the parts I've removed or simplified weren't intended to do what they were doing. --- .../boostorg/TlsSettingsMisconfiguration.ql | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 1a5dbfb74fcb..369dbf77973d 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -22,11 +22,9 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { - exists( - BoostorgAsio::SslContextFlowsToSetOptionConfig config, ExistsAnyFlowConfig anyFlowConfig, - Expr optionsSink + exists(BoostorgAsio::SslContextClass c, ExistsAnyFlowConfig anyFlowConfig | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + c.getAContructorCall() = cc and exists(VariableAccess contextSetOptions | anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | @@ -55,15 +53,14 @@ predicate isOptionNotSet(ConstructorCall cc, int flag) { from BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, - BoostorgAsio::SslContextFlowsToSetOptionConfig config, Expr protocolSource, Expr protocolSink, - ConstructorCall cc, Expr e, string msg + Expr protocolSource, Expr protocolSink, + BoostorgAsio::SslContextClass c, ConstructorCall cc, Expr e, string msg where configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and ( BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and - not exists(Expr optionsSink | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + not ( isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoSsl3(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and @@ -72,8 +69,7 @@ where or BoostorgAsio::isExprTlsBoostProtocol(protocolSource) and not BoostorgAsio::isExprSslV23BoostProtocol(protocolSource) and - not exists(Expr optionsSink | - config.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(optionsSink)) and + not ( isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1(), _) and isOptionSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_1(), _) and isOptionNotSet(cc, BoostorgAsio::getShiftedSslOptionsNoTls1_2()) From 08293d00095c4f01b8b1fe067b3716291c5a08a1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 17:56:22 +0000 Subject: [PATCH 0149/2538] CPP: Simplify. --- .../boostorg/TlsSettingsMisconfiguration.ql | 36 +++++++++---------- 1 file changed, 17 insertions(+), 19 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 369dbf77973d..6c2026c83d64 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -14,7 +14,9 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { ExistsAnyFlowConfig() { this = "ExistsAnyFlowConfig" } override predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof ConstructorCall + exists(BoostorgAsio::SslContextClass c | + c.getAContructorCall() = source.asExpr() + ) } override predicate isSink(DataFlow::Node sink) { any() } @@ -22,23 +24,19 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { bindingset[flag] predicate isOptionSet(ConstructorCall cc, int flag, FunctionCall fcSetOptions) { - exists(BoostorgAsio::SslContextClass c, ExistsAnyFlowConfig anyFlowConfig - | - c.getAContructorCall() = cc and - exists(VariableAccess contextSetOptions | - anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and - exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | - contextSetOptions = fcSetOptions.getQualifier() and - forall( - Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, - Expr optionArgumentSource - | - optionArgument = fcSetOptions.getArgument(0) and - optionArgConfig - .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) - | - optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag - ) + exists(ExistsAnyFlowConfig anyFlowConfig, VariableAccess contextSetOptions | + anyFlowConfig.hasFlow(DataFlow::exprNode(cc), DataFlow::exprNode(contextSetOptions)) and + exists(BoostorgAsio::SslSetOptionsFunction f | f.getACallToThisFunction() = fcSetOptions | + contextSetOptions = fcSetOptions.getQualifier() and + forall( + Expr optionArgument, BoostorgAsio::SslOptionConfig optionArgConfig, + Expr optionArgumentSource + | + optionArgument = fcSetOptions.getArgument(0) and + optionArgConfig + .hasFlow(DataFlow::exprNode(optionArgumentSource), DataFlow::exprNode(optionArgument)) + | + optionArgument.getValue().toInt().bitShiftRight(16).bitAnd(flag) = flag ) ) ) @@ -54,7 +52,7 @@ predicate isOptionNotSet(ConstructorCall cc, int flag) { from BoostorgAsio::SslContextCallTlsProtocolConfig configConstructor, Expr protocolSource, Expr protocolSink, - BoostorgAsio::SslContextClass c, ConstructorCall cc, Expr e, string msg + ConstructorCall cc, Expr e, string msg where configConstructor.hasFlow(DataFlow::exprNode(protocolSource), DataFlow::exprNode(protocolSink)) and cc.getArgument(0) = protocolSink and From c2812197a96059247677c7bfd3f62aab9b675bf0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 1 Nov 2019 18:16:12 +0000 Subject: [PATCH 0150/2538] CPP: Further speedup. --- .../Protocols/boostorg/TlsSettingsMisconfiguration.ql | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql index 6c2026c83d64..85f4ca1a8605 100644 --- a/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql +++ b/cpp/ql/src/Likely Bugs/Protocols/boostorg/TlsSettingsMisconfiguration.ql @@ -19,7 +19,12 @@ class ExistsAnyFlowConfig extends DataFlow::Configuration { ) } - override predicate isSink(DataFlow::Node sink) { any() } + override predicate isSink(DataFlow::Node sink) { + exists(BoostorgAsio::SslSetOptionsFunction f, FunctionCall fcSetOptions | + f.getACallToThisFunction() = fcSetOptions and + fcSetOptions.getQualifier() = sink.asExpr() + ) + } } bindingset[flag] From 2bad9394b7d909186bb8977ce147982c36d00041 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Fri, 1 Nov 2019 15:24:22 -0700 Subject: [PATCH 0151/2538] [CPP-434] Squelch alerts for expressions inside macros; try to make Qhelp Jenkins-friendly. --- .../Arithmetic/SignedOverflowCheck.qhelp | 46 +++++++++---------- .../Arithmetic/SignedOverflowCheck.ql | 1 + .../SignedOverflowCheck.cpp | 7 +++ 3 files changed, 31 insertions(+), 23 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index da7f86f021ba..302fbd4ed233 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -24,81 +24,81 @@ into unsigned form. The table below lists various expressions where signed overflow may occur, along with proposed rewritings. It should not be -considered as exhaustive. +considered exhaustive.

    - + - - + + - + - + - +
    Original Construct Alternate Construct(s) Notes
    - + - +
    unsigned short i, delta;
    i + delta < i
    - + - +
    unsigned short i, delta;
    (unsigned short)(i + delta) < i
    i + deltadoes not actually overflow due to int promotion
      - + - +
    unsigned short i, delta;
    i > USHORT_MAX - delta
    Must include limits.h or climitsMust include limits.h or climits; delta > 0
    - + - +
    int i, delta;
    i + delta < i
    - + - +
    int i, delta;
    i > INT_MAX - delta
    Must include limits.h or climitsMust include limits.h or climits; delta > 0
      - + - +
    int i, delta;
    (unsigned)i + delta < i
    Change in program semantics
      - + - +
    unsigned int i, delta;
    i + delta < i
    Change in program semantics
    @@ -131,7 +131,7 @@ narrower short type, the addition is guaranteed not to overflow and is therefore defined. But the fact that n1 + delta never overflows means that the condition n1 + delta < n1 will never hold true, which likely is not what the programmer intended. (see also the -BadArithmeticOverflow.Check.ql query). +cpp/bad-addition-overflow-check query).

    @@ -147,6 +147,6 @@ the right-hand side does not need to be promoted to a signed int.

  • comp.lang.c FAQ list · Question 3.19 (Preserving rules)
  • INT31-C. Ensure that integer conversions do not result in lost or misinterpreted data
  • -
  • W. Dietz,∗ P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • +
  • W. Dietz, P. Li, J. Regehr, V. Adve. Understanding Integer Overflow in C/C++
  • diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index 7ea5df5da641..bd79a1141726 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -22,5 +22,6 @@ where ro.getAnOperand() = expr2 and globalValueNumber(expr1) = globalValueNumber(expr2) and add.getUnspecifiedType().(IntegralType).isSigned() and + not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and exprMightOverflowPositively(add) select ro, "Testing for signed overflow may produce undefined results." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp index bbfb1c3fad82..e359fb098eb1 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Arithmetic/BadAdditionOverflowCheck/SignedOverflowCheck.cpp @@ -121,3 +121,10 @@ int overflow12b(int n) { // not deleted by gcc or clang return ((unsigned)(n + 32) <= (unsigned)n? -1: 1); // BAD: n + 32 may overflow } + +#define MACRO(E1, E2) (E1) <= (E2)? -1: 1 + +int overflow12_macro(int n) { + return MACRO((unsigned)(n + 32), (unsigned)n); // GOOD: inside a macro expansion +} + From fb4dac597c819df53d29ecf6b9c19553e0a0d1a4 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Sun, 3 Nov 2019 16:21:21 +0100 Subject: [PATCH 0152/2538] C++: Minimal caching of the IR type system This was the minimal amount of predicates I could easily cache without introducing extra cached stages. The predicates that are not cached here, like `CppType::getTypeSize` and `getCanonicalLanguageType`, appear to be cheap. I've tested that this avoids recomputation of the IR type system by running grep -c 'Starting to evaluate predicate CppType::CppType::getIRType_dispred' on the evaluator log for `IRSanity.ql`. It drops from 4 to 1. The pretty-printed DIL drops from 79,175 lines to 76,326 lines. --- cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll | 1 + cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 0abfa14023d8..5534ed20914d 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -4,6 +4,7 @@ private import internal.IRTypeInternal +cached private newtype TIRType = TIRVoidType() or TIRUnknownType() or diff --git a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll index 88184d90345f..e967dc9920c1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/internal/CppType.qll @@ -175,6 +175,7 @@ private IRType getIRTypeForPRValue(Type type) { ) } +cached private newtype TCppType = TPRValueType(Type type) { exists(getIRTypeForPRValue(type)) } or TFunctionGLValueType() or @@ -203,6 +204,7 @@ class CppType extends TCppType { * Gets the `IRType` that represents this `CppType`. Many different `CppType`s can map to a single * `IRType`. */ + cached IRType getIRType() { none() } /** From 637394fb62ed028486731297ba7c2ad1e402fd8c Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 12:04:11 +0000 Subject: [PATCH 0153/2538] TS: Add TypeScript-3.7.1-rc --- .../extractor/lib/typescript/package.json | 2 +- javascript/extractor/lib/typescript/yarn.lock | 89 ++++++++++--------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index fd440415096a..966210ec8b27 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -2,7 +2,7 @@ "name": "typescript-parser-wrapper", "private": true, "dependencies": { - "typescript": "3.6.3" + "typescript": "^3.7.1-rc" }, "scripts": { "build": "tsc --project tsconfig.json", diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index 62205cc17f46..9b539464ceca 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -4,31 +4,31 @@ "@types/node@12.7.11": version "12.7.11" - resolved "node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446" + resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446 ansi-regex@^2.0.0: version "2.1.1" - resolved "ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" + resolved ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df ansi-styles@^2.2.1: version "2.2.1" - resolved "ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" + resolved ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe ansi-styles@^3.1.0: version "3.2.0" - resolved "ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" + resolved ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88 dependencies: color-convert "^1.9.0" argparse@^1.0.7: version "1.0.9" - resolved "argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" + resolved argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86 dependencies: sprintf-js "~1.0.2" babel-code-frame@^6.22.0: version "6.26.0" - resolved "babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" + resolved babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -36,22 +36,22 @@ babel-code-frame@^6.22.0: balanced-match@^1.0.0: version "1.0.0" - resolved "balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" + resolved balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767 brace-expansion@^1.1.7: version "1.1.8" - resolved "brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" + resolved brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292 dependencies: balanced-match "^1.0.0" concat-map "0.0.1" builtin-modules@^1.1.1: version "1.1.1" - resolved "builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" + resolved builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f chalk@^1.1.3: version "1.1.3" - resolved "chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" + resolved chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98 dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -61,7 +61,7 @@ chalk@^1.1.3: chalk@^2.3.0: version "2.3.0" - resolved "chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" + resolved chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba dependencies: ansi-styles "^3.1.0" escape-string-regexp "^1.0.5" @@ -69,45 +69,45 @@ chalk@^2.3.0: color-convert@^1.9.0: version "1.9.1" - resolved "color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" + resolved color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed dependencies: color-name "^1.1.1" color-name@^1.1.1: version "1.1.3" - resolved "color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" + resolved color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25 commander@^2.12.1: version "2.13.0" - resolved "commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" + resolved commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c concat-map@0.0.1: version "0.0.1" - resolved "concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + resolved concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b diff@^3.2.0: version "3.4.0" - resolved "diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" + resolved diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved "escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" + resolved escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4 esprima@^4.0.0: version "4.0.0" - resolved "esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" + resolved esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804 esutils@^2.0.2: version "2.0.2" - resolved "esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" + resolved esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b fs.realpath@^1.0.0: version "1.0.0" - resolved "fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + resolved fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f glob@^7.1.1: version "7.1.2" - resolved "glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" + resolved glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15 dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -118,93 +118,93 @@ glob@^7.1.1: has-ansi@^2.0.0: version "2.0.0" - resolved "has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" + resolved has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91 dependencies: ansi-regex "^2.0.0" has-flag@^2.0.0: version "2.0.0" - resolved "has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" + resolved has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51 inflight@^1.0.4: version "1.0.6" - resolved "inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + resolved inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9 dependencies: once "^1.3.0" wrappy "1" inherits@2: version "2.0.3" - resolved "inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" + resolved inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de js-tokens@^3.0.2: version "3.0.2" - resolved "js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" + resolved js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b js-yaml@^3.7.0: version "3.10.0" - resolved "js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" + resolved js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc dependencies: argparse "^1.0.7" esprima "^4.0.0" minimatch@^3.0.4: version "3.0.4" - resolved "minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" + resolved minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083 dependencies: brace-expansion "^1.1.7" once@^1.3.0: version "1.4.0" - resolved "once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + resolved once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1 dependencies: wrappy "1" path-is-absolute@^1.0.0: version "1.0.1" - resolved "path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + resolved path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f path-parse@^1.0.5: version "1.0.5" - resolved "path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" + resolved path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1 resolve@^1.3.2: version "1.5.0" - resolved "resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" + resolved resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36 dependencies: path-parse "^1.0.5" semver@^5.3.0: version "5.5.0" - resolved "semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" + resolved semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab sprintf-js@~1.0.2: version "1.0.3" - resolved "sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + resolved sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c strip-ansi@^3.0.0: version "3.0.1" - resolved "strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" + resolved strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf dependencies: ansi-regex "^2.0.0" supports-color@^2.0.0: version "2.0.0" - resolved "supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" + resolved supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7 supports-color@^4.0.0: version "4.5.0" - resolved "supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" + resolved supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b dependencies: has-flag "^2.0.0" tslib@^1.8.0, tslib@^1.8.1: version "1.9.0" - resolved "tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" + resolved tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8 tslint@^5.9.1: version "5.9.1" - resolved "tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae" + resolved tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae dependencies: babel-code-frame "^6.22.0" builtin-modules "^1.1.1" @@ -221,14 +221,15 @@ tslint@^5.9.1: tsutils@^2.12.1: version "2.19.1" - resolved "tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7" + resolved tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7 dependencies: tslib "^1.8.1" -typescript@3.6.3: - version "3.6.3" - resolved "typescript-3.6.3.tgz#fea942fabb20f7e1ca7164ff626f1a9f3f70b4da" +typescript@^3.7.1-rc: + version "3.7.1-rc" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.1-rc.tgz#2054b872d67f8dc732e36c1df397f9327f37ada0" + integrity sha512-2rMtWppLsaPvmpXsoIAXWDBQVnJMw1ITGGSnidMuayLj9iCmMRT69ncKZw/Mk5rXfJkilApKucWQZxproALoRw== wrappy@1: version "1.0.2" - resolved "wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + resolved wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f From 36b6c32f4fa177aa1f4021b162801346aac69bfe Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 12:14:07 +0000 Subject: [PATCH 0154/2538] TS: Update expected output --- .../TypeScript/PromiseType/PromiseType.expected | 2 -- .../TypeScript/Types/GetExprType.expected | 2 +- .../TypeScript/Types/GetTypeDefinitionType.expected | 2 +- .../TypeScript/Types/GetTypeExprType.expected | 12 ++++++------ .../TypeScript/Types/ReferenceDefinition.expected | 2 ++ 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/javascript/ql/test/library-tests/TypeScript/PromiseType/PromiseType.expected b/javascript/ql/test/library-tests/TypeScript/PromiseType/PromiseType.expected index bd0c467ad144..40c1f30e72a3 100644 --- a/javascript/ql/test/library-tests/TypeScript/PromiseType/PromiseType.expected +++ b/javascript/ql/test/library-tests/TypeScript/PromiseType/PromiseType.expected @@ -1,10 +1,8 @@ | p1 | MyPromise | string | | p2 | MyPromise | any | | p3 | Promise | string | -| p4 | PromiseLike | string | | p5 | PromiseLike | string | | p6 | Thenable | string | -| p7 | Thenable | string | | p8 | ThenPromise | string | | p9 | JQueryPromise | string | | p10 | JQueryGenericPromise | string | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected b/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected index 371cdb05b21f..429f056d2df2 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected @@ -115,4 +115,4 @@ | type_definitions.ts:16:5:16:9 | color | Color | | type_definitions.ts:18:6:18:22 | EnumWithOneMember | EnumWithOneMember | | type_definitions.ts:19:5:19:5 | e | EnumWithOneMember | -| type_definitions.ts:22:5:22:23 | aliasForNumberArray | number[] | +| type_definitions.ts:22:5:22:23 | aliasForNumberArray | Alias | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected index 00d2813750e8..670cb08a713a 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected @@ -5,4 +5,4 @@ | type_definitions.ts:8:1:10:1 | class C ... x: T\\n} | C | | type_definitions.ts:13:1:15:1 | enum Co ... blue\\n} | Color | | type_definitions.ts:18:1:18:33 | enum En ... ember } | EnumWithOneMember | -| type_definitions.ts:21:1:21:20 | type Alias = T[]; | T[] | +| type_definitions.ts:21:1:21:20 | type Alias = T[]; | Alias | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected index 5bd82703bd8d..3efd9dee5726 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected @@ -57,14 +57,14 @@ | tst.ts:37:17:37:18 | [] | [] | | tst.ts:38:27:38:47 | [number ... ring[]] | [number, ...string[]] | | tst.ts:38:28:38:33 | number | number | -| tst.ts:38:36:38:46 | ...string[] | string[] | +| tst.ts:38:36:38:46 | ...string[] | string | | tst.ts:38:39:38:44 | string | string | | tst.ts:38:39:38:46 | string[] | string[] | | tst.ts:39:39:39:68 | [number ... mber[]] | [number, string?, ...number[]] | | tst.ts:39:40:39:45 | number | number | | tst.ts:39:48:39:53 | string | string | | tst.ts:39:48:39:54 | string? | string | -| tst.ts:39:57:39:67 | ...number[] | number[] | +| tst.ts:39:57:39:67 | ...number[] | number | | tst.ts:39:60:39:65 | number | number | | tst.ts:39:60:39:67 | number[] | number[] | | tst.ts:40:18:40:24 | unknown | unknown | @@ -84,10 +84,10 @@ | type_definitions.ts:11:10:11:15 | number | number | | type_definitions.ts:16:12:16:16 | Color | Color | | type_definitions.ts:19:8:19:24 | EnumWithOneMember | EnumWithOneMember | -| type_definitions.ts:21:6:21:10 | Alias | T[] | +| type_definitions.ts:21:6:21:10 | Alias | Alias | | type_definitions.ts:21:12:21:12 | T | T | | type_definitions.ts:21:17:21:17 | T | T | -| type_definitions.ts:21:17:21:19 | T[] | T[] | -| type_definitions.ts:22:26:22:30 | Alias | T[] | -| type_definitions.ts:22:26:22:38 | Alias | number[] | +| type_definitions.ts:21:17:21:19 | T[] | Alias | +| type_definitions.ts:22:26:22:30 | Alias | Alias | +| type_definitions.ts:22:26:22:38 | Alias | Alias | | type_definitions.ts:22:32:22:37 | number | number | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected b/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected index 9704ac96d536..12c9ebd4a107 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected @@ -1,3 +1,5 @@ +| Alias | type_definitions.ts:21:1:21:20 | type Alias = T[]; | +| Alias | type_definitions.ts:21:1:21:20 | type Alias = T[]; | | C | type_definition_objects.ts:3:8:3:17 | class C {} | | C | type_definitions.ts:8:1:10:1 | class C ... x: T\\n} | | C | type_definitions.ts:8:1:10:1 | class C ... x: T\\n} | From f76006e490de30d8fe9a6fb2e47bb93b86074438 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 13:05:41 +0000 Subject: [PATCH 0155/2538] JS: Delete duplicate test case (typo) --- .../OptionalChaining/ShortCirtuiting.expected | 8 -------- .../library-tests/OptionalChaining/ShortCirtuiting.ql | 7 ------- 2 files changed, 15 deletions(-) delete mode 100644 javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.expected delete mode 100644 javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.ql diff --git a/javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.expected b/javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.expected deleted file mode 100644 index d61dccc8c5a3..000000000000 --- a/javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.expected +++ /dev/null @@ -1,8 +0,0 @@ -| short-circuiting.js:4:10:4:11 | o1 | file://:0:0:0:0 | null | -| short-circuiting.js:4:10:4:11 | o1 | short-circuiting.js:2:14:2:15 | object literal | -| short-circuiting.js:8:10:8:11 | o2 | file://:0:0:0:0 | null | -| short-circuiting.js:8:10:8:11 | o2 | short-circuiting.js:6:14:6:15 | object literal | -| short-circuiting.js:13:10:13:11 | o3 | file://:0:0:0:0 | null | -| short-circuiting.js:13:10:13:11 | o3 | short-circuiting.js:10:14:10:15 | object literal | -| short-circuiting.js:14:10:14:11 | o4 | file://:0:0:0:0 | null | -| short-circuiting.js:14:10:14:11 | o4 | short-circuiting.js:11:14:11:15 | object literal | diff --git a/javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.ql b/javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.ql deleted file mode 100644 index e14838bd3ed2..000000000000 --- a/javascript/ql/test/library-tests/OptionalChaining/ShortCirtuiting.ql +++ /dev/null @@ -1,7 +0,0 @@ -import javascript - -from CallExpr c, Expr arg -where - c.getCalleeName() = "DUMP" and - arg = c.getArgument(0) -select arg, arg.analyze().getAValue() From 869fe4558f3039b9d02cd01040c732c5fcddc35e Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 13:21:07 +0000 Subject: [PATCH 0156/2538] TS: Support optional chaining --- .../src/com/semmle/jcorn/CustomParser.java | 4 +- .../src/com/semmle/jcorn/Parser.java | 16 +- .../src/com/semmle/js/ast/Chainable.java | 10 + .../js/parser/TypeScriptASTConverter.java | 23 +- .../tests/ts/input/optionalChaining.ts | 3 + .../ts/output/trap/optionalChaining.ts.trap | 303 ++++++++++++++++++ .../OptionalChainRoot.expected | 18 ++ .../OptionalChaining/OptionalUse.expected | 18 ++ .../OptionalChaining/ShortCircuiting.expected | 8 + .../short-circuiting-typescript.ts | 15 + .../OptionalChaining/tst-typescript.ts | 15 + 11 files changed, 417 insertions(+), 16 deletions(-) create mode 100644 javascript/extractor/tests/ts/input/optionalChaining.ts create mode 100644 javascript/extractor/tests/ts/output/trap/optionalChaining.ts.trap create mode 100644 javascript/ql/test/library-tests/OptionalChaining/short-circuiting-typescript.ts create mode 100644 javascript/ql/test/library-tests/OptionalChaining/tst-typescript.ts diff --git a/javascript/extractor/src/com/semmle/jcorn/CustomParser.java b/javascript/extractor/src/com/semmle/jcorn/CustomParser.java index a77548ed21f5..888a0aec6390 100644 --- a/javascript/extractor/src/com/semmle/jcorn/CustomParser.java +++ b/javascript/extractor/src/com/semmle/jcorn/CustomParser.java @@ -7,6 +7,7 @@ import com.semmle.js.ast.BlockStatement; import com.semmle.js.ast.CallExpression; import com.semmle.js.ast.CatchClause; +import com.semmle.js.ast.Chainable; import com.semmle.js.ast.ClassExpression; import com.semmle.js.ast.ComprehensionBlock; import com.semmle.js.ast.ComprehensionExpression; @@ -470,7 +471,8 @@ protected Pair parseSubscript( Expression property = this.parsePropertyIdentifierOrIdentifier(); MemberExpression node = - new MemberExpression(start, base, property, false, false, isOnOptionalChain(false, base)); + new MemberExpression( + start, base, property, false, false, Chainable.isOnOptionalChain(false, base)); return Pair.make(this.finishNode(node), true); } else if (this.eat(doubleDot)) { SourceLocation start = new SourceLocation(startLoc); diff --git a/javascript/extractor/src/com/semmle/jcorn/Parser.java b/javascript/extractor/src/com/semmle/jcorn/Parser.java index 013f8e571810..f0e3c0d004f7 100644 --- a/javascript/extractor/src/com/semmle/jcorn/Parser.java +++ b/javascript/extractor/src/com/semmle/jcorn/Parser.java @@ -1520,10 +1520,6 @@ protected Expression parseSubscripts( } } - protected boolean isOnOptionalChain(boolean optional, Expression base) { - return optional || base instanceof Chainable && ((Chainable) base).isOnOptionalChain(); - } - /** * Parse a single subscript {@code s}; if more subscripts could follow, return {@code Pair.make(s, * true}, otherwise return {@code Pair.make(s, false)}. @@ -1544,7 +1540,7 @@ protected Pair parseSubscript( this.parseExpression(false, null), true, optional, - isOnOptionalChain(optional, base)); + Chainable.isOnOptionalChain(optional, base)); this.expect(TokenType.bracketR); return Pair.make(this.finishNode(node), true); } else if (!noCalls && this.eat(TokenType.parenL)) { @@ -1572,10 +1568,10 @@ protected Pair parseSubscript( new ArrayList<>(), exprList, optional, - isOnOptionalChain(optional, base)); + Chainable.isOnOptionalChain(optional, base)); return Pair.make(this.finishNode(node), true); } else if (this.type == TokenType.backQuote) { - if (isOnOptionalChain(optional, base)) { + if (Chainable.isOnOptionalChain(optional, base)) { this.raise(base, "An optional chain may not be used in a tagged template expression."); } TaggedTemplateExpression node = @@ -1590,7 +1586,7 @@ protected Pair parseSubscript( this.parseIdent(true), false, optional, - isOnOptionalChain(optional, base)); + Chainable.isOnOptionalChain(optional, base)); return Pair.make(this.finishNode(node), true); } else { return Pair.make(base, false); @@ -1832,7 +1828,7 @@ protected Expression parseNew() { Expression callee = this.parseSubscripts(this.parseExprAtom(null), innerStartPos, innerStartLoc, true); - if (isOnOptionalChain(false, callee)) + if (Chainable.isOnOptionalChain(false, callee)) this.raise(callee, "An optional chain may not be used in a `new` expression."); return parseNewArguments(startLoc, callee); @@ -2314,7 +2310,7 @@ protected INode toAssignable(INode node, boolean isBinding) { } if (node instanceof MemberExpression) { - if (isOnOptionalChain(false, (MemberExpression) node)) + if (Chainable.isOnOptionalChain(false, (MemberExpression) node)) this.raise(node, "Invalid left-hand side in assignment"); if (!isBinding) return node; } diff --git a/javascript/extractor/src/com/semmle/js/ast/Chainable.java b/javascript/extractor/src/com/semmle/js/ast/Chainable.java index a6efe38d1eba..7d6e17d360b7 100644 --- a/javascript/extractor/src/com/semmle/js/ast/Chainable.java +++ b/javascript/extractor/src/com/semmle/js/ast/Chainable.java @@ -7,4 +7,14 @@ public interface Chainable { /** Is this on an optional chain? */ abstract boolean isOnOptionalChain(); + + /** + * Returns true if a chainable node is on an optional chain. + * + * @param optional true if the node in question is itself optional (has the ?. token) + * @param base the calle or base of the optional access + */ + public static boolean isOnOptionalChain(boolean optional, Expression base) { + return optional || base instanceof Chainable && ((Chainable) base).isOnOptionalChain(); + } } diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index 33d131cbf00b..1c39417e02ec 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -17,6 +17,7 @@ import com.semmle.js.ast.BreakStatement; import com.semmle.js.ast.CallExpression; import com.semmle.js.ast.CatchClause; +import com.semmle.js.ast.Chainable; import com.semmle.js.ast.ClassBody; import com.semmle.js.ast.ClassDeclaration; import com.semmle.js.ast.ClassExpression; @@ -877,7 +878,10 @@ private Node convertCallExpression(JsonObject node, SourceLocation loc) throws P } Expression callee = convertChild(node, "expression"); List typeArguments = convertChildrenAsTypes(node, "typeArguments"); - CallExpression call = new CallExpression(loc, callee, typeArguments, arguments, false, false); + boolean optional = node.has("questionDotToken"); + boolean onOptionalChain = Chainable.isOnOptionalChain(optional, callee); + CallExpression call = + new CallExpression(loc, callee, typeArguments, arguments, optional, onOptionalChain); attachResolvedSignature(call, node); return call; } @@ -1108,7 +1112,9 @@ private Node convertElementAccessExpression(JsonObject node, SourceLocation loc) throws ParseError { Expression object = convertChild(node, "expression"); Expression property = convertChild(node, "argumentExpression"); - return new MemberExpression(loc, object, property, true, false, false); + boolean optional = node.has("questionDotToken"); + boolean onOptionalChain = Chainable.isOnOptionalChain(optional, object); + return new MemberExpression(loc, object, property, true, optional, onOptionalChain); } private Node convertEmptyStatement(SourceLocation loc) { @@ -1584,10 +1590,14 @@ private Node convertMappedType(JsonObject node, SourceLocation loc) throws Parse private Node convertMetaProperty(JsonObject node, SourceLocation loc) throws ParseError { Position metaStart = loc.getStart(); - String keywordKind = syntaxKinds.get(node.getAsJsonPrimitive("keywordToken").getAsInt() + "").getAsString(); + String keywordKind = + syntaxKinds.get(node.getAsJsonPrimitive("keywordToken").getAsInt() + "").getAsString(); String identifier = keywordKind.equals("ImportKeyword") ? "import" : "new"; Position metaEnd = - new Position(metaStart.getLine(), metaStart.getColumn() + identifier.length(), metaStart.getOffset() + identifier.length()); + new Position( + metaStart.getLine(), + metaStart.getColumn() + identifier.length(), + metaStart.getOffset() + identifier.length()); SourceLocation metaLoc = new SourceLocation(identifier, metaStart, metaEnd); Identifier meta = new Identifier(metaLoc, identifier); return new MetaProperty(loc, meta, convertChild(node, "name")); @@ -1967,8 +1977,11 @@ private String getOperator(JsonObject node) throws ParseError { private Node convertPropertyAccessExpression(JsonObject node, SourceLocation loc) throws ParseError { + Expression base = convertChild(node, "expression"); + boolean optional = node.has("questionDotToken"); + boolean onOptionalChain = Chainable.isOnOptionalChain(optional, base); return new MemberExpression( - loc, convertChild(node, "expression"), convertChild(node, "name"), false, false, false); + loc, base, convertChild(node, "name"), false, optional, onOptionalChain); } private Node convertPropertyAssignment(JsonObject node, SourceLocation loc) throws ParseError { diff --git a/javascript/extractor/tests/ts/input/optionalChaining.ts b/javascript/extractor/tests/ts/input/optionalChaining.ts new file mode 100644 index 000000000000..5070e38ab240 --- /dev/null +++ b/javascript/extractor/tests/ts/input/optionalChaining.ts @@ -0,0 +1,3 @@ +base?.x.y; +base?.(x).y; +base?.[z].y; diff --git a/javascript/extractor/tests/ts/output/trap/optionalChaining.ts.trap b/javascript/extractor/tests/ts/output/trap/optionalChaining.ts.trap new file mode 100644 index 000000000000..0a414c9da57e --- /dev/null +++ b/javascript/extractor/tests/ts/output/trap/optionalChaining.ts.trap @@ -0,0 +1,303 @@ +#10000=@"/optionalChaining.ts;sourcefile" +files(#10000,"/optionalChaining.ts","optionalChaining","ts",0) +#10001=@"/;folder" +folders(#10001,"/","") +containerparent(#10001,#10000) +#10002=@"loc,{#10000},0,0,0,0" +locations_default(#10002,#10000,0,0,0,0) +hasLocation(#10000,#10002) +#20000=@"global_scope" +scopes(#20000,0) +#20001=@"script;{#10000},1,1" +#20002=* +lines(#20002,#20001,"base?.x.y;"," +") +#20003=@"loc,{#10000},1,1,1,10" +locations_default(#20003,#10000,1,1,1,10) +hasLocation(#20002,#20003) +#20004=* +lines(#20004,#20001,"base?.(x).y;"," +") +#20005=@"loc,{#10000},2,1,2,12" +locations_default(#20005,#10000,2,1,2,12) +hasLocation(#20004,#20005) +#20006=* +lines(#20006,#20001,"base?.[z].y;"," +") +#20007=@"loc,{#10000},3,1,3,12" +locations_default(#20007,#10000,3,1,3,12) +hasLocation(#20006,#20007) +numlines(#20001,3,3,0) +#20008=* +tokeninfo(#20008,6,#20001,0,"base") +#20009=@"loc,{#10000},1,1,1,4" +locations_default(#20009,#10000,1,1,1,4) +hasLocation(#20008,#20009) +#20010=* +tokeninfo(#20010,8,#20001,1,"?.") +#20011=@"loc,{#10000},1,5,1,6" +locations_default(#20011,#10000,1,5,1,6) +hasLocation(#20010,#20011) +#20012=* +tokeninfo(#20012,6,#20001,2,"x") +#20013=@"loc,{#10000},1,7,1,7" +locations_default(#20013,#10000,1,7,1,7) +hasLocation(#20012,#20013) +#20014=* +tokeninfo(#20014,8,#20001,3,".") +#20015=@"loc,{#10000},1,8,1,8" +locations_default(#20015,#10000,1,8,1,8) +hasLocation(#20014,#20015) +#20016=* +tokeninfo(#20016,6,#20001,4,"y") +#20017=@"loc,{#10000},1,9,1,9" +locations_default(#20017,#10000,1,9,1,9) +hasLocation(#20016,#20017) +#20018=* +tokeninfo(#20018,8,#20001,5,";") +#20019=@"loc,{#10000},1,10,1,10" +locations_default(#20019,#10000,1,10,1,10) +hasLocation(#20018,#20019) +#20020=* +tokeninfo(#20020,6,#20001,6,"base") +#20021=@"loc,{#10000},2,1,2,4" +locations_default(#20021,#10000,2,1,2,4) +hasLocation(#20020,#20021) +#20022=* +tokeninfo(#20022,8,#20001,7,"?.") +#20023=@"loc,{#10000},2,5,2,6" +locations_default(#20023,#10000,2,5,2,6) +hasLocation(#20022,#20023) +#20024=* +tokeninfo(#20024,8,#20001,8,"(") +#20025=@"loc,{#10000},2,7,2,7" +locations_default(#20025,#10000,2,7,2,7) +hasLocation(#20024,#20025) +#20026=* +tokeninfo(#20026,6,#20001,9,"x") +#20027=@"loc,{#10000},2,8,2,8" +locations_default(#20027,#10000,2,8,2,8) +hasLocation(#20026,#20027) +#20028=* +tokeninfo(#20028,8,#20001,10,")") +#20029=@"loc,{#10000},2,9,2,9" +locations_default(#20029,#10000,2,9,2,9) +hasLocation(#20028,#20029) +#20030=* +tokeninfo(#20030,8,#20001,11,".") +#20031=@"loc,{#10000},2,10,2,10" +locations_default(#20031,#10000,2,10,2,10) +hasLocation(#20030,#20031) +#20032=* +tokeninfo(#20032,6,#20001,12,"y") +#20033=@"loc,{#10000},2,11,2,11" +locations_default(#20033,#10000,2,11,2,11) +hasLocation(#20032,#20033) +#20034=* +tokeninfo(#20034,8,#20001,13,";") +#20035=@"loc,{#10000},2,12,2,12" +locations_default(#20035,#10000,2,12,2,12) +hasLocation(#20034,#20035) +#20036=* +tokeninfo(#20036,6,#20001,14,"base") +#20037=@"loc,{#10000},3,1,3,4" +locations_default(#20037,#10000,3,1,3,4) +hasLocation(#20036,#20037) +#20038=* +tokeninfo(#20038,8,#20001,15,"?.") +#20039=@"loc,{#10000},3,5,3,6" +locations_default(#20039,#10000,3,5,3,6) +hasLocation(#20038,#20039) +#20040=* +tokeninfo(#20040,8,#20001,16,"[") +#20041=@"loc,{#10000},3,7,3,7" +locations_default(#20041,#10000,3,7,3,7) +hasLocation(#20040,#20041) +#20042=* +tokeninfo(#20042,6,#20001,17,"z") +#20043=@"loc,{#10000},3,8,3,8" +locations_default(#20043,#10000,3,8,3,8) +hasLocation(#20042,#20043) +#20044=* +tokeninfo(#20044,8,#20001,18,"]") +#20045=@"loc,{#10000},3,9,3,9" +locations_default(#20045,#10000,3,9,3,9) +hasLocation(#20044,#20045) +#20046=* +tokeninfo(#20046,8,#20001,19,".") +#20047=@"loc,{#10000},3,10,3,10" +locations_default(#20047,#10000,3,10,3,10) +hasLocation(#20046,#20047) +#20048=* +tokeninfo(#20048,6,#20001,20,"y") +#20049=@"loc,{#10000},3,11,3,11" +locations_default(#20049,#10000,3,11,3,11) +hasLocation(#20048,#20049) +#20050=* +tokeninfo(#20050,8,#20001,21,";") +#20051=@"loc,{#10000},3,12,3,12" +locations_default(#20051,#10000,3,12,3,12) +hasLocation(#20050,#20051) +#20052=* +tokeninfo(#20052,0,#20001,22,"") +#20053=@"loc,{#10000},4,1,4,0" +locations_default(#20053,#10000,4,1,4,0) +hasLocation(#20052,#20053) +toplevels(#20001,0) +#20054=@"loc,{#10000},1,1,4,0" +locations_default(#20054,#10000,1,1,4,0) +hasLocation(#20001,#20054) +#20055=* +stmts(#20055,2,#20001,0,"base?.x.y;") +hasLocation(#20055,#20003) +stmtContainers(#20055,#20001) +#20056=* +exprs(#20056,14,#20055,0,"base?.x.y") +#20057=@"loc,{#10000},1,1,1,9" +locations_default(#20057,#10000,1,1,1,9) +hasLocation(#20056,#20057) +enclosingStmt(#20056,#20055) +exprContainers(#20056,#20001) +#20058=* +exprs(#20058,14,#20056,0,"base?.x") +#20059=@"loc,{#10000},1,1,1,7" +locations_default(#20059,#10000,1,1,1,7) +hasLocation(#20058,#20059) +enclosingStmt(#20058,#20055) +exprContainers(#20058,#20001) +#20060=* +exprs(#20060,79,#20058,0,"base") +hasLocation(#20060,#20009) +enclosingStmt(#20060,#20055) +exprContainers(#20060,#20001) +literals("base","base",#20060) +#20061=@"var;{base};{#20000}" +variables(#20061,"base",#20000) +bind(#20060,#20061) +#20062=* +exprs(#20062,0,#20058,1,"x") +hasLocation(#20062,#20013) +enclosingStmt(#20062,#20055) +exprContainers(#20062,#20001) +literals("x","x",#20062) +isOptionalChaining(#20058) +#20063=* +exprs(#20063,0,#20056,1,"y") +hasLocation(#20063,#20017) +enclosingStmt(#20063,#20055) +exprContainers(#20063,#20001) +literals("y","y",#20063) +#20064=* +stmts(#20064,2,#20001,1,"base?.(x).y;") +hasLocation(#20064,#20005) +stmtContainers(#20064,#20001) +#20065=* +exprs(#20065,14,#20064,0,"base?.(x).y") +#20066=@"loc,{#10000},2,1,2,11" +locations_default(#20066,#10000,2,1,2,11) +hasLocation(#20065,#20066) +enclosingStmt(#20065,#20064) +exprContainers(#20065,#20001) +#20067=* +exprs(#20067,13,#20065,0,"base?.(x)") +#20068=@"loc,{#10000},2,1,2,9" +locations_default(#20068,#10000,2,1,2,9) +hasLocation(#20067,#20068) +enclosingStmt(#20067,#20064) +exprContainers(#20067,#20001) +#20069=* +exprs(#20069,79,#20067,-1,"base") +hasLocation(#20069,#20021) +enclosingStmt(#20069,#20064) +exprContainers(#20069,#20001) +literals("base","base",#20069) +bind(#20069,#20061) +#20070=* +exprs(#20070,79,#20067,0,"x") +hasLocation(#20070,#20027) +enclosingStmt(#20070,#20064) +exprContainers(#20070,#20001) +literals("x","x",#20070) +#20071=@"var;{x};{#20000}" +variables(#20071,"x",#20000) +bind(#20070,#20071) +isOptionalChaining(#20067) +#20072=* +exprs(#20072,0,#20065,1,"y") +hasLocation(#20072,#20033) +enclosingStmt(#20072,#20064) +exprContainers(#20072,#20001) +literals("y","y",#20072) +#20073=* +stmts(#20073,2,#20001,2,"base?.[z].y;") +hasLocation(#20073,#20007) +stmtContainers(#20073,#20001) +#20074=* +exprs(#20074,14,#20073,0,"base?.[z].y") +#20075=@"loc,{#10000},3,1,3,11" +locations_default(#20075,#10000,3,1,3,11) +hasLocation(#20074,#20075) +enclosingStmt(#20074,#20073) +exprContainers(#20074,#20001) +#20076=* +exprs(#20076,15,#20074,0,"base?.[z]") +#20077=@"loc,{#10000},3,1,3,9" +locations_default(#20077,#10000,3,1,3,9) +hasLocation(#20076,#20077) +enclosingStmt(#20076,#20073) +exprContainers(#20076,#20001) +#20078=* +exprs(#20078,79,#20076,0,"base") +hasLocation(#20078,#20037) +enclosingStmt(#20078,#20073) +exprContainers(#20078,#20001) +literals("base","base",#20078) +bind(#20078,#20061) +#20079=* +exprs(#20079,79,#20076,1,"z") +hasLocation(#20079,#20043) +enclosingStmt(#20079,#20073) +exprContainers(#20079,#20001) +literals("z","z",#20079) +#20080=@"var;{z};{#20000}" +variables(#20080,"z",#20000) +bind(#20079,#20080) +isOptionalChaining(#20076) +#20081=* +exprs(#20081,0,#20074,1,"y") +hasLocation(#20081,#20049) +enclosingStmt(#20081,#20073) +exprContainers(#20081,#20001) +literals("y","y",#20081) +#20082=* +entry_cfg_node(#20082,#20001) +#20083=@"loc,{#10000},1,1,1,0" +locations_default(#20083,#10000,1,1,1,0) +hasLocation(#20082,#20083) +#20084=* +exit_cfg_node(#20084,#20001) +hasLocation(#20084,#20053) +successor(#20073,#20078) +successor(#20081,#20074) +successor(#20079,#20076) +successor(#20078,#20079) +successor(#20076,#20081) +successor(#20078,#20084) +successor(#20074,#20084) +successor(#20064,#20069) +successor(#20072,#20065) +successor(#20070,#20067) +successor(#20069,#20070) +successor(#20067,#20072) +successor(#20069,#20073) +successor(#20065,#20073) +successor(#20055,#20060) +successor(#20063,#20056) +successor(#20062,#20058) +successor(#20060,#20062) +successor(#20058,#20063) +successor(#20060,#20064) +successor(#20056,#20064) +successor(#20082,#20055) +numlines(#10000,3,3,0) +filetype(#10000,"typescript") diff --git a/javascript/ql/test/library-tests/OptionalChaining/OptionalChainRoot.expected b/javascript/ql/test/library-tests/OptionalChaining/OptionalChainRoot.expected index 5ec86ee74624..1ff8c71d6db9 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/OptionalChainRoot.expected +++ b/javascript/ql/test/library-tests/OptionalChaining/OptionalChainRoot.expected @@ -1,7 +1,25 @@ +| short-circuiting-typescript.ts:3:5:3:18 | x?.(o1 = null) | short-circuiting-typescript.ts:3:5:3:18 | x?.(o1 = null) | +| short-circuiting-typescript.ts:7:5:7:18 | x?.[o2 = null] | short-circuiting-typescript.ts:7:5:7:18 | x?.[o2 = null] | +| short-circuiting-typescript.ts:12:5:12:31 | x?.[o3 ... = null) | short-circuiting-typescript.ts:12:5:12:18 | x?.[o3 = null] | +| short-circuiting-typescript.ts:12:5:12:31 | x?.[o3 ... = null) | short-circuiting-typescript.ts:12:5:12:31 | x?.[o3 ... = null) | | short-circuiting.js:3:5:3:18 | x?.(o1 = null) | short-circuiting.js:3:5:3:18 | x?.(o1 = null) | | short-circuiting.js:7:5:7:18 | x?.[o2 = null] | short-circuiting.js:7:5:7:18 | x?.[o2 = null] | | short-circuiting.js:12:5:12:31 | x?.[o3 ... = null) | short-circuiting.js:12:5:12:18 | x?.[o3 = null] | | short-circuiting.js:12:5:12:31 | x?.[o3 ... = null) | short-circuiting.js:12:5:12:31 | x?.[o3 ... = null) | +| tst-typescript.ts:2:1:2:6 | a?.b.c | tst-typescript.ts:2:1:2:4 | a?.b | +| tst-typescript.ts:3:1:3:6 | a.b?.c | tst-typescript.ts:3:1:3:6 | a.b?.c | +| tst-typescript.ts:4:1:4:7 | a?.b?.c | tst-typescript.ts:4:1:4:4 | a?.b | +| tst-typescript.ts:4:1:4:7 | a?.b?.c | tst-typescript.ts:4:1:4:7 | a?.b?.c | +| tst-typescript.ts:7:1:7:7 | f?.()() | tst-typescript.ts:7:1:7:5 | f?.() | +| tst-typescript.ts:8:1:8:7 | f()?.() | tst-typescript.ts:8:1:8:7 | f()?.() | +| tst-typescript.ts:9:1:9:9 | f?.()?.() | tst-typescript.ts:9:1:9:5 | f?.() | +| tst-typescript.ts:9:1:9:9 | f?.()?.() | tst-typescript.ts:9:1:9:9 | f?.()?.() | +| tst-typescript.ts:12:1:12:8 | a?.m().b | tst-typescript.ts:12:1:12:4 | a?.m | +| tst-typescript.ts:13:1:13:9 | a.m?.().b | tst-typescript.ts:13:1:13:7 | a.m?.() | +| tst-typescript.ts:14:1:14:8 | a.m()?.b | tst-typescript.ts:14:1:14:8 | a.m()?.b | +| tst-typescript.ts:15:1:15:11 | a?.m?.()?.b | tst-typescript.ts:15:1:15:4 | a?.m | +| tst-typescript.ts:15:1:15:11 | a?.m?.()?.b | tst-typescript.ts:15:1:15:8 | a?.m?.() | +| tst-typescript.ts:15:1:15:11 | a?.m?.()?.b | tst-typescript.ts:15:1:15:11 | a?.m?.()?.b | | tst.js:2:1:2:6 | a?.b.c | tst.js:2:1:2:4 | a?.b | | tst.js:3:1:3:6 | a.b?.c | tst.js:3:1:3:6 | a.b?.c | | tst.js:4:1:4:7 | a?.b?.c | tst.js:4:1:4:4 | a?.b | diff --git a/javascript/ql/test/library-tests/OptionalChaining/OptionalUse.expected b/javascript/ql/test/library-tests/OptionalChaining/OptionalUse.expected index 430d4d522998..8358bb0ecde1 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/OptionalUse.expected +++ b/javascript/ql/test/library-tests/OptionalChaining/OptionalUse.expected @@ -1,7 +1,25 @@ +| short-circuiting-typescript.ts:3:5:3:18 | x?.(o1 = null) | +| short-circuiting-typescript.ts:7:5:7:18 | x?.[o2 = null] | +| short-circuiting-typescript.ts:12:5:12:18 | x?.[o3 = null] | +| short-circuiting-typescript.ts:12:5:12:31 | x?.[o3 ... = null) | | short-circuiting.js:3:5:3:18 | x?.(o1 = null) | | short-circuiting.js:7:5:7:18 | x?.[o2 = null] | | short-circuiting.js:12:5:12:18 | x?.[o3 = null] | | short-circuiting.js:12:5:12:31 | x?.[o3 ... = null) | +| tst-typescript.ts:2:1:2:4 | a?.b | +| tst-typescript.ts:3:1:3:6 | a.b?.c | +| tst-typescript.ts:4:1:4:4 | a?.b | +| tst-typescript.ts:4:1:4:7 | a?.b?.c | +| tst-typescript.ts:7:1:7:5 | f?.() | +| tst-typescript.ts:8:1:8:7 | f()?.() | +| tst-typescript.ts:9:1:9:5 | f?.() | +| tst-typescript.ts:9:1:9:9 | f?.()?.() | +| tst-typescript.ts:12:1:12:4 | a?.m | +| tst-typescript.ts:13:1:13:7 | a.m?.() | +| tst-typescript.ts:14:1:14:8 | a.m()?.b | +| tst-typescript.ts:15:1:15:4 | a?.m | +| tst-typescript.ts:15:1:15:8 | a?.m?.() | +| tst-typescript.ts:15:1:15:11 | a?.m?.()?.b | | tst.js:2:1:2:4 | a?.b | | tst.js:3:1:3:6 | a.b?.c | | tst.js:4:1:4:4 | a?.b | diff --git a/javascript/ql/test/library-tests/OptionalChaining/ShortCircuiting.expected b/javascript/ql/test/library-tests/OptionalChaining/ShortCircuiting.expected index d61dccc8c5a3..6711c7048289 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/ShortCircuiting.expected +++ b/javascript/ql/test/library-tests/OptionalChaining/ShortCircuiting.expected @@ -1,3 +1,11 @@ +| short-circuiting-typescript.ts:4:10:4:11 | o1 | file://:0:0:0:0 | null | +| short-circuiting-typescript.ts:4:10:4:11 | o1 | short-circuiting-typescript.ts:2:14:2:15 | object literal | +| short-circuiting-typescript.ts:8:10:8:11 | o2 | file://:0:0:0:0 | null | +| short-circuiting-typescript.ts:8:10:8:11 | o2 | short-circuiting-typescript.ts:6:14:6:15 | object literal | +| short-circuiting-typescript.ts:13:10:13:11 | o3 | file://:0:0:0:0 | null | +| short-circuiting-typescript.ts:13:10:13:11 | o3 | short-circuiting-typescript.ts:10:14:10:15 | object literal | +| short-circuiting-typescript.ts:14:10:14:11 | o4 | file://:0:0:0:0 | null | +| short-circuiting-typescript.ts:14:10:14:11 | o4 | short-circuiting-typescript.ts:11:14:11:15 | object literal | | short-circuiting.js:4:10:4:11 | o1 | file://:0:0:0:0 | null | | short-circuiting.js:4:10:4:11 | o1 | short-circuiting.js:2:14:2:15 | object literal | | short-circuiting.js:8:10:8:11 | o2 | file://:0:0:0:0 | null | diff --git a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting-typescript.ts b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting-typescript.ts new file mode 100644 index 000000000000..7367e64dd4c8 --- /dev/null +++ b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting-typescript.ts @@ -0,0 +1,15 @@ +(function() { + var o1 = {}; + x?.(o1 = null); + DUMP(o1); + + var o2 = {}; + x?.[o2 = null]; + DUMP(o2); + + var o3 = {}, + o4 = {}; + x?.[o3 = null]?.(o4 = null); + DUMP(o3); + DUMP(o4); +}); diff --git a/javascript/ql/test/library-tests/OptionalChaining/tst-typescript.ts b/javascript/ql/test/library-tests/OptionalChaining/tst-typescript.ts new file mode 100644 index 000000000000..39389024d6d0 --- /dev/null +++ b/javascript/ql/test/library-tests/OptionalChaining/tst-typescript.ts @@ -0,0 +1,15 @@ +a.b.c; +a?.b.c; +a.b?.c; +a?.b?.c; + +f()(); +f?.()(); +f()?.(); +f?.()?.(); + +a.m().b; +a?.m().b; +a.m?.().b; +a.m()?.b; +a?.m?.()?.b; From f50f3b48c4f09920cfec667461054e8028fefdbd Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 13:35:50 +0000 Subject: [PATCH 0157/2538] TS: Add test for ?? operator (already works) --- javascript/ql/test/library-tests/Flow/AbstractValues.expected | 2 ++ javascript/ql/test/library-tests/Flow/abseval.expected | 2 ++ javascript/ql/test/library-tests/Flow/getAPrototype.expected | 1 + javascript/ql/test/library-tests/Flow/nullish-coalescing-op.ts | 3 +++ javascript/ql/test/library-tests/Flow/types.expected | 1 + 5 files changed, 9 insertions(+) create mode 100644 javascript/ql/test/library-tests/Flow/nullish-coalescing-op.ts diff --git a/javascript/ql/test/library-tests/Flow/AbstractValues.expected b/javascript/ql/test/library-tests/Flow/AbstractValues.expected index f172a33c0009..42117cac98a7 100644 --- a/javascript/ql/test/library-tests/Flow/AbstractValues.expected +++ b/javascript/ql/test/library-tests/Flow/AbstractValues.expected @@ -208,6 +208,8 @@ | nodeJsLib.js:1:18:1:43 | instance of function nodeJsModule | | nodeJsLib.js:3:15:3:37 | function nodeJsFoo | | nodeJsLib.js:3:15:3:37 | instance of function nodeJsFoo | +| nullish-coalescing-op.ts:1:1:3:1 | function test | +| nullish-coalescing-op.ts:1:1:3:1 | instance of function test | | o.js:1:1:2:0 | exports object of module o | | o.js:1:1:2:0 | module object of module o | | objlit.js:1:14:1:15 | object literal | diff --git a/javascript/ql/test/library-tests/Flow/abseval.expected b/javascript/ql/test/library-tests/Flow/abseval.expected index 30169b47e8bb..00d7f27da89a 100644 --- a/javascript/ql/test/library-tests/Flow/abseval.expected +++ b/javascript/ql/test/library-tests/Flow/abseval.expected @@ -204,6 +204,8 @@ | nodeJsClient.js:5:5:5:6 | x2 | nodeJsClient.js:5:10:5:15 | es.foo | esLib.js:3:8:3:24 | function foo | | nodeJsClient.js:5:5:5:6 | x2 | nodeJsClient.js:5:10:5:15 | es.foo | file://:0:0:0:0 | indefinite value (call) | | nodeJsClient.js:5:5:5:6 | x2 | nodeJsClient.js:5:10:5:15 | es.foo | file://:0:0:0:0 | indefinite value (heap) | +| nullish-coalescing-op.ts:2:7:2:7 | y | nullish-coalescing-op.ts:2:11:2:18 | x ?? 0.5 | file://:0:0:0:0 | indefinite value (call) | +| nullish-coalescing-op.ts:2:7:2:7 | y | nullish-coalescing-op.ts:2:11:2:18 | x ?? 0.5 | file://:0:0:0:0 | non-zero value | | objlit.js:1:5:1:5 | A | objlit.js:1:9:1:15 | A \|\| {} | file://:0:0:0:0 | indefinite value (global) | | objlit.js:1:5:1:5 | A | objlit.js:1:9:1:15 | A \|\| {} | objlit.js:1:14:1:15 | object literal | | objlit.js:7:5:7:5 | B | objlit.js:7:9:7:10 | {} | objlit.js:7:9:7:10 | object literal | diff --git a/javascript/ql/test/library-tests/Flow/getAPrototype.expected b/javascript/ql/test/library-tests/Flow/getAPrototype.expected index e88255157157..07ff1f76b244 100644 --- a/javascript/ql/test/library-tests/Flow/getAPrototype.expected +++ b/javascript/ql/test/library-tests/Flow/getAPrototype.expected @@ -40,6 +40,7 @@ | nestedImport.js:9:1:12:1 | instance of function tst | nestedImport.js:9:1:12:1 | instance of function tst | | nodeJsLib.js:1:18:1:43 | instance of function nodeJsModule | nodeJsLib.js:1:18:1:43 | instance of function nodeJsModule | | nodeJsLib.js:3:15:3:37 | instance of function nodeJsFoo | nodeJsLib.js:3:15:3:37 | instance of function nodeJsFoo | +| nullish-coalescing-op.ts:1:1:3:1 | instance of function test | nullish-coalescing-op.ts:1:1:3:1 | instance of function test | | objlit.js:2:9:2:21 | instance of anonymous function | objlit.js:2:9:2:21 | instance of anonymous function | | objlit.js:4:8:4:20 | instance of method baz | objlit.js:4:8:4:20 | instance of method baz | | objlit.js:10:2:12:1 | instance of anonymous function | objlit.js:10:2:12:1 | instance of anonymous function | diff --git a/javascript/ql/test/library-tests/Flow/nullish-coalescing-op.ts b/javascript/ql/test/library-tests/Flow/nullish-coalescing-op.ts new file mode 100644 index 000000000000..9fb2e4c1312a --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/nullish-coalescing-op.ts @@ -0,0 +1,3 @@ +function test(x) { + let y = x ?? 0.5; +} diff --git a/javascript/ql/test/library-tests/Flow/types.expected b/javascript/ql/test/library-tests/Flow/types.expected index ba7aca62b088..9b13b469bede 100644 --- a/javascript/ql/test/library-tests/Flow/types.expected +++ b/javascript/ql/test/library-tests/Flow/types.expected @@ -113,6 +113,7 @@ | nodeJsClient.js:2:5:2:6 | es | nodeJsClient.js:2:10:2:27 | require('./esLib') | boolean, class, date, function, null, number, object, regular expression,string or undefined | | nodeJsClient.js:4:5:4:6 | x1 | nodeJsClient.js:4:10:4:15 | nj.foo | boolean, class, date, function, null, number, object, regular expression,string or undefined | | nodeJsClient.js:5:5:5:6 | x2 | nodeJsClient.js:5:10:5:15 | es.foo | boolean, class, date, function, null, number, object, regular expression,string or undefined | +| nullish-coalescing-op.ts:2:7:2:7 | y | nullish-coalescing-op.ts:2:11:2:18 | x ?? 0.5 | boolean, class, date, function, null, number, object, regular expression,string or undefined | | objlit.js:1:5:1:5 | A | objlit.js:1:9:1:15 | A \|\| {} | boolean, class, date, function, null, number, object, regular expression,string or undefined | | objlit.js:7:5:7:5 | B | objlit.js:7:9:7:10 | {} | object | | objlit.js:14:5:14:6 | x1 | objlit.js:14:10:14:10 | A | boolean, class, date, function, null, number, object, regular expression,string or undefined | From 4e7b987fa37fb6988d2659884974bd9581f8da79 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 14:16:57 +0000 Subject: [PATCH 0158/2538] TS: Rename IsTypeExpr -> PredicateTypeExpr --- .../src/com/semmle/js/ast/DefaultVisitor.java | 4 +-- .../src/com/semmle/js/ast/NodeCopier.java | 7 ++-- .../src/com/semmle/js/ast/Visitor.java | 4 +-- .../com/semmle/js/extractor/ASTExtractor.java | 8 ++--- .../com/semmle/js/extractor/ScopeManager.java | 6 ++-- .../semmle/js/extractor/TypeExprKinds.java | 4 +-- .../js/parser/TypeScriptASTConverter.java | 4 +-- .../src/com/semmle/ts/ast/IsTypeExpr.java | 32 ----------------- .../com/semmle/ts/ast/PredicateTypeExpr.java | 34 +++++++++++++++++++ .../ql/src/semmle/javascript/TypeScript.qll | 2 +- .../ql/src/semmlecode.javascript.dbscheme | 2 +- .../src/semmlecode.javascript.dbscheme.stats | 2 +- 12 files changed, 56 insertions(+), 53 deletions(-) delete mode 100644 javascript/extractor/src/com/semmle/ts/ast/IsTypeExpr.java create mode 100644 javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java diff --git a/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java b/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java index d6779fdaa3bb..cb11b9376ea7 100644 --- a/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/DefaultVisitor.java @@ -34,13 +34,13 @@ import com.semmle.ts.ast.InterfaceDeclaration; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.KeywordTypeExpr; import com.semmle.ts.ast.MappedTypeExpr; import com.semmle.ts.ast.NamespaceDeclaration; import com.semmle.ts.ast.NonNullAssertion; import com.semmle.ts.ast.OptionalTypeExpr; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.RestTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeAliasDeclaration; @@ -634,7 +634,7 @@ public R visit(TypeofTypeExpr nd, C c) { } @Override - public R visit(IsTypeExpr nd, C c) { + public R visit(PredicateTypeExpr nd, C c) { return visit((TypeExpression) nd, c); } diff --git a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java index cdfc0441a573..0a8716ed732a 100644 --- a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java +++ b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java @@ -30,13 +30,13 @@ import com.semmle.ts.ast.InterfaceDeclaration; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.KeywordTypeExpr; import com.semmle.ts.ast.MappedTypeExpr; import com.semmle.ts.ast.NamespaceDeclaration; import com.semmle.ts.ast.NonNullAssertion; import com.semmle.ts.ast.OptionalTypeExpr; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.RestTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeAliasDeclaration; @@ -717,8 +717,9 @@ public INode visit(TypeofTypeExpr nd, Void c) { } @Override - public INode visit(IsTypeExpr nd, Void c) { - return new IsTypeExpr(visit(nd.getLoc()), copy(nd.getLeft()), copy(nd.getRight())); + public INode visit(PredicateTypeExpr nd, Void c) { + return new PredicateTypeExpr( + visit(nd.getLoc()), copy(nd.getExpression()), copy(nd.getTypeExpr())); } @Override diff --git a/javascript/extractor/src/com/semmle/js/ast/Visitor.java b/javascript/extractor/src/com/semmle/js/ast/Visitor.java index f825d4487192..97a0dd731181 100644 --- a/javascript/extractor/src/com/semmle/js/ast/Visitor.java +++ b/javascript/extractor/src/com/semmle/js/ast/Visitor.java @@ -30,13 +30,13 @@ import com.semmle.ts.ast.InterfaceDeclaration; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.KeywordTypeExpr; import com.semmle.ts.ast.MappedTypeExpr; import com.semmle.ts.ast.NamespaceDeclaration; import com.semmle.ts.ast.NonNullAssertion; import com.semmle.ts.ast.OptionalTypeExpr; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.RestTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeAliasDeclaration; @@ -256,7 +256,7 @@ public interface Visitor { public R visit(TypeofTypeExpr nd, C c); - public R visit(IsTypeExpr nd, C c); + public R visit(PredicateTypeExpr nd, C c); public R visit(InterfaceTypeExpr nd, C c); diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index c2a3ee70cb8a..cc29551b3918 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -125,13 +125,13 @@ import com.semmle.ts.ast.InterfaceDeclaration; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.KeywordTypeExpr; import com.semmle.ts.ast.MappedTypeExpr; import com.semmle.ts.ast.NamespaceDeclaration; import com.semmle.ts.ast.NonNullAssertion; import com.semmle.ts.ast.OptionalTypeExpr; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.RestTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeAliasDeclaration; @@ -1707,10 +1707,10 @@ public Label visit(TypeofTypeExpr nd, Context c) { } @Override - public Label visit(IsTypeExpr nd, Context c) { + public Label visit(PredicateTypeExpr nd, Context c) { Label key = super.visit(nd, c); - visit(nd.getLeft(), key, 0, IdContext.varInTypeBind); - visit(nd.getRight(), key, 1, IdContext.typeBind); + visit(nd.getExpression(), key, 0, IdContext.varInTypeBind); + visit(nd.getTypeExpr(), key, 1, IdContext.typeBind); return key; } diff --git a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java index 1270b0a94092..3bffa4ad3ae4 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ScopeManager.java @@ -46,9 +46,9 @@ import com.semmle.ts.ast.InterfaceDeclaration; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.NamespaceDeclaration; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeAliasDeclaration; import com.semmle.ts.ast.UnionTypeExpr; @@ -660,8 +660,8 @@ public Void visit(IntersectionTypeExpr nd, Void c) { } @Override - public Void visit(IsTypeExpr nd, Void c) { - return nd.getRight().accept(this, c); + public Void visit(PredicateTypeExpr nd, Void c) { + return nd.getTypeExpr().accept(this, c); } @Override diff --git a/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java b/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java index 78b901da475c..6c9263a53602 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java +++ b/javascript/extractor/src/com/semmle/js/extractor/TypeExprKinds.java @@ -16,11 +16,11 @@ import com.semmle.ts.ast.InferTypeExpr; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.KeywordTypeExpr; import com.semmle.ts.ast.MappedTypeExpr; import com.semmle.ts.ast.OptionalTypeExpr; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.RestTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeParameter; @@ -159,7 +159,7 @@ public Integer visit(TypeofTypeExpr nd, Void c) { } @Override - public Integer visit(IsTypeExpr nd, Void c) { + public Integer visit(PredicateTypeExpr nd, Void c) { return isTypeExpr; } diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index 1c39417e02ec..af0cf755a0e2 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -127,13 +127,13 @@ import com.semmle.ts.ast.InterfaceDeclaration; import com.semmle.ts.ast.InterfaceTypeExpr; import com.semmle.ts.ast.IntersectionTypeExpr; -import com.semmle.ts.ast.IsTypeExpr; import com.semmle.ts.ast.KeywordTypeExpr; import com.semmle.ts.ast.MappedTypeExpr; import com.semmle.ts.ast.NamespaceDeclaration; import com.semmle.ts.ast.NonNullAssertion; import com.semmle.ts.ast.OptionalTypeExpr; import com.semmle.ts.ast.ParenthesizedTypeExpr; +import com.semmle.ts.ast.PredicateTypeExpr; import com.semmle.ts.ast.RestTypeExpr; import com.semmle.ts.ast.TupleTypeExpr; import com.semmle.ts.ast.TypeAliasDeclaration; @@ -2199,7 +2199,7 @@ private Node convertTypeParameter(JsonObject node, SourceLocation loc) throws Pa } private Node convertTypePredicate(JsonObject node, SourceLocation loc) throws ParseError { - return new IsTypeExpr( + return new PredicateTypeExpr( loc, convertChildAsType(node, "parameterName"), convertChildAsType(node, "type")); } diff --git a/javascript/extractor/src/com/semmle/ts/ast/IsTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/IsTypeExpr.java deleted file mode 100644 index a64fdb83650a..000000000000 --- a/javascript/extractor/src/com/semmle/ts/ast/IsTypeExpr.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.semmle.ts.ast; - -import com.semmle.js.ast.SourceLocation; -import com.semmle.js.ast.Visitor; - -/** - * A type of form E is T where E is a parameter name or this and - * T is a type. - */ -public class IsTypeExpr extends TypeExpression { - private final ITypeExpression left; // Always Identifier or KeywordTypeExpr (in case of 'this') - private final ITypeExpression right; - - public IsTypeExpr(SourceLocation loc, ITypeExpression left, ITypeExpression right) { - super("IsTypeExpr", loc); - this.left = left; - this.right = right; - } - - public ITypeExpression getLeft() { - return left; - } - - public ITypeExpression getRight() { - return right; - } - - @Override - public R accept(Visitor v, C c) { - return v.visit(this, c); - } -} diff --git a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java new file mode 100644 index 000000000000..215a345646af --- /dev/null +++ b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java @@ -0,0 +1,34 @@ +package com.semmle.ts.ast; + +import com.semmle.js.ast.SourceLocation; +import com.semmle.js.ast.Visitor; + +/** + * A type of form E is T where E is a parameter name or this and + * T is a type. + */ +public class PredicateTypeExpr extends TypeExpression { + private final ITypeExpression expression; + private final ITypeExpression type; + + public PredicateTypeExpr(SourceLocation loc, ITypeExpression expression, ITypeExpression type) { + super("PredicateTypeExpr", loc); + this.expression = expression; + this.type = type; + } + + /** Returns the E in E is T. */ + public ITypeExpression getExpression() { + return expression; + } + + /** Returns the T in E is T. */ + public ITypeExpression getTypeExpr() { + return type; + } + + @Override + public R accept(Visitor v, C c) { + return v.visit(this, c); + } +} diff --git a/javascript/ql/src/semmle/javascript/TypeScript.qll b/javascript/ql/src/semmle/javascript/TypeScript.qll index 005f9a5ee128..e85ea681ece3 100644 --- a/javascript/ql/src/semmle/javascript/TypeScript.qll +++ b/javascript/ql/src/semmle/javascript/TypeScript.qll @@ -918,7 +918,7 @@ class TypeofTypeExpr extends @typeoftypeexpr, TypeExpr { * * This can only occur as the return type of a function type. */ -class IsTypeExpr extends @istypeexpr, TypeExpr { +class IsTypeExpr extends @predicatetypeexpr, TypeExpr { /** * Gets the parameter name or `this` token `E` in `E is T`. */ diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index 874ebfcd4d2f..735e288e580c 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -559,7 +559,7 @@ case @typeexpr.kind of | 17 = @localvartypeaccess | 18 = @qualifiedvartypeaccess | 19 = @thisvartypeaccess -| 20 = @istypeexpr +| 20 = @predicatetypeexpr | 21 = @interfacetypeexpr | 22 = @typeparameter | 23 = @plainfunctiontypeexpr diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme.stats b/javascript/ql/src/semmlecode.javascript.dbscheme.stats index 146950b5be70..f9ac74395481 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme.stats +++ b/javascript/ql/src/semmlecode.javascript.dbscheme.stats @@ -850,7 +850,7 @@ 20 -@istypeexpr +@predicatetypeexpr 86 From b81931e402c87659bf98e279770aa18b48f92e24 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 14:51:00 +0000 Subject: [PATCH 0159/2538] TS: Support assertion types --- .../src/com/semmle/js/ast/NodeCopier.java | 5 ++- .../com/semmle/js/extractor/ASTExtractor.java | 3 ++ .../js/parser/TypeScriptASTConverter.java | 5 ++- .../com/semmle/ts/ast/PredicateTypeExpr.java | 12 +++++- .../ql/src/semmle/javascript/TypeScript.qll | 42 ++++++++++++++++--- .../ql/src/semmlecode.javascript.dbscheme | 2 + .../src/semmlecode.javascript.dbscheme.stats | 11 +++++ .../TypeScript/TypeAnnotations/IsTypeExpr.qll | 5 --- .../TypeAnnotations/PredicateTypeExpr.qll | 13 ++++++ .../TypeScript/TypeAnnotations/tests.expected | 16 +++++++ .../TypeScript/TypeAnnotations/tests.ql | 2 +- .../TypeScript/TypeAnnotations/tst.ts | 12 ++++++ 12 files changed, 113 insertions(+), 15 deletions(-) delete mode 100644 javascript/ql/test/library-tests/TypeScript/TypeAnnotations/IsTypeExpr.qll create mode 100644 javascript/ql/test/library-tests/TypeScript/TypeAnnotations/PredicateTypeExpr.qll diff --git a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java index 0a8716ed732a..9c61ca081df6 100644 --- a/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java +++ b/javascript/extractor/src/com/semmle/js/ast/NodeCopier.java @@ -719,7 +719,10 @@ public INode visit(TypeofTypeExpr nd, Void c) { @Override public INode visit(PredicateTypeExpr nd, Void c) { return new PredicateTypeExpr( - visit(nd.getLoc()), copy(nd.getExpression()), copy(nd.getTypeExpr())); + visit(nd.getLoc()), + copy(nd.getExpression()), + copy(nd.getTypeExpr()), + nd.hasAssertsKeyword()); } @Override diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index cc29551b3918..d3571fc5a573 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -1711,6 +1711,9 @@ public Label visit(PredicateTypeExpr nd, Context c) { Label key = super.visit(nd, c); visit(nd.getExpression(), key, 0, IdContext.varInTypeBind); visit(nd.getTypeExpr(), key, 1, IdContext.typeBind); + if (nd.hasAssertsKeyword()) { + trapwriter.addTuple("hasAssertsKeyword", key); + } return key; } diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index af0cf755a0e2..7f826a7dc1d8 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -2200,7 +2200,10 @@ private Node convertTypeParameter(JsonObject node, SourceLocation loc) throws Pa private Node convertTypePredicate(JsonObject node, SourceLocation loc) throws ParseError { return new PredicateTypeExpr( - loc, convertChildAsType(node, "parameterName"), convertChildAsType(node, "type")); + loc, + convertChildAsType(node, "parameterName"), + convertChildAsType(node, "type"), + node.has("assertsModifier")); } private Node convertTypeReference(JsonObject node, SourceLocation loc) throws ParseError { diff --git a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java index 215a345646af..474cb888c0b6 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java @@ -10,11 +10,17 @@ public class PredicateTypeExpr extends TypeExpression { private final ITypeExpression expression; private final ITypeExpression type; + private final boolean hasAssertsKeyword; - public PredicateTypeExpr(SourceLocation loc, ITypeExpression expression, ITypeExpression type) { + public PredicateTypeExpr( + SourceLocation loc, + ITypeExpression expression, + ITypeExpression type, + boolean hasAssertsKeyword) { super("PredicateTypeExpr", loc); this.expression = expression; this.type = type; + this.hasAssertsKeyword = hasAssertsKeyword; } /** Returns the E in E is T. */ @@ -27,6 +33,10 @@ public ITypeExpression getTypeExpr() { return type; } + public boolean hasAssertsKeyword() { + return hasAssertsKeyword; + } + @Override public R accept(Visitor v, C c) { return v.visit(this, c); diff --git a/javascript/ql/src/semmle/javascript/TypeScript.qll b/javascript/ql/src/semmle/javascript/TypeScript.qll index e85ea681ece3..597c059eb058 100644 --- a/javascript/ql/src/semmle/javascript/TypeScript.qll +++ b/javascript/ql/src/semmle/javascript/TypeScript.qll @@ -914,20 +914,49 @@ class TypeofTypeExpr extends @typeoftypeexpr, TypeExpr { } /** - * A type of form `E is T` where `E` is a parameter name or `this`, and `T` is a type. + * A function return type that refines the type of one of its parameters or `this`. * - * This can only occur as the return type of a function type. + * Examples: + * ```js + * function f(x): x is string {} + * function f(x): asserts x is string {} + * function f(x): asserts x {} + * ``` */ -class IsTypeExpr extends @predicatetypeexpr, TypeExpr { +class PredicateTypeExpr extends @predicatetypeexpr, TypeExpr { /** * Gets the parameter name or `this` token `E` in `E is T`. */ VarTypeAccess getParameterName() { result = this.getChildTypeExpr(0) } /** - * Gets the type `T` in `E is T`. + * Gets the type `T` in `E is T` or `asserts E is T`. + * + * Has no results for types of form `asserts E`. */ TypeExpr getPredicateType() { result = this.getChildTypeExpr(1) } + + /** + * Holds if this is a type of form `asserts E is T` or `asserts E`. + */ + predicate hasAssertsKeyword() { + hasAssertsKeyword(this) + } +} + +/** + * A function return type of form `x is T` or `asserts x is T`. + * + * Examples: + * ```js + * function f(x): x is string {} + * function f(x): asserts x is string {} + * ``` + */ +class IsTypeExpr extends PredicateTypeExpr { + IsTypeExpr() { + exists(getPredicateType()) + } } /** @@ -966,15 +995,16 @@ class ReadonlyTypeExpr extends @readonlytypeexpr, TypeExpr { * * This can occur as * - part of the operand to a `typeof` type, or - * - as the first operand to an `is` type. + * - as the first operand to a predicate type * * For example, it may occur as the `E` in these examples: * ``` * var x : typeof E * function f(...) : E is T {} + * function f(...) : asserts E {} * ``` * - * In the latter case, this may also refer to the pseudo-variable `this`. + * In the latter two cases, this may also refer to the pseudo-variable `this`. */ class VarTypeAccess extends @vartypeaccess, TypeExpr { } diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index 735e288e580c..e0bd730ef98a 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -637,6 +637,8 @@ case @type.kind of @unionorintersectiontype = @uniontype | @intersectiontype; @typevariabletype = @canonicaltypevariabletype | @lexicaltypevariabletype; +hasAssertsKeyword(int node: @predicatetypeexpr ref); + @typed_ast_node = @expr | @typeexpr | @function; ast_node_type( unique int node: @typed_ast_node ref, diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme.stats b/javascript/ql/src/semmlecode.javascript.dbscheme.stats index f9ac74395481..0c1660bc7c83 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme.stats +++ b/javascript/ql/src/semmlecode.javascript.dbscheme.stats @@ -7918,6 +7918,17 @@ +hasAssertsKeyword +66 + + +stmt +66 + + + + + isAbstractMember 66 diff --git a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/IsTypeExpr.qll b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/IsTypeExpr.qll deleted file mode 100644 index a0ff44c2bddd..000000000000 --- a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/IsTypeExpr.qll +++ /dev/null @@ -1,5 +0,0 @@ -import javascript - -query predicate test_IsTypeExpr(IsTypeExpr type, VarTypeAccess res0, TypeExpr res1) { - res0 = type.getParameterName() and res1 = type.getPredicateType() -} diff --git a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/PredicateTypeExpr.qll b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/PredicateTypeExpr.qll new file mode 100644 index 000000000000..c38bf54ad1fd --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/PredicateTypeExpr.qll @@ -0,0 +1,13 @@ +import javascript + +query predicate test_IsTypeExpr(IsTypeExpr type, VarTypeAccess res0, TypeExpr res1) { + res0 = type.getParameterName() and res1 = type.getPredicateType() +} + +query predicate test_PredicateTypeExpr(PredicateTypeExpr type, VarTypeAccess res0) { + res0 = type.getParameterName() +} + +query predicate test_hasAssertsKeyword(PredicateTypeExpr type) { + type.hasAssertsKeyword() +} diff --git a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.expected b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.expected index eb0c717b2db5..5db52c2afcd0 100644 --- a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.expected +++ b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.expected @@ -105,6 +105,9 @@ test_VariableTypes | tst.ts:135:5:135:24 | tupleWithRestElement | tupleWithRestElement | tst.ts:135:27:135:47 | [number ... ring[]] | | tst.ts:136:5:136:36 | tupleWi ... lements | tupleWithOptionalAndRestElements | tst.ts:136:39:136:68 | [number ... mber[]] | | tst.ts:137:5:137:15 | unknownType | unknownType | tst.ts:137:18:137:24 | unknown | +| tst.ts:142:17:142:25 | condition | condition | tst.ts:142:28:142:30 | any | +| tst.ts:142:33:142:35 | msg | msg | tst.ts:142:39:142:44 | string | +| tst.ts:148:25:148:27 | val | val | tst.ts:148:30:148:32 | any | test_QualifiedTypeAccess | tst.ts:63:19:63:21 | N.I | tst.ts:63:19:63:19 | N | tst.ts:63:21:63:21 | I | | tst.ts:64:20:64:24 | N.M.I | tst.ts:64:20:64:22 | N.M | tst.ts:64:24:64:24 | I | @@ -148,6 +151,17 @@ test_IsTypeExpr | tst.ts:76:21:76:32 | that is Leaf | tst.ts:76:21:76:24 | that | tst.ts:76:29:76:32 | Leaf | | tst.ts:80:36:80:55 | x is Generic | tst.ts:80:36:80:36 | x | tst.ts:80:41:80:55 | Generic | | tst.ts:81:38:81:50 | x is typeof x | tst.ts:81:38:81:38 | x | tst.ts:81:43:81:50 | typeof x | +| tst.ts:148:36:148:56 | asserts ... string | tst.ts:148:44:148:46 | val | tst.ts:148:51:148:56 | string | +test_PredicateTypeExpr +| tst.ts:75:17:75:28 | this is Leaf | tst.ts:75:17:75:20 | this | +| tst.ts:76:21:76:32 | that is Leaf | tst.ts:76:21:76:24 | that | +| tst.ts:80:36:80:55 | x is Generic | tst.ts:80:36:80:36 | x | +| tst.ts:81:38:81:50 | x is typeof x | tst.ts:81:38:81:38 | x | +| tst.ts:142:48:142:64 | asserts condition | tst.ts:142:56:142:64 | condition | +| tst.ts:148:36:148:56 | asserts ... string | tst.ts:148:44:148:46 | val | +test_hasAssertsKeyword +| tst.ts:142:48:142:64 | asserts condition | +| tst.ts:148:36:148:56 | asserts ... string | test_ThisParameterTypes | function hasThisParam | tst.ts:116:29:116:32 | void | | method hasThisParam of interface InterfaceWithThisParam | tst.ts:119:22:119:43 | Interfa ... isParam | @@ -254,6 +268,8 @@ test_ReturnTypes | tst.ts:94:1:94:37 | functio ... rn x; } | function f1 | tst.ts:94:23:94:23 | S | | tst.ts:95:1:95:53 | functio ... x,y]; } | function f2 | tst.ts:95:31:95:35 | [S,T] | | tst.ts:96:1:96:52 | functio ... rn x; } | function f3 | tst.ts:96:38:96:38 | S | +| tst.ts:142:1:146:1 | functio ... )\\n }\\n} | function assert | tst.ts:142:48:142:64 | asserts condition | +| tst.ts:148:1:152:1 | functio ... ;\\n }\\n} | function assertIsString | tst.ts:148:36:148:56 | asserts ... string | test_KeyofTypeExpr | tst.ts:49:16:49:30 | keyof Interface | tst.ts:49:22:49:30 | Interface | | tst.ts:113:26:113:35 | keyof Node | tst.ts:113:32:113:35 | Node | diff --git a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.ql b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.ql index ff894fb06a5c..bdabbc5f5333 100644 --- a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.ql +++ b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tests.ql @@ -11,7 +11,7 @@ import GenericTypeExpr import IntersectionTypeExpr import FunctionTypeReturns import InterfaceTypeExpr -import IsTypeExpr +import PredicateTypeExpr import ThisParameterTypes import ChildIndex import TypeArguments diff --git a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tst.ts b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tst.ts index a9985b42878a..faeb9e9c833d 100644 --- a/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/TypeAnnotations/tst.ts @@ -138,3 +138,15 @@ let unknownType: unknown; let taggedTemplateLiteralTypeArg1 = someTag`Hello`; let taggedTemplateLiteralTypeArg2 = someTag`Hello`; + +function assert(condition: any, msg?: string): asserts condition { + if (!condition) { + throw new AssertionError(msg) + } +} + +function assertIsString(val: any): asserts val is string { + if (typeof val !== "string") { + throw new AssertionError("Not a string!"); + } +} From 341c11523c806fa2739b4aae6bbe5a24ca349a3a Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 15:02:08 +0000 Subject: [PATCH 0160/2538] TS: Add recursive type alias tests (already works) --- .../TypeScript/Types/GetExprType.expected | 24 +++++++++++++ .../Types/GetTypeDefinitionType.expected | 3 ++ .../TypeScript/Types/GetTypeExprType.expected | 36 +++++++++++++++++++ .../Types/ReferenceDefinition.expected | 4 +++ .../TypeScript/Types/type_alias.ts | 24 +++++++++++++ 5 files changed, 91 insertions(+) diff --git a/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected b/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected index 429f056d2df2..628322656493 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/GetExprType.expected @@ -93,6 +93,30 @@ | tst.ts:43:28:43:30 | foo | "foo" | | tst.ts:43:33:43:37 | "foo" | "foo" | | type_alias.ts:3:5:3:5 | b | boolean | +| type_alias.ts:7:5:7:5 | c | ValueOrArray | +| type_alias.ts:14:9:14:32 | [proper ... ]: Json | any | +| type_alias.ts:14:10:14:17 | property | string | +| type_alias.ts:17:5:17:8 | json | Json | +| type_alias.ts:21:18:21:35 | [key: string]: any | any | +| type_alias.ts:21:19:21:21 | key | string | +| type_alias.ts:23:7:23:12 | myNode | VirtualNode | +| type_alias.ts:24:5:27:5 | ["div", ... ]\\n ] | VirtualNode | +| type_alias.ts:24:6:24:10 | "div" | "div" | +| type_alias.ts:24:13:24:28 | { id: "parent" } | string \| { [key: string]: any; } | +| type_alias.ts:24:15:24:16 | id | string | +| type_alias.ts:24:19:24:26 | "parent" | "parent" | +| type_alias.ts:25:9:25:61 | ["div", ... child"] | VirtualNode | +| type_alias.ts:25:10:25:14 | "div" | "div" | +| type_alias.ts:25:17:25:37 | { id: " ... hild" } | string \| { [key: string]: any; } | +| type_alias.ts:25:19:25:20 | id | string | +| type_alias.ts:25:23:25:35 | "first-child" | "first-child" | +| type_alias.ts:25:40:25:60 | "I'm th ... child" | "I'm the first child" | +| type_alias.ts:26:9:26:63 | ["div", ... child"] | VirtualNode | +| type_alias.ts:26:10:26:14 | "div" | "div" | +| type_alias.ts:26:17:26:38 | { id: " ... hild" } | string \| { [key: string]: any; } | +| type_alias.ts:26:19:26:20 | id | string | +| type_alias.ts:26:23:26:36 | "second-child" | "second-child" | +| type_alias.ts:26:41:26:62 | "I'm th ... child" | "I'm the second child" | | type_definition_objects.ts:1:13:1:17 | dummy | typeof dummy.ts | | type_definition_objects.ts:1:24:1:32 | "./dummy" | any | | type_definition_objects.ts:3:14:3:14 | C | C | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected index 670cb08a713a..66c343fd6013 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeDefinitionType.expected @@ -1,4 +1,7 @@ | type_alias.ts:1:1:1:17 | type B = boolean; | boolean | +| type_alias.ts:5:1:5:50 | type Va ... ay>; | ValueOrArray | +| type_alias.ts:9:1:15:13 | type Js ... Json[]; | Json | +| type_alias.ts:19:1:21:57 | type Vi ... ode[]]; | VirtualNode | | type_definition_objects.ts:3:8:3:17 | class C {} | C | | type_definition_objects.ts:6:8:6:16 | enum E {} | E | | type_definitions.ts:3:1:5:1 | interfa ... x: S;\\n} | I | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected index 3efd9dee5726..0b9af7801863 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/GetTypeExprType.expected @@ -71,6 +71,42 @@ | type_alias.ts:1:6:1:6 | B | boolean | | type_alias.ts:1:10:1:16 | boolean | boolean | | type_alias.ts:3:8:3:8 | B | boolean | +| type_alias.ts:5:6:5:17 | ValueOrArray | ValueOrArray | +| type_alias.ts:5:19:5:19 | T | T | +| type_alias.ts:5:24:5:24 | T | T | +| type_alias.ts:5:24:5:49 | T \| Arr ... ray> | ValueOrArray | +| type_alias.ts:5:28:5:32 | Array | T[] | +| type_alias.ts:5:28:5:49 | Array> | ValueOrArray[] | +| type_alias.ts:5:34:5:45 | ValueOrArray | ValueOrArray | +| type_alias.ts:5:34:5:48 | ValueOrArray | ValueOrArray | +| type_alias.ts:5:47:5:47 | T | T | +| type_alias.ts:7:8:7:19 | ValueOrArray | ValueOrArray | +| type_alias.ts:7:8:7:27 | ValueOrArray | ValueOrArray | +| type_alias.ts:7:21:7:26 | number | number | +| type_alias.ts:9:6:9:9 | Json | Json | +| type_alias.ts:10:5:15:12 | \| strin ... Json[] | Json | +| type_alias.ts:10:7:10:12 | string | string | +| type_alias.ts:11:7:11:12 | number | number | +| type_alias.ts:12:7:12:13 | boolean | boolean | +| type_alias.ts:13:7:13:10 | null | null | +| type_alias.ts:14:7:14:34 | { [prop ... Json } | { [property: string]: Json; } | +| type_alias.ts:14:20:14:25 | string | string | +| type_alias.ts:14:29:14:32 | Json | Json | +| type_alias.ts:15:7:15:10 | Json | Json | +| type_alias.ts:15:7:15:12 | Json[] | Json[] | +| type_alias.ts:17:11:17:14 | Json | Json | +| type_alias.ts:19:6:19:16 | VirtualNode | VirtualNode | +| type_alias.ts:20:5:21:56 | \| strin ... Node[]] | VirtualNode | +| type_alias.ts:20:7:20:12 | string | string | +| type_alias.ts:21:7:21:56 | [string ... Node[]] | [string, { [key: string]: any; }, ...VirtualNod... | +| type_alias.ts:21:8:21:13 | string | string | +| type_alias.ts:21:16:21:37 | { [key: ... : any } | { [key: string]: any; } | +| type_alias.ts:21:24:21:29 | string | string | +| type_alias.ts:21:33:21:35 | any | any | +| type_alias.ts:21:40:21:55 | ...VirtualNode[] | VirtualNode | +| type_alias.ts:21:43:21:53 | VirtualNode | VirtualNode | +| type_alias.ts:21:43:21:55 | VirtualNode[] | VirtualNode[] | +| type_alias.ts:23:15:23:25 | VirtualNode | VirtualNode | | type_definitions.ts:3:11:3:11 | I | I | | type_definitions.ts:3:13:3:13 | S | S | | type_definitions.ts:4:6:4:6 | S | S | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected b/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected index 12c9ebd4a107..3426a9361892 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected +++ b/javascript/ql/test/library-tests/TypeScript/Types/ReferenceDefinition.expected @@ -11,3 +11,7 @@ | EnumWithOneMember | type_definitions.ts:18:26:18:31 | member | | I | type_definitions.ts:3:1:5:1 | interfa ... x: S;\\n} | | I | type_definitions.ts:3:1:5:1 | interfa ... x: S;\\n} | +| Json | type_alias.ts:9:1:15:13 | type Js ... Json[]; | +| ValueOrArray | type_alias.ts:5:1:5:50 | type Va ... ay>; | +| ValueOrArray | type_alias.ts:5:1:5:50 | type Va ... ay>; | +| VirtualNode | type_alias.ts:19:1:21:57 | type Vi ... ode[]]; | diff --git a/javascript/ql/test/library-tests/TypeScript/Types/type_alias.ts b/javascript/ql/test/library-tests/TypeScript/Types/type_alias.ts index 3a8317669911..d13eb159754f 100644 --- a/javascript/ql/test/library-tests/TypeScript/Types/type_alias.ts +++ b/javascript/ql/test/library-tests/TypeScript/Types/type_alias.ts @@ -1,3 +1,27 @@ type B = boolean; var b: B; + +type ValueOrArray = T | Array>; + +var c: ValueOrArray; + +type Json = + | string + | number + | boolean + | null + | { [property: string]: Json } + | Json[]; + +var json: Json; + +type VirtualNode = + | string + | [string, { [key: string]: any }, ...VirtualNode[]]; + +const myNode: VirtualNode = + ["div", { id: "parent" }, + ["div", { id: "first-child" }, "I'm the first child"], + ["div", { id: "second-child" }, "I'm the second child"] + ]; From 7dfd4e06875d690be8e3e5a78409773c3a7efd2e Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 15:11:05 +0000 Subject: [PATCH 0161/2538] TS: Stop using the deprecated TypeReference.typeArguments --- .../extractor/lib/typescript/src/type_table.ts | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/javascript/extractor/lib/typescript/src/type_table.ts b/javascript/extractor/lib/typescript/src/type_table.ts index 553afcf2e41a..19eb64a8f10e 100644 --- a/javascript/extractor/lib/typescript/src/type_table.ts +++ b/javascript/extractor/lib/typescript/src/type_table.ts @@ -597,7 +597,7 @@ export class TypeTable { let tupleType = tupleReference.target; let minLength = tupleType.minLength != null ? tupleType.minLength - : tupleReference.typeArguments.length; + : this.typeChecker.getTypeArguments(tupleReference).length; let hasRestElement = tupleType.hasRestElement ? 't' : 'f'; let prefix = `tuple;${minLength};${hasRestElement}`; return this.makeTypeStringVectorFromTypeReferenceArguments(prefix, type); @@ -714,11 +714,12 @@ export class TypeTable { // There can be an extra type argument at the end, denoting an explicit 'this' type argument. // We discard the extra argument in our model. let target = type.target; - if (type.typeArguments == null) return tag; + let typeArguments = this.typeChecker.getTypeArguments(type); + if (typeArguments == null) return tag; if (target.typeParameters != null) { - return this.makeTypeStringVector(tag, type.typeArguments, target.typeParameters.length); + return this.makeTypeStringVector(tag, typeArguments, target.typeParameters.length); } else { - return this.makeTypeStringVector(tag, type.typeArguments); + return this.makeTypeStringVector(tag, typeArguments); } } @@ -992,7 +993,7 @@ export class TypeTable { * `T` is the type parameter declared on the `Promise` interface. */ private getSelfType(type: ts.Type): ts.TypeReference { - if (isTypeReference(type) && type.typeArguments != null && type.typeArguments.length > 0) { + if (isTypeReference(type) && this.typeChecker.getTypeArguments(type).length > 0) { return type.target; } return null; @@ -1181,8 +1182,9 @@ export class TypeTable { if (isTypeReference(type)) { // Note that this case also handles tuple types, since a tuple type is represented as // a reference to a synthetic generic interface. - if (type.typeArguments != null) { - type.typeArguments.forEach(callback); + let typeArguments = this.typeChecker.getTypeArguments(type); + if (typeArguments != null) { + typeArguments.forEach(callback); } } else if (type.flags & ts.TypeFlags.UnionOrIntersection) { (type as ts.UnionOrIntersectionType).types.forEach(callback); From 4846e53a101c7ba2895abba4c57fa1aa34b2e5dc Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 15:45:06 +0000 Subject: [PATCH 0162/2538] TS: Blacklist another cyclic property --- javascript/extractor/lib/typescript/src/main.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/lib/typescript/src/main.ts b/javascript/extractor/lib/typescript/src/main.ts index f0f847fd29a5..bce59fc79d3c 100644 --- a/javascript/extractor/lib/typescript/src/main.ts +++ b/javascript/extractor/lib/typescript/src/main.ts @@ -126,7 +126,7 @@ function checkCycle(root: any) { function isBlacklistedProperty(k: string) { return k === "parent" || k === "pos" || k === "end" || k === "symbol" || k === "localSymbol" - || k === "flowNode" || k === "returnFlowNode" + || k === "flowNode" || k === "returnFlowNode" || k === "endFlowNode" || k === "nextContainer" || k === "locals" || k === "bindDiagnostics" || k === "bindSuggestionDiagnostics"; } From 1b8335a4e912a9e0cbb7ac3099a20fda0a0ac5c4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 13:30:39 +0000 Subject: [PATCH 0163/2538] JS: Update change note --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 20f9ad1df875..b8f9fca3b3fa 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -12,7 +12,7 @@ * The call graph has been improved to resolve method calls in more cases. This may produce more security alerts. -* TypeScript 3.6 features are supported. +* TypeScript 3.6 and 3.7 features are now supported. ## New queries From 09a25424773d148a84a7d0657081d59bf758414b Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 1 Nov 2019 11:09:25 +0000 Subject: [PATCH 0164/2538] TS: Update a javadoc comment --- .../extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java index 474cb888c0b6..27bd3c1718c1 100644 --- a/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java +++ b/javascript/extractor/src/com/semmle/ts/ast/PredicateTypeExpr.java @@ -4,8 +4,8 @@ import com.semmle.js.ast.Visitor; /** - * A type of form E is T where E is a parameter name or this and - * T is a type. + * A type of form E is T, asserts E is T or asserts E where E is + * a parameter name or this and T is a type. */ public class PredicateTypeExpr extends TypeExpression { private final ITypeExpression expression; From 9bc45f351ccb66652f436a7ce669e93196c4083c Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 1 Nov 2019 16:16:58 +0000 Subject: [PATCH 0165/2538] TS: Fix typo in stats file --- javascript/ql/src/semmlecode.javascript.dbscheme.stats | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme.stats b/javascript/ql/src/semmlecode.javascript.dbscheme.stats index 0c1660bc7c83..f7d36078a5a0 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme.stats +++ b/javascript/ql/src/semmlecode.javascript.dbscheme.stats @@ -7922,7 +7922,7 @@ 66 -stmt +node 66 From 79dbdac8fa5d6dcc05ff5c82af0003171141be0a Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 1 Nov 2019 16:44:30 +0000 Subject: [PATCH 0166/2538] TS: Support declare modifier for fields --- .../com/semmle/js/ast/DeclarationFlags.java | 18 +++++++++++++++--- .../com/semmle/js/ast/MemberDefinition.java | 5 +++++ .../com/semmle/js/extractor/ASTExtractor.java | 4 ++++ .../js/parser/TypeScriptASTConverter.java | 3 +++ .../ql/src/semmle/javascript/Classes.qll | 6 ++++++ .../ql/src/semmlecode.javascript.dbscheme | 4 ++-- .../TypeScript/DeclareInClass/test.expected | 1 + .../TypeScript/DeclareInClass/test.ql | 5 +++++ .../TypeScript/DeclareInClass/tst.ts | 3 +++ 9 files changed, 44 insertions(+), 5 deletions(-) create mode 100644 javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.expected create mode 100644 javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.ql create mode 100644 javascript/ql/test/library-tests/TypeScript/DeclareInClass/tst.ts diff --git a/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java b/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java index 2a936bcc3b7e..8a6921cb20bd 100644 --- a/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java +++ b/javascript/extractor/src/com/semmle/js/ast/DeclarationFlags.java @@ -17,9 +17,10 @@ public class DeclarationFlags { public static final int protected_ = 1 << 6; public static final int optional = 1 << 7; public static final int definiteAssignmentAssertion = 1 << 8; + public static final int declareKeyword = 1 << 9; public static final int none = 0; - public static final int numberOfFlags = 9; + public static final int numberOfFlags = 10; public static final List names = Arrays.asList( @@ -31,7 +32,8 @@ public class DeclarationFlags { "private", "protected", "optional", - "definiteAssignmentAssertion"); + "definiteAssignmentAssertion", + "declare"); public static final List relationNames = Arrays.asList( @@ -43,7 +45,8 @@ public class DeclarationFlags { "hasPrivateKeyword", "hasProtectedKeyword", "isOptionalMember", - "hasDefiniteAssignmentAssertion"); + "hasDefiniteAssignmentAssertion", + "hasDeclareKeyword"); public static boolean isComputed(int flags) { return (flags & computed) != 0; @@ -81,6 +84,10 @@ public static boolean hasDefiniteAssignmentAssertion(int flags) { return (flags & definiteAssignmentAssertion) != 0; } + public static boolean hasDeclareKeyword(int flags) { + return (flags & declareKeyword) != 0; + } + /** Returns a mask with the computed bit set to the value of enable. */ public static int getComputed(boolean enable) { return enable ? computed : 0; @@ -128,6 +135,11 @@ public static int getDefiniteAssignmentAssertion(boolean enable) { return enable ? definiteAssignmentAssertion : 0; } + /** Returns a mask with the declare keyword bit set to the value of enable. */ + public static int getDeclareKeyword(boolean enable) { + return enable ? declareKeyword : 0; + } + /** Returns true if the nth bit is set in flags. */ public static boolean hasNthFlag(int flags, int n) { return (flags & (1 << n)) != 0; diff --git a/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java b/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java index bfd0f62462fb..c04b79fa3663 100644 --- a/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java +++ b/javascript/extractor/src/com/semmle/js/ast/MemberDefinition.java @@ -75,6 +75,11 @@ public boolean hasReadonlyKeyword() { return DeclarationFlags.isReadonly(flags); } + /** Returns true if this has the declare modifier. */ + public boolean hasDeclareKeyword() { + return DeclarationFlags.hasDeclareKeyword(flags); + } + /** * Returns the expression denoting the name of the member, or {@code null} if this is a * call/construct signature. diff --git a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java index d3571fc5a573..af15c7ad51cf 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/ASTExtractor.java @@ -1410,6 +1410,10 @@ public Label visit(MemberDefinition nd, Context c) { } } + if (nd.hasDeclareKeyword()) { + trapwriter.addTuple("hasDeclareKeyword", methkey); + } + return methkey; } diff --git a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java index 7f826a7dc1d8..4912b5577f8c 100644 --- a/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java +++ b/javascript/extractor/src/com/semmle/js/parser/TypeScriptASTConverter.java @@ -2009,6 +2009,9 @@ private Node convertPropertyDeclaration(JsonObject node, String kind, SourceLoca if (node.get("exclamationToken") != null) { flags |= DeclarationFlags.definiteAssignmentAssertion; } + if (hasModifier(node, "DeclareKeyword")) { + flags |= DeclarationFlags.declareKeyword; + } FieldDefinition fieldDefinition = new FieldDefinition( loc, diff --git a/javascript/ql/src/semmle/javascript/Classes.qll b/javascript/ql/src/semmle/javascript/Classes.qll index 5cf94d409f5d..793ff5a92e4c 100644 --- a/javascript/ql/src/semmle/javascript/Classes.qll +++ b/javascript/ql/src/semmle/javascript/Classes.qll @@ -1059,6 +1059,12 @@ class FieldDeclaration extends MemberDeclaration, @field { /** Holds if this is a TypeScript field marked as definitely assigned with the `!` operator. */ predicate hasDefiniteAssignmentAssertion() { hasDefiniteAssignmentAssertion(this) } + + override predicate isAmbient() { + hasDeclareKeyword(this) + or + getParent().isAmbient() + } } /** diff --git a/javascript/ql/src/semmlecode.javascript.dbscheme b/javascript/ql/src/semmlecode.javascript.dbscheme index e0bd730ef98a..5a5adbf98dce 100644 --- a/javascript/ql/src/semmlecode.javascript.dbscheme +++ b/javascript/ql/src/semmlecode.javascript.dbscheme @@ -200,8 +200,8 @@ case @stmt.kind of isInstantiated(unique int decl: @namespacedeclaration ref); -@declarablestmt = @declstmt | @namespacedeclaration | @classdeclstmt | @functiondeclstmt | @enumdeclaration | @externalmoduledeclaration | @globalaugmentationdeclaration; -hasDeclareKeyword(unique int stmt: @declarablestmt ref); +@declarablenode = @declstmt | @namespacedeclaration | @classdeclstmt | @functiondeclstmt | @enumdeclaration | @externalmoduledeclaration | @globalaugmentationdeclaration | @field; +hasDeclareKeyword(unique int stmt: @declarablenode ref); isForAwaitOf(unique int forof: @forofstmt ref); diff --git a/javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.expected b/javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.expected new file mode 100644 index 000000000000..17658f9c17d3 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.expected @@ -0,0 +1 @@ +| tst.ts:2:5:2:22 | declare x: number; | true | diff --git a/javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.ql b/javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.ql new file mode 100644 index 000000000000..b4a528dc9b1a --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/DeclareInClass/test.ql @@ -0,0 +1,5 @@ +import javascript + +from FieldDeclaration f, boolean ambient +where if f.isAmbient() then ambient = true else ambient = false +select f, ambient diff --git a/javascript/ql/test/library-tests/TypeScript/DeclareInClass/tst.ts b/javascript/ql/test/library-tests/TypeScript/DeclareInClass/tst.ts new file mode 100644 index 000000000000..0952c23532d6 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/DeclareInClass/tst.ts @@ -0,0 +1,3 @@ +class C { + declare x: number; +} From 2d7443ef986c66d354c7d4ed13d9fd842922abb6 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 4 Nov 2019 07:55:20 +0000 Subject: [PATCH 0167/2538] TS: Add upgrade script --- .../old.dbscheme | 1173 ++++++++++++++++ .../semmlecode.javascript.dbscheme | 1175 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 2350 insertions(+) create mode 100644 javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/old.dbscheme create mode 100644 javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/semmlecode.javascript.dbscheme create mode 100644 javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/upgrade.properties diff --git a/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/old.dbscheme b/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/old.dbscheme new file mode 100644 index 000000000000..874ebfcd4d2f --- /dev/null +++ b/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/old.dbscheme @@ -0,0 +1,1173 @@ +/*** Standard fragments ***/ + +/** Files and folders **/ + +@location = @location_default; + +locations_default(unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref + ); + +@sourceline = @locatable; + +numlines(int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref + ); + + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files(unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders(unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + + +@container = @folder | @file ; + + +containerparent(int parent: @container ref, + unique int child: @container ref); + +/** Duplicate code **/ + +duplicateCode( + unique int id : @duplication, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +similarCode( + unique int id : @similarity, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +@duplication_or_similarity = @duplication | @similarity; + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref); + +/** External data **/ + +externalData( + int id : @externalDataElement, + varchar(900) path : string ref, + int column: int ref, + varchar(900) value : string ref +); + +snapshotDate(unique date snapshotDate : date ref); + +sourceLocationPrefix(varchar(900) prefix : string ref); + +/** Version control data **/ + +svnentries( + int id : @svnentry, + varchar(500) revision : string ref, + varchar(500) author : string ref, + date revisionDate : date ref, + int changeSize : int ref +); + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + varchar(500) action : string ref +); + +svnentrymsg( + int id : @svnentry ref, + varchar(500) message : string ref +); + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +); + + +/*** JavaScript-specific part ***/ + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +isExterns (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url; + +isModule (int tl: @toplevel ref); +isNodejs (int tl: @toplevel ref); +isES2015Module (int tl: @toplevel ref); +isClosureModule (int tl: @toplevel ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +stmtContainers (unique int stmt: @stmt ref, + int container: @stmt_container ref); + +jumpTargets (unique int jump: @stmt ref, + int target: @stmt ref); + +@stmtparent = @stmt | @toplevel | @functionexpr | @arrowfunctionexpr; +@stmt_container = @toplevel | @function | @namespacedeclaration | @externalmoduledeclaration | @globalaugmentationdeclaration; + +case @stmt.kind of + 0 = @emptystmt +| 1 = @blockstmt +| 2 = @exprstmt +| 3 = @ifstmt +| 4 = @labeledstmt +| 5 = @breakstmt +| 6 = @continuestmt +| 7 = @withstmt +| 8 = @switchstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @trystmt +| 12 = @whilestmt +| 13 = @dowhilestmt +| 14 = @forstmt +| 15 = @forinstmt +| 16 = @debuggerstmt +| 17 = @functiondeclstmt +| 18 = @vardeclstmt +| 19 = @case +| 20 = @catchclause +| 21 = @forofstmt +| 22 = @constdeclstmt +| 23 = @letstmt +| 24 = @legacy_letstmt +| 25 = @foreachstmt +| 26 = @classdeclstmt +| 27 = @importdeclaration +| 28 = @exportalldeclaration +| 29 = @exportdefaultdeclaration +| 30 = @exportnameddeclaration +| 31 = @namespacedeclaration +| 32 = @importequalsdeclaration +| 33 = @exportassigndeclaration +| 34 = @interfacedeclaration +| 35 = @typealiasdeclaration +| 36 = @enumdeclaration +| 37 = @externalmoduledeclaration +| 38 = @exportasnamespacedeclaration +| 39 = @globalaugmentationdeclaration +; + +@declstmt = @vardeclstmt | @constdeclstmt | @letstmt | @legacy_letstmt; + +@exportdeclaration = @exportalldeclaration | @exportdefaultdeclaration | @exportnameddeclaration; + +@namespacedefinition = @namespacedeclaration | @enumdeclaration; +@typedefinition = @classdefinition | @interfacedeclaration | @enumdeclaration | @typealiasdeclaration | @enum_member; + +isInstantiated(unique int decl: @namespacedeclaration ref); + +@declarablestmt = @declstmt | @namespacedeclaration | @classdeclstmt | @functiondeclstmt | @enumdeclaration | @externalmoduledeclaration | @globalaugmentationdeclaration; +hasDeclareKeyword(unique int stmt: @declarablestmt ref); + +isForAwaitOf(unique int forof: @forofstmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @exprparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @exprortype ref); + +enclosingStmt (unique int expr: @exprortype ref, + int stmt: @stmt ref); + +exprContainers (unique int expr: @exprortype ref, + int container: @stmt_container ref); + +arraySize (unique int ae: @arraylike ref, + int sz: int ref); + +isDelegating (int yield: @yieldexpr ref); + +@exprorstmt = @expr | @stmt; +@exprortype = @expr | @typeexpr; +@exprparent = @exprorstmt | @property | @functiontypeexpr; +@arraylike = @arrayexpr | @arraypattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; + +case @expr.kind of + 0 = @label +| 1 = @nullliteral +| 2 = @booleanliteral +| 3 = @numberliteral +| 4 = @stringliteral +| 5 = @regexpliteral +| 6 = @thisexpr +| 7 = @arrayexpr +| 8 = @objexpr +| 9 = @functionexpr +| 10 = @seqexpr +| 11 = @conditionalexpr +| 12 = @newexpr +| 13 = @callexpr +| 14 = @dotexpr +| 15 = @indexexpr +| 16 = @negexpr +| 17 = @plusexpr +| 18 = @lognotexpr +| 19 = @bitnotexpr +| 20 = @typeofexpr +| 21 = @voidexpr +| 22 = @deleteexpr +| 23 = @eqexpr +| 24 = @neqexpr +| 25 = @eqqexpr +| 26 = @neqqexpr +| 27 = @ltexpr +| 28 = @leexpr +| 29 = @gtexpr +| 30 = @geexpr +| 31 = @lshiftexpr +| 32 = @rshiftexpr +| 33 = @urshiftexpr +| 34 = @addexpr +| 35 = @subexpr +| 36 = @mulexpr +| 37 = @divexpr +| 38 = @modexpr +| 39 = @bitorexpr +| 40 = @xorexpr +| 41 = @bitandexpr +| 42 = @inexpr +| 43 = @instanceofexpr +| 44 = @logandexpr +| 45 = @logorexpr +| 47 = @assignexpr +| 48 = @assignaddexpr +| 49 = @assignsubexpr +| 50 = @assignmulexpr +| 51 = @assigndivexpr +| 52 = @assignmodexpr +| 53 = @assignlshiftexpr +| 54 = @assignrshiftexpr +| 55 = @assignurshiftexpr +| 56 = @assignorexpr +| 57 = @assignxorexpr +| 58 = @assignandexpr +| 59 = @preincexpr +| 60 = @postincexpr +| 61 = @predecexpr +| 62 = @postdecexpr +| 63 = @parexpr +| 64 = @vardeclarator +| 65 = @arrowfunctionexpr +| 66 = @spreadelement +| 67 = @arraypattern +| 68 = @objectpattern +| 69 = @yieldexpr +| 70 = @taggedtemplateexpr +| 71 = @templateliteral +| 72 = @templateelement +| 73 = @arraycomprehensionexpr +| 74 = @generatorexpr +| 75 = @forincomprehensionblock +| 76 = @forofcomprehensionblock +| 77 = @legacy_letexpr +| 78 = @vardecl +| 79 = @proper_varaccess +| 80 = @classexpr +| 81 = @superexpr +| 82 = @newtargetexpr +| 83 = @namedimportspecifier +| 84 = @importdefaultspecifier +| 85 = @importnamespacespecifier +| 86 = @namedexportspecifier +| 87 = @expexpr +| 88 = @assignexpexpr +| 89 = @jsxelement +| 90 = @jsxqualifiedname +| 91 = @jsxemptyexpr +| 92 = @awaitexpr +| 93 = @functionsentexpr +| 94 = @decorator +| 95 = @exportdefaultspecifier +| 96 = @exportnamespacespecifier +| 97 = @bindexpr +| 98 = @externalmodulereference +| 99 = @dynamicimport +| 100 = @expressionwithtypearguments +| 101 = @prefixtypeassertion +| 102 = @astypeassertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigintliteral +| 107 = @nullishcoalescingexpr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @importmetaexpr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @vardecl | @varaccess; + +@identifier = @label | @varref | @typeidentifier; + +@literal = @nullliteral | @booleanliteral | @numberliteral | @stringliteral | @regexpliteral | @bigintliteral; + +@propaccess = @dotexpr | @indexexpr; + +@invokeexpr = @newexpr | @callexpr; + +@unaryexpr = @negexpr | @plusexpr | @lognotexpr | @bitnotexpr | @typeofexpr | @voidexpr | @deleteexpr | @spreadelement; + +@equalitytest = @eqexpr | @neqexpr | @eqqexpr | @neqqexpr; + +@comparison = @equalitytest | @ltexpr | @leexpr | @gtexpr | @geexpr; + +@binaryexpr = @comparison | @lshiftexpr | @rshiftexpr | @urshiftexpr | @addexpr | @subexpr | @mulexpr | @divexpr | @modexpr | @expexpr | @bitorexpr | @xorexpr | @bitandexpr | @inexpr | @instanceofexpr | @logandexpr | @logorexpr | @nullishcoalescingexpr; + +@assignment = @assignexpr | @assignaddexpr | @assignsubexpr | @assignmulexpr | @assigndivexpr | @assignmodexpr | @assignexpexpr | @assignlshiftexpr | @assignrshiftexpr | @assignurshiftexpr | @assignorexpr | @assignxorexpr | @assignandexpr; + +@updateexpr = @preincexpr | @postincexpr | @predecexpr | @postdecexpr; + +@pattern = @varref | @arraypattern | @objectpattern; + +@comprehensionexpr = @arraycomprehensionexpr | @generatorexpr; + +@comprehensionblock = @forincomprehensionblock | @forofcomprehensionblock; + +@importspecifier = @namedimportspecifier | @importdefaultspecifier | @importnamespacespecifier; + +@exportspecifier = @namedexportspecifier | @exportdefaultspecifier | @exportnamespacespecifier; + +@typeassertion = @astypeassertion | @prefixtypeassertion; + +@classdefinition = @classdeclstmt | @classexpr; +@interfacedefinition = @interfacedeclaration | @interfacetypeexpr; +@classorinterface = @classdefinition | @interfacedefinition; + +@lexical_decl = @vardecl | @typedecl; +@lexical_access = @varaccess | @localtypeaccess | @localvartypeaccess | @localnamespaceaccess; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @globalscope +| 1 = @functionscope +| 2 = @catchscope +| 3 = @modulescope +| 4 = @blockscope +| 5 = @forscope +| 6 = @forinscope // for-of scopes work the same as for-in scopes +| 7 = @comprehensionblockscope +| 8 = @classexprscope +| 9 = @namespacescope +| 10 = @classdeclscope +| 11 = @interfacescope +| 12 = @typealiasscope +| 13 = @mappedtypescope +| 14 = @enumscope +| 15 = @externalmodulescope +| 16 = @conditionaltypescope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @functiondeclstmt | @functionexpr | @arrowfunctionexpr; + +@parameterized = @function | @catchclause; +@type_parameterized = @function | @classorinterface | @typealiasdeclaration | @mappedtypeexpr | @infertypeexpr; + +isGenerator (int fun: @function ref); +hasRestParameter (int fun: @function ref); +isAsync (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +isArgumentsObject (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @localvartypeaccess; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @vardecl ref, + int decl: @variable ref); + +@typebind_id = @localtypeaccess | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @typedecl | @vardecl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @vardecl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @localnamespaceaccess | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +; + +@property_parent = @objexpr | @objectpattern | @classdefinition | @jsxelement | @interfacedefinition | @enumdeclaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @vardeclarator; + +isComputed (int id: @property ref); +isMethod (int id: @property ref); +isStatic (int id: @property ref); +isAbstractMember (int id: @property ref); +isConstEnum (int id: @enumdeclaration ref); +isAbstractClass (int id: @classdeclstmt ref); + +hasPublicKeyword (int id: @property ref); +hasPrivateKeyword (int id: @property ref); +hasProtectedKeyword (int id: @property ref); +hasReadonlyKeyword (int id: @property ref); +isOptionalMember (int id: @property ref); +hasDefiniteAssignmentAssertion (int id: @field_or_vardeclarator ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @functionexpr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @localtypeaccess +| 1 = @typedecl +| 2 = @keywordtypeexpr +| 3 = @stringliteraltypeexpr +| 4 = @numberliteraltypeexpr +| 5 = @booleanliteraltypeexpr +| 6 = @arraytypeexpr +| 7 = @uniontypeexpr +| 8 = @indexedaccesstypeexpr +| 9 = @intersectiontypeexpr +| 10 = @parenthesizedtypeexpr +| 11 = @tupletypeexpr +| 12 = @keyoftypeexpr +| 13 = @qualifiedtypeaccess +| 14 = @generictypeexpr +| 15 = @typelabel +| 16 = @typeoftypeexpr +| 17 = @localvartypeaccess +| 18 = @qualifiedvartypeaccess +| 19 = @thisvartypeaccess +| 20 = @istypeexpr +| 21 = @interfacetypeexpr +| 22 = @typeparameter +| 23 = @plainfunctiontypeexpr +| 24 = @constructortypeexpr +| 25 = @localnamespaceaccess +| 26 = @qualifiednamespaceaccess +| 27 = @mappedtypeexpr +| 28 = @conditionaltypeexpr +| 29 = @infertypeexpr +| 30 = @importtypeaccess +| 31 = @importnamespaceaccess +| 32 = @importvartypeaccess +| 33 = @optionaltypeexpr +| 34 = @resttypeexpr +| 35 = @bigintliteraltypeexpr +| 36 = @readonlytypeexpr +; + +@typeref = @typeaccess | @typedecl; +@typeidentifier = @typedecl | @localtypeaccess | @typelabel | @localvartypeaccess | @localnamespaceaccess; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literaltypeexpr = @stringliteraltypeexpr | @numberliteraltypeexpr | @booleanliteraltypeexpr | @bigintliteraltypeexpr; +@typeaccess = @localtypeaccess | @qualifiedtypeaccess | @importtypeaccess; +@vartypeaccess = @localvartypeaccess | @qualifiedvartypeaccess | @thisvartypeaccess | @importvartypeaccess; +@namespaceaccess = @localnamespaceaccess | @qualifiednamespaceaccess | @importnamespaceaccess; +@importtypeexpr = @importtypeaccess | @importnamespaceaccess | @importvartypeaccess; + +@functiontypeexpr = @plainfunctiontypeexpr | @constructortypeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @anytype +| 1 = @stringtype +| 2 = @numbertype +| 3 = @uniontype +| 4 = @truetype +| 5 = @falsetype +| 6 = @typereference +| 7 = @objecttype +| 8 = @canonicaltypevariabletype +| 9 = @typeoftype +| 10 = @voidtype +| 11 = @undefinedtype +| 12 = @nulltype +| 13 = @nevertype +| 14 = @plainsymboltype +| 15 = @uniquesymboltype +| 16 = @objectkeywordtype +| 17 = @intersectiontype +| 18 = @tupletype +| 19 = @lexicaltypevariabletype +| 20 = @thistype +| 21 = @numberliteraltype +| 22 = @stringliteraltype +| 23 = @unknowntype +| 24 = @biginttype +| 25 = @bigintliteraltype +; + +@booleanliteraltype = @truetype | @falsetype; +@symboltype = @plainsymboltype | @uniquesymboltype; +@unionorintersectiontype = @uniontype | @intersectiontype; +@typevariabletype = @canonicaltypevariabletype | @lexicaltypevariabletype; + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@type_with_symbol = @typereference | @typevariabletype | @typeoftype | @uniquesymboltype; +@ast_node_with_symbol = @typedefinition | @namespacedefinition | @toplevel | @typeaccess | @namespaceaccess | @vardecl | @function | @invokeexpr; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +@literaltype = @stringliteraltype | @numberliteraltype | @booleanliteraltype | @bigintliteraltype; +@type_with_literal_value = @stringliteraltype | @numberliteraltype | @bigintliteraltype; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @typereference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest( + unique int typ: @type ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslashcomment +| 1 = @slashstarcomment +| 2 = @doccomment +| 3 = @htmlcommentstart +| 4 = @htmlcommentend; + +@htmlcomment = @htmlcommentstart | @htmlcommentend; +@linecomment = @slashslashcomment | @htmlcomment; +@blockcomment = @slashstarcomment | @doccomment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +jsParseErrors (unique int id: @js_parse_error, + int toplevel: @toplevel ref, + varchar(900) message: string ref, + varchar(900) line: string ref); + +// regular expressions +#keyset[parent, idx] +regexpterm (unique int id: @regexpterm, + int kind: int ref, + int parent: @regexpparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +@regexpparent = @regexpterm | @regexpliteral; + +case @regexpterm.kind of + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_char +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape; + +regexpParseErrors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_char | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; + +isGreedy (int id: @regexp_quantifier ref); +rangeQuantifierLowerBound (unique int id: @regexp_range ref, int lo: int ref); +rangeQuantifierUpperBound (unique int id: @regexp_range ref, int hi: int ref); +isCapture (unique int id: @regexp_group ref, int number: int ref); +isNamedCapture (unique int id: @regexp_group ref, string name: string ref); +isInverted (int id: @regexp_char_class ref); +regexpConstValue (unique int id: @regexp_constant ref, varchar(1) value: string ref); +charClassEscape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +namedBackref (unique int id: @regexp_backref ref, string name: string ref); +unicodePropertyEscapeName (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicodePropertyEscapeValue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @exprparent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +// YAML +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + varchar(900) tag: string ref, + varchar(900) tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + varchar(900) anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + varchar(900) target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + varchar(900) value: string ref); + +yaml_errors (unique int id: @yaml_error, + varchar(900) message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/* XML Files */ + +xmlEncoding( + unique int id: @file ref, + varchar(900) encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +@dataflownode = @expr | @functiondeclstmt | @classdeclstmt | @namespacedeclaration | @enumdeclaration | @property; + +@optionalchainable = @callexpr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** + * Non-timing related data for the extraction of a single file. + * This table contains non-deterministic content. + */ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) diff --git a/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/semmlecode.javascript.dbscheme b/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/semmlecode.javascript.dbscheme new file mode 100644 index 000000000000..5a5adbf98dce --- /dev/null +++ b/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/semmlecode.javascript.dbscheme @@ -0,0 +1,1175 @@ +/*** Standard fragments ***/ + +/** Files and folders **/ + +@location = @location_default; + +locations_default(unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref + ); + +@sourceline = @locatable; + +numlines(int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref + ); + + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files(unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders(unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + + +@container = @folder | @file ; + + +containerparent(int parent: @container ref, + unique int child: @container ref); + +/** Duplicate code **/ + +duplicateCode( + unique int id : @duplication, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +similarCode( + unique int id : @similarity, + varchar(900) relativePath : string ref, + int equivClass : int ref); + +@duplication_or_similarity = @duplication | @similarity; + +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref); + +/** External data **/ + +externalData( + int id : @externalDataElement, + varchar(900) path : string ref, + int column: int ref, + varchar(900) value : string ref +); + +snapshotDate(unique date snapshotDate : date ref); + +sourceLocationPrefix(varchar(900) prefix : string ref); + +/** Version control data **/ + +svnentries( + int id : @svnentry, + varchar(500) revision : string ref, + varchar(500) author : string ref, + date revisionDate : date ref, + int changeSize : int ref +); + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + varchar(500) action : string ref +); + +svnentrymsg( + int id : @svnentry ref, + varchar(500) message : string ref +); + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +); + + +/*** JavaScript-specific part ***/ + +filetype( + int file: @file ref, + string filetype: string ref +) + +// top-level code fragments +toplevels (unique int id: @toplevel, + int kind: int ref); + +isExterns (int toplevel: @toplevel ref); + +case @toplevel.kind of + 0 = @script +| 1 = @inline_script +| 2 = @event_handler +| 3 = @javascript_url; + +isModule (int tl: @toplevel ref); +isNodejs (int tl: @toplevel ref); +isES2015Module (int tl: @toplevel ref); +isClosureModule (int tl: @toplevel ref); + +// statements +#keyset[parent, idx] +stmts (unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +stmtContainers (unique int stmt: @stmt ref, + int container: @stmt_container ref); + +jumpTargets (unique int jump: @stmt ref, + int target: @stmt ref); + +@stmtparent = @stmt | @toplevel | @functionexpr | @arrowfunctionexpr; +@stmt_container = @toplevel | @function | @namespacedeclaration | @externalmoduledeclaration | @globalaugmentationdeclaration; + +case @stmt.kind of + 0 = @emptystmt +| 1 = @blockstmt +| 2 = @exprstmt +| 3 = @ifstmt +| 4 = @labeledstmt +| 5 = @breakstmt +| 6 = @continuestmt +| 7 = @withstmt +| 8 = @switchstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @trystmt +| 12 = @whilestmt +| 13 = @dowhilestmt +| 14 = @forstmt +| 15 = @forinstmt +| 16 = @debuggerstmt +| 17 = @functiondeclstmt +| 18 = @vardeclstmt +| 19 = @case +| 20 = @catchclause +| 21 = @forofstmt +| 22 = @constdeclstmt +| 23 = @letstmt +| 24 = @legacy_letstmt +| 25 = @foreachstmt +| 26 = @classdeclstmt +| 27 = @importdeclaration +| 28 = @exportalldeclaration +| 29 = @exportdefaultdeclaration +| 30 = @exportnameddeclaration +| 31 = @namespacedeclaration +| 32 = @importequalsdeclaration +| 33 = @exportassigndeclaration +| 34 = @interfacedeclaration +| 35 = @typealiasdeclaration +| 36 = @enumdeclaration +| 37 = @externalmoduledeclaration +| 38 = @exportasnamespacedeclaration +| 39 = @globalaugmentationdeclaration +; + +@declstmt = @vardeclstmt | @constdeclstmt | @letstmt | @legacy_letstmt; + +@exportdeclaration = @exportalldeclaration | @exportdefaultdeclaration | @exportnameddeclaration; + +@namespacedefinition = @namespacedeclaration | @enumdeclaration; +@typedefinition = @classdefinition | @interfacedeclaration | @enumdeclaration | @typealiasdeclaration | @enum_member; + +isInstantiated(unique int decl: @namespacedeclaration ref); + +@declarablenode = @declstmt | @namespacedeclaration | @classdeclstmt | @functiondeclstmt | @enumdeclaration | @externalmoduledeclaration | @globalaugmentationdeclaration | @field; +hasDeclareKeyword(unique int stmt: @declarablenode ref); + +isForAwaitOf(unique int forof: @forofstmt ref); + +// expressions +#keyset[parent, idx] +exprs (unique int id: @expr, + int kind: int ref, + int parent: @exprparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @exprortype ref); + +enclosingStmt (unique int expr: @exprortype ref, + int stmt: @stmt ref); + +exprContainers (unique int expr: @exprortype ref, + int container: @stmt_container ref); + +arraySize (unique int ae: @arraylike ref, + int sz: int ref); + +isDelegating (int yield: @yieldexpr ref); + +@exprorstmt = @expr | @stmt; +@exprortype = @expr | @typeexpr; +@exprparent = @exprorstmt | @property | @functiontypeexpr; +@arraylike = @arrayexpr | @arraypattern; +@type_annotation = @typeexpr | @jsdoc_type_expr; + +case @expr.kind of + 0 = @label +| 1 = @nullliteral +| 2 = @booleanliteral +| 3 = @numberliteral +| 4 = @stringliteral +| 5 = @regexpliteral +| 6 = @thisexpr +| 7 = @arrayexpr +| 8 = @objexpr +| 9 = @functionexpr +| 10 = @seqexpr +| 11 = @conditionalexpr +| 12 = @newexpr +| 13 = @callexpr +| 14 = @dotexpr +| 15 = @indexexpr +| 16 = @negexpr +| 17 = @plusexpr +| 18 = @lognotexpr +| 19 = @bitnotexpr +| 20 = @typeofexpr +| 21 = @voidexpr +| 22 = @deleteexpr +| 23 = @eqexpr +| 24 = @neqexpr +| 25 = @eqqexpr +| 26 = @neqqexpr +| 27 = @ltexpr +| 28 = @leexpr +| 29 = @gtexpr +| 30 = @geexpr +| 31 = @lshiftexpr +| 32 = @rshiftexpr +| 33 = @urshiftexpr +| 34 = @addexpr +| 35 = @subexpr +| 36 = @mulexpr +| 37 = @divexpr +| 38 = @modexpr +| 39 = @bitorexpr +| 40 = @xorexpr +| 41 = @bitandexpr +| 42 = @inexpr +| 43 = @instanceofexpr +| 44 = @logandexpr +| 45 = @logorexpr +| 47 = @assignexpr +| 48 = @assignaddexpr +| 49 = @assignsubexpr +| 50 = @assignmulexpr +| 51 = @assigndivexpr +| 52 = @assignmodexpr +| 53 = @assignlshiftexpr +| 54 = @assignrshiftexpr +| 55 = @assignurshiftexpr +| 56 = @assignorexpr +| 57 = @assignxorexpr +| 58 = @assignandexpr +| 59 = @preincexpr +| 60 = @postincexpr +| 61 = @predecexpr +| 62 = @postdecexpr +| 63 = @parexpr +| 64 = @vardeclarator +| 65 = @arrowfunctionexpr +| 66 = @spreadelement +| 67 = @arraypattern +| 68 = @objectpattern +| 69 = @yieldexpr +| 70 = @taggedtemplateexpr +| 71 = @templateliteral +| 72 = @templateelement +| 73 = @arraycomprehensionexpr +| 74 = @generatorexpr +| 75 = @forincomprehensionblock +| 76 = @forofcomprehensionblock +| 77 = @legacy_letexpr +| 78 = @vardecl +| 79 = @proper_varaccess +| 80 = @classexpr +| 81 = @superexpr +| 82 = @newtargetexpr +| 83 = @namedimportspecifier +| 84 = @importdefaultspecifier +| 85 = @importnamespacespecifier +| 86 = @namedexportspecifier +| 87 = @expexpr +| 88 = @assignexpexpr +| 89 = @jsxelement +| 90 = @jsxqualifiedname +| 91 = @jsxemptyexpr +| 92 = @awaitexpr +| 93 = @functionsentexpr +| 94 = @decorator +| 95 = @exportdefaultspecifier +| 96 = @exportnamespacespecifier +| 97 = @bindexpr +| 98 = @externalmodulereference +| 99 = @dynamicimport +| 100 = @expressionwithtypearguments +| 101 = @prefixtypeassertion +| 102 = @astypeassertion +| 103 = @export_varaccess +| 104 = @decorator_list +| 105 = @non_null_assertion +| 106 = @bigintliteral +| 107 = @nullishcoalescingexpr +| 108 = @e4x_xml_anyname +| 109 = @e4x_xml_static_attribute_selector +| 110 = @e4x_xml_dynamic_attribute_selector +| 111 = @e4x_xml_filter_expression +| 112 = @e4x_xml_static_qualident +| 113 = @e4x_xml_dynamic_qualident +| 114 = @e4x_xml_dotdotexpr +| 115 = @importmetaexpr +; + +@varaccess = @proper_varaccess | @export_varaccess; +@varref = @vardecl | @varaccess; + +@identifier = @label | @varref | @typeidentifier; + +@literal = @nullliteral | @booleanliteral | @numberliteral | @stringliteral | @regexpliteral | @bigintliteral; + +@propaccess = @dotexpr | @indexexpr; + +@invokeexpr = @newexpr | @callexpr; + +@unaryexpr = @negexpr | @plusexpr | @lognotexpr | @bitnotexpr | @typeofexpr | @voidexpr | @deleteexpr | @spreadelement; + +@equalitytest = @eqexpr | @neqexpr | @eqqexpr | @neqqexpr; + +@comparison = @equalitytest | @ltexpr | @leexpr | @gtexpr | @geexpr; + +@binaryexpr = @comparison | @lshiftexpr | @rshiftexpr | @urshiftexpr | @addexpr | @subexpr | @mulexpr | @divexpr | @modexpr | @expexpr | @bitorexpr | @xorexpr | @bitandexpr | @inexpr | @instanceofexpr | @logandexpr | @logorexpr | @nullishcoalescingexpr; + +@assignment = @assignexpr | @assignaddexpr | @assignsubexpr | @assignmulexpr | @assigndivexpr | @assignmodexpr | @assignexpexpr | @assignlshiftexpr | @assignrshiftexpr | @assignurshiftexpr | @assignorexpr | @assignxorexpr | @assignandexpr; + +@updateexpr = @preincexpr | @postincexpr | @predecexpr | @postdecexpr; + +@pattern = @varref | @arraypattern | @objectpattern; + +@comprehensionexpr = @arraycomprehensionexpr | @generatorexpr; + +@comprehensionblock = @forincomprehensionblock | @forofcomprehensionblock; + +@importspecifier = @namedimportspecifier | @importdefaultspecifier | @importnamespacespecifier; + +@exportspecifier = @namedexportspecifier | @exportdefaultspecifier | @exportnamespacespecifier; + +@typeassertion = @astypeassertion | @prefixtypeassertion; + +@classdefinition = @classdeclstmt | @classexpr; +@interfacedefinition = @interfacedeclaration | @interfacetypeexpr; +@classorinterface = @classdefinition | @interfacedefinition; + +@lexical_decl = @vardecl | @typedecl; +@lexical_access = @varaccess | @localtypeaccess | @localvartypeaccess | @localnamespaceaccess; +@lexical_ref = @lexical_decl | @lexical_access; + +@e4x_xml_attribute_selector = @e4x_xml_static_attribute_selector | @e4x_xml_dynamic_attribute_selector; +@e4x_xml_qualident = @e4x_xml_static_qualident | @e4x_xml_dynamic_qualident; + +// scopes +scopes (unique int id: @scope, + int kind: int ref); + +case @scope.kind of + 0 = @globalscope +| 1 = @functionscope +| 2 = @catchscope +| 3 = @modulescope +| 4 = @blockscope +| 5 = @forscope +| 6 = @forinscope // for-of scopes work the same as for-in scopes +| 7 = @comprehensionblockscope +| 8 = @classexprscope +| 9 = @namespacescope +| 10 = @classdeclscope +| 11 = @interfacescope +| 12 = @typealiasscope +| 13 = @mappedtypescope +| 14 = @enumscope +| 15 = @externalmodulescope +| 16 = @conditionaltypescope; + +scopenodes (unique int node: @ast_node ref, + int scope: @scope ref); + +scopenesting (unique int inner: @scope ref, + int outer: @scope ref); + +// functions +@function = @functiondeclstmt | @functionexpr | @arrowfunctionexpr; + +@parameterized = @function | @catchclause; +@type_parameterized = @function | @classorinterface | @typealiasdeclaration | @mappedtypeexpr | @infertypeexpr; + +isGenerator (int fun: @function ref); +hasRestParameter (int fun: @function ref); +isAsync (int fun: @function ref); + +// variables and lexically scoped type names +#keyset[scope, name] +variables (unique int id: @variable, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_type_names (unique int id: @local_type_name, + varchar(900) name: string ref, + int scope: @scope ref); + +#keyset[scope, name] +local_namespace_names (unique int id: @local_namespace_name, + varchar(900) name: string ref, + int scope: @scope ref); + +isArgumentsObject (int id: @variable ref); + +@lexical_name = @variable | @local_type_name | @local_namespace_name; + +@bind_id = @varaccess | @localvartypeaccess; +bind (unique int id: @bind_id ref, + int decl: @variable ref); + +decl (unique int id: @vardecl ref, + int decl: @variable ref); + +@typebind_id = @localtypeaccess | @export_varaccess; +typebind (unique int id: @typebind_id ref, + int decl: @local_type_name ref); + +@typedecl_id = @typedecl | @vardecl; +typedecl (unique int id: @typedecl_id ref, + int decl: @local_type_name ref); + +namespacedecl (unique int id: @vardecl ref, + int decl: @local_namespace_name ref); + +@namespacebind_id = @localnamespaceaccess | @export_varaccess; +namespacebind (unique int id: @namespacebind_id ref, + int decl: @local_namespace_name ref); + + +// properties in object literals, property patterns in object patterns, and method declarations in classes +#keyset[parent, index] +properties (unique int id: @property, + int parent: @property_parent ref, + int index: int ref, + int kind: int ref, + varchar(900) tostring: string ref); + +case @property.kind of + 0 = @value_property +| 1 = @property_getter +| 2 = @property_setter +| 3 = @jsx_attribute +| 4 = @function_call_signature +| 5 = @constructor_call_signature +| 6 = @index_signature +| 7 = @enum_member +| 8 = @proper_field +| 9 = @parameter_field +; + +@property_parent = @objexpr | @objectpattern | @classdefinition | @jsxelement | @interfacedefinition | @enumdeclaration; +@property_accessor = @property_getter | @property_setter; +@call_signature = @function_call_signature | @constructor_call_signature; +@field = @proper_field | @parameter_field; +@field_or_vardeclarator = @field | @vardeclarator; + +isComputed (int id: @property ref); +isMethod (int id: @property ref); +isStatic (int id: @property ref); +isAbstractMember (int id: @property ref); +isConstEnum (int id: @enumdeclaration ref); +isAbstractClass (int id: @classdeclstmt ref); + +hasPublicKeyword (int id: @property ref); +hasPrivateKeyword (int id: @property ref); +hasProtectedKeyword (int id: @property ref); +hasReadonlyKeyword (int id: @property ref); +isOptionalMember (int id: @property ref); +hasDefiniteAssignmentAssertion (int id: @field_or_vardeclarator ref); + +#keyset[constructor, param_index] +parameter_fields( + unique int field: @parameter_field ref, + int constructor: @functionexpr ref, + int param_index: int ref +); + +// types +#keyset[parent, idx] +typeexprs ( + unique int id: @typeexpr, + int kind: int ref, + int parent: @typeexpr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref +); + +case @typeexpr.kind of + 0 = @localtypeaccess +| 1 = @typedecl +| 2 = @keywordtypeexpr +| 3 = @stringliteraltypeexpr +| 4 = @numberliteraltypeexpr +| 5 = @booleanliteraltypeexpr +| 6 = @arraytypeexpr +| 7 = @uniontypeexpr +| 8 = @indexedaccesstypeexpr +| 9 = @intersectiontypeexpr +| 10 = @parenthesizedtypeexpr +| 11 = @tupletypeexpr +| 12 = @keyoftypeexpr +| 13 = @qualifiedtypeaccess +| 14 = @generictypeexpr +| 15 = @typelabel +| 16 = @typeoftypeexpr +| 17 = @localvartypeaccess +| 18 = @qualifiedvartypeaccess +| 19 = @thisvartypeaccess +| 20 = @predicatetypeexpr +| 21 = @interfacetypeexpr +| 22 = @typeparameter +| 23 = @plainfunctiontypeexpr +| 24 = @constructortypeexpr +| 25 = @localnamespaceaccess +| 26 = @qualifiednamespaceaccess +| 27 = @mappedtypeexpr +| 28 = @conditionaltypeexpr +| 29 = @infertypeexpr +| 30 = @importtypeaccess +| 31 = @importnamespaceaccess +| 32 = @importvartypeaccess +| 33 = @optionaltypeexpr +| 34 = @resttypeexpr +| 35 = @bigintliteraltypeexpr +| 36 = @readonlytypeexpr +; + +@typeref = @typeaccess | @typedecl; +@typeidentifier = @typedecl | @localtypeaccess | @typelabel | @localvartypeaccess | @localnamespaceaccess; +@typeexpr_parent = @expr | @stmt | @property | @typeexpr; +@literaltypeexpr = @stringliteraltypeexpr | @numberliteraltypeexpr | @booleanliteraltypeexpr | @bigintliteraltypeexpr; +@typeaccess = @localtypeaccess | @qualifiedtypeaccess | @importtypeaccess; +@vartypeaccess = @localvartypeaccess | @qualifiedvartypeaccess | @thisvartypeaccess | @importvartypeaccess; +@namespaceaccess = @localnamespaceaccess | @qualifiednamespaceaccess | @importnamespaceaccess; +@importtypeexpr = @importtypeaccess | @importnamespaceaccess | @importvartypeaccess; + +@functiontypeexpr = @plainfunctiontypeexpr | @constructortypeexpr; + +// types +types ( + unique int id: @type, + int kind: int ref, + varchar(900) tostring: string ref +); + +#keyset[parent, idx] +type_child ( + int child: @type ref, + int parent: @type ref, + int idx: int ref +); + +case @type.kind of + 0 = @anytype +| 1 = @stringtype +| 2 = @numbertype +| 3 = @uniontype +| 4 = @truetype +| 5 = @falsetype +| 6 = @typereference +| 7 = @objecttype +| 8 = @canonicaltypevariabletype +| 9 = @typeoftype +| 10 = @voidtype +| 11 = @undefinedtype +| 12 = @nulltype +| 13 = @nevertype +| 14 = @plainsymboltype +| 15 = @uniquesymboltype +| 16 = @objectkeywordtype +| 17 = @intersectiontype +| 18 = @tupletype +| 19 = @lexicaltypevariabletype +| 20 = @thistype +| 21 = @numberliteraltype +| 22 = @stringliteraltype +| 23 = @unknowntype +| 24 = @biginttype +| 25 = @bigintliteraltype +; + +@booleanliteraltype = @truetype | @falsetype; +@symboltype = @plainsymboltype | @uniquesymboltype; +@unionorintersectiontype = @uniontype | @intersectiontype; +@typevariabletype = @canonicaltypevariabletype | @lexicaltypevariabletype; + +hasAssertsKeyword(int node: @predicatetypeexpr ref); + +@typed_ast_node = @expr | @typeexpr | @function; +ast_node_type( + unique int node: @typed_ast_node ref, + int typ: @type ref); + +declared_function_signature( + unique int node: @function ref, + int sig: @signature_type ref +); + +invoke_expr_signature( + unique int node: @invokeexpr ref, + int sig: @signature_type ref +); + +invoke_expr_overload_index( + unique int node: @invokeexpr ref, + int index: int ref +); + +symbols ( + unique int id: @symbol, + int kind: int ref, + varchar(900) name: string ref +); + +symbol_parent ( + unique int symbol: @symbol ref, + int parent: @symbol ref +); + +symbol_module ( + int symbol: @symbol ref, + varchar(900) moduleName: string ref +); + +symbol_global ( + int symbol: @symbol ref, + varchar(900) globalName: string ref +); + +case @symbol.kind of + 0 = @root_symbol +| 1 = @member_symbol +| 2 = @other_symbol +; + +@type_with_symbol = @typereference | @typevariabletype | @typeoftype | @uniquesymboltype; +@ast_node_with_symbol = @typedefinition | @namespacedefinition | @toplevel | @typeaccess | @namespaceaccess | @vardecl | @function | @invokeexpr; + +ast_node_symbol( + unique int node: @ast_node_with_symbol ref, + int symbol: @symbol ref); + +type_symbol( + unique int typ: @type_with_symbol ref, + int symbol: @symbol ref); + +#keyset[typ, name] +type_property( + int typ: @type ref, + varchar(900) name: string ref, + int propertyType: @type ref); + +@literaltype = @stringliteraltype | @numberliteraltype | @booleanliteraltype | @bigintliteraltype; +@type_with_literal_value = @stringliteraltype | @numberliteraltype | @bigintliteraltype; +type_literal_value( + unique int typ: @type_with_literal_value ref, + varchar(900) value: string ref); + +signature_types ( + unique int id: @signature_type, + int kind: int ref, + varchar(900) tostring: string ref, + int type_parameters: int ref, + int required_params: int ref +); + +case @signature_type.kind of + 0 = @function_signature_type +| 1 = @constructor_signature_type +; + +#keyset[typ, kind, index] +type_contains_signature ( + int typ: @type ref, + int kind: int ref, // constructor/call/index + int index: int ref, // ordering of overloaded signatures + int sig: @signature_type ref +); + +#keyset[parent, index] +signature_contains_type ( + int child: @type ref, + int parent: @signature_type ref, + int index: int ref +); + +#keyset[sig, index] +signature_parameter_name ( + int sig: @signature_type ref, + int index: int ref, + varchar(900) name: string ref +); + +number_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +string_index_type ( + unique int baseType: @type ref, + int propertyType: @type ref +); + +base_type_names( + int typeName: @symbol ref, + int baseTypeName: @symbol ref +); + +self_types( + int typeName: @symbol ref, + int selfType: @typereference ref +); + +tuple_type_min_length( + unique int typ: @type ref, + int minLength: int ref +); + +tuple_type_rest( + unique int typ: @type ref +); + +// comments +comments (unique int id: @comment, + int kind: int ref, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(900) tostring: string ref); + +case @comment.kind of + 0 = @slashslashcomment +| 1 = @slashstarcomment +| 2 = @doccomment +| 3 = @htmlcommentstart +| 4 = @htmlcommentend; + +@htmlcomment = @htmlcommentstart | @htmlcommentend; +@linecomment = @slashslashcomment | @htmlcomment; +@blockcomment = @slashstarcomment | @doccomment; + +// source lines +lines (unique int id: @line, + int toplevel: @toplevel ref, + varchar(900) text: string ref, + varchar(2) terminator: string ref); +indentation (int file: @file ref, + int lineno: int ref, + varchar(1) indentChar: string ref, + int indentDepth: int ref); + +// JavaScript parse errors +jsParseErrors (unique int id: @js_parse_error, + int toplevel: @toplevel ref, + varchar(900) message: string ref, + varchar(900) line: string ref); + +// regular expressions +#keyset[parent, idx] +regexpterm (unique int id: @regexpterm, + int kind: int ref, + int parent: @regexpparent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +@regexpparent = @regexpterm | @regexpliteral; + +case @regexpterm.kind of + 0 = @regexp_alt +| 1 = @regexp_seq +| 2 = @regexp_caret +| 3 = @regexp_dollar +| 4 = @regexp_wordboundary +| 5 = @regexp_nonwordboundary +| 6 = @regexp_positive_lookahead +| 7 = @regexp_negative_lookahead +| 8 = @regexp_star +| 9 = @regexp_plus +| 10 = @regexp_opt +| 11 = @regexp_range +| 12 = @regexp_dot +| 13 = @regexp_group +| 14 = @regexp_normal_char +| 15 = @regexp_hex_escape +| 16 = @regexp_unicode_escape +| 17 = @regexp_dec_escape +| 18 = @regexp_oct_escape +| 19 = @regexp_ctrl_escape +| 20 = @regexp_char_class_escape +| 21 = @regexp_id_escape +| 22 = @regexp_backref +| 23 = @regexp_char_class +| 24 = @regexp_char_range +| 25 = @regexp_positive_lookbehind +| 26 = @regexp_negative_lookbehind +| 27 = @regexp_unicode_property_escape; + +regexpParseErrors (unique int id: @regexp_parse_error, + int regexp: @regexpterm ref, + varchar(900) message: string ref); + +@regexp_quantifier = @regexp_star | @regexp_plus | @regexp_opt | @regexp_range; +@regexp_escape = @regexp_char_escape | @regexp_char_class_escape | @regexp_unicode_property_escape; +@regexp_char_escape = @regexp_hex_escape | @regexp_unicode_escape | @regexp_dec_escape | @regexp_oct_escape | @regexp_ctrl_escape | @regexp_id_escape; +@regexp_constant = @regexp_normal_char | @regexp_char_escape; +@regexp_lookahead = @regexp_positive_lookahead | @regexp_negative_lookahead; +@regexp_lookbehind = @regexp_positive_lookbehind | @regexp_negative_lookbehind; +@regexp_subpattern = @regexp_lookahead | @regexp_lookbehind; + +isGreedy (int id: @regexp_quantifier ref); +rangeQuantifierLowerBound (unique int id: @regexp_range ref, int lo: int ref); +rangeQuantifierUpperBound (unique int id: @regexp_range ref, int hi: int ref); +isCapture (unique int id: @regexp_group ref, int number: int ref); +isNamedCapture (unique int id: @regexp_group ref, string name: string ref); +isInverted (int id: @regexp_char_class ref); +regexpConstValue (unique int id: @regexp_constant ref, varchar(1) value: string ref); +charClassEscape (unique int id: @regexp_char_class_escape ref, varchar(1) value: string ref); +backref (unique int id: @regexp_backref ref, int value: int ref); +namedBackref (unique int id: @regexp_backref ref, string name: string ref); +unicodePropertyEscapeName (unique int id: @regexp_unicode_property_escape ref, string name: string ref); +unicodePropertyEscapeValue (unique int id: @regexp_unicode_property_escape ref, string value: string ref); + +// tokens +#keyset[toplevel, idx] +tokeninfo (unique int id: @token, + int kind: int ref, + int toplevel: @toplevel ref, + int idx: int ref, + varchar(900) value: string ref); + +case @token.kind of + 0 = @token_eof +| 1 = @token_null_literal +| 2 = @token_boolean_literal +| 3 = @token_numeric_literal +| 4 = @token_string_literal +| 5 = @token_regular_expression +| 6 = @token_identifier +| 7 = @token_keyword +| 8 = @token_punctuator; + +// associate comments with the token immediately following them (which may be EOF) +next_token (int comment: @comment ref, int token: @token ref); + +// JSON +#keyset[parent, idx] +json (unique int id: @json_value, + int kind: int ref, + int parent: @json_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); + +json_literals (varchar(900) value: string ref, + varchar(900) raw: string ref, + unique int expr: @json_value ref); + +json_properties (int obj: @json_object ref, + varchar(900) property: string ref, + int value: @json_value ref); + +json_errors (unique int id: @json_parse_error, + varchar(900) message: string ref); + +json_locations(unique int locatable: @json_locatable ref, + int location: @location_default ref); + +case @json_value.kind of + 0 = @json_null +| 1 = @json_boolean +| 2 = @json_number +| 3 = @json_string +| 4 = @json_array +| 5 = @json_object; + +@json_parent = @json_object | @json_array | @file; + +@json_locatable = @json_value | @json_parse_error; + +// locations +@ast_node = @toplevel | @stmt | @expr | @property | @typeexpr; + +@locatable = @file + | @ast_node + | @comment + | @line + | @js_parse_error | @regexp_parse_error + | @regexpterm + | @json_locatable + | @token + | @cfg_node + | @jsdoc | @jsdoc_type_expr | @jsdoc_tag + | @yaml_locatable + | @xmllocatable + | @configLocatable; + +hasLocation (unique int locatable: @locatable ref, + int location: @location ref); + +// CFG +entry_cfg_node (unique int id: @entry_node, int container: @stmt_container ref); +exit_cfg_node (unique int id: @exit_node, int container: @stmt_container ref); +guard_node (unique int id: @guard_node, int kind: int ref, int test: @expr ref); +case @guard_node.kind of + 0 = @falsy_guard +| 1 = @truthy_guard; +@condition_guard = @falsy_guard | @truthy_guard; + +@synthetic_cfg_node = @entry_node | @exit_node | @guard_node; +@cfg_node = @synthetic_cfg_node | @exprparent; + +successor (int pred: @cfg_node ref, int succ: @cfg_node ref); + +// JSDoc comments +jsdoc (unique int id: @jsdoc, varchar(900) description: string ref, int comment: @comment ref); +#keyset[parent, idx] +jsdoc_tags (unique int id: @jsdoc_tag, varchar(900) title: string ref, + int parent: @jsdoc ref, int idx: int ref, varchar(900) tostring: string ref); +jsdoc_tag_descriptions (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); +jsdoc_tag_names (unique int tag: @jsdoc_tag ref, varchar(900) text: string ref); + +#keyset[parent, idx] +jsdoc_type_exprs (unique int id: @jsdoc_type_expr, + int kind: int ref, + int parent: @jsdoc_type_expr_parent ref, + int idx: int ref, + varchar(900) tostring: string ref); +case @jsdoc_type_expr.kind of + 0 = @jsdoc_any_type_expr +| 1 = @jsdoc_null_type_expr +| 2 = @jsdoc_undefined_type_expr +| 3 = @jsdoc_unknown_type_expr +| 4 = @jsdoc_void_type_expr +| 5 = @jsdoc_named_type_expr +| 6 = @jsdoc_applied_type_expr +| 7 = @jsdoc_nullable_type_expr +| 8 = @jsdoc_non_nullable_type_expr +| 9 = @jsdoc_record_type_expr +| 10 = @jsdoc_array_type_expr +| 11 = @jsdoc_union_type_expr +| 12 = @jsdoc_function_type_expr +| 13 = @jsdoc_optional_type_expr +| 14 = @jsdoc_rest_type_expr +; + +#keyset[id, idx] +jsdoc_record_field_name (int id: @jsdoc_record_type_expr ref, int idx: int ref, varchar(900) name: string ref); +jsdoc_prefix_qualifier (int id: @jsdoc_type_expr ref); +jsdoc_has_new_parameter (int fn: @jsdoc_function_type_expr ref); + +@jsdoc_type_expr_parent = @jsdoc_type_expr | @jsdoc_tag; + +jsdoc_errors (unique int id: @jsdoc_error, int tag: @jsdoc_tag ref, varchar(900) message: string ref, varchar(900) tostring: string ref); + +// YAML +#keyset[parent, idx] +yaml (unique int id: @yaml_node, + int kind: int ref, + int parent: @yaml_node_parent ref, + int idx: int ref, + varchar(900) tag: string ref, + varchar(900) tostring: string ref); + +case @yaml_node.kind of + 0 = @yaml_scalar_node +| 1 = @yaml_mapping_node +| 2 = @yaml_sequence_node +| 3 = @yaml_alias_node +; + +@yaml_collection_node = @yaml_mapping_node | @yaml_sequence_node; + +@yaml_node_parent = @yaml_collection_node | @file; + +yaml_anchors (unique int node: @yaml_node ref, + varchar(900) anchor: string ref); + +yaml_aliases (unique int alias: @yaml_alias_node ref, + varchar(900) target: string ref); + +yaml_scalars (unique int scalar: @yaml_scalar_node ref, + int style: int ref, + varchar(900) value: string ref); + +yaml_errors (unique int id: @yaml_error, + varchar(900) message: string ref); + +yaml_locations(unique int locatable: @yaml_locatable ref, + int location: @location_default ref); + +@yaml_locatable = @yaml_node | @yaml_error; + +/* XML Files */ + +xmlEncoding( + unique int id: @file ref, + varchar(900) encoding: string ref +); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +@dataflownode = @expr | @functiondeclstmt | @classdeclstmt | @namespacedeclaration | @enumdeclaration | @property; + +@optionalchainable = @callexpr | @propaccess; + +isOptionalChaining(int id: @optionalchainable ref); + +/* + * configuration files with key value pairs + */ + +configs( + unique int id: @config +); + +configNames( + unique int id: @configName, + int config: @config ref, + string name: string ref +); + +configValues( + unique int id: @configValue, + int config: @config ref, + string value: string ref +); + +configLocations( + int locatable: @configLocatable ref, + int location: @location_default ref +); + +@configLocatable = @config | @configName | @configValue; + +/** + * The time taken for the extraction of a file. + * This table contains non-deterministic content. + * + * The sum of the `time` column for each (`file`, `timerKind`) pair + * is the total time taken for extraction of `file`. The `extractionPhase` + * column provides a granular view of the extraction time of the file. + */ +extraction_time( + int file : @file ref, + // see `com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase`. + int extractionPhase: int ref, + // 0 for the elapsed CPU time in nanoseconds, 1 for the elapsed wallclock time in nanoseconds + int timerKind: int ref, + float time: float ref +) + +/** + * Non-timing related data for the extraction of a single file. + * This table contains non-deterministic content. + */ +extraction_data( + int file : @file ref, + // the absolute path to the cache file + varchar(900) cacheFile: string ref, + boolean fromCache: boolean ref, + int length: int ref +) diff --git a/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/upgrade.properties b/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/upgrade.properties new file mode 100644 index 000000000000..bf1a8cb0c613 --- /dev/null +++ b/javascript/upgrades/874ebfcd4d2fd346c10ebec145466d9071d78606/upgrade.properties @@ -0,0 +1,2 @@ +description: add support for TypeScript 3.7 features +compatibility: backwards From 7f55e3f336ffc7f838aea2c0b8c468826a83d5af Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Mon, 4 Nov 2019 09:05:50 +0100 Subject: [PATCH 0168/2538] JS: classify Doxygen-generated files as "generated" --- change-notes/1.23/analysis-javascript.md | 1 + javascript/ql/src/semmle/javascript/GeneratedCode.qll | 5 +++++ .../filters/ClassifyFiles/ClassifyFiles.expected | 1 + .../filters/ClassifyFiles/doxygen-generated.html | 8 ++++++++ 4 files changed, 15 insertions(+) create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/doxygen-generated.html diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 20f9ad1df875..554827ee9e48 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -14,6 +14,7 @@ * TypeScript 3.6 features are supported. +* Automatic classification of generated files has been improved, in particular files generated by Doxygen are now recognized. ## New queries diff --git a/javascript/ql/src/semmle/javascript/GeneratedCode.qll b/javascript/ql/src/semmle/javascript/GeneratedCode.qll index b4877f8a8fa8..0f8b161e7aea 100644 --- a/javascript/ql/src/semmle/javascript/GeneratedCode.qll +++ b/javascript/ql/src/semmle/javascript/GeneratedCode.qll @@ -137,6 +137,11 @@ private predicate isGeneratedHtml(File f) { e.getAttributeByName("name").getValue() = "generator" ) or + exists(HTML::CommentNode comment | + comment.getText().regexpMatch("\\s*Generated by [\\w-]+ \\d+\\.\\d+\\.\\d+\\s*") and + comment.getFile() = f + ) + or 20 < countStartingHtmlElements(f, _) } diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected index 045fccd225e7..7c583b1bf398 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected @@ -6,6 +6,7 @@ | ai.1.2.3-build0123.js:0:0:0:0 | ai.1.2.3-build0123.js | library | | bundle-directive.js:0:0:0:0 | bundle-directive.js | generated | | data.js:0:0:0:0 | data.js | generated | +| doxygen-generated.html:0:0:0:0 | doxygen-generated.html | generated | | etherpad.html:0:0:0:0 | etherpad.html | generated | | exported-data.js:0:0:0:0 | exported-data.js | generated | | htmltidy.html:0:0:0:0 | htmltidy.html | generated | diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/doxygen-generated.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/doxygen-generated.html new file mode 100644 index 000000000000..b659cc3fcb0a --- /dev/null +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/doxygen-generated.html @@ -0,0 +1,8 @@ + + + + + + 1 + + From 508b09f565fa9338b8f77e73cbe2bb19ab31ce55 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Mon, 4 Nov 2019 13:43:39 +0100 Subject: [PATCH 0169/2538] C#: Address review comments --- change-notes/1.23/analysis-csharp.md | 4 ++-- .../src/Security Features/CWE-502/UnsafeDeserialization.qhelp | 2 +- .../CWE-502/UnsafeDeserializationUntrustedInput.qhelp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/change-notes/1.23/analysis-csharp.md b/change-notes/1.23/analysis-csharp.md index f81007a2fc9c..c60c32ba0296 100644 --- a/change-notes/1.23/analysis-csharp.md +++ b/change-notes/1.23/analysis-csharp.md @@ -9,9 +9,9 @@ The following changes in version 1.23 affect C# analysis in all applications. | **Query** | **Tags** | **Purpose** | |-----------------------------|-----------|--------------------------------------------------------------------| | Deserialized delegate (`cs/deserialized-delegate`) | security, external/cwe/cwe-502 | Finds unsafe deserialization of delegate types. | -| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security | Finds flow of untrusted input to calls to unsafe deserializers. | +| Deserialization of untrusted data (`cs/unsafe-deserialization-untrusted-input`) | security, external/cwe/cwe-502 | Finds flow of untrusted input to calls to unsafe deserializers. | | Unsafe year argument for 'DateTime' constructor (`cs/unsafe-year-construction`) | reliability, date-time | Finds incorrect manipulation of `DateTime` values, which could lead to invalid dates. | -| Unsafe deserializer (`cs/unsafe-deserialization`) | security | Finds calls to unsafe deserializers. | +| Unsafe deserializer (`cs/unsafe-deserialization`) | security, external/cwe/cwe-502 | Finds calls to unsafe deserializers. | | Mishandling the Japanese era start date (`cs/mishandling-japanese-era`) | reliability, date-time | Finds hard-coded Japanese era start dates that could be invalid. | ## Changes to existing queries diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp index 7acfd20fe3a6..3c68b74a1d92 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserialization.qhelp @@ -5,7 +5,7 @@

    Deserializing an object from untrusted input may result in security problems, such -as denial-of-service or remote code execution.

    +as denial of service or remote code execution.

    diff --git a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp index ef946f401368..3ba934ba391d 100644 --- a/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp +++ b/csharp/ql/src/Security Features/CWE-502/UnsafeDeserializationUntrustedInput.qhelp @@ -5,7 +5,7 @@

    Deserializing an object from untrusted input may result in security problems, such -as denial-of-service or remote code execution.

    +as denial of service or remote code execution.

    From b6f4ce024400ad1e7cb6fc33793c4bdbfe82667f Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 4 Nov 2019 14:58:38 +0000 Subject: [PATCH 0170/2538] TS: Depend on typescript 3.7.2 --- javascript/extractor/lib/typescript/package.json | 2 +- javascript/extractor/lib/typescript/yarn.lock | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/javascript/extractor/lib/typescript/package.json b/javascript/extractor/lib/typescript/package.json index 966210ec8b27..3b3360158d3e 100644 --- a/javascript/extractor/lib/typescript/package.json +++ b/javascript/extractor/lib/typescript/package.json @@ -2,7 +2,7 @@ "name": "typescript-parser-wrapper", "private": true, "dependencies": { - "typescript": "^3.7.1-rc" + "typescript": "^3.7.2" }, "scripts": { "build": "tsc --project tsconfig.json", diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index 9b539464ceca..f2236efb4294 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -225,10 +225,9 @@ tsutils@^2.12.1: dependencies: tslib "^1.8.1" -typescript@^3.7.1-rc: - version "3.7.1-rc" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.1-rc.tgz#2054b872d67f8dc732e36c1df397f9327f37ada0" - integrity sha512-2rMtWppLsaPvmpXsoIAXWDBQVnJMw1ITGGSnidMuayLj9iCmMRT69ncKZw/Mk5rXfJkilApKucWQZxproALoRw== +typescript@^3.7.2: + version "3.7.2" + resolved "typescript-3.7.2.tgz" wrappy@1: version "1.0.2" From 57aa166bffd57703bbaf6d767d5fc89dfb2afcdd Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 4 Nov 2019 14:59:31 +0000 Subject: [PATCH 0171/2538] TS: Clean up yarn.lock --- javascript/extractor/lib/typescript/yarn.lock | 82 +++++++++---------- 1 file changed, 41 insertions(+), 41 deletions(-) diff --git a/javascript/extractor/lib/typescript/yarn.lock b/javascript/extractor/lib/typescript/yarn.lock index f2236efb4294..5116c7eb5c31 100644 --- a/javascript/extractor/lib/typescript/yarn.lock +++ b/javascript/extractor/lib/typescript/yarn.lock @@ -4,31 +4,31 @@ "@types/node@12.7.11": version "12.7.11" - resolved node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446 + resolved "node-12.7.11.tgz#be879b52031cfb5d295b047f5462d8ef1a716446" ansi-regex@^2.0.0: version "2.1.1" - resolved ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df + resolved "ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" ansi-styles@^2.2.1: version "2.2.1" - resolved ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe + resolved "ansi-styles-2.2.1.tgz#b432dd3358b634cf75e1e4664368240533c1ddbe" ansi-styles@^3.1.0: version "3.2.0" - resolved ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88 + resolved "ansi-styles-3.2.0.tgz#c159b8d5be0f9e5a6f346dab94f16ce022161b88" dependencies: color-convert "^1.9.0" argparse@^1.0.7: version "1.0.9" - resolved argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86 + resolved "argparse-1.0.9.tgz#73d83bc263f86e97f8cc4f6bae1b0e90a7d22c86" dependencies: sprintf-js "~1.0.2" babel-code-frame@^6.22.0: version "6.26.0" - resolved babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b + resolved "babel-code-frame-6.26.0.tgz#63fd43f7dc1e3bb7ce35947db8fe369a3f58c74b" dependencies: chalk "^1.1.3" esutils "^2.0.2" @@ -36,22 +36,22 @@ babel-code-frame@^6.22.0: balanced-match@^1.0.0: version "1.0.0" - resolved balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767 + resolved "balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" brace-expansion@^1.1.7: version "1.1.8" - resolved brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292 + resolved "brace-expansion-1.1.8.tgz#c07b211c7c952ec1f8efd51a77ef0d1d3990a292" dependencies: balanced-match "^1.0.0" concat-map "0.0.1" builtin-modules@^1.1.1: version "1.1.1" - resolved builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f + resolved "builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" chalk@^1.1.3: version "1.1.3" - resolved chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98 + resolved "chalk-1.1.3.tgz#a8115c55e4a702fe4d150abd3872822a7e09fc98" dependencies: ansi-styles "^2.2.1" escape-string-regexp "^1.0.2" @@ -61,7 +61,7 @@ chalk@^1.1.3: chalk@^2.3.0: version "2.3.0" - resolved chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba + resolved "chalk-2.3.0.tgz#b5ea48efc9c1793dccc9b4767c93914d3f2d52ba" dependencies: ansi-styles "^3.1.0" escape-string-regexp "^1.0.5" @@ -69,45 +69,45 @@ chalk@^2.3.0: color-convert@^1.9.0: version "1.9.1" - resolved color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed + resolved "color-convert-1.9.1.tgz#c1261107aeb2f294ebffec9ed9ecad529a6097ed" dependencies: color-name "^1.1.1" color-name@^1.1.1: version "1.1.3" - resolved color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25 + resolved "color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" commander@^2.12.1: version "2.13.0" - resolved commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c + resolved "commander-2.13.0.tgz#6964bca67685df7c1f1430c584f07d7597885b9c" concat-map@0.0.1: version "0.0.1" - resolved concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b + resolved "concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" diff@^3.2.0: version "3.4.0" - resolved diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c + resolved "diff-3.4.0.tgz#b1d85507daf3964828de54b37d0d73ba67dda56c" escape-string-regexp@^1.0.2, escape-string-regexp@^1.0.5: version "1.0.5" - resolved escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4 + resolved "escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" esprima@^4.0.0: version "4.0.0" - resolved esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804 + resolved "esprima-4.0.0.tgz#4499eddcd1110e0b218bacf2fa7f7f59f55ca804" esutils@^2.0.2: version "2.0.2" - resolved esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b + resolved "esutils-2.0.2.tgz#0abf4f1caa5bcb1f7a9d8acc6dea4faaa04bac9b" fs.realpath@^1.0.0: version "1.0.0" - resolved fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f + resolved "fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" glob@^7.1.1: version "7.1.2" - resolved glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15 + resolved "glob-7.1.2.tgz#c19c9df9a028702d678612384a6552404c636d15" dependencies: fs.realpath "^1.0.0" inflight "^1.0.4" @@ -118,93 +118,93 @@ glob@^7.1.1: has-ansi@^2.0.0: version "2.0.0" - resolved has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91 + resolved "has-ansi-2.0.0.tgz#34f5049ce1ecdf2b0649af3ef24e45ed35416d91" dependencies: ansi-regex "^2.0.0" has-flag@^2.0.0: version "2.0.0" - resolved has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51 + resolved "has-flag-2.0.0.tgz#e8207af1cc7b30d446cc70b734b5e8be18f88d51" inflight@^1.0.4: version "1.0.6" - resolved inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9 + resolved "inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" dependencies: once "^1.3.0" wrappy "1" inherits@2: version "2.0.3" - resolved inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de + resolved "inherits-2.0.3.tgz#633c2c83e3da42a502f52466022480f4208261de" js-tokens@^3.0.2: version "3.0.2" - resolved js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b + resolved "js-tokens-3.0.2.tgz#9866df395102130e38f7f996bceb65443209c25b" js-yaml@^3.7.0: version "3.10.0" - resolved js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc + resolved "js-yaml-3.10.0.tgz#2e78441646bd4682e963f22b6e92823c309c62dc" dependencies: argparse "^1.0.7" esprima "^4.0.0" minimatch@^3.0.4: version "3.0.4" - resolved minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083 + resolved "minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" dependencies: brace-expansion "^1.1.7" once@^1.3.0: version "1.4.0" - resolved once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1 + resolved "once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" dependencies: wrappy "1" path-is-absolute@^1.0.0: version "1.0.1" - resolved path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f + resolved "path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" path-parse@^1.0.5: version "1.0.5" - resolved path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1 + resolved "path-parse-1.0.5.tgz#3c1adf871ea9cd6c9431b6ea2bd74a0ff055c4c1" resolve@^1.3.2: version "1.5.0" - resolved resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36 + resolved "resolve-1.5.0.tgz#1f09acce796c9a762579f31b2c1cc4c3cddf9f36" dependencies: path-parse "^1.0.5" semver@^5.3.0: version "5.5.0" - resolved semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab + resolved "semver-5.5.0.tgz#dc4bbc7a6ca9d916dee5d43516f0092b58f7b8ab" sprintf-js@~1.0.2: version "1.0.3" - resolved sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c + resolved "sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" strip-ansi@^3.0.0: version "3.0.1" - resolved strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf + resolved "strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" dependencies: ansi-regex "^2.0.0" supports-color@^2.0.0: version "2.0.0" - resolved supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7 + resolved "supports-color-2.0.0.tgz#535d045ce6b6363fa40117084629995e9df324c7" supports-color@^4.0.0: version "4.5.0" - resolved supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b + resolved "supports-color-4.5.0.tgz#be7a0de484dec5c5cddf8b3d59125044912f635b" dependencies: has-flag "^2.0.0" tslib@^1.8.0, tslib@^1.8.1: version "1.9.0" - resolved tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8 + resolved "tslib-1.9.0.tgz#e37a86fda8cbbaf23a057f473c9f4dc64e5fc2e8" tslint@^5.9.1: version "5.9.1" - resolved tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae + resolved "tslint-5.9.1.tgz#1255f87a3ff57eb0b0e1f0e610a8b4748046c9ae" dependencies: babel-code-frame "^6.22.0" builtin-modules "^1.1.1" @@ -221,7 +221,7 @@ tslint@^5.9.1: tsutils@^2.12.1: version "2.19.1" - resolved tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7 + resolved "tsutils-2.19.1.tgz#76d7ebdea9d7a7bf4a05f50ead3701b0168708d7" dependencies: tslib "^1.8.1" @@ -231,4 +231,4 @@ typescript@^3.7.2: wrappy@1: version "1.0.2" - resolved wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f + resolved "wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" From 016808b92ea17a62abe3a29688cf6be02a97ec68 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Mon, 4 Nov 2019 17:00:12 +0000 Subject: [PATCH 0172/2538] JavaScript: Address review comments. --- change-notes/1.23/analysis-javascript.md | 1 + javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index aa9d2086d149..c87e16ce569f 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -31,6 +31,7 @@ | **Query** | **Expected impact** | **Change** | |--------------------------------|------------------------------|---------------------------------------------------------------------------| +| Double escaping or unescaping (`js/double-escaping`) | More results | This rule now detects additional escaping and unescaping functions. | | Incomplete string escaping or encoding (`js/incomplete-sanitization`) | Fewer false-positive results | This rule now recognizes additional ways delimiters can be stripped away. | | Client-side cross-site scripting (`js/xss`) | More results, fewer false-positive results | More potential vulnerabilities involving functions that manipulate DOM attributes are now recognized, and more sanitizers are detected. | | Code injection (`js/code-injection`) | More results | More potential vulnerabilities involving functions that manipulate DOM event handler attributes are now recognized. | diff --git a/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp b/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp index 02cce7c5911b..6c36fde4b281 100644 --- a/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp +++ b/javascript/ql/src/Security/CWE-116/DoubleEscaping.qhelp @@ -10,8 +10,8 @@ attacks such as cross-site scripting. One particular example of this is HTML ent where HTML special characters are replaced by HTML character entities to prevent them from being interpreted as HTML markup. For example, the less-than character is encoded as &lt; and the double-quote character as &quot;. -Other examples include backslash-escaping for including untrusted data in string literals and -percent-encoding for URI components. +Other examples include backslash escaping or JSON encoding for including untrusted data in string +literals, and percent-encoding for URI components.

    The reverse process of replacing escape sequences with the characters they represent is known as From 6cac9619d3faeaa47b1db702425731058517dcec Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:44:13 +0100 Subject: [PATCH 0173/2538] add missing not Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 77ec29ba9ee7..59d88bc51a01 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -131,7 +131,7 @@ DataFlow::SourceNode array() { result = array(DataFlow::TypeTracker::end()) } /** * Holds if `call` is an Array or Lodash method accepting a callback `func`, * where the `call` expects a callback that returns an expression, - * but `func` does return a value. + * but `func` does not return a value. */ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { hasNonVoidCallbackMethod(call.getCalleeName()) and From 8ebfe15f0d286139b370a0cc2f3016459c9b1520 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:54:43 +0100 Subject: [PATCH 0174/2538] apply doc feedback from mchammer01 Co-Authored-By: mc <42146119+mchammer01@users.noreply.github.com> --- javascript/ql/src/Statements/IgnoreArrayResult.qhelp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp index 2232784d881e..048ca6680fc5 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -22,17 +22,17 @@ or slice.

    -In the following example a function extend is defined. The +A function extend is defined in the following example. The function uses the concat method to add elements to the arr array. However, the extend function has no -effect as the return value from concat is ignored. +effect as the return value from concat is ignored:

    Assigning the returned value from the call to concat to the -arr variable fixes the error. +arr variable fixes the error:

    From aa47e3f6d2ff7d45dac3d7b3a5c00b83d4da3931 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:52:29 +0100 Subject: [PATCH 0175/2538] update change-note to reflect changed query --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 90f46403f26c..e3421a3de45e 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -23,7 +23,7 @@ | Use of returnless function (`js/use-of-returnless-function`) | maintainability, correctness | Highlights calls where the return value is used, but the callee never returns a value. Results are shown on LGTM by default. | | Useless regular expression character escape (`js/useless-regexp-character-escape`) | correctness, security, external/cwe/cwe-20 | Highlights regular expression strings with useless character escapes, indicating a possible violation of [CWE-20](https://cwe.mitre.org/data/definitions/20.html). Results are shown on LGTM by default. | | Unreachable method overloads (`js/unreachable-method-overloads`) | correctness, typescript | Highlights method overloads that are impossible to use from client code. Results are shown on LGTM by default. | -| Ignoring return from concat (`js/ignore-return-from-concat`) | maintainability, correctness | Highlights calls to the concat method on array where the return value is ignored. Results are shown on LGTM by default. | +| Ignoring result from pure array method (`js/ignore-array-result`) | maintainability, correctness | Highlights calls to array methods without side effects where the return value is ignored. Results are shown on LGTM by default. | ## Changes to existing queries From bdb81c268c22a92758c60cdea795459fab268f07 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Mon, 4 Nov 2019 18:56:03 +0100 Subject: [PATCH 0176/2538] change tense --- javascript/ql/src/Statements/IgnoreArrayResult.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp index 048ca6680fc5..70e3cb4e5ccd 100644 --- a/javascript/ql/src/Statements/IgnoreArrayResult.qhelp +++ b/javascript/ql/src/Statements/IgnoreArrayResult.qhelp @@ -5,7 +5,7 @@

    The concat, join and slice methods are -pure and do not modify any of the inputs or the array the method was called +pure and do not modify any of the inputs or the array the method is called on. It is therefore generally an error to ignore the return value from a call to one of these methods.

    From ce8ba86f2d35df8e302dc7240d3f8e9e771a64eb Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 4 Nov 2019 12:30:52 -0800 Subject: [PATCH 0177/2538] [CPP-434] Use a bullet list instead of a table in order to placate Jenkins. --- .../Arithmetic/SignedOverflowCheck.qhelp | 102 +++++------------- 1 file changed, 27 insertions(+), 75 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 302fbd4ed233..a6f8f4dc373a 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,85 +22,36 @@ categories: (1) rewrite the signed expression so that overflow cannot occur but the signedness remains, or (2) rewrite (or cast) the signed expression into unsigned form. -The table below lists various expressions where signed overflow may +The bullet list below lists various expressions where signed overflow may occur, along with proposed rewritings. It should not be considered exhaustive.

    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Original ConstructAlternate Construct(s)Notes
    - - - - - -
    unsigned short i, delta;
    i + delta < i
    - - - - - -
    unsigned short i, delta;
    (unsigned short)(i + delta) < i
    i + deltadoes not actually overflow due to int promotion
      - - - - - -
    unsigned short i, delta;
    i > USHORT_MAX - delta
    Must include limits.h or climits; delta > 0
    - - - - - -
    int i, delta;
    i + delta < i
    - - - - - -
    int i, delta;
    i > INT_MAX - delta
    Must include limits.h or climits; delta > 0
      - - - - - -
    int i, delta;
    (unsigned)i + delta < i
    Change in program semantics
      - - - - - -
    unsigned int i, delta;
    i + delta < i
    Change in program semantics
    + +
  • Given unsigned short i, delta and i + delta < i, +it is possible to rewrite it as (unsigned short)(i + delta) < i. +Note that i + deltadoes not actually overflow, due to int promotion
  • + +
  • Given unsigned short i, delta and i + delta < i, +it is also possible to rewrite it as USHORT_MAX - delta. It must be true +that delta > 0 and the limits.h or climits +header has been included.
  • + +
  • Given int i, delta and i + delta < i, +it is possible to rewrite it as INT_MAX - delta. It must be true +that delta > 0 and the limits.h or climits +header has been included.
  • + +
  • Given int i, delta and i + delta < i, +it is also possible to rewrite it as (unsigned)i + delta < i. +Note that program semantics are affected by this change.
  • + +
  • Given int i, delta and i + delta < i, +it is also possible to rewrite it as unsigned int i, delta and +i + delta < i. Note that program semantics are +affected by this change.
  • +
    +

    In the following example, even though delta has been declared @@ -142,6 +93,7 @@ so that unsigned short "wrap around" may now be observed. Furthermore, since the left-hand side is now of type unsigned short, the right-hand side does not need to be promoted to a signed int.

    +
    From 398896a4b21127b2d286d9fc2bd456b2456959bd Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 4 Nov 2019 16:44:31 -0800 Subject: [PATCH 0178/2538] [CPP-434] Change list items to ordinary paragraphs in the Recommendation section. --- .../Arithmetic/SignedOverflowCheck.qhelp | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index a6f8f4dc373a..4d5dfabef142 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -22,34 +22,35 @@ categories: (1) rewrite the signed expression so that overflow cannot occur but the signedness remains, or (2) rewrite (or cast) the signed expression into unsigned form. -The bullet list below lists various expressions where signed overflow may -occur, along with proposed rewritings. It should not be +Below we list examples of expressions where signed overflow may +occur, along with proposed solutions. The list should not be considered exhaustive.

    -
  • Given unsigned short i, delta and i + delta < i, +

    +Given unsigned short i, delta and i + delta < i, it is possible to rewrite it as (unsigned short)(i + delta) < i. -Note that i + deltadoes not actually overflow, due to int promotion

  • +Note that i + deltadoes not actually overflow, due to int promotion -
  • Given unsigned short i, delta and i + delta < i, +Given unsigned short i, delta and i + delta < i, it is also possible to rewrite it as USHORT_MAX - delta. It must be true that delta > 0 and the limits.h or climits -header has been included.
  • +header has been included. -
  • Given int i, delta and i + delta < i, +Given int i, delta and i + delta < i, it is possible to rewrite it as INT_MAX - delta. It must be true that delta > 0 and the limits.h or climits -header has been included.
  • +header has been included. -
  • Given int i, delta and i + delta < i, +Given int i, delta and i + delta < i, it is also possible to rewrite it as (unsigned)i + delta < i. -Note that program semantics are affected by this change.
  • +Note that program semantics are affected by this change. -
  • Given int i, delta and i + delta < i, +Given int i, delta and i + delta < i, it is also possible to rewrite it as unsigned int i, delta and i + delta < i. Note that program semantics are -affected by this change.
  • - +affected by this change. +

    From 9407ba1a353ab626ce5ea0c4625d9c73c614130d Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 28 Oct 2019 19:36:20 -0700 Subject: [PATCH 0179/2538] [zlaski/pointer-overflow-check] Initial version. --- .../PointerOverflowCheck-bad.cpp | 3 ++ .../PointerOverflowCheck-good.cpp | 3 ++ .../PointerOverflowCheck.qhelp | 53 +++++++++++++++++++ .../Memory Management/PointerOverflowCheck.ql | 25 +++++++++ .../PointerOverflowCheck.expected | 1 + .../PointerOverflowCheck.qlref | 1 + .../PointerOverflowCheck/test.cpp | 13 +++++ 7 files changed, 99 insertions(+) create mode 100644 cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-bad.cpp create mode 100644 cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp create mode 100644 cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp create mode 100644 cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.expected create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.qlref create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-bad.cpp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-bad.cpp new file mode 100644 index 000000000000..0b7379411748 --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-bad.cpp @@ -0,0 +1,3 @@ +bool check_pointer_overflow(P *ptr) { + return ptr + 0x12345678 < ptr; // BAD +} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp new file mode 100644 index 000000000000..0d10ea1fb19e --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp @@ -0,0 +1,3 @@ +bool check_pointer_overflow(P *ptr, P *ptr_end) { + return ptr + 4 >= ptr_end; // GOOD +} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp new file mode 100644 index 000000000000..4b1f711fd15b --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp @@ -0,0 +1,53 @@ + + + +

    +When checking for out-of-range pointer values, one might write tests like +p + a < p and check if the value "wraps around". +Such a test is wrong in that it relies on the overflow of p + a, +which is undefined behavior. In fact, many optimizing compilers will remove +p + a < p altogether and replace it with the value 0 +(false). Conversely, should p + a not overflow, +the programmer may erroneously assume that the memory location p + a +is accessible to the program, even though it may be inaccessible (protected by +the operating system) or nonexistent. +

    +
    + +

    +When checking for an out-of-range pointer, compare the pointer +value p against a known value p_max representing +the highest allowable memory address. Ideally, p_max should +point just past the end of a data structure, such as an array or a vector. +For lower-level work, it should point at the highest address in the program +heap. It is also important that p + a points at a valid object +and that a is small enough so that the expression p + a +does not itself overflow. +

    +
    + +

    +In the first example, a constant value is being added to a pointer and +then tested for "wrap around". Should the test fail, the developer +might assume that memory location ptr + 0x12345678 is a +valid one for the program to use, even though it may be either +inaccessible (protected from the current process by the operating +system) or nonexistent. Furthermore, it may be impossible to tell when +the test succeeds, since pointer overflow has undefined behavior. +

    + +

    +The next example shows how to properly check for an out-of-range pointer. +In order to do so, we need to obtain the value ptr_end +representing the highest allowable memory address. In this case, +the address lies just beyond the end of an array. +

    + +
    + +
  • Pointer Overflow Checking [Embedded in Academia]
  • +
  • GCC and pointer overflows [LWN]
  • +
    +
    diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql new file mode 100644 index 000000000000..c8874bb214ae --- /dev/null +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql @@ -0,0 +1,25 @@ +/** + * @name Dangerous pointer out-of-range check + * @description Testing for out-of-range pointers by adding a value to a pointer + * to see if it "wraps around" is dangerous because it relies + * on undefined behavior and may lead to attempted use of + * nonexistent or inaccessible memory locations + * @kind problem + * @problem.severity warning + * @precision high + * @id cpp/pointer-overflow-check + * @tags reliability + * security + */ + +import cpp +private import semmle.code.cpp.valuenumbering.GlobalValueNumbering +private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +from RelationalOperation ro, PointerAddExpr add, Expr expr1, Expr expr2 +where + ro.getAnOperand() = add and + add.getAnOperand() = expr1 and + ro.getAnOperand() = expr2 and + globalValueNumber(expr1) = globalValueNumber(expr2) +select ro, "Pointer out-of-range check relying on pointer overflow is undefined." diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.expected new file mode 100644 index 000000000000..c17cdaf85b2b --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.expected @@ -0,0 +1 @@ +| test.cpp:6:12:6:33 | ... < ... | Pointer out-of-range check relying on pointer overflow is undefined. | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.qlref b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.qlref new file mode 100644 index 000000000000..7e3ccd163a62 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/PointerOverflowCheck.qlref @@ -0,0 +1 @@ +Likely Bugs/Memory Management/PointerOverflowCheck.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp new file mode 100644 index 000000000000..e1143431330f --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp @@ -0,0 +1,13 @@ +struct P { int a, b; }; +bool check_pointer_overflow(P *ptr) { + // x86-64 gcc 9.2 -O2: deleted + // x86-64 clang 9.9.9 -O2: deleted + // x64 msvc v19.22 /O2: not deleted + return ptr + 0x12345678 < ptr; // BAD +} +bool check_pointer_overflow(P *ptr, P *ptr_end) { + // x86-64 gcc 9.2 -O2: not deleted + // x86-64 clang 9.0.0 -O2: not deleted + // x64 msvc v19.22 /O2: not deleted + return ptr + 4 >= ptr_end; // GOOD +} From 9228844604174968c719c7865c9ab185088aedac Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 29 Oct 2019 15:17:30 -0700 Subject: [PATCH 0180/2538] [zlaski/pointer-overflow-check] Expand test case. --- .../PointerOverflowCheck/test.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp index e1143431330f..24f16198e7b7 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp @@ -11,3 +11,17 @@ bool check_pointer_overflow(P *ptr, P *ptr_end) { // x64 msvc v19.22 /O2: not deleted return ptr + 4 >= ptr_end; // GOOD } + +struct Q { + #define Q_SIZE 32 + char arr[Q_SIZE]; + char *begin() { return &arr[0]; } + char *end() { return &arr[Q_SIZE]; } +}; + +void foo(int untrusted_int) { + Q q; + if (q.begin() + untrusted_int > q.end() || // GOOD + q.begin() + untrusted_int < q.begin()) // BAD + throw q; +} From 3aafcf46045e2320d042c46613be98a8d0f92601 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 29 Oct 2019 15:30:41 -0700 Subject: [PATCH 0181/2538] [zlaski/pointer-overflow-check] Minor tweak to Qhelp. --- .../Likely Bugs/Memory Management/PointerOverflowCheck.qhelp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp index 4b1f711fd15b..6d251e3e2b12 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp @@ -7,7 +7,7 @@ When checking for out-of-range pointer values, one might write tests like p + a < p and check if the value "wraps around". Such a test is wrong in that it relies on the overflow of p + a, -which is undefined behavior. In fact, many optimizing compilers will remove +which has undefined behavior. In fact, many optimizing compilers will remove p + a < p altogether and replace it with the value 0 (false). Conversely, should p + a not overflow, the programmer may erroneously assume that the memory location p + a From df3c70e57e1613c6ad1096e3028924634c612196 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 5 Nov 2019 10:40:14 +0100 Subject: [PATCH 0182/2538] add js/ignore-array-result to correctness-core suite --- javascript/config/suites/javascript/correctness-core | 1 + 1 file changed, 1 insertion(+) diff --git a/javascript/config/suites/javascript/correctness-core b/javascript/config/suites/javascript/correctness-core index 6a53405e1c3f..d6b91e83a07c 100644 --- a/javascript/config/suites/javascript/correctness-core +++ b/javascript/config/suites/javascript/correctness-core @@ -37,5 +37,6 @@ + semmlecode-javascript-queries/RegExp/UnboundBackref.ql: /Correctness/Regular Expressions + semmlecode-javascript-queries/RegExp/UnmatchableCaret.ql: /Correctness/Regular Expressions + semmlecode-javascript-queries/RegExp/UnmatchableDollar.ql: /Correctness/Regular Expressions ++ semmlecode-javascript-queries/Statements/IgnoreArrayResult.ql: /Correctness/Statements + semmlecode-javascript-queries/Statements/InconsistentLoopOrientation.ql: /Correctness/Statements + semmlecode-javascript-queries/Statements/UnreachableStatement.ql: /Correctness/Statements From d8f3a2c55037421e30a5d02cb7273af53e3cf9e7 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 31 Oct 2019 12:58:39 +0000 Subject: [PATCH 0183/2538] JS: Add lvalue of for..of loop as a PropRead --- .../semmle/javascript/dataflow/DataFlow.qll | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37c..07920cba3c93 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -741,7 +741,8 @@ module DataFlow { PropReadAsSourceNode() { this = TPropNode(any(PropertyPattern p)) or this instanceof RestPatternNode or - this instanceof ElementPatternNode + this instanceof ElementPatternNode or + this = lvalueNode(any(ForOfStmt stmt).getLValue()) } } @@ -826,6 +827,24 @@ module DataFlow { override string getPropertyName() { result = astNode.getImportedName() } } + /** + * The left-hand side of a `for..of` statement, seen as a property read + * on the object being iterated over. + */ + private class ForOfLvalueAsPropRead extends PropRead { + ForOfStmt stmt; + + ForOfLvalueAsPropRead() { + this = lvalueNode(stmt.getLValue()) + } + + override Node getBase() { result = stmt.getIterationDomain().flow() } + + override Expr getPropertyNameExpr() { none() } + + override string getPropertyName() { none() } + } + /** * A data flow node representing an unused parameter. * From d8ac0abb7f26879e59d7f6addd8cbe995aeedf5b Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 10:06:21 +0000 Subject: [PATCH 0184/2538] JS: Add test --- .../ql/test/library-tests/DataFlow/flowStep.expected | 5 +++++ .../ql/test/library-tests/DataFlow/incomplete.expected | 5 +++++ .../ql/test/library-tests/DataFlow/parameters.expected | 1 + javascript/ql/test/library-tests/DataFlow/sources.expected | 7 +++++++ javascript/ql/test/library-tests/DataFlow/sources.js | 5 +++++ 5 files changed, 23 insertions(+) diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index a6446732fbe6..107dcfb98c73 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -7,6 +7,11 @@ | sources.js:3:11:3:11 | x | sources.js:4:10:4:10 | x | | sources.js:4:10:4:13 | x+19 | sources.js:3:1:5:6 | (functi ... \\n})(23) | | sources.js:5:4:5:5 | 23 | sources.js:3:11:3:11 | x | +| sources.js:9:14:9:18 | array | sources.js:10:19:10:23 | array | +| sources.js:9:14:9:18 | array | sources.js:11:23:11:27 | array | +| sources.js:10:12:10:14 | key | sources.js:10:28:10:30 | key | +| sources.js:11:12:11:18 | key | sources.js:11:32:11:34 | key | +| sources.js:11:14:11:16 | key | sources.js:11:12:11:18 | key | | tst.js:1:1:1:1 | x | tst.js:28:2:28:1 | x | | tst.js:1:1:1:1 | x | tst.js:32:1:32:0 | x | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | diff --git a/javascript/ql/test/library-tests/DataFlow/incomplete.expected b/javascript/ql/test/library-tests/DataFlow/incomplete.expected index aee8fd444216..35413033fe7f 100644 --- a/javascript/ql/test/library-tests/DataFlow/incomplete.expected +++ b/javascript/ql/test/library-tests/DataFlow/incomplete.expected @@ -8,6 +8,11 @@ | sources.js:1:6:1:11 | exceptional return of anonymous function | call | | sources.js:3:1:5:6 | exceptional return of (functi ... \\n})(23) | call | | sources.js:3:2:5:1 | exceptional return of anonymous function | call | +| sources.js:9:1:12:1 | exceptional return of function foo | call | +| sources.js:9:14:9:18 | array | call | +| sources.js:10:12:10:14 | key | heap | +| sources.js:11:12:11:18 | key | heap | +| sources.js:11:14:11:16 | key | heap | | tst.js:1:10:1:11 | fs | import | | tst.js:16:1:20:9 | exceptional return of (functi ... ("arg") | call | | tst.js:16:2:20:1 | exceptional return of function f | call | diff --git a/javascript/ql/test/library-tests/DataFlow/parameters.expected b/javascript/ql/test/library-tests/DataFlow/parameters.expected index b7746f41c8a4..31bab07c4e27 100644 --- a/javascript/ql/test/library-tests/DataFlow/parameters.expected +++ b/javascript/ql/test/library-tests/DataFlow/parameters.expected @@ -1,5 +1,6 @@ | sources.js:1:6:1:6 | x | | sources.js:3:11:3:11 | x | +| sources.js:9:14:9:18 | array | | tst.js:16:13:16:13 | a | | tst.js:32:12:32:12 | b | | tst.js:87:11:87:24 | { p: x, ...o } | diff --git a/javascript/ql/test/library-tests/DataFlow/sources.expected b/javascript/ql/test/library-tests/DataFlow/sources.expected index 185cc89e4adc..37a540273715 100644 --- a/javascript/ql/test/library-tests/DataFlow/sources.expected +++ b/javascript/ql/test/library-tests/DataFlow/sources.expected @@ -13,6 +13,12 @@ | sources.js:3:2:5:1 | functio ... x+19;\\n} | | sources.js:3:11:3:11 | x | | sources.js:7:1:7:3 | /x/ | +| sources.js:9:1:9:0 | this | +| sources.js:9:1:12:1 | functio ... ey; }\\n} | +| sources.js:9:14:9:18 | array | +| sources.js:10:12:10:14 | key | +| sources.js:11:12:11:18 | { key } | +| sources.js:11:14:11:16 | key | | tst.js:1:1:1:0 | this | | tst.js:1:1:1:24 | import ... m 'fs'; | | tst.js:1:10:1:11 | fs | @@ -60,6 +66,7 @@ | tst.js:72:9:72:9 | p | | tst.js:72:9:72:11 | p() | | tst.js:75:9:75:21 | import('foo') | +| tst.js:80:10:80:10 | v | | tst.js:83:11:83:28 | [ for (v of o) v ] | | tst.js:85:11:85:28 | ( for (v of o) v ) | | tst.js:87:1:96:2 | (functi ... r: 0\\n}) | diff --git a/javascript/ql/test/library-tests/DataFlow/sources.js b/javascript/ql/test/library-tests/DataFlow/sources.js index 653c5fc129cd..7a5bb869efe5 100644 --- a/javascript/ql/test/library-tests/DataFlow/sources.js +++ b/javascript/ql/test/library-tests/DataFlow/sources.js @@ -5,3 +5,8 @@ new (x => x); })(23); /x/; + +function foo(array) { + for (let key of array) { key; } + for (let { key } of array) { key; } +} From c373be0dee9b4c8b4edbfb5980b1b0b3f5586bde Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 10:26:04 +0000 Subject: [PATCH 0185/2538] JS: Update TaintBarriers test --- .../library-tests/TaintBarriers/SanitizingGuard.expected | 5 ----- .../ql/test/library-tests/TaintBarriers/TaintedSink.expected | 1 - .../ql/test/library-tests/TaintBarriers/isBarrier.expected | 1 + javascript/ql/test/library-tests/TaintBarriers/tst.js | 2 +- 4 files changed, 2 insertions(+), 7 deletions(-) diff --git a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected index c58a7c511d11..010375e1ab81 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/SanitizingGuard.expected @@ -44,14 +44,11 @@ | tst.js:236:9:236:24 | isWhitelisted(v) | ExampleConfiguration | true | tst.js:236:23:236:23 | v | | tst.js:240:9:240:28 | config.allowValue(v) | ExampleConfiguration | true | tst.js:240:27:240:27 | v | | tst.js:252:16:252:36 | whiteli ... ains(x) | ExampleConfiguration | true | tst.js:252:35:252:35 | x | -| tst.js:254:9:254:12 | f(v) | ExampleConfiguration | true | tst.js:254:11:254:11 | v | | tst.js:261:25:261:45 | whiteli ... ains(y) | ExampleConfiguration | true | tst.js:261:44:261:44 | y | -| tst.js:264:9:264:12 | g(v) | ExampleConfiguration | true | tst.js:264:11:264:11 | v | | tst.js:271:25:271:45 | whiteli ... ains(z) | ExampleConfiguration | true | tst.js:271:44:271:44 | z | | tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:16:281:17 | x2 | | tst.js:281:16:281:25 | x2 != null | ExampleConfiguration | false | tst.js:281:22:281:25 | null | | tst.js:281:30:281:51 | whiteli ... ins(x2) | ExampleConfiguration | true | tst.js:281:49:281:50 | x2 | -| tst.js:283:9:283:13 | f2(v) | ExampleConfiguration | true | tst.js:283:12:283:12 | v | | tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:16:290:17 | x3 | | tst.js:290:16:290:25 | x3 == null | ExampleConfiguration | true | tst.js:290:22:290:25 | null | | tst.js:290:30:290:51 | whiteli ... ins(x3) | ExampleConfiguration | true | tst.js:290:49:290:50 | x3 | @@ -61,7 +58,6 @@ | tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:25:327:26 | x7 | | tst.js:327:25:327:34 | x7 != null | ExampleConfiguration | false | tst.js:327:31:327:34 | null | | tst.js:327:39:327:60 | whiteli ... ins(x7) | ExampleConfiguration | true | tst.js:327:58:327:59 | x7 | -| tst.js:330:9:330:13 | f7(v) | ExampleConfiguration | true | tst.js:330:12:330:12 | v | | tst.js:337:25:337:46 | whiteli ... ins(x8) | ExampleConfiguration | true | tst.js:337:44:337:45 | x8 | | tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:16:338:17 | x8 | | tst.js:338:16:338:25 | x8 != null | ExampleConfiguration | false | tst.js:338:22:338:25 | null | @@ -70,6 +66,5 @@ | tst.js:356:16:356:27 | x10 !== null | ExampleConfiguration | false | tst.js:356:24:356:27 | null | | tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:32:356:34 | x10 | | tst.js:356:32:356:48 | x10 !== undefined | ExampleConfiguration | false | tst.js:356:40:356:48 | undefined | -| tst.js:358:9:358:14 | f10(v) | ExampleConfiguration | false | tst.js:358:13:358:13 | v | | tst.js:370:9:370:29 | o.p == ... listed" | ExampleConfiguration | true | tst.js:370:9:370:11 | o.p | | tst.js:377:11:377:32 | o[p] == ... listed" | ExampleConfiguration | true | tst.js:377:11:377:14 | o[p] | diff --git a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected index 050f80bc0719..54b35166b15a 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/TaintedSink.expected @@ -53,7 +53,6 @@ | tst.js:333:14:333:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:341:14:341:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:343:14:343:14 | v | tst.js:248:13:248:20 | SOURCE() | -| tst.js:350:14:350:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:352:14:352:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:359:14:359:14 | v | tst.js:248:13:248:20 | SOURCE() | | tst.js:368:10:368:12 | o.p | tst.js:367:13:367:20 | SOURCE() | diff --git a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected index 50804043f95b..f650c93185c6 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected +++ b/javascript/ql/test/library-tests/TaintBarriers/isBarrier.expected @@ -37,6 +37,7 @@ | tst.js:265:14:265:14 | v | ExampleConfiguration | | tst.js:284:14:284:14 | v | ExampleConfiguration | | tst.js:331:14:331:14 | v | ExampleConfiguration | +| tst.js:350:14:350:14 | v | ExampleConfiguration | | tst.js:356:16:356:27 | x10 | ExampleConfiguration | | tst.js:356:32:356:34 | x10 | ExampleConfiguration | | tst.js:361:14:361:14 | v | ExampleConfiguration | diff --git a/javascript/ql/test/library-tests/TaintBarriers/tst.js b/javascript/ql/test/library-tests/TaintBarriers/tst.js index 78986d6af376..a7a05590540c 100644 --- a/javascript/ql/test/library-tests/TaintBarriers/tst.js +++ b/javascript/ql/test/library-tests/TaintBarriers/tst.js @@ -347,7 +347,7 @@ function IndirectSanitizer () { return unknown() && whitelist.contains(x9) && unknown(); } if (f9(v)) { - SINK(v); // SANITIZATION OF THIS IS NOT YET SUPPORTED + SINK(v); } else { SINK(v); } From 48c7d1d7c1218ad0b022bab561e69c74905876ce Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:20:16 +0100 Subject: [PATCH 0186/2538] C++: add *_template_parameter_value() tuples --- cpp/ql/src/semmlecode.cpp.dbscheme | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme b/cpp/ql/src/semmlecode.cpp.dbscheme index 98a075d5495d..bd182f697bf1 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme +++ b/cpp/ql/src/semmlecode.cpp.dbscheme @@ -731,6 +731,11 @@ class_template_argument( int index: int ref, int arg_type: @type ref ); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); is_proxy_class_for( unique int id: @usertype ref, @@ -755,6 +760,11 @@ function_template_argument( int index: int ref, int arg_type: @type ref ); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); is_variable_template(unique int id: @variable ref); variable_instantiation( @@ -766,6 +776,11 @@ variable_template_argument( int index: int ref, int arg_type: @type ref ); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); /* Fixed point types From df7d21220be83026d76636877c98693fffc08ef0 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:20:48 +0100 Subject: [PATCH 0187/2538] C++: Basic lib support for template param values --- cpp/ql/src/semmle/code/cpp/Class.qll | 9 +++++++++ cpp/ql/src/semmle/code/cpp/Declaration.qll | 7 +++++++ cpp/ql/src/semmle/code/cpp/Function.qll | 10 ++++++++++ cpp/ql/src/semmle/code/cpp/Variable.qll | 9 +++++++++ 4 files changed, 35 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 5ac4f52392e7..44e8b4e65ef3 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -614,6 +614,15 @@ class Class extends UserType { class_template_argument(underlyingElement(this), i, unresolveElement(result)) } + /** + * Gets the `i`th template argument value used to instantiate this class from a + * class template. When called on a class template, this will return the + * `i`th template parameter value. + */ + override Expr getTemplateArgumentValue(int i) { + class_template_argument_value(underlyingElement(this), i, unresolveElement(result)) + } + /** * Holds if this class/struct is polymorphic (has a virtual function, or * inherits one). diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 5d13bf4883a7..a3a93aaca965 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -203,6 +203,13 @@ abstract class Declaration extends Locatable, @declaration { */ Type getTemplateArgument(int index) { none() } + /** + * Gets the `i`th template argument value used to instantiate this declaration + * from a template. When called on a template, this will return the `i`th template + * parameter value if it exists. + */ + Expr getTemplateArgumentValue(int index) { none() } + /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 94d11d63575c..be031f2b9153 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -352,6 +352,16 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { function_template_argument(underlyingElement(this), index, unresolveElement(result)) } + /** + * Gets the value of the `i`th template argument used to instantiate this + * function from a function template if that argument was a 'non-type' + * argument. When called on a function template, this with return the value + * of the `i`th template parameter. + */ + override Expr getTemplateArgumentValue(int index) { + function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } + /** * Holds if this function is defined in several files. This is illegal in * C (though possible in some C++ compilers), and likely indicates that diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 6fd33d9a037a..deae1069aabe 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -164,6 +164,15 @@ class Variable extends Declaration, @variable { variable_template_argument(underlyingElement(this), index, unresolveElement(result)) } + /** + * Gets the `i`th template argument value used to instantiate this variable from a + * variable template. When called on a variable template, this will return the + * `i`th template parameter value. + */ + override Expr getTemplateArgumentValue(int index) { + variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } + /** * Holds if this is a compiler-generated variable. For example, a * [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for) From faf5ba432b2306d09d77965c48a84edc1c245d94 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:22:03 +0100 Subject: [PATCH 0188/2538] C++: Update expected test results --- .../library-tests/ir/ir/PrintAST.expected | 10 ++++---- .../test/library-tests/ir/ir/raw_ir.expected | 23 +++++++++++++++++++ .../ptr_to_member/segfault/exprs.expected | 4 ++++ .../templates/CPP-202/template_args.expected | 4 ++-- .../templates/CPP-204/element.expected | 6 +++++ 5 files changed, 40 insertions(+), 7 deletions(-) diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index 19a4288a4c44..e61fe2b440f8 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -67,7 +67,7 @@ bad_asts.cpp: # 5| params: #-----| 0: [Parameter] p#0 #-----| Type = [RValueReferenceType] S && -# 9| [MemberFunction] int Bad::S::MemberFunction(int) +# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -79,8 +79,9 @@ bad_asts.cpp: # 10| 0: [AddExpr] ... + ... # 10| Type = [IntType] int # 10| ValueCategory = prvalue -# 10| 0: [Literal] Unknown literal +# 10| 0: [Literal] 6 # 10| Type = [IntType] int +# 10| Value = [Literal] 6 # 10| ValueCategory = prvalue # 10| 1: [PointerFieldAccess] x # 10| Type = [IntType] int @@ -91,7 +92,7 @@ bad_asts.cpp: # 10| 1: [VariableAccess] y # 10| Type = [IntType] int # 10| ValueCategory = prvalue(load) -# 9| [TopLevelFunction] int MemberFunction(int) +# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -103,9 +104,8 @@ bad_asts.cpp: # 10| 0: [AddExpr] ... + ... # 10| Type = [IntType] int # 10| ValueCategory = prvalue -# 10| 0: [Literal] 6 +# 10| 0: [Literal] Unknown literal # 10| Type = [IntType] int -# 10| Value = [Literal] 6 # 10| ValueCategory = prvalue # 10| 1: [PointerFieldAccess] x # 10| Type = [IntType] int diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 90c3061114ef..f0c96d2bfa00 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,4 +1,27 @@ bad_asts.cpp: +# 9| int Bad::S::MemberFunction(int) +# 9| Block 0 +# 9| v0_0(void) = EnterFunction : +# 9| mu0_1(unknown) = AliasedDefinition : +# 9| mu0_2(unknown) = UnmodeledDefinition : +# 9| r0_3(glval) = InitializeThis : +# 9| r0_4(glval) = VariableAddress[y] : +# 9| mu0_5(int) = InitializeParameter[y] : &:r0_4 +# 10| r0_6(glval) = VariableAddress[#return] : +# 10| r0_7(int) = Constant[6] : +#-----| r0_8(S *) = CopyValue : r0_3 +# 10| r0_9(glval) = FieldAddress[x] : r0_8 +# 10| r0_10(int) = Load : &:r0_9, ~mu0_2 +# 10| r0_11(int) = Add : r0_7, r0_10 +# 10| r0_12(glval) = VariableAddress[y] : +# 10| r0_13(int) = Load : &:r0_12, ~mu0_2 +# 10| r0_14(int) = Add : r0_11, r0_13 +# 10| mu0_15(int) = Store : &:r0_6, r0_14 +# 9| r0_16(glval) = VariableAddress[#return] : +# 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 +# 9| v0_18(void) = UnmodeledUse : mu* +# 9| v0_19(void) = ExitFunction : + # 14| void Bad::CallBadMemberFunction() # 14| Block 0 # 14| v0_0(void) = EnterFunction : diff --git a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected index 7af2f7c8c172..e745ca0142dc 100644 --- a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected +++ b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected @@ -1,3 +1,7 @@ +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:48:25:55 | __second | segfault.cpp:15:7:15:11 | tuple | diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected index 0f20692d443f..ae10f9ddf63b 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected @@ -1,6 +1,6 @@ | file://:0:0:0:0 | __va_list_tag | | -| test.cpp:3:8:3:9 | s1<> | | -| test.cpp:3:8:3:9 | s1<> | | +| test.cpp:3:8:3:9 | s1<> | bool | +| test.cpp:3:8:3:9 | s1<> | bool | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:7:8:7:9 | s3> | (unnamed) | diff --git a/cpp/ql/test/library-tests/templates/CPP-204/element.expected b/cpp/ql/test/library-tests/templates/CPP-204/element.expected index 6cb84a117d5c..b1662c2a3b33 100644 --- a/cpp/ql/test/library-tests/templates/CPP-204/element.expected +++ b/cpp/ql/test/library-tests/templates/CPP-204/element.expected @@ -1,6 +1,12 @@ | file://:0:0:0:0 | | | file://:0:0:0:0 | 0 | | file://:0:0:0:0 | (global namespace) | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | Unknown literal | | file://:0:0:0:0 | __va_list_tag | | file://:0:0:0:0 | __va_list_tag & | | file://:0:0:0:0 | __va_list_tag && | From 6334ad92c5de06fa362f51e4727d3da5397f11ba Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 11:25:15 +0100 Subject: [PATCH 0189/2538] C++: Add DB Upgrade script. --- .../old.dbscheme | 1918 ++++++++++++++++ .../semmlecode.cpp.dbscheme | 1933 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3853 insertions(+) create mode 100644 cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme create mode 100644 cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme create mode 100644 cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme new file mode 100644 index 000000000000..98a075d5495d --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/old.dbscheme @@ -0,0 +1,1918 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme new file mode 100644 index 000000000000..bd182f697bf1 --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/semmlecode.cpp.dbscheme @@ -0,0 +1,1933 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * gcc -c f1.c f2.c f3.c + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + /** + * An invocation of the compiler. Note that more than one file may + * be compiled per invocation. For example, this command compiles + * three source files: + * + * gcc -c f1.c f2.c f3.c + */ + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--mimic` + * 2 | `/usr/bin/gcc` + * 3 | `-c` + * 4 | f1.c + * 5 | f2.c + * 6 | f3.c + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * gcc -c f1.c f2.c f3.c + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.c + * 1 | f2.c + * 2 | f3.c + * + * Note that even if those files `#include` headers, those headers + * do not appear as rows. + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + + +/** + * External data, loaded from CSV files during snapshot creation. See + * [Tutorial: Incorporating external data](https://help.semmle.com/wiki/display/SD/Tutorial%3A+Incorporating+external+data) + * for more information. + */ +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +/** + * The date of the snapshot. + */ +snapshotDate(unique date snapshotDate : date ref); + +/** + * The source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string ref); + +/** + * Data used by the 'duplicate code' detection. + */ +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'similar code' detection. + */ +similarCode( + unique int id : @similarity, + string relativePath : string ref, + int equivClass : int ref +); + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +@duplication_or_similarity = @duplication | @similarity + +/** + * Data used by the 'duplicate code' and 'similar code' detection. + */ +#keyset[id, offset] +tokens( + int id : @duplication_or_similarity ref, + int offset : int ref, + int beginLine : int ref, + int beginColumn : int ref, + int endLine : int ref, + int endColumn : int ref +); + +/** + * Information about packages that provide code used during compilation. + * The `id` is just a unique identifier. + * The `namespace` is typically the name of the package manager that + * provided the package (e.g. "dpkg" or "yum"). + * The `package_name` is the name of the package, and `version` is its + * version (as a string). + */ +external_packages( + unique int id: @external_package, + string namespace : string ref, + string package_name : string ref, + string version : string ref +); + +/** + * Holds if File `fileid` was provided by package `package`. + */ +header_to_external_package( + int fileid : @file ref, + int package : @external_package ref +); + +/* + * Version history + */ + +svnentries( + unique int id : @svnentry, + string revision : string ref, + string author : string ref, + date revisionDate : date ref, + int changeSize : int ref +) + +svnaffectedfiles( + int id : @svnentry ref, + int file : @file ref, + string action : string ref +) + +svnentrymsg( + unique int id : @svnentry ref, + string message : string ref +) + +svnchurn( + int commit : @svnentry ref, + int file : @file ref, + int addedLines : int ref, + int deletedLines : int ref +) + +/* + * C++ dbscheme + */ + +@location = @location_stmt | @location_expr | @location_default ; + +/** + * The location of an element that is not an expression or a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_default( + /** The location of an element that is not an expression or a statement. */ + unique int id: @location_default, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of a statement. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_stmt( + /** The location of a statement. */ + unique int id: @location_stmt, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** + * The location of an expression. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `file`. + * For more information, see + * [Locations](https://help.semmle.com/QL/learn-ql/ql/locations.html). + */ +locations_expr( + /** The location of an expression. */ + unique int id: @location_expr, + int container: @container ref, + int startLine: int ref, + int startColumn: int ref, + int endLine: int ref, + int endColumn: int ref +); + +/** An element for which line-count information is available. */ +@sourceline = @file | @function | @variable | @enumconstant | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + string name: string ref, + string simple: string ref, + string ext: string ref, + int fromSource: int ref +); + +folders( + unique int id: @folder, + string name: string ref, + string simple: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +fileannotations( + int id: @file ref, + int kind: int ref, + string name: string ref, + string value: string ref +); + +inmacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +affectedbymacroexpansion( + int id: @element ref, + int inv: @macroinvocation ref +); + +/* + case @macroinvocations.kind of + 1 = macro expansion + | 2 = other macro reference + ; +*/ +macroinvocations( + unique int id: @macroinvocation, + int macro_id: @ppd_define ref, + int location: @location_default ref, + int kind: int ref +); + +macroparent( + unique int id: @macroinvocation ref, + int parent_id: @macroinvocation ref +); + +// a macroinvocation may be part of another location +// the way to find a constant expression that uses a macro +// is thus to find a constant expression that has a location +// to which a macro invocation is bound +macrolocationbind( + int id: @macroinvocation ref, + int location: @location ref +); + +#keyset[invocation, argument_index] +macro_argument_unexpanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +#keyset[invocation, argument_index] +macro_argument_expanded( + int invocation: @macroinvocation ref, + int argument_index: int ref, + string text: string ref +); + +/* + case @function.kind of + 1 = normal + | 2 = constructor + | 3 = destructor + | 4 = conversion + | 5 = operator + | 6 = builtin // GCC built-in functions, e.g. __builtin___memcpy_chk + ; +*/ +functions( + unique int id: @function, + string name: string ref, + int kind: int ref +); + +function_entry_point(int id: @function ref, unique int entry_point: @stmt ref); + +function_return_type(int id: @function ref, int return_type: @type ref); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + + + +#keyset[id, type_id] +fun_decls( + int id: @fun_decl, + int function: @function ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +fun_def(unique int id: @fun_decl ref); +fun_specialized(unique int id: @fun_decl ref); +fun_implicit(unique int id: @fun_decl ref); +fun_decl_specifiers( + int id: @fun_decl ref, + string name: string ref +) +#keyset[fun_decl, index] +fun_decl_throws( + int fun_decl: @fun_decl ref, + int index: int ref, + int type_id: @type ref +); +/* an empty throw specification is different from none */ +fun_decl_empty_throws(unique int fun_decl: @fun_decl ref); +fun_decl_noexcept( + int fun_decl: @fun_decl ref, + int constant: @expr ref +); +fun_decl_empty_noexcept(int fun_decl: @fun_decl ref); +fun_decl_typedef_type( + unique int fun_decl: @fun_decl ref, + int typedeftype_id: @usertype ref +); + +param_decl_bind( + unique int id: @var_decl ref, + int index: int ref, + int fun_decl: @fun_decl ref +); + +#keyset[id, type_id] +var_decls( + int id: @var_decl, + int variable: @variable ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); +var_def(unique int id: @var_decl ref); +var_decl_specifiers( + int id: @var_decl ref, + string name: string ref +) + +type_decls( + unique int id: @type_decl, + int type_id: @type ref, + int location: @location_default ref +); +type_def(unique int id: @type_decl ref); +type_decl_top( + unique int type_decl: @type_decl ref +); + +namespace_decls( + unique int id: @namespace_decl, + int namespace_id: @namespace ref, + int location: @location_default ref, + int bodylocation: @location_default ref +); + +usings( + unique int id: @using, + int element_id: @element ref, + int location: @location_default ref +); + +/** The element which contains the `using` declaration. */ +using_container( + int parent: @element ref, + int child: @using ref +); + +static_asserts( + unique int id: @static_assert, + int condition : @expr ref, + string message : string ref, + int location: @location_default ref +); + +// each function has an ordered list of parameters +#keyset[id, type_id] +#keyset[function, index, type_id] +params( + int id: @parameter, + int function: @functionorblock ref, + int index: int ref, + int type_id: @type ref +); + +overrides(int new: @function ref, int old: @function ref); + +#keyset[id, type_id] +membervariables( + int id: @membervariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +globalvariables( + int id: @globalvariable, + int type_id: @type ref, + string name: string ref +); + +#keyset[id, type_id] +localvariables( + int id: @localvariable, + int type_id: @type ref, + string name: string ref +); + +autoderivation( + unique int var: @variable ref, + int derivation_type: @type ref +); + +enumconstants( + unique int id: @enumconstant, + int parent: @usertype ref, + int index: int ref, + int type_id: @type ref, + string name: string ref, + int location: @location_default ref +); + +@variable = @localscopevariable | @globalvariable | @membervariable; + +@localscopevariable = @localvariable | @parameter; + +/* + Built-in types are the fundamental types, e.g., integral, floating, and void. + + case @builtintype.kind of + 1 = error + | 2 = unknown + | 3 = void + | 4 = boolean + | 5 = char + | 6 = unsigned_char + | 7 = signed_char + | 8 = short + | 9 = unsigned_short + | 10 = signed_short + | 11 = int + | 12 = unsigned_int + | 13 = signed_int + | 14 = long + | 15 = unsigned_long + | 16 = signed_long + | 17 = long_long + | 18 = unsigned_long_long + | 19 = signed_long_long + | 20 = __int8 // Microsoft-specific + | 21 = __int16 // Microsoft-specific + | 22 = __int32 // Microsoft-specific + | 23 = __int64 // Microsoft-specific + | 24 = float + | 25 = double + | 26 = long_double + | 27 = _Complex_float // C99-specific + | 28 = _Complex_double // C99-specific + | 29 = _Complex_long double // C99-specific + | 30 = _Imaginary_float // C99-specific + | 31 = _Imaginary_double // C99-specific + | 32 = _Imaginary_long_double // C99-specific + | 33 = wchar_t // Microsoft-specific + | 34 = decltype_nullptr // C++11 + | 35 = __int128 + | 36 = unsigned___int128 + | 37 = signed___int128 + | 38 = __float128 + | 39 = _Complex___float128 + | 40 = _Decimal32 + | 41 = _Decimal64 + | 42 = _Decimal128 + | 43 = char16_t + | 44 = char32_t + | 45 = _Float32 + | 46 = _Float32x + | 47 = _Float64 + | 48 = _Float64x + | 49 = _Float128 + | 50 = _Float128x + ; +*/ +builtintypes( + unique int id: @builtintype, + string name: string ref, + int kind: int ref, + int size: int ref, + int sign: int ref, + int alignment: int ref +); + +/* + Derived types are types that are directly derived from existing types and + point to, refer to, transform type data to return a new type. + + case @derivedtype.kind of + 1 = pointer + | 2 = reference + | 3 = type_with_specifiers + | 4 = array + | 5 = gnu_vector + | 6 = routineptr + | 7 = routinereference + | 8 = rvalue_reference // C++11 +// ... 9 type_conforming_to_protocols deprecated + | 10 = block + ; +*/ +derivedtypes( + unique int id: @derivedtype, + string name: string ref, + int kind: int ref, + int type_id: @type ref +); + +pointerishsize(unique int id: @derivedtype ref, + int size: int ref, + int alignment: int ref); + +arraysizes( + unique int id: @derivedtype ref, + int num_elements: int ref, + int bytesize: int ref, + int alignment: int ref +); + +typedefbase( + unique int id: @usertype ref, + int type_id: @type ref +); + +decltypes( + unique int id: @decltype, + int expr: @expr ref, + int base_type: @type ref, + boolean parentheses_would_change_meaning: boolean ref +); + +/* + case @usertype.kind of + 1 = struct + | 2 = class + | 3 = union + | 4 = enum + | 5 = typedef // classic C: typedef typedef type name + | 6 = template + | 7 = template_parameter + | 8 = template_template_parameter + | 9 = proxy_class // a proxy class associated with a template parameter +// ... 10 objc_class deprecated +// ... 11 objc_protocol deprecated +// ... 12 objc_category deprecated + | 13 = scoped_enum + | 14 = using_alias // a using name = type style typedef + ; +*/ +usertypes( + unique int id: @usertype, + string name: string ref, + int kind: int ref +); + +usertypesize( + unique int id: @usertype ref, + int size: int ref, + int alignment: int ref +); + +usertype_final(unique int id: @usertype ref); + +usertype_uuid( + unique int id: @usertype ref, + unique string uuid: string ref +); + +mangled_name( + unique int id: @declaration ref, + int mangled_name : @mangledname +); + +is_pod_class(unique int id: @usertype ref); +is_standard_layout_class(unique int id: @usertype ref); + +is_complete(unique int id: @usertype ref); + +is_class_template(unique int id: @usertype ref); +class_instantiation( + int to: @usertype ref, + int from: @usertype ref +); +class_template_argument( + int type_id: @usertype ref, + int index: int ref, + int arg_type: @type ref +); +class_template_argument_value( + int type_id: @usertype ref, + int index: int ref, + int arg_value: @expr ref +); + +is_proxy_class_for( + unique int id: @usertype ref, + unique int templ_param_id: @usertype ref +); + +type_mentions( + unique int id: @type_mention, + int type_id: @type ref, + int location: @location ref, + // a_symbol_reference_kind from the EDG frontend. See symbol_ref.h there. + int kind: int ref +); + +is_function_template(unique int id: @function ref); +function_instantiation( + unique int to: @function ref, + int from: @function ref +); +function_template_argument( + int function_id: @function ref, + int index: int ref, + int arg_type: @type ref +); +function_template_argument_value( + int function_id: @function ref, + int index: int ref, + int arg_value: @expr ref +); + +is_variable_template(unique int id: @variable ref); +variable_instantiation( + unique int to: @variable ref, + int from: @variable ref +); +variable_template_argument( + int variable_id: @variable ref, + int index: int ref, + int arg_type: @type ref +); +variable_template_argument_value( + int variable_id: @variable ref, + int index: int ref, + int arg_value: @expr ref +); + +/* + Fixed point types + precision(1) = short, precision(2) = default, precision(3) = long + is_unsigned(1) = unsigned is_unsigned(2) = signed + is_fract_type(1) = declared with _Fract + saturating(1) = declared with _Sat +*/ +/* TODO +fixedpointtypes( + unique int id: @fixedpointtype, + int precision: int ref, + int is_unsigned: int ref, + int is_fract_type: int ref, + int saturating: int ref); +*/ + +routinetypes( + unique int id: @routinetype, + int return_type: @type ref +); + +routinetypeargs( + int routine: @routinetype ref, + int index: int ref, + int type_id: @type ref +); + +ptrtomembers( + unique int id: @ptrtomember, + int type_id: @type ref, + int class_id: @type ref +); + +/* + specifiers for types, functions, and variables + + "public", + "protected", + "private", + + "const", + "volatile", + "static", + + "pure", + "virtual", + "sealed", // Microsoft + "__interface", // Microsoft + "inline", + "explicit", + + "near", // near far extension + "far", // near far extension + "__ptr32", // Microsoft + "__ptr64", // Microsoft + "__sptr", // Microsoft + "__uptr", // Microsoft + "dllimport", // Microsoft + "dllexport", // Microsoft + "thread", // Microsoft + "naked", // Microsoft + "microsoft_inline", // Microsoft + "forceinline", // Microsoft + "selectany", // Microsoft + "nothrow", // Microsoft + "novtable", // Microsoft + "noreturn", // Microsoft + "noinline", // Microsoft + "noalias", // Microsoft + "restrict", // Microsoft +*/ + +specifiers( + unique int id: @specifier, + unique string str: string ref +); + +typespecifiers( + int type_id: @type ref, + int spec_id: @specifier ref +); + +funspecifiers( + int func_id: @function ref, + int spec_id: @specifier ref +); + +varspecifiers( + int var_id: @accessible ref, + int spec_id: @specifier ref +); + +attributes( + unique int id: @attribute, + int kind: int ref, + string name: string ref, + string name_space: string ref, + int location: @location_default ref +); + +case @attribute.kind of + 0 = @gnuattribute +| 1 = @stdattribute +| 2 = @declspec +| 3 = @msattribute +| 4 = @alignas +// ... 5 @objc_propertyattribute deprecated +; + +attribute_args( + unique int id: @attribute_arg, + int kind: int ref, + int attribute: @attribute ref, + int index: int ref, + int location: @location_default ref +); + +case @attribute_arg.kind of + 0 = @attribute_arg_empty +| 1 = @attribute_arg_token +| 2 = @attribute_arg_constant +| 3 = @attribute_arg_type +; + +attribute_arg_value( + unique int arg: @attribute_arg ref, + string value: string ref +); +attribute_arg_type( + unique int arg: @attribute_arg ref, + int type_id: @type ref +); +attribute_arg_name( + unique int arg: @attribute_arg ref, + string name: string ref +); + +typeattributes( + int type_id: @type ref, + int spec_id: @attribute ref +); + +funcattributes( + int func_id: @function ref, + int spec_id: @attribute ref +); + +varattributes( + int var_id: @accessible ref, + int spec_id: @attribute ref +); + +stmtattributes( + int stmt_id: @stmt ref, + int spec_id: @attribute ref +); + +@type = @builtintype + | @derivedtype + | @usertype + /* TODO | @fixedpointtype */ + | @routinetype + | @ptrtomember + | @decltype; + +unspecifiedtype( + unique int type_id: @type ref, + int unspecified_type_id: @type ref +); + +member( + int parent: @type ref, + int index: int ref, + int child: @member ref +); + +@enclosingfunction_child = @usertype | @variable | @namespace + +enclosingfunction( + unique int child: @enclosingfunction_child ref, + int parent: @function ref +); + +derivations( + unique int derivation: @derivation, + int sub: @type ref, + int index: int ref, + int super: @type ref, + int location: @location_default ref +); + +derspecifiers( + int der_id: @derivation ref, + int spec_id: @specifier ref +); + +/** + * Contains the byte offset of the base class subobject within the derived + * class. Only holds for non-virtual base classes, but see table + * `virtual_base_offsets` for offsets of virtual base class subobjects. + */ +direct_base_offsets( + unique int der_id: @derivation ref, + int offset: int ref +); + +/** + * Contains the byte offset of the virtual base class subobject for class + * `super` within a most-derived object of class `sub`. `super` can be either a + * direct or indirect base class. + */ +#keyset[sub, super] +virtual_base_offsets( + int sub: @usertype ref, + int super: @usertype ref, + int offset: int ref +); + +frienddecls( + unique int id: @frienddecl, + int type_id: @type ref, + int decl_id: @declaration ref, + int location: @location_default ref +); + +@declaredtype = @usertype ; + +@declaration = @function + | @declaredtype + | @variable + | @enumconstant + | @frienddecl; + +@member = @membervariable + | @function + | @declaredtype + | @enumconstant; + +@locatable = @diagnostic + | @declaration + | @ppd_include + | @ppd_define + | @macroinvocation + /*| @funcall*/ + | @xmllocatable + | @attribute + | @attribute_arg; + +@namedscope = @namespace | @usertype; + +@element = @locatable + | @file + | @folder + | @specifier + | @type + | @expr + | @namespace + | @initialiser + | @stmt + | @derivation + | @comment + | @preprocdirect + | @fun_decl + | @var_decl + | @type_decl + | @namespace_decl + | @using + | @namequalifier + | @specialnamequalifyingelement + | @static_assert + | @type_mention + | @lambdacapture; + +@exprparent = @element; + +comments( + unique int id: @comment, + string contents: string ref, + int location: @location_default ref +); + +commentbinding( + int id: @comment ref, + int element: @element ref +); + +exprconv( + int converted: @expr ref, + unique int conversion: @expr ref +); + +compgenerated(unique int id: @element ref); + +/** + * `destructor_call` destructs the `i`'th entity that should be + * destructed following `element`. Note that entities should be + * destructed in reverse construction order, so for a given `element` + * these should be called from highest to lowest `i`. + */ +#keyset[element, destructor_call] +#keyset[element, i] +synthetic_destructor_call( + int element: @element ref, + int i: int ref, + int destructor_call: @routineexpr ref +); + +namespaces( + unique int id: @namespace, + string name: string ref +); + +namespace_inline( + unique int id: @namespace ref +); + +namespacembrs( + int parentid: @namespace ref, + unique int memberid: @namespacembr ref +); + +@namespacembr = @declaration | @namespace; + +exprparents( + int expr_id: @expr ref, + int child_index: int ref, + int parent_id: @exprparent ref +); + +expr_isload(unique int expr_id: @expr ref); + +@cast = @c_style_cast + | @const_cast + | @dynamic_cast + | @reinterpret_cast + | @static_cast + ; + +/* +case @conversion.kind of + 0 = @simple_conversion // a numeric conversion, qualification conversion, or a reinterpret_cast +| 1 = @bool_conversion // conversion to 'bool' +| 2 = @base_class_conversion // a derived-to-base conversion +| 3 = @derived_class_conversion // a base-to-derived conversion +| 4 = @pm_base_class_conversion // a derived-to-base conversion of a pointer to member +| 5 = @pm_derived_class_conversion // a base-to-derived conversion of a pointer to member +| 6 = @glvalue_adjust // an adjustment of the type of a glvalue +| 7 = @prvalue_adjust // an adjustment of the type of a prvalue +; +*/ +/** + * Describes the semantics represented by a cast expression. This is largely + * independent of the source syntax of the cast, so it is separate from the + * regular expression kind. + */ +conversionkinds( + unique int expr_id: @cast ref, + int kind: int ref +); + +/* +case @funbindexpr.kind of + 0 = @normal_call // a normal call +| 1 = @virtual_call // a virtual call +| 2 = @adl_call // a call whose target is only found by ADL +; +*/ +iscall(unique int caller: @funbindexpr ref, int kind: int ref); + +numtemplatearguments( + unique int expr_id: @expr ref, + int num: int ref +); + +specialnamequalifyingelements( + unique int id: @specialnamequalifyingelement, + unique string name: string ref +); + +@namequalifiableelement = @expr | @namequalifier; +@namequalifyingelement = @namespace + | @specialnamequalifyingelement + | @usertype; + +namequalifiers( + unique int id: @namequalifier, + unique int qualifiableelement: @namequalifiableelement ref, + int qualifyingelement: @namequalifyingelement ref, + int location: @location_default ref +); + +varbind( + int expr: @varbindexpr ref, + int var: @accessible ref +); + +funbind( + int expr: @funbindexpr ref, + int fun: @function ref +); + +@any_new_expr = @new_expr + | @new_array_expr; + +@new_or_delete_expr = @any_new_expr + | @delete_expr + | @delete_array_expr; + +/* + case @allocator.form of + 0 = plain + | 1 = alignment + ; +*/ + +/** + * The allocator function associated with a `new` or `new[]` expression. + * The `form` column specified whether the allocation call contains an alignment + * argument. + */ +expr_allocator( + unique int expr: @any_new_expr ref, + int func: @function ref, + int form: int ref +); + +/* + case @deallocator.form of + 0 = plain + | 1 = size + | 2 = alignment + | 3 = size_and_alignment + ; +*/ + +/** + * The deallocator function associated with a `delete`, `delete[]`, `new`, or + * `new[]` expression. For a `new` or `new[]` expression, the deallocator is the + * one used to free memory if the initialization throws an exception. + * The `form` column specifies whether the deallocation call contains a size + * argument, and alignment argument, or both. + */ +expr_deallocator( + unique int expr: @new_or_delete_expr ref, + int func: @function ref, + int form: int ref +); + +/** + * Holds if the `@conditionalexpr` is of the two operand form + * `guard ? : false`. + */ +expr_cond_two_operand( + unique int cond: @conditionalexpr ref +); + +/** + * The guard of `@conditionalexpr` `guard ? true : false` + */ +expr_cond_guard( + unique int cond: @conditionalexpr ref, + int guard: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` holds. For the two operand form + * `guard ?: false` consider using `expr_cond_guard` instead. + */ +expr_cond_true( + unique int cond: @conditionalexpr ref, + int true: @expr ref +); + +/** + * The expression used when the guard of `@conditionalexpr` + * `guard ? true : false` does not hold. + */ +expr_cond_false( + unique int cond: @conditionalexpr ref, + int false: @expr ref +); + +/** A string representation of the value. */ +values( + unique int id: @value, + string str: string ref +); + +/** The actual text in the source code for the value, if any. */ +valuetext( + unique int id: @value ref, + string text: string ref +); + +valuebind( + int val: @value ref, + unique int expr: @expr ref +); + +fieldoffsets( + unique int id: @variable ref, + int byteoffset: int ref, + int bitoffset: int ref +); + +bitfield( + unique int id: @variable ref, + int bits: int ref, + int declared_bits: int ref +); + +/* TODO +memberprefix( + int member: @expr ref, + int prefix: @expr ref +); +*/ + +/* + kind(1) = mbrcallexpr + kind(2) = mbrptrcallexpr + kind(3) = mbrptrmbrcallexpr + kind(4) = ptrmbrptrmbrcallexpr + kind(5) = mbrreadexpr // x.y + kind(6) = mbrptrreadexpr // p->y + kind(7) = mbrptrmbrreadexpr // x.*pm + kind(8) = mbrptrmbrptrreadexpr // x->*pm + kind(9) = staticmbrreadexpr // static x.y + kind(10) = staticmbrptrreadexpr // static p->y +*/ +/* TODO +memberaccess( + int member: @expr ref, + int kind: int ref +); +*/ + +initialisers( + unique int init: @initialiser, + int var: @accessible ref, + unique int expr: @expr ref, + int location: @location_expr ref +); + +/** + * An ancestor for the expression, for cases in which we cannot + * otherwise find the expression's parent. + */ +expr_ancestor( + int exp: @expr ref, + int ancestor: @element ref +); + +exprs( + unique int id: @expr, + int kind: int ref, + int location: @location_expr ref +); + +/* + case @value.category of + 1 = prval + | 2 = xval + | 3 = lval + ; +*/ +expr_types( + int id: @expr ref, + int typeid: @type ref, + int value_category: int ref +); + +case @expr.kind of + 1 = @errorexpr +| 2 = @address_of // & AddressOfExpr +| 3 = @reference_to // ReferenceToExpr (implicit?) +| 4 = @indirect // * PointerDereferenceExpr +| 5 = @ref_indirect // ReferenceDereferenceExpr (implicit?) +// ... +| 8 = @array_to_pointer // (???) +| 9 = @vacuous_destructor_call // VacuousDestructorCall +// ... +| 11 = @assume // Microsoft +| 12 = @parexpr +| 13 = @arithnegexpr +| 14 = @unaryplusexpr +| 15 = @complementexpr +| 16 = @notexpr +| 17 = @conjugation // GNU ~ operator +| 18 = @realpartexpr // GNU __real +| 19 = @imagpartexpr // GNU __imag +| 20 = @postincrexpr +| 21 = @postdecrexpr +| 22 = @preincrexpr +| 23 = @predecrexpr +| 24 = @conditionalexpr +| 25 = @addexpr +| 26 = @subexpr +| 27 = @mulexpr +| 28 = @divexpr +| 29 = @remexpr +| 30 = @jmulexpr // C99 mul imaginary +| 31 = @jdivexpr // C99 div imaginary +| 32 = @fjaddexpr // C99 add real + imaginary +| 33 = @jfaddexpr // C99 add imaginary + real +| 34 = @fjsubexpr // C99 sub real - imaginary +| 35 = @jfsubexpr // C99 sub imaginary - real +| 36 = @paddexpr // pointer add (pointer + int or int + pointer) +| 37 = @psubexpr // pointer sub (pointer - integer) +| 38 = @pdiffexpr // difference between two pointers +| 39 = @lshiftexpr +| 40 = @rshiftexpr +| 41 = @andexpr +| 42 = @orexpr +| 43 = @xorexpr +| 44 = @eqexpr +| 45 = @neexpr +| 46 = @gtexpr +| 47 = @ltexpr +| 48 = @geexpr +| 49 = @leexpr +| 50 = @minexpr // GNU minimum +| 51 = @maxexpr // GNU maximum +| 52 = @assignexpr +| 53 = @assignaddexpr +| 54 = @assignsubexpr +| 55 = @assignmulexpr +| 56 = @assigndivexpr +| 57 = @assignremexpr +| 58 = @assignlshiftexpr +| 59 = @assignrshiftexpr +| 60 = @assignandexpr +| 61 = @assignorexpr +| 62 = @assignxorexpr +| 63 = @assignpaddexpr // assign pointer add +| 64 = @assignpsubexpr // assign pointer sub +| 65 = @andlogicalexpr +| 66 = @orlogicalexpr +| 67 = @commaexpr +| 68 = @subscriptexpr // access to member of an array, e.g., a[5] +// ... 69 @objc_subscriptexpr deprecated +// ... 70 @cmdaccess deprecated +// ... +| 73 = @virtfunptrexpr +| 74 = @callexpr +// ... 75 @msgexpr_normal deprecated +// ... 76 @msgexpr_super deprecated +// ... 77 @atselectorexpr deprecated +// ... 78 @atprotocolexpr deprecated +| 79 = @vastartexpr +| 80 = @vaargexpr +| 81 = @vaendexpr +| 82 = @vacopyexpr +// ... 83 @atencodeexpr deprecated +| 84 = @varaccess +| 85 = @thisaccess +// ... 86 @objc_box_expr deprecated +| 87 = @new_expr +| 88 = @delete_expr +| 89 = @throw_expr +| 90 = @condition_decl // a variable declared in a condition, e.g., if(int x = y > 2) +| 91 = @braced_init_list +| 92 = @type_id +| 93 = @runtime_sizeof +| 94 = @runtime_alignof +| 95 = @sizeof_pack +| 96 = @expr_stmt // GNU extension +| 97 = @routineexpr +| 98 = @type_operand // used to access a type in certain contexts (haven't found any examples yet....) +| 99 = @offsetofexpr // offsetof ::= type and field +| 100 = @hasassignexpr // __has_assign ::= type +| 101 = @hascopyexpr // __has_copy ::= type +| 102 = @hasnothrowassign // __has_nothrow_assign ::= type +| 103 = @hasnothrowconstr // __has_nothrow_constructor ::= type +| 104 = @hasnothrowcopy // __has_nothrow_copy ::= type +| 105 = @hastrivialassign // __has_trivial_assign ::= type +| 106 = @hastrivialconstr // __has_trivial_constructor ::= type +| 107 = @hastrivialcopy // __has_trivial_copy ::= type +| 108 = @hasuserdestr // __has_user_destructor ::= type +| 109 = @hasvirtualdestr // __has_virtual_destructor ::= type +| 110 = @isabstractexpr // __is_abstract ::= type +| 111 = @isbaseofexpr // __is_base_of ::= type type +| 112 = @isclassexpr // __is_class ::= type +| 113 = @isconvtoexpr // __is_convertible_to ::= type type +| 114 = @isemptyexpr // __is_empty ::= type +| 115 = @isenumexpr // __is_enum ::= type +| 116 = @ispodexpr // __is_pod ::= type +| 117 = @ispolyexpr // __is_polymorphic ::= type +| 118 = @isunionexpr // __is_union ::= type +| 119 = @typescompexpr // GNU __builtin_types_compatible ::= type type +| 120 = @intaddrexpr // EDG internal builtin, used to implement offsetof +// ... +| 122 = @hastrivialdestructor // __has_trivial_destructor ::= type +| 123 = @literal +| 124 = @uuidof +| 127 = @aggregateliteral +| 128 = @delete_array_expr +| 129 = @new_array_expr +// ... 130 @objc_array_literal deprecated +// ... 131 @objc_dictionary_literal deprecated +| 132 = @foldexpr +// ... +| 200 = @ctordirectinit +| 201 = @ctorvirtualinit +| 202 = @ctorfieldinit +| 203 = @ctordelegatinginit +| 204 = @dtordirectdestruct +| 205 = @dtorvirtualdestruct +| 206 = @dtorfielddestruct +// ... +| 210 = @static_cast +| 211 = @reinterpret_cast +| 212 = @const_cast +| 213 = @dynamic_cast +| 214 = @c_style_cast +| 215 = @lambdaexpr +| 216 = @param_ref +| 217 = @noopexpr +// ... +| 294 = @istriviallyconstructibleexpr +| 295 = @isdestructibleexpr +| 296 = @isnothrowdestructibleexpr +| 297 = @istriviallydestructibleexpr +| 298 = @istriviallyassignableexpr +| 299 = @isnothrowassignableexpr +| 300 = @istrivialexpr +| 301 = @isstandardlayoutexpr +| 302 = @istriviallycopyableexpr +| 303 = @isliteraltypeexpr +| 304 = @hastrivialmoveconstructorexpr +| 305 = @hastrivialmoveassignexpr +| 306 = @hasnothrowmoveassignexpr +| 307 = @isconstructibleexpr +| 308 = @isnothrowconstructibleexpr +| 309 = @hasfinalizerexpr +| 310 = @isdelegateexpr +| 311 = @isinterfaceclassexpr +| 312 = @isrefarrayexpr +| 313 = @isrefclassexpr +| 314 = @issealedexpr +| 315 = @issimplevalueclassexpr +| 316 = @isvalueclassexpr +| 317 = @isfinalexpr +| 319 = @noexceptexpr +| 320 = @builtinshufflevector +| 321 = @builtinchooseexpr +| 322 = @builtinaddressof +| 323 = @vec_fill +| 324 = @builtinconvertvector +| 325 = @builtincomplex +; + +new_allocated_type( + unique int expr: @new_expr ref, + int type_id: @type ref +); + +new_array_allocated_type( + unique int expr: @new_array_expr ref, + int type_id: @type ref +); + +/** + * The field being initialized by an initializer expression within an aggregate + * initializer for a class/struct/union. + */ +#keyset[aggregate, field] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. + */ +#keyset[aggregate, element_index] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref +); + +@ctorinit = @ctordirectinit + | @ctorvirtualinit + | @ctorfieldinit + | @ctordelegatinginit; +@dtordestruct = @dtordirectdestruct + | @dtorvirtualdestruct + | @dtorfielddestruct; + + +condition_decl_bind( + unique int expr: @condition_decl ref, + unique int decl: @declaration ref +); + +typeid_bind( + unique int expr: @type_id ref, + int type_id: @type ref +); + +uuidof_bind( + unique int expr: @uuidof ref, + int type_id: @type ref +); + +@runtime_sizeof_or_alignof = @runtime_sizeof | @runtime_alignof; + +sizeof_bind( + unique int expr: @runtime_sizeof_or_alignof ref, + int type_id: @type ref +); + +code_block( + unique int block: @literal ref, + unique int routine: @function ref +); + +lambdas( + unique int expr: @lambdaexpr ref, + string default_capture: string ref, + boolean has_explicit_return_type: boolean ref +); + +lambda_capture( + unique int id: @lambdacapture, + int lambda: @lambdaexpr ref, + int index: int ref, + int field: @membervariable ref, + boolean captured_by_reference: boolean ref, + boolean is_implicit: boolean ref, + int location: @location_default ref +); + +@funbindexpr = @routineexpr + | @new_expr + | @delete_expr + | @delete_array_expr + | @ctordirectinit + | @ctorvirtualinit + | @ctordelegatinginit + | @dtordirectdestruct + | @dtorvirtualdestruct; + +@varbindexpr = @varaccess | @ctorfieldinit | @dtorfielddestruct; +@addressable = @function | @variable ; +@accessible = @addressable | @enumconstant ; + +fold( + int expr: @foldexpr ref, + string operator: string ref, + boolean is_left_fold: boolean ref +); + +stmts( + unique int id: @stmt, + int kind: int ref, + int location: @location_stmt ref +); + +case @stmt.kind of + 1 = @stmt_expr +| 2 = @stmt_if +| 3 = @stmt_while +| 4 = @stmt_goto +| 5 = @stmt_label +| 6 = @stmt_return +| 7 = @stmt_block +| 8 = @stmt_end_test_while // do { ... } while ( ... ) +| 9 = @stmt_for +| 10 = @stmt_switch_case +| 11 = @stmt_switch +| 13 = @stmt_asm // "asm" statement or the body of an asm function +| 15 = @stmt_try_block +| 16 = @stmt_microsoft_try // Microsoft +| 17 = @stmt_decl +| 18 = @stmt_set_vla_size // C99 +| 19 = @stmt_vla_decl // C99 +| 25 = @stmt_assigned_goto // GNU +| 26 = @stmt_empty +| 27 = @stmt_continue +| 28 = @stmt_break +| 29 = @stmt_range_based_for // C++11 +// ... 30 @stmt_at_autoreleasepool_block deprecated +// ... 31 @stmt_objc_for_in deprecated +// ... 32 @stmt_at_synchronized deprecated +| 33 = @stmt_handler +// ... 34 @stmt_finally_end deprecated +| 35 = @stmt_constexpr_if +; + +type_vla( + int type_id: @type ref, + int decl: @stmt_vla_decl ref +); + +variable_vla( + int var: @variable ref, + int decl: @stmt_vla_decl ref +); + +if_then( + unique int if_stmt: @stmt_if ref, + int then_id: @stmt ref +); + +if_else( + unique int if_stmt: @stmt_if ref, + int else_id: @stmt ref +); + +constexpr_if_then( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int then_id: @stmt ref +); + +constexpr_if_else( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int else_id: @stmt ref +); + +while_body( + unique int while_stmt: @stmt_while ref, + int body_id: @stmt ref +); + +do_body( + unique int do_stmt: @stmt_end_test_while ref, + int body_id: @stmt ref +); + +#keyset[switch_stmt, index] +switch_case( + int switch_stmt: @stmt_switch ref, + int index: int ref, + int case_id: @stmt_switch_case ref +); + +switch_body( + unique int switch_stmt: @stmt_switch ref, + int body_id: @stmt ref +); + +for_initialization( + unique int for_stmt: @stmt_for ref, + int init_id: @stmt ref +); + +for_condition( + unique int for_stmt: @stmt_for ref, + int condition_id: @expr ref +); + +for_update( + unique int for_stmt: @stmt_for ref, + int update_id: @expr ref +); + +for_body( + unique int for_stmt: @stmt_for ref, + int body_id: @stmt ref +); + +@stmtparent = @stmt | @expr_stmt ; +stmtparents( + unique int id: @stmt ref, + int index: int ref, + int parent: @stmtparent ref +); + +ishandler(unique int block: @stmt_block ref); + +@cfgnode = @stmt | @expr | @function | @initialiser ; +successors( + int from: @cfgnode ref, + int to: @cfgnode ref +); + +truecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +falsecond( + unique int from: @cfgnode ref, + int to: @cfgnode ref +); + +stmt_decl_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl: @declaration ref +); + +stmt_decl_entry_bind( + int stmt: @stmt_decl ref, + int num: int ref, + int decl_entry: @element ref +); + +@functionorblock = @function | @stmt_block; + +blockscope( + unique int block: @stmt_block ref, + int enclosing: @functionorblock ref +); + +@jump = @stmt_goto | @stmt_break | @stmt_continue; + +@jumporlabel = @jump | @stmt_label | @literal; + +jumpinfo( + unique int id: @jumporlabel ref, + string str: string ref, + int target: @stmt ref +); + +preprocdirects( + unique int id: @preprocdirect, + int kind: int ref, + int location: @location_default ref +); +case @preprocdirect.kind of + 0 = @ppd_if +| 1 = @ppd_ifdef +| 2 = @ppd_ifndef +| 3 = @ppd_elif +| 4 = @ppd_else +| 5 = @ppd_endif +| 6 = @ppd_plain_include +| 7 = @ppd_define +| 8 = @ppd_undef +| 9 = @ppd_line +| 10 = @ppd_error +| 11 = @ppd_pragma +| 12 = @ppd_objc_import +| 13 = @ppd_include_next +| 18 = @ppd_warning +; + +@ppd_include = @ppd_plain_include | @ppd_objc_import | @ppd_include_next; + +@ppd_branch = @ppd_if | @ppd_ifdef | @ppd_ifndef | @ppd_elif; + +preprocpair( + int begin : @ppd_branch ref, + int elseelifend : @preprocdirect ref +); + +preproctrue(int branch : @ppd_branch ref); +preprocfalse(int branch : @ppd_branch ref); + +preproctext( + unique int id: @preprocdirect ref, + string head: string ref, + string body: string ref +); + +includes( + unique int id: @ppd_include ref, + int included: @file ref +); + +link_targets( + unique int id: @link_target, + int binary: @file ref +); + +link_parent( + int element : @element ref, + int link_target : @link_target ref +); + +/* XML Files */ + +xmlEncoding(unique int id: @file ref, string encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + string root: string ref, + string publicId: string ref, + string systemId: string ref, + int fileid: @file ref +); + +xmlElements( + unique int id: @xmlelement, + string name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref +); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + string name: string ref, + string value: string ref, + int idx: int ref, + int fileid: @file ref +); + +xmlNs( + int id: @xmlnamespace, + string prefixName: string ref, + string URI: string ref, + int fileid: @file ref +); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref +); + +xmlComments( + unique int id: @xmlcomment, + string text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref +); + +xmlChars( + unique int id: @xmlcharacters, + string text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref +); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref +); + +@xmllocatable = @xmlcharacters + | @xmlelement + | @xmlcomment + | @xmlattribute + | @xmldtd + | @file + | @xmlnamespace; diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties new file mode 100644 index 000000000000..3388d1abe281 --- /dev/null +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties @@ -0,0 +1,2 @@ +description: Add support for value template paramters. +compatibility: partial From 4ab87291f35bb831dae94d314f91308bd4c0c2d1 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 15:29:16 +0100 Subject: [PATCH 0190/2538] C++: Further use of TemplateArgumentValue --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 6 ++++++ cpp/ql/src/semmle/code/cpp/exprs/Call.qll | 18 ++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index a3a93aaca965..a10faf0f9185 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -197,6 +197,12 @@ abstract class Declaration extends Locatable, @declaration { */ final Type getATemplateArgument() { result = getTemplateArgument(_) } + /** + * Gets a template argument used to instantiate this declaration from a template. + * When called on a template, this will return a template parameter value. + */ + final Expr getATemplateArgumentValue() { result = getTemplateArgumentValue(_) } + /** * Gets the `i`th template argument used to instantiate this declaration from a * template. When called on a template, this will return the `i`th template parameter. diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll index 882918316f61..85807cf0d14c 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll @@ -141,15 +141,27 @@ class FunctionCall extends Call, @funbindexpr { /** Gets an explicit template argument for this call. */ Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + /** Gets an explicit template argument value for this call. */ + Expr getAnExplicitTemplateArgumentValue() { result = getExplicitTemplateArgumentValue(_) } + /** Gets a template argument for this call. */ Type getATemplateArgument() { result = getTarget().getATemplateArgument() } + /** Gets a template argument value for this call. */ + Expr getATemplateArgumentValue() { result = getTarget().getATemplateArgumentValue() } + /** Gets the nth explicit template argument for this call. */ Type getExplicitTemplateArgument(int n) { n < getNumberOfExplicitTemplateArguments() and result = getTemplateArgument(n) } + /** Gets the nth explicit template argument value for this call. */ + Expr getExplicitTemplateArgumentValue(int n) { + n < getNumberOfExplicitTemplateArguments() and + result = getTemplateArgumentValue(n) + } + /** Gets the number of explicit template arguments for this call. */ int getNumberOfExplicitTemplateArguments() { if numtemplatearguments(underlyingElement(this), _) @@ -160,9 +172,15 @@ class FunctionCall extends Call, @funbindexpr { /** Gets the number of template arguments for this call. */ int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } + /** Gets the number of template argument which are values for this call. */ + int getNumberOfTemplateArgumentValues() { result = count(int i | exists(getTemplateArgumentValue(i))) } + /** Gets the nth template argument for this call (indexed from 0). */ Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + /** Gets the nth template argument value for this call (indexed from 0). */ + Expr getTemplateArgumentValue(int n) { result = getTarget().getTemplateArgumentValue(n) } + /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { exists(int i | From 469832668fae1aa5202bf8881af4b7796949f14c Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 18 Oct 2019 15:30:41 +0100 Subject: [PATCH 0191/2538] C++: Add some simple non-type template tests --- .../templates/nontype_instantiations/classes/test.cpp | 4 ++++ .../templates/nontype_instantiations/classes/test.expected | 2 ++ .../templates/nontype_instantiations/classes/test.ql | 4 ++++ .../templates/nontype_instantiations/functions/test.cpp | 5 +++++ .../templates/nontype_instantiations/functions/test.expected | 2 ++ .../templates/nontype_instantiations/functions/test.ql | 4 ++++ 6 files changed, 21 insertions(+) create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp new file mode 100644 index 000000000000..4f16f623daf0 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.cpp @@ -0,0 +1,4 @@ +template +class Int { }; + +Int<10> i; diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected new file mode 100644 index 000000000000..524097b88d67 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected @@ -0,0 +1,2 @@ +| test.cpp:2:7:2:9 | Int<10> | file://:0:0:0:0 | int | test.cpp:4:5:4:6 | 10 | +| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql new file mode 100644 index 000000000000..347bb2dba00f --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Class c +select c, c.getATemplateArgument(), c.getATemplateArgumentValue() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp new file mode 100644 index 000000000000..625258906dba --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.cpp @@ -0,0 +1,5 @@ +// semmle-extractor-options: --edg --trap_container=folder --edg --trap-compression=none +template +int addToSelf() { return i + i; }; + +int bar() { return addToSelf<10>(); } diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected new file mode 100644 index 000000000000..70e845e7b595 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected @@ -0,0 +1,2 @@ +| test.cpp:3:5:3:5 | addToSelf | file://:0:0:0:0 | int | test.cpp:5:30:5:31 | 10 | +| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql new file mode 100644 index 000000000000..4dd6e754cd6c --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Function f +select f, f.getATemplateArgument(), f.getATemplateArgumentValue() From 57cd9b3990f2396e36c3d38c53db8ca4e6f70e79 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Mon, 21 Oct 2019 17:12:20 +0100 Subject: [PATCH 0192/2538] C++: Update test results We now support getting the name used for non-type template parameters --- .../ptr_to_member/segfault/exprs.expected | 8 ++++---- .../library-tests/templates/CPP-204/element.expected | 12 ++++++------ .../nontype_instantiations/classes/test.expected | 2 +- .../nontype_instantiations/functions/test.expected | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected index e745ca0142dc..e5539a762ab0 100644 --- a/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected +++ b/cpp/ql/test/library-tests/ptr_to_member/segfault/exprs.expected @@ -1,7 +1,7 @@ -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | -| file://:0:0:0:0 | Unknown literal | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | __i | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | +| file://:0:0:0:0 | uls | file://:0:0:0:0 | unsigned long | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:46:25:65 | call to S | file://:0:0:0:0 | void | | segfault.cpp:25:48:25:55 | __second | segfault.cpp:15:7:15:11 | tuple | diff --git a/cpp/ql/test/library-tests/templates/CPP-204/element.expected b/cpp/ql/test/library-tests/templates/CPP-204/element.expected index b1662c2a3b33..44384471af9e 100644 --- a/cpp/ql/test/library-tests/templates/CPP-204/element.expected +++ b/cpp/ql/test/library-tests/templates/CPP-204/element.expected @@ -1,12 +1,12 @@ | file://:0:0:0:0 | | | file://:0:0:0:0 | 0 | | file://:0:0:0:0 | (global namespace) | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | -| file://:0:0:0:0 | Unknown literal | +| file://:0:0:0:0 | B | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | X | +| file://:0:0:0:0 | Y | | file://:0:0:0:0 | __va_list_tag | | file://:0:0:0:0 | __va_list_tag & | | file://:0:0:0:0 | __va_list_tag && | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected index 524097b88d67..ffa9bfb2cf4c 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.expected @@ -1,2 +1,2 @@ | test.cpp:2:7:2:9 | Int<10> | file://:0:0:0:0 | int | test.cpp:4:5:4:6 | 10 | -| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | +| test.cpp:2:7:2:9 | Int | file://:0:0:0:0 | int | file://:0:0:0:0 | i | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected index 70e845e7b595..493e9f03b207 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.expected @@ -1,2 +1,2 @@ | test.cpp:3:5:3:5 | addToSelf | file://:0:0:0:0 | int | test.cpp:5:30:5:31 | 10 | -| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | Unknown literal | +| test.cpp:3:5:3:13 | addToSelf | file://:0:0:0:0 | int | file://:0:0:0:0 | i | From ca898d4be04ec3d899637e2e9e1627c5f5fd5541 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 22 Oct 2019 10:54:14 +0100 Subject: [PATCH 0193/2538] C++: Further nontype template testcases. --- .../nontype_instantiations/general/test.cpp | 19 +++++++++++++++++++ .../general/test.expected | 10 ++++++++++ .../nontype_instantiations/general/test.ql | 4 ++++ 3 files changed, 33 insertions(+) create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected create mode 100644 cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp new file mode 100644 index 000000000000..1baabe3ca305 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.cpp @@ -0,0 +1,19 @@ +// semmle-extractor-options: --edg --trap_container=folder --edg --trap-compression=none +template +struct C { }; + +static const int one1 = 1, one2 = 1; +C c = C(); +C e; + +template +struct D { }; + +D a; +D b; + +template +struct E { }; + +E z; + diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected new file mode 100644 index 000000000000..70dfdbc3edfa --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected @@ -0,0 +1,10 @@ +| test.cpp:3:8:3:8 | C<1> | file://:0:0:0:0 | int | test.cpp:5:25:5:25 | 1 | +| test.cpp:3:8:3:8 | C<2> | file://:0:0:0:0 | int | file://:0:0:0:0 | 2 | +| test.cpp:3:8:3:8 | C | file://:0:0:0:0 | int | file://:0:0:0:0 | x | +| test.cpp:10:8:10:8 | D | test.cpp:9:19:9:19 | T | file://:0:0:0:0 | X | +| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | int | test.cpp:12:8:12:8 | 2 | +| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | long | file://:0:0:0:0 | 2 | +| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | T * | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | test.cpp:15:19:15:19 | T | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int | file://:0:0:0:0 | 0 | +| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int * | file://:0:0:0:0 | 0 | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql new file mode 100644 index 000000000000..8915d6523b67 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Declaration d +select d, d.getATemplateArgument(), d.getATemplateArgumentValue() From f1c3ce04d1ae8a17a37dcea8010872ebe3377760 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 22 Oct 2019 10:54:58 +0100 Subject: [PATCH 0194/2538] C++: Correct spelling mistake --- .../98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties index 3388d1abe281..495bdeebdac2 100644 --- a/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties +++ b/cpp/upgrades/98a075d5495d7be7ede26557708cf22cfa3964ef/upgrade.properties @@ -1,2 +1,2 @@ -description: Add support for value template paramters. +description: Add support for value template parameters. compatibility: partial From 809d97de02f362e10381d2fc23b0c989705d7c40 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Wed, 23 Oct 2019 16:29:32 +0100 Subject: [PATCH 0195/2538] C++: Print print nontype template params --- cpp/ql/src/semmle/code/cpp/Print.qll | 10 +++++++++- cpp/ql/test/library-tests/ir/ir/PrintAST.expected | 7 ++++--- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 2 +- 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index ab979d89b03f..7be1537e83b3 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -35,6 +35,14 @@ private string getParameterTypeString(Type parameterType) { else result = parameterType.(DumpType).getTypeIdentityString() } +private string getTemplateArgumentString(Declaration d, int i) { + if exists(d.getTemplateArgumentValue(i)) + then + result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() + " " + d.getTemplateArgumentValue(i) + else + result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() +} + /** * A `Declaration` extended to add methods for generating strings useful only for dumps and debugging. */ @@ -56,7 +64,7 @@ abstract private class DumpDeclaration extends Declaration { strictconcat(int i | exists(this.getTemplateArgument(i)) | - this.getTemplateArgument(i).(DumpType).getTypeIdentityString(), ", " order by i + getTemplateArgumentString(this, i), ", " order by i ) + ">" else result = "" } diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected index e61fe2b440f8..dab6a40fae6f 100644 --- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected +++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected @@ -67,7 +67,7 @@ bad_asts.cpp: # 5| params: #-----| 0: [Parameter] p#0 #-----| Type = [RValueReferenceType] S && -# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) +# 9| [FunctionTemplateInstantiation,MemberFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -92,7 +92,7 @@ bad_asts.cpp: # 10| 1: [VariableAccess] y # 10| Type = [IntType] int # 10| ValueCategory = prvalue(load) -# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) +# 9| [MemberFunction,TemplateFunction] int Bad::S::MemberFunction(int) # 9| params: # 9| 0: [Parameter] y # 9| Type = [IntType] int @@ -104,8 +104,9 @@ bad_asts.cpp: # 10| 0: [AddExpr] ... + ... # 10| Type = [IntType] int # 10| ValueCategory = prvalue -# 10| 0: [Literal] Unknown literal +# 10| 0: [Literal] t # 10| Type = [IntType] int +# 10| Value = [Literal] t # 10| ValueCategory = prvalue # 10| 1: [PointerFieldAccess] x # 10| Type = [IntType] int diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index f0c96d2bfa00..b38e63e6e760 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -1,5 +1,5 @@ bad_asts.cpp: -# 9| int Bad::S::MemberFunction(int) +# 9| int Bad::S::MemberFunction(int) # 9| Block 0 # 9| v0_0(void) = EnterFunction : # 9| mu0_1(unknown) = AliasedDefinition : From afeaa6254d4fb367c02bad6e0edb12963402bbd4 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 29 Oct 2019 14:06:15 +0000 Subject: [PATCH 0196/2538] C++: Improve Template Value docs. --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 33 ++++++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index a10faf0f9185..b3d12efe1e9f 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -193,19 +193,34 @@ abstract class Declaration extends Locatable, @declaration { /** * Gets a template argument used to instantiate this declaration from a template. - * When called on a template, this will return a template parameter. + * When called on a template, this will return a template parameter type for + * both typed and non-typed parameters. */ final Type getATemplateArgument() { result = getTemplateArgument(_) } /** * Gets a template argument used to instantiate this declaration from a template. - * When called on a template, this will return a template parameter value. + * When called on a template, this will return a non-typed template + * parameter value. */ final Expr getATemplateArgumentValue() { result = getTemplateArgumentValue(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a - * template. When called on a template, this will return the `i`th template parameter. + * template. When called on a template, this will return the `i`th template + * parameter's type. + * + * For example: + * + * `template class Foo;` + * + * Will have `getTemplateArgument(0)` return `T`, and + * `getTemplateArgument(1)` return `T`. + * + * `Foo bar; + * + * Will have `getTemplateArgument())` return `int`, and + * `getTemplateArgument(1)` return `int`. */ Type getTemplateArgument(int index) { none() } @@ -213,6 +228,18 @@ abstract class Declaration extends Locatable, @declaration { * Gets the `i`th template argument value used to instantiate this declaration * from a template. When called on a template, this will return the `i`th template * parameter value if it exists. + * + * For example: + * + * `template class Foo;` + * + * Will have `getTemplateArgumentValue(1)` return `X`, and no result for + * `getTemplateArgumentValue(0)`. + * + * `Foo bar; + * + * Will have `getTemplateArgumentValue(1)` return `10`, and no result for + * `getTemplateArgumentValue(0)`. */ Expr getTemplateArgumentValue(int index) { none() } From 45ec8527c3c03812e2d02bfd8abb4de4a91a945a Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 29 Oct 2019 16:21:41 +0000 Subject: [PATCH 0197/2538] C++: Update expected test output. --- cpp/ql/test/library-tests/ir/ir/raw_ir.expected | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index b38e63e6e760..a188c1b36292 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -20,7 +20,8 @@ bad_asts.cpp: # 9| r0_16(glval) = VariableAddress[#return] : # 9| v0_17(void) = ReturnValue : &:r0_16, ~mu0_2 # 9| v0_18(void) = UnmodeledUse : mu* -# 9| v0_19(void) = ExitFunction : +# 9| v0_19(void) = AliasedUse : ~mu0_2 +# 9| v0_20(void) = ExitFunction : # 14| void Bad::CallBadMemberFunction() # 14| Block 0 From 6fe22a76da7dd14eda5b002df5d3788c2f366652 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 1 Nov 2019 14:31:51 +0000 Subject: [PATCH 0198/2538] C++: Change API for exposing template parameters. Note that Declaration::getTemplateArgumentType() and Declaration::getTemplateArgumentValue() need to be public so that they can be overriden in derived classes. --- cpp/ql/src/semmle/code/cpp/Class.qll | 4 +- cpp/ql/src/semmle/code/cpp/Declaration.qll | 51 ++++++++++++++----- cpp/ql/src/semmle/code/cpp/Function.qll | 2 +- cpp/ql/src/semmle/code/cpp/Print.qll | 8 +-- cpp/ql/src/semmle/code/cpp/Type.qll | 2 +- cpp/ql/src/semmle/code/cpp/Variable.qll | 2 +- cpp/ql/src/semmle/code/cpp/exprs/Call.qll | 21 ++++---- .../templates/CPP-202/template_args.expected | 4 +- .../nontype_instantiations/classes/test.ql | 2 +- .../nontype_instantiations/functions/test.ql | 2 +- .../general/test.expected | 23 +++++---- .../nontype_instantiations/general/test.ql | 14 ++++- 12 files changed, 86 insertions(+), 49 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 44e8b4e65ef3..5ccf6193c4ff 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -610,7 +610,7 @@ class Class extends UserType { * class template. When called on a class template, this will return the * `i`th template parameter. */ - override Type getTemplateArgument(int i) { + override Type getTemplateArgumentType(int i) { class_template_argument(underlyingElement(this), i, unresolveElement(result)) } @@ -632,7 +632,7 @@ class Class extends UserType { } override predicate involvesTemplateParameter() { - getATemplateArgument().involvesTemplateParameter() + getATemplateArgument().(Type).involvesTemplateParameter() } /** Holds if this class, struct or union was declared 'final'. */ diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index b3d12efe1e9f..9c8ce250d8d6 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -196,33 +196,36 @@ abstract class Declaration extends Locatable, @declaration { * When called on a template, this will return a template parameter type for * both typed and non-typed parameters. */ - final Type getATemplateArgument() { result = getTemplateArgument(_) } + final Locatable getATemplateArgument() { result = getTemplateArgument(_) } /** * Gets a template argument used to instantiate this declaration from a template. * When called on a template, this will return a non-typed template * parameter value. */ - final Expr getATemplateArgumentValue() { result = getTemplateArgumentValue(_) } + final Locatable getATemplateArgumentKind() { result = getTemplateArgumentKind(_) } /** * Gets the `i`th template argument used to instantiate this declaration from a - * template. When called on a template, this will return the `i`th template - * parameter's type. + * template. * * For example: * * `template class Foo;` * * Will have `getTemplateArgument(0)` return `T`, and - * `getTemplateArgument(1)` return `T`. + * `getTemplateArgument(1)` return `X`. * * `Foo bar; * * Will have `getTemplateArgument())` return `int`, and - * `getTemplateArgument(1)` return `int`. + * `getTemplateArgument(1)` return `1`. */ - Type getTemplateArgument(int index) { none() } + final Locatable getTemplateArgument(int index) { + if exists(getTemplateArgumentValue(index)) + then result = getTemplateArgumentValue(index) + else result = getTemplateArgumentType(index) + } /** * Gets the `i`th template argument value used to instantiate this declaration @@ -233,20 +236,44 @@ abstract class Declaration extends Locatable, @declaration { * * `template class Foo;` * - * Will have `getTemplateArgumentValue(1)` return `X`, and no result for - * `getTemplateArgumentValue(0)`. + * Will have `getTemplateArgumentKind(1)` return `T`, and no result for + * `getTemplateArgumentKind(0)`. * * `Foo bar; * - * Will have `getTemplateArgumentValue(1)` return `10`, and no result for - * `getTemplateArgumentValue(0)`. + * Will have `getTemplateArgumentKind(1)` return `int`, and no result for + * `getTemplateArgumentKind(0)`. */ - Expr getTemplateArgumentValue(int index) { none() } + final Locatable getTemplateArgumentKind(int index) { + if exists(getTemplateArgumentValue(index)) + then result = getTemplateArgumentType(index) + else none() + } /** Gets the number of template arguments for this declaration. */ final int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } + + /** + * INTERNAL: Do not use. + * + * Gets a Type for a template argument. May be the template argument itself + * or the type of a non-type template argument. + * + * Use `getTemplateArgument` or `getTemplateKind` instead. + */ + Type getTemplateArgumentType(int index) { none() } + + /** + * INTERNAL: Do not use. + * + * Gets an Expression representing the value of a non-type template + * argument. + * + * Use `getTemplateArgument` or `getTemplateKind` instead. + */ + Expr getTemplateArgumentValue(int index) { none() } } /** diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index be031f2b9153..5436c3ba2183 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -348,7 +348,7 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { * function template. When called on a function template, this will return the * `i`th template parameter. */ - override Type getTemplateArgument(int index) { + override Type getTemplateArgumentType(int index) { function_template_argument(underlyingElement(this), index, unresolveElement(result)) } diff --git a/cpp/ql/src/semmle/code/cpp/Print.qll b/cpp/ql/src/semmle/code/cpp/Print.qll index 7be1537e83b3..e3ad19f60282 100644 --- a/cpp/ql/src/semmle/code/cpp/Print.qll +++ b/cpp/ql/src/semmle/code/cpp/Print.qll @@ -36,11 +36,11 @@ private string getParameterTypeString(Type parameterType) { } private string getTemplateArgumentString(Declaration d, int i) { - if exists(d.getTemplateArgumentValue(i)) + if exists(d.getTemplateArgumentKind(i)) then - result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() + " " + d.getTemplateArgumentValue(i) - else - result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() + result = d.getTemplateArgumentKind(i).(DumpType).getTypeIdentityString() + " " + + d.getTemplateArgument(i) + else result = d.getTemplateArgument(i).(DumpType).getTypeIdentityString() } /** diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index 10a1b6b17246..ea1e7fd50268 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -210,7 +210,7 @@ class Type extends Locatable, @type { // A function call that provides an explicit template argument that refers to T uses T. // We exclude calls within instantiations, since they do not appear directly in the source. exists(FunctionCall c | - c.getAnExplicitTemplateArgument().refersTo(this) and + c.getAnExplicitTemplateArgument().(Type).refersTo(this) and result = c and not c.getEnclosingFunction().isConstructedFrom(_) ) diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index deae1069aabe..689f1c3bfa51 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -160,7 +160,7 @@ class Variable extends Declaration, @variable { * variable template. When called on a variable template, this will return the * `i`th template parameter. */ - override Type getTemplateArgument(int index) { + override Type getTemplateArgumentType(int index) { variable_template_argument(underlyingElement(this), index, unresolveElement(result)) } diff --git a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll index 85807cf0d14c..22a25969a8f6 100644 --- a/cpp/ql/src/semmle/code/cpp/exprs/Call.qll +++ b/cpp/ql/src/semmle/code/cpp/exprs/Call.qll @@ -139,27 +139,27 @@ class FunctionCall extends Call, @funbindexpr { override string getCanonicalQLClass() { result = "FunctionCall" } /** Gets an explicit template argument for this call. */ - Type getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } + Locatable getAnExplicitTemplateArgument() { result = getExplicitTemplateArgument(_) } /** Gets an explicit template argument value for this call. */ - Expr getAnExplicitTemplateArgumentValue() { result = getExplicitTemplateArgumentValue(_) } + Locatable getAnExplicitTemplateArgumentKind() { result = getExplicitTemplateArgumentKind(_) } /** Gets a template argument for this call. */ - Type getATemplateArgument() { result = getTarget().getATemplateArgument() } + Locatable getATemplateArgument() { result = getTarget().getATemplateArgument() } /** Gets a template argument value for this call. */ - Expr getATemplateArgumentValue() { result = getTarget().getATemplateArgumentValue() } + Locatable getATemplateArgumentKind() { result = getTarget().getATemplateArgumentKind() } /** Gets the nth explicit template argument for this call. */ - Type getExplicitTemplateArgument(int n) { + Locatable getExplicitTemplateArgument(int n) { n < getNumberOfExplicitTemplateArguments() and result = getTemplateArgument(n) } /** Gets the nth explicit template argument value for this call. */ - Expr getExplicitTemplateArgumentValue(int n) { + Locatable getExplicitTemplateArgumentKind(int n) { n < getNumberOfExplicitTemplateArguments() and - result = getTemplateArgumentValue(n) + result = getTemplateArgumentKind(n) } /** Gets the number of explicit template arguments for this call. */ @@ -172,14 +172,11 @@ class FunctionCall extends Call, @funbindexpr { /** Gets the number of template arguments for this call. */ int getNumberOfTemplateArguments() { result = count(int i | exists(getTemplateArgument(i))) } - /** Gets the number of template argument which are values for this call. */ - int getNumberOfTemplateArgumentValues() { result = count(int i | exists(getTemplateArgumentValue(i))) } - /** Gets the nth template argument for this call (indexed from 0). */ - Type getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } + Locatable getTemplateArgument(int n) { result = getTarget().getTemplateArgument(n) } /** Gets the nth template argument value for this call (indexed from 0). */ - Expr getTemplateArgumentValue(int n) { result = getTarget().getTemplateArgumentValue(n) } + Locatable getTemplateArgumentKind(int n) { result = getTarget().getTemplateArgumentKind(n) } /** Holds if any template arguments for this call are implicit / deduced. */ predicate hasImplicitTemplateArguments() { diff --git a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected index ae10f9ddf63b..f38eef610e44 100644 --- a/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected +++ b/cpp/ql/test/library-tests/templates/CPP-202/template_args.expected @@ -1,6 +1,6 @@ | file://:0:0:0:0 | __va_list_tag | | -| test.cpp:3:8:3:9 | s1<> | bool | -| test.cpp:3:8:3:9 | s1<> | bool | +| test.cpp:3:8:3:9 | s1<> | {...} | +| test.cpp:3:8:3:9 | s1<> | (null) | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:5:8:5:9 | s2 | T | | test.cpp:7:8:7:9 | s3> | (unnamed) | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql index 347bb2dba00f..900424eb501a 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/classes/test.ql @@ -1,4 +1,4 @@ import cpp from Class c -select c, c.getATemplateArgument(), c.getATemplateArgumentValue() +select c, c.getATemplateArgumentKind(), c.getATemplateArgument() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql index 4dd6e754cd6c..98f8a4112d47 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/functions/test.ql @@ -1,4 +1,4 @@ import cpp from Function f -select f, f.getATemplateArgument(), f.getATemplateArgumentValue() +select f, f.getATemplateArgumentKind(), f.getATemplateArgument() diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected index 70dfdbc3edfa..fa5df86f68fe 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.expected @@ -1,10 +1,13 @@ -| test.cpp:3:8:3:8 | C<1> | file://:0:0:0:0 | int | test.cpp:5:25:5:25 | 1 | -| test.cpp:3:8:3:8 | C<2> | file://:0:0:0:0 | int | file://:0:0:0:0 | 2 | -| test.cpp:3:8:3:8 | C | file://:0:0:0:0 | int | file://:0:0:0:0 | x | -| test.cpp:10:8:10:8 | D | test.cpp:9:19:9:19 | T | file://:0:0:0:0 | X | -| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | int | test.cpp:12:8:12:8 | 2 | -| test.cpp:10:8:10:8 | D | file://:0:0:0:0 | long | file://:0:0:0:0 | 2 | -| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | T * | file://:0:0:0:0 | X | -| test.cpp:16:8:16:8 | E | test.cpp:15:19:15:19 | T | file://:0:0:0:0 | X | -| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int | file://:0:0:0:0 | 0 | -| test.cpp:16:8:16:8 | E | file://:0:0:0:0 | int * | file://:0:0:0:0 | 0 | +| test.cpp:3:8:3:8 | C<1> | 0 | int | test.cpp:5:25:5:25 | 1 | +| test.cpp:3:8:3:8 | C<2> | 0 | int | file://:0:0:0:0 | 2 | +| test.cpp:3:8:3:8 | C | 0 | int | file://:0:0:0:0 | x | +| test.cpp:10:8:10:8 | D | 0 | | test.cpp:9:19:9:19 | T | +| test.cpp:10:8:10:8 | D | 1 | T | file://:0:0:0:0 | X | +| test.cpp:10:8:10:8 | D | 0 | | file://:0:0:0:0 | int | +| test.cpp:10:8:10:8 | D | 1 | int | test.cpp:12:8:12:8 | 2 | +| test.cpp:10:8:10:8 | D | 0 | | file://:0:0:0:0 | long | +| test.cpp:10:8:10:8 | D | 1 | long | file://:0:0:0:0 | 2 | +| test.cpp:16:8:16:8 | E | 0 | | test.cpp:15:19:15:19 | T | +| test.cpp:16:8:16:8 | E | 1 | T * | file://:0:0:0:0 | X | +| test.cpp:16:8:16:8 | E | 0 | | file://:0:0:0:0 | int | +| test.cpp:16:8:16:8 | E | 1 | int * | file://:0:0:0:0 | 0 | diff --git a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql index 8915d6523b67..68d597e0f983 100644 --- a/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql +++ b/cpp/ql/test/library-tests/templates/nontype_instantiations/general/test.ql @@ -1,4 +1,14 @@ import cpp -from Declaration d -select d, d.getATemplateArgument(), d.getATemplateArgumentValue() +string maybeGetTemplateArgumentKind(Declaration d, int i) { + ( + if exists(d.getTemplateArgumentKind(i)) + then result = d.getTemplateArgumentKind(i).toString() + else result = "" + ) and + i = [0 .. d.getNumberOfTemplateArguments()] +} + +from Declaration d, int i +where i >= 0 and i < d.getNumberOfTemplateArguments() +select d, i, maybeGetTemplateArgumentKind(d, i), d.getTemplateArgument(i) From 6b4506dbea2edc9113c39238041d5a337087142c Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Fri, 1 Nov 2019 14:35:48 +0000 Subject: [PATCH 0199/2538] C++: Update schema stats --- cpp/ql/src/semmlecode.cpp.dbscheme.stats | 10192 +++++++++++---------- 1 file changed, 5395 insertions(+), 4797 deletions(-) diff --git a/cpp/ql/src/semmlecode.cpp.dbscheme.stats b/cpp/ql/src/semmlecode.cpp.dbscheme.stats index bd1964b0d4f9..3a73724456a1 100644 --- a/cpp/ql/src/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/src/semmlecode.cpp.dbscheme.stats @@ -1,15 +1,15 @@ @compilation -10588 +10177 @externalDataElement -72 +70 @duplication -185332 +185440 @similarity @@ -17,7 +17,7 @@ @external_package -133 +128 @svnentry @@ -25,67 +25,67 @@ @location_default -9664446 +9335283 @location_stmt -2176932 +2178211 @location_expr -9745314 +9746017 @diagnostic -76160 +73204 @file -66167 +63599 @folder -12107 +11637 @macroinvocation -40814994 +39320374 @function -3565918 +3552236 @fun_decl -3657006 +3635139 @var_decl -5579181 +5495954 @type_decl -1469165 +1413769 @namespace_decl -151627 +145743 @using -320601 +308161 @static_assert -132358 +131017 @parameter -4779409 +4724692 @membervariable -325099 +321201 @globalvariable @@ -93,47 +93,47 @@ @localvariable -527101 +521758 @enumconstant -94487 +94097 @builtintype -559 +537 @derivedtype -4572495 +4651908 @decltype -45841 +44063 @usertype -4363319 +4337028 @mangledname -532986 +514256 @type_mention -1699359 +1682135 @routinetype -444572 +436132 @ptrtomember -12180 +13227 @specifier -547 +525 @gnuattribute @@ -141,11 +141,11 @@ @stdattribute -369 +365 @declspec -58441 +57849 @msattribute @@ -153,7 +153,7 @@ @alignas -267 +257 @attribute_arg_empty @@ -161,55 +161,55 @@ @attribute_arg_token -15930 +15768 @attribute_arg_constant -111500 +111565 @attribute_arg_type -60 +58 @derivation -370309 +392220 @frienddecl -231178 +222208 @comment -1743633 +1675974 @namespace -8497 +8167 @specialnamequalifyingelement -12 +11 @namequalifier -1125621 +1116919 @value -8776796 +8788031 @initialiser -1685017 +1668506 @literal -4374193 +4381545 @errorexpr -48066 +46201 @address_of @@ -217,15 +217,15 @@ @reference_to -1077837 +1039133 @indirect -294638 +294811 @ref_indirect -1267903 +1225212 @array_to_pointer @@ -233,31 +233,31 @@ @vacuous_destructor_call -4449 +4288 @assume -3328 +3294 @parexpr -3001187 +3002950 @arithnegexpr -654789 +654792 @unaryplusexpr -206 +198 @complementexpr -28027 +28043 @notexpr -357915 +358125 @conjugation @@ -265,51 +265,51 @@ @realpartexpr -72 +70 @imagpartexpr -72 +70 @postincrexpr -43039 +43064 @postdecrexpr -5401 +5404 @preincrexpr -63954 +61508 @predecrexpr -26586 +25554 @conditionalexpr -154429 +154519 @addexpr -209503 +209626 @subexpr -134974 +135053 @mulexpr -91616 +91670 @divexpr -63973 +64010 @remexpr -4657 +4660 @jmulexpr @@ -337,59 +337,59 @@ @paddexpr -87252 +87303 @psubexpr -23151 +23165 @pdiffexpr -25868 +24865 @lshiftexpr -347564 +347768 @rshiftexpr -59286 +59321 @andexpr -236938 +237077 @orexpr -145217 +143745 @xorexpr -37281 +37303 @eqexpr -212621 +212746 @neexpr -88456 +88508 @gtexpr -43936 +43962 @ltexpr -54831 +54863 @geexpr -22361 +22374 @leexpr -213875 +214001 @minexpr @@ -401,7 +401,7 @@ @assignexpr -551713 +552037 @assignaddexpr @@ -413,15 +413,15 @@ @assignmulexpr -7597 +7302 @assigndivexpr -2297 +2208 @assignremexpr -303 +292 @assignlshiftexpr @@ -433,39 +433,39 @@ @assignandexpr -7740 +7744 @assignorexpr -18663 +18674 @assignxorexpr -21992 +22005 @assignpaddexpr -13214 +13080 @assignpsubexpr -583 +577 @andlogicalexpr -116840 +116908 @orlogicalexpr -57827 +57861 @commaexpr -10721 +10329 @subscriptexpr -165754 +165851 @virtfunptrexpr @@ -473,15 +473,15 @@ @callexpr -248513 +239197 @vastartexpr -3710 +3673 @vaargexpr -1094 +1051 @vaendexpr @@ -493,63 +493,63 @@ @varaccess -5376400 +5325591 @thisaccess -1181340 +1169367 @new_expr -29515 +28370 @delete_expr -6564 +6309 @throw_expr -23777 +22855 @condition_decl -7646 +7349 @braced_init_list -133 +128 @type_id -4899 +4708 @runtime_sizeof -281622 +281787 @runtime_alignof -1560 +1561 @sizeof_pack -267 +502 @expr_stmt -160546 +160640 @routineexpr -2309113 +2232038 @type_operand -127928 +128003 @offsetofexpr -35356 +35377 @hasassignexpr @@ -597,11 +597,11 @@ @isbaseofexpr -19 +39 @isclassexpr -6 +215 @isconvtoexpr @@ -609,15 +609,15 @@ @isemptyexpr -5 +175 @isenumexpr -3 +23 @ispodexpr -3 +11 @ispolyexpr @@ -629,7 +629,7 @@ @typescompexpr -46285 +46312 @intaddrexpr @@ -637,11 +637,11 @@ @hastrivialdestructor -97 +105 @uuidof -856 +848 @aggregateliteral @@ -649,11 +649,11 @@ @delete_array_expr -1495 +1437 @new_array_expr -5364 +5310 @foldexpr @@ -661,59 +661,59 @@ @ctordirectinit -93264 +89645 @ctorvirtualinit -6904 +6636 @ctorfieldinit -209661 +201538 @ctordelegatinginit -741 +712 @dtordirectdestruct -30828 +30111 @dtorvirtualdestruct -2698 +2594 @dtorfielddestruct -32542 +31279 @static_cast -224735 +226064 @reinterpret_cast -31207 +30891 @const_cast -5847 +5643 @dynamic_cast -1094 +1051 @c_style_cast -4242732 +4244118 @lambdaexpr -12641 +12513 @param_ref -53208 +51144 @noopexpr @@ -745,7 +745,7 @@ @istrivialexpr -2565 +2512 @isstandardlayoutexpr @@ -753,7 +753,7 @@ @istriviallycopyableexpr -48 +46 @isliteraltypeexpr @@ -813,11 +813,11 @@ @isfinalexpr -2 +175 @noexceptexpr -449 +432 @builtinshufflevector @@ -825,11 +825,11 @@ @builtinchooseexpr -7028 +7032 @builtinaddressof -4388 +4218 @vec_fill @@ -845,67 +845,67 @@ @lambdacapture -21730 +21509 @stmt_expr -1284462 +1271443 @stmt_if -524558 +524866 @stmt_while -32907 +31630 @stmt_goto -111432 +111498 @stmt_label -85508 +85558 @stmt_return -1197201 +1154730 @stmt_block -1398281 +1348007 @stmt_end_test_while -149900 +149988 @stmt_for -32387 +32059 @stmt_switch_case -281530 +281695 @stmt_switch -55225 +55258 @stmt_asm -251715 +251863 @stmt_try_block -18964 +18228 @stmt_microsoft_try -171 +169 @stmt_decl -647378 +623601 @stmt_set_vla_size @@ -917,27 +917,27 @@ @stmt_assigned_goto -9137 +9142 @stmt_empty -103681 +102630 @stmt_continue -8603 +8608 @stmt_break -232406 +232543 @stmt_range_based_for -24 +23 @stmt_handler -21888 +21666 @stmt_constexpr_if @@ -945,51 +945,51 @@ @ppd_plain_include -321707 +309224 @ppd_define -349947 +336367 @ppd_if -171077 +164439 @ppd_ifdef -66823 +64230 @ppd_ifndef -91793 +88231 @ppd_elif -22768 +21885 @ppd_else -63638 +61169 @ppd_endif -329694 +316901 @ppd_undef -21152 +20331 @ppd_line -12523 +12530 @ppd_error -48 +46 @ppd_pragma -37040 +36665 @ppd_objc_import @@ -997,7 +997,7 @@ @ppd_include_next -97 +93 @ppd_warning @@ -1005,7 +1005,7 @@ @link_target -644 +619 @xmldtd @@ -1034,15 +1034,15 @@ compilations -10588 +10177 id -10588 +10177 cwd -12 +11 @@ -1056,7 +1056,7 @@ 1 2 -10588 +10177 @@ -1072,7 +1072,7 @@ 871 872 -12 +11 @@ -1082,11 +1082,11 @@ compilation_args -394124 +394355 id -4637 +4640 num @@ -1094,7 +1094,7 @@ arg -20097 +20109 @@ -1113,7 +1113,7 @@ 87 88 -3527 +3529 88 @@ -1149,7 +1149,7 @@ 86 87 -3529 +3531 87 @@ -1322,12 +1322,12 @@ 1 2 -19123 +19134 2 2575 -974 +975 @@ -1343,7 +1343,7 @@ 1 2 -19748 +19760 2 @@ -1358,19 +1358,19 @@ compilation_compiling_files -10588 +10177 id -10588 +10177 num -12 +11 file -5373 +5164 @@ -1384,7 +1384,7 @@ 1 2 -10588 +10177 @@ -1400,7 +1400,7 @@ 1 2 -10588 +10177 @@ -1416,7 +1416,7 @@ 871 872 -12 +11 @@ -1432,7 +1432,7 @@ 442 443 -12 +11 @@ -1448,17 +1448,17 @@ 1 2 -303 +292 2 3 -5044 +4849 3 14 -24 +23 @@ -1474,7 +1474,7 @@ 1 2 -5373 +5164 @@ -1484,23 +1484,23 @@ compilation_time -42255 +40616 id -10563 +10154 num -12 +11 kind -48 +46 seconds -12375 +11965 @@ -1514,7 +1514,7 @@ 1 2 -10563 +10154 @@ -1530,7 +1530,7 @@ 4 5 -10563 +10154 @@ -1544,14 +1544,19 @@ 12 +2 +3 +58 + + 3 4 -3160 +2792 4 5 -7403 +7302 @@ -1567,7 +1572,7 @@ 869 870 -12 +11 @@ -1583,7 +1588,7 @@ 4 5 -12 +11 @@ -1597,9 +1602,9 @@ 12 -1018 -1019 -12 +1024 +1025 +11 @@ -1615,7 +1620,7 @@ 869 870 -48 +46 @@ -1631,7 +1636,7 @@ 1 2 -48 +46 @@ -1645,24 +1650,24 @@ 12 -6 -7 -12 +7 +8 +11 -9 -10 -12 +10 +11 +11 -561 -562 -12 +560 +561 +11 -597 -598 -12 +591 +592 +11 @@ -1678,27 +1683,27 @@ 1 2 -7755 +7501 2 3 -2613 +2617 3 4 -1045 +759 4 -324 -936 +8 +899 -417 -614 -24 +8 +632 +186 @@ -1714,7 +1719,7 @@ 1 2 -12375 +11965 @@ -1730,12 +1735,17 @@ 1 2 -10490 +10305 2 3 -1884 +1635 + + +3 +4 +23 @@ -1745,23 +1755,23 @@ diagnostic_for -940397 +903906 diagnostic -940397 +73204 compilation -10223 +9826 file_number -12 +11 file_number_diagnostic_number -7208 +6929 @@ -1775,7 +1785,17 @@ 1 2 -940397 +9861 + + +2 +3 +60456 + + +118 +840 +2886 @@ -1791,7 +1811,7 @@ 1 2 -940397 +73204 @@ -1807,7 +1827,12 @@ 1 2 -940397 +73181 + + +2 +3 +23 @@ -1823,37 +1848,37 @@ 2 3 -24 +23 7 8 -5227 +5024 8 9 -1665 +1600 9 10 -218 +210 247 248 -2066 +1986 263 444 -802 +771 446 594 -218 +210 @@ -1869,7 +1894,7 @@ 1 2 -10223 +9826 @@ -1885,37 +1910,37 @@ 2 3 -24 +23 7 8 -5227 +5024 8 9 -1665 +1600 9 10 -218 +210 247 248 -2066 +1986 263 444 -802 +771 446 594 -218 +210 @@ -1931,7 +1956,7 @@ 6265 6266 -12 +11 @@ -1947,7 +1972,7 @@ 841 842 -12 +11 @@ -1963,7 +1988,7 @@ 593 594 -12 +11 @@ -1979,47 +2004,47 @@ 1 2 -2954 +2839 2 5 -656 +630 5 6 -1057 +1016 7 14 -571 +549 15 16 -60 +58 17 18 -632 +607 18 23 -486 +467 26 40 -583 +560 42 842 -206 +198 @@ -2035,52 +2060,52 @@ 4 9 -619 +595 10 11 -1057 +1016 14 27 -571 +549 30 31 -60 +58 34 35 -632 +607 36 45 -486 +467 52 79 -583 +560 84 85 -194 +186 254 255 -2893 +2780 272 842 -109 +105 @@ -2096,7 +2121,7 @@ 1 2 -7208 +6929 @@ -2106,19 +2131,19 @@ compilation_finished -10588 +10177 id -10588 +10177 cpu_seconds -8436 +7957 elapsed_seconds -182 +186 @@ -2132,7 +2157,7 @@ 1 2 -10588 +10177 @@ -2148,7 +2173,7 @@ 1 2 -10588 +10177 @@ -2164,17 +2189,17 @@ 1 2 -7184 +6730 2 3 -850 +712 3 -12 -401 +9 +514 @@ -2190,12 +2215,12 @@ 1 2 -8023 +7560 2 3 -413 +397 @@ -2211,67 +2236,62 @@ 1 2 -36 +35 2 3 -12 +35 3 4 -12 - - -4 -5 -12 +11 -8 -9 -12 +7 +8 +11 10 11 -12 +11 -20 -21 -12 +21 +22 +11 -22 -23 -12 +27 +28 +11 53 54 -12 +11 -124 -125 -12 +120 +121 +11 -134 -135 -12 +125 +126 +11 -230 -231 -12 +233 +234 +11 -258 -259 -12 +263 +264 +11 @@ -2287,67 +2307,62 @@ 1 2 -36 +35 2 3 -12 +35 3 4 -12 - - -4 -5 -12 +11 -8 -9 -12 +7 +8 +11 10 11 -12 +11 -20 -21 -12 +21 +22 +11 -22 -23 -12 +26 +27 +11 -49 -50 -12 +51 +52 +11 -100 -101 -12 +92 +93 +11 118 119 -12 +11 -172 -173 -12 +163 +164 +11 -217 -218 -12 +215 +216 +11 @@ -2357,23 +2372,23 @@ externalData -145 +140 id -72 +70 path -12 +11 column -24 +23 value -145 +140 @@ -2387,7 +2402,7 @@ 1 2 -72 +70 @@ -2403,7 +2418,7 @@ 2 3 -72 +70 @@ -2419,7 +2434,7 @@ 2 3 -72 +70 @@ -2435,7 +2450,7 @@ 6 7 -12 +11 @@ -2451,7 +2466,7 @@ 2 3 -12 +11 @@ -2467,7 +2482,7 @@ 12 13 -12 +11 @@ -2483,7 +2498,7 @@ 6 7 -24 +23 @@ -2499,7 +2514,7 @@ 1 2 -24 +23 @@ -2515,7 +2530,7 @@ 6 7 -24 +23 @@ -2531,7 +2546,7 @@ 1 2 -145 +140 @@ -2547,7 +2562,7 @@ 1 2 -145 +140 @@ -2563,7 +2578,7 @@ 1 2 -145 +140 @@ -2573,41 +2588,41 @@ snapshotDate -12 +11 snapshotDate -12 +11 sourceLocationPrefix -12 +11 prefix -12 +11 duplicateCode -185332 +185440 id -185332 +185440 relativePath -761 +762 equivClass -76596 +76641 @@ -2621,7 +2636,7 @@ 1 2 -185332 +185440 @@ -2637,7 +2652,7 @@ 1 2 -185332 +185440 @@ -2765,27 +2780,27 @@ 1 2 -20462 +20474 2 3 -32635 +32655 3 4 -10716 +10723 4 5 -6015 +6019 5 9 -5954 +5957 9 @@ -2806,7 +2821,7 @@ 1 2 -75730 +75775 2 @@ -3122,27 +3137,27 @@ tokens -39620249 +39643528 id -279171 +279335 offset -21169 +21181 beginLine -785436 +785898 beginColumn -1302 +1303 endLine -785436 +785898 endColumn @@ -3160,72 +3175,72 @@ 100 101 -8596 +8601 101 102 -27640 +27656 102 105 -22613 +22626 105 108 -24506 +24520 108 111 -13844 +13852 111 114 -23787 +23801 114 116 -22681 +22694 116 124 -23658 +23672 124 132 -21660 +21673 132 154 -21347 +21360 154 186 -21323 +21335 186 202 -23418 +23432 202 416 -20978 +20991 416 3446 -3115 +3117 @@ -3246,47 +3261,47 @@ 5 6 -109755 +109819 6 7 -15399 +15408 7 8 -28395 +28412 8 12 -23645 +23659 12 17 -22797 +22811 17 19 -18969 +18980 19 22 -22791 +22805 22 28 -21470 +21483 28 151 -14545 +14553 @@ -3302,42 +3317,42 @@ 2 26 -22933 +22946 26 31 -22318 +22331 31 32 -2642 +2643 32 33 -163572 +163668 33 51 -21310 +21323 51 61 -22472 +22485 61 80 -21058 +21071 80 132 -2863 +2865 @@ -3358,47 +3373,47 @@ 5 6 -109755 +109819 6 7 -15399 +15408 7 8 -28395 +28412 8 12 -23645 +23659 12 17 -22797 +22811 17 19 -18969 +18980 19 22 -22791 +22805 22 28 -21470 +21483 28 151 -14545 +14553 @@ -3414,42 +3429,42 @@ 2 26 -21667 +21679 26 31 -24352 +24366 31 32 -1622 +1623 32 33 -163861 +163957 33 54 -22103 +22116 54 63 -20942 +20954 63 82 -21488 +21501 82 133 -3133 +3135 @@ -3465,17 +3480,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3485,37 +3500,37 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 250 -1597 +1598 251 982 -1591 +1592 986 45432 -1929 +1930 @@ -3531,17 +3546,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3551,42 +3566,42 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 246 -1597 +1598 247 964 -1591 +1592 969 32541 -1591 +1592 32546 33841 -337 +338 @@ -3602,47 +3617,47 @@ 1 2 -5899 +5902 2 3 -3416 +3418 3 4 -1609 +1610 4 7 -1886 +1887 7 12 -1837 +1838 12 15 -1640 +1641 15 23 -1591 +1592 23 68 -1609 +1610 68 161 -1591 +1592 161 @@ -3663,17 +3678,17 @@ 2 3 -4559 +4562 4 5 -1339 +1340 6 7 -2593 +2594 8 @@ -3683,42 +3698,42 @@ 11 12 -1609 +1610 13 23 -1855 +1856 24 62 -1622 +1623 64 130 -1646 +1647 141 246 -1597 +1598 247 964 -1591 +1592 969 32541 -1591 +1592 32546 33841 -337 +338 @@ -3734,47 +3749,47 @@ 1 2 -5899 +5902 2 3 -3416 +3418 3 4 -1609 +1610 4 7 -1911 +1912 7 12 -1825 +1826 12 15 -1609 +1610 15 24 -1677 +1678 24 74 -1616 +1617 74 169 -1591 +1592 170 @@ -3795,37 +3810,37 @@ 1 2 -403939 +404176 2 3 -103118 +103179 3 4 -44274 +44300 4 6 -70568 +70610 6 8 -58457 +58491 8 13 -65861 +65900 13 138 -39217 +39240 @@ -3841,52 +3856,52 @@ 1 7 -64810 +64849 7 12 -64350 +64387 12 23 -60079 +60114 23 32 -36740 +36762 32 33 -267244 +267401 33 41 -62672 +62709 41 55 -61271 +61307 55 69 -61541 +61577 69 94 -59243 +59278 94 248 -47482 +47510 @@ -3902,47 +3917,47 @@ 1 5 -64429 +64467 5 9 -62611 +62647 9 15 -63016 +63053 15 29 -59870 +59905 29 32 -9205 +9210 32 33 -349310 +349515 33 37 -61959 +61996 37 42 -61400 +61436 42 122 -53633 +53664 @@ -3958,7 +3973,7 @@ 1 2 -785436 +785898 @@ -3974,47 +3989,47 @@ 1 5 -64294 +64332 5 9 -62611 +62647 9 15 -63133 +63170 15 29 -59735 +59770 29 32 -9254 +9259 32 33 -350355 +350560 33 37 -63588 +63625 37 43 -65241 +65279 43 123 -47224 +47251 @@ -4430,37 +4445,37 @@ 1 2 -403939 +404176 2 3 -103118 +103179 3 4 -44274 +44300 4 6 -70568 +70610 6 8 -58457 +58491 8 13 -65861 +65900 13 138 -39217 +39240 @@ -4476,52 +4491,52 @@ 1 7 -64810 +64849 7 12 -64350 +64387 12 23 -60079 +60114 23 32 -36740 +36762 32 33 -267244 +267401 33 41 -62672 +62709 41 55 -61271 +61307 55 69 -61541 +61577 69 94 -59243 +59278 94 248 -47482 +47510 @@ -4537,7 +4552,7 @@ 1 2 -785436 +785898 @@ -4553,47 +4568,47 @@ 1 5 -64429 +64467 5 9 -62611 +62647 9 15 -63016 +63053 15 29 -59870 +59905 29 32 -9205 +9210 32 33 -349310 +349515 33 37 -61959 +61996 37 42 -61400 +61436 42 122 -53633 +53664 @@ -4609,47 +4624,47 @@ 1 5 -64294 +64332 5 9 -62611 +62647 9 15 -63133 +63170 15 29 -59735 +59770 29 32 -9254 +9259 32 33 -350355 +350560 33 37 -63588 +63625 37 43 -65241 +65279 43 123 -47224 +47251 @@ -5039,23 +5054,23 @@ external_packages -133 +128 id -133 +128 namespace -12 +11 package_name -133 +128 version -133 +128 @@ -5069,7 +5084,7 @@ 1 2 -133 +128 @@ -5085,7 +5100,7 @@ 1 2 -133 +128 @@ -5101,7 +5116,7 @@ 1 2 -133 +128 @@ -5117,7 +5132,7 @@ 11 12 -12 +11 @@ -5133,7 +5148,7 @@ 11 12 -12 +11 @@ -5149,7 +5164,7 @@ 11 12 -12 +11 @@ -5165,7 +5180,7 @@ 1 2 -133 +128 @@ -5181,7 +5196,7 @@ 1 2 -133 +128 @@ -5197,7 +5212,7 @@ 1 2 -133 +128 @@ -5213,7 +5228,7 @@ 1 2 -133 +128 @@ -5229,7 +5244,7 @@ 1 2 -133 +128 @@ -5245,7 +5260,7 @@ 1 2 -133 +128 @@ -5255,15 +5270,15 @@ header_to_external_package -9093 +8740 fileid -9093 +8740 package -133 +128 @@ -5277,7 +5292,7 @@ 1 2 -9093 +8740 @@ -5293,42 +5308,42 @@ 1 2 -36 +35 2 3 -12 +11 15 16 -24 +23 63 64 -12 +11 71 72 -12 +11 85 86 -12 +11 243 244 -12 +11 251 252 -12 +11 @@ -6546,31 +6561,31 @@ locations_default -9664446 +9335283 id -9664446 +9335283 container -78275 +75237 startLine -161084 +154834 startColumn -6017 +5818 endLine -160902 +154658 endColumn -8169 +11182 @@ -6584,7 +6599,7 @@ 1 2 -9664446 +9335283 @@ -6600,7 +6615,7 @@ 1 2 -9664446 +9335283 @@ -6616,7 +6631,7 @@ 1 2 -9664446 +9335283 @@ -6632,7 +6647,7 @@ 1 2 -9664446 +9335283 @@ -6648,7 +6663,7 @@ 1 2 -9664446 +9335283 @@ -6664,62 +6679,62 @@ 1 2 -12752 +12257 2 19 -6625 +6368 19 25 -6090 +5818 25 31 -6066 +5830 31 41 -6491 +6204 41 54 -6138 +5854 54 72 -6175 +5877 72 -99 -5968 +98 +5690 -99 -137 -5944 +98 +136 +5702 -137 -221 -5895 +136 +216 +5690 -221 -431 -5871 +216 +417 +5655 -431 +417 19703 -4254 +4288 @@ -6735,62 +6750,62 @@ 1 2 -12752 +12257 2 15 -6503 +6251 15 20 -6758 +6496 20 25 -6102 +5842 25 32 -6710 +6461 32 41 -6284 +6052 41 53 -6321 +6064 53 70 -5932 +5690 70 96 -5908 +5678 96 152 -5883 +5667 152 -325 -5871 +322 +5643 -325 +324 8863 -3245 +3131 @@ -6806,62 +6821,62 @@ 1 2 -12752 +12257 2 4 -6722 +6461 4 8 -7087 +6812 8 11 -5895 +5632 11 14 -6418 +6099 14 18 -6880 +6601 18 23 -6394 +6134 23 29 -6455 +6227 29 37 -6260 +6029 37 50 -6224 +6052 50 78 -5944 +5737 78 -167 -1239 +168 +1191 @@ -6877,62 +6892,62 @@ 1 2 -12752 +12257 2 15 -6479 +6227 15 20 -6795 +6531 20 25 -6029 +5772 25 32 -6710 +6473 32 41 -6297 +6052 41 53 -6309 +6052 53 70 -6017 +5772 70 96 -5920 +5690 96 153 -5932 +5725 153 332 -5883 +5643 332 8863 -3148 +3038 @@ -6948,62 +6963,62 @@ 1 2 -12752 +12257 2 14 -6236 +5994 14 19 -6710 +6414 19 23 -6224 +5994 23 27 -6005 +5690 27 32 -6187 +5994 32 38 -6005 +5690 38 45 -6138 +5830 45 54 -5920 +5713 54 65 -5993 +5807 65 -79 -5883 +80 +5842 -79 -184 -4218 +80 +336 +4007 @@ -7019,62 +7034,62 @@ 1 2 -31193 +29982 2 3 -19802 +19034 3 4 -18234 +17527 4 5 -10260 +9861 5 6 -9129 +8775 6 7 -6734 +6473 7 9 -14344 +13787 9 13 -13943 +13390 13 30 -12350 +11871 30 112 -12119 +11637 112 -2168 -12083 +2116 +11614 -2193 +2135 6440 -887 +876 @@ -7090,42 +7105,42 @@ 1 2 -57268 +55046 2 3 -35496 +34119 3 4 -11341 +10901 4 5 -8983 +8635 5 8 -14794 +14220 8 26 -12363 +11871 26 115 -12095 +11637 115 6440 -8740 +8401 @@ -7141,57 +7156,57 @@ 1 2 -32287 +31034 2 3 -19693 +18929 3 4 -20544 +19747 4 5 -9737 +9359 5 6 -9384 +9020 6 7 -6856 +6590 7 9 -14612 +14033 9 13 -14028 +13495 13 27 -12436 +11953 27 60 -12132 +11637 60 153 -9372 +9032 @@ -7207,22 +7222,22 @@ 1 2 -119911 +115246 2 3 -18976 +18239 3 7 -13530 +13016 7 184 -8667 +8331 @@ -7238,57 +7253,57 @@ 1 2 -32311 +31057 2 3 -19584 +18824 3 4 -19024 +18286 4 5 -10247 +9850 5 6 -9409 +9043 6 7 -6637 +6379 7 9 -14636 +14068 9 13 -13700 +13168 13 28 -12144 +11673 28 -68 -12119 +69 +11813 -68 -190 -11269 +69 +258 +10668 @@ -7304,57 +7319,57 @@ 1 2 -948 +934 2 3 -1142 +1074 3 5 -534 +537 5 8 -547 +514 8 16 -474 +467 16 -38 -461 +37 +444 -39 -126 -461 +37 +119 +444 -135 -517 -461 +125 +511 +444 -553 -5009 -461 +518 +4987 +444 -5423 -19562 -461 +5021 +19113 +444 -23702 -199709 -60 +19590 +199744 +70 @@ -7370,47 +7385,47 @@ 1 2 -2589 +2500 2 3 -522 +525 3 6 -474 +455 6 15 -486 +467 15 55 -461 +444 59 -223 -461 +226 +444 229 -1196 -461 +1198 +444 -1266 +1275 2344 -461 +444 -2536 +2542 6440 -97 +93 @@ -7426,57 +7441,57 @@ 1 2 -984 +969 2 3 -1130 +1063 3 4 -291 +280 4 6 -498 +502 6 10 -486 +455 10 -21 -474 +20 +444 -21 -60 -461 +20 +55 +444 -60 -208 -461 +56 +195 +444 -209 -929 -461 +196 +829 +444 -957 -1965 -461 +851 +1958 +444 -1969 +1958 6490 -303 +327 @@ -7492,55 +7507,55 @@ 1 2 -984 +969 2 3 -1130 +1063 3 4 -291 +280 4 6 -498 +502 6 10 -486 +455 10 -21 -474 +20 +444 -21 -60 -461 +20 +55 +444 -60 -208 -461 +56 +195 +444 -209 -931 -461 +205 +828 +444 -958 -1966 -461 +851 +1962 +467 -1969 +1965 6462 303 @@ -7558,42 +7573,42 @@ 1 2 -2735 +2640 2 3 -522 +525 3 7 -547 +525 7 13 -474 +455 13 29 -498 +479 29 -51 -474 +54 +455 -51 -90 -461 +54 +109 +444 -91 +110 428 -303 +292 @@ -7609,62 +7624,62 @@ 1 2 -30670 +29480 2 3 -20240 +19455 3 4 -17979 +17281 4 5 -10430 +10025 5 6 -8898 +8553 6 7 -6868 +6601 7 9 -14368 +13811 9 13 -13992 +13437 13 30 -12302 +11824 30 111 -12144 +11649 111 -2100 -12071 +2058 +11602 -2100 +2083 6440 -936 +934 @@ -7680,42 +7695,42 @@ 1 2 -56758 +54555 2 3 -35654 +34271 3 4 -11341 +10901 4 5 -9105 +8751 5 7 -11949 +11474 7 19 -12338 +11859 19 76 -12083 +11614 76 6440 -11670 +11229 @@ -7731,22 +7746,22 @@ 1 2 -118792 +114171 2 3 -19267 +18508 3 7 -12983 +12502 7 46 -9858 +9476 @@ -7762,57 +7777,57 @@ 1 2 -31752 +30520 2 3 -20082 +19303 3 4 -20252 +19466 4 5 -9992 +9604 5 6 -9263 +8903 6 7 -6977 +6707 7 9 -14599 +14021 9 13 -14101 +13565 13 27 -12350 +11871 27 60 -12107 +11626 60 153 -9421 +9067 @@ -7828,57 +7843,57 @@ 1 2 -31801 +30567 2 3 -19973 +19197 3 4 -18745 +18017 4 5 -10490 +10083 5 6 -9263 +8903 6 7 -6710 +6449 7 9 -14526 +13963 9 13 -14174 +13612 13 29 -12350 +11871 29 71 -12132 +11602 71 -190 -10734 +258 +10387 @@ -7894,52 +7909,47 @@ 1 2 -2309 +4428 2 3 -1094 +1180 3 4 -607 +888 4 -7 -753 - - -7 -17 -656 +6 +1004 -17 -49 -619 +6 +13 +841 -55 -236 -619 +13 +61 +841 -241 -4440 -619 +61 +698 +841 -4617 -11969 -619 +705 +10765 +841 -12066 -25444 -267 +11014 +25447 +315 @@ -7955,47 +7965,42 @@ 1 2 -3257 +5106 2 3 -1033 +1285 3 4 -583 +1028 4 -9 -644 - - -9 -29 -619 +7 +969 -29 -166 -619 +7 +33 +841 -172 -1667 -619 +33 +376 +841 -1667 -2846 -619 +387 +2684 +841 -2870 +2688 6440 -170 +268 @@ -8011,52 +8016,47 @@ 1 2 -2334 +4463 2 3 -1106 +1180 3 4 -632 +899 4 -7 -741 - - -7 -17 -632 +6 +1004 -17 -45 -619 +6 +14 +852 -45 -189 -619 +14 +57 +852 -192 -1191 -619 +58 +510 +841 -1218 -2414 -619 +518 +2401 +841 -2469 +2415 4808 -243 +245 @@ -8072,42 +8072,42 @@ 1 2 -3367 +5141 2 3 -1130 +1343 3 4 -595 +1028 4 -11 -668 +7 +969 -11 +7 23 -632 +852 23 -40 -632 +47 +864 -40 -68 -632 +47 +81 +864 -68 -82 -510 +81 +83 +116 @@ -8123,52 +8123,47 @@ 1 2 -2334 +4463 2 3 -1106 +1180 3 4 -632 +911 4 -7 -741 - - -7 -17 -644 +6 +993 -17 -46 -619 +6 +13 +841 -46 -194 -619 +13 +56 +841 -202 -1220 -619 +56 +501 +841 -1252 -2470 -619 +505 +2374 +841 -2481 +2398 4808 -230 +268 @@ -8178,31 +8173,31 @@ locations_stmt -2176932 +2178211 id -2176932 +2178211 container -3078 +3080 startLine -296727 +296902 startColumn -1228 +1229 endLine -294872 +295045 endColumn -1493 +1494 @@ -8216,7 +8211,7 @@ 1 2 -2176932 +2178211 @@ -8232,7 +8227,7 @@ 1 2 -2176932 +2178211 @@ -8248,7 +8243,7 @@ 1 2 -2176932 +2178211 @@ -8264,7 +8259,7 @@ 1 2 -2176932 +2178211 @@ -8280,7 +8275,7 @@ 1 2 -2176932 +2178211 @@ -8493,7 +8488,7 @@ 38 48 -251 +252 48 @@ -8534,7 +8529,7 @@ 6 15 -251 +252 15 @@ -8681,37 +8676,37 @@ 1 2 -113847 +113914 2 3 -78993 +79039 3 4 -31327 +31345 4 6 -24942 +24957 6 16 -22619 +22632 16 129 -22275 +22288 129 222 -2722 +2723 @@ -8727,32 +8722,32 @@ 1 2 -175967 +176070 2 3 -51906 +51936 3 5 -22552 +22565 5 13 -22373 +22386 13 125 -22257 +22270 125 176 -1671 +1672 @@ -8768,32 +8763,32 @@ 1 2 -130943 +131019 2 3 -73506 +73549 3 4 -30767 +30785 4 7 -26583 +26598 7 16 -22312 +22325 16 45 -12615 +12623 @@ -8809,27 +8804,27 @@ 1 2 -192251 +192364 2 3 -47310 +47337 3 4 -21765 +21778 4 9 -23264 +23278 9 30 -12136 +12143 @@ -8845,32 +8840,32 @@ 1 2 -156444 +156536 2 3 -62371 +62408 3 4 -20782 +20794 4 9 -24659 +24674 9 30 -22398 +22411 30 73 -10071 +10077 @@ -9266,37 +9261,37 @@ 1 2 -116305 +116374 2 3 -72848 +72891 3 4 -31996 +32015 4 6 -25618 +25633 6 16 -23031 +23044 16 126 -22121 +22134 126 228 -2949 +2951 @@ -9312,27 +9307,27 @@ 1 2 -175604 +175707 2 3 -52066 +52096 3 5 -22207 +22220 5 14 -23375 +23389 14 173 -21617 +21630 @@ -9348,27 +9343,27 @@ 1 2 -194592 +194706 2 3 -42314 +42339 3 4 -20677 +20689 4 8 -22760 +22774 8 32 -14526 +14535 @@ -9384,32 +9379,32 @@ 1 2 -133173 +133251 2 3 -67871 +67910 3 4 -32611 +32630 4 7 -26503 +26518 7 16 -22183 +22196 16 46 -12529 +12536 @@ -9425,32 +9420,32 @@ 1 2 -156272 +156364 2 3 -62230 +62266 3 4 -21132 +21144 4 9 -23756 +23770 9 33 -22318 +22331 33 73 -9162 +9167 @@ -9830,15 +9825,15 @@ locations_expr -9745314 +9746017 id -9745314 +9746017 container -3559 +3563 startLine @@ -9868,7 +9863,7 @@ 1 2 -9745314 +9746017 @@ -9884,7 +9879,7 @@ 1 2 -9745314 +9746017 @@ -9900,7 +9895,7 @@ 1 2 -9745314 +9746017 @@ -9916,7 +9911,7 @@ 1 2 -9745314 +9746017 @@ -9932,7 +9927,7 @@ 1 2 -9745314 +9746017 @@ -9953,67 +9948,67 @@ 4 11 -280 +284 11 -36 -267 +37 +272 -36 -112 -270 +37 +114 +269 -112 -207 -268 +114 +210 +269 -207 -326 +210 +328 268 -326 -493 -267 +328 +498 +268 -493 -760 -267 +499 +771 +269 -760 -1208 -267 +772 +1223 +268 -1210 -1899 -267 +1223 +1918 +268 -1900 -3251 -267 +1918 +3307 +268 -3258 -7330 -267 +3322 +7569 +268 -7359 -51115 -267 +7607 +160039 +268 -51126 +170837 491727 -16 +3 @@ -10029,17 +10024,17 @@ 1 3 -300 +296 3 7 -315 +319 7 17 -271 +272 17 @@ -10049,47 +10044,47 @@ 35 59 -279 +278 59 88 -270 +271 88 138 -268 +271 138 -206 -267 +207 +271 -206 -336 +207 +339 268 -336 -525 +339 +532 268 -525 -946 -267 +532 +949 +268 -947 -2013 -267 +951 +2069 +268 -2019 +2076 142752 -248 +242 @@ -10105,67 +10100,67 @@ 1 3 -308 +307 3 7 -293 +296 7 17 -273 +274 17 -35 -267 +36 +283 -35 -51 -278 +36 +52 +287 -51 -63 -289 +52 +64 +297 -63 -73 -290 +64 +74 +279 -73 -83 -282 +74 +84 +296 -83 -92 -276 +84 +93 +270 -92 -104 -270 +93 +106 +282 -104 -120 -276 +106 +122 +271 -120 -145 -270 +122 +150 +268 -145 +150 330 -187 +153 @@ -10181,17 +10176,17 @@ 1 3 -300 +296 3 7 -312 +316 7 17 -274 +275 17 @@ -10201,17 +10196,17 @@ 35 59 -278 +277 59 89 -275 +277 89 139 -271 +273 139 @@ -10230,18 +10225,18 @@ 547 -971 -267 +973 +269 -972 -2152 -267 +975 +2167 +268 -2152 +2170 143560 -242 +239 @@ -10257,7 +10252,7 @@ 1 3 -278 +279 3 @@ -10267,57 +10262,57 @@ 7 19 -278 +281 19 -41 -268 +42 +275 -41 +42 60 -279 +272 60 -72 -267 +73 +294 -72 -83 -280 +73 +84 +277 -83 -94 -283 +84 +95 +291 -94 -105 -292 +95 +106 +279 -105 -119 -278 +106 +120 +282 -119 -136 -279 +120 +138 +275 -136 -162 -269 +138 +166 +270 -162 +166 416 -210 +190 @@ -10667,22 +10662,22 @@ 16130 -46279 +46280 29 -48722 -86671 +48729 +86681 29 -87010 -224371 +87033 +224378 29 -237409 -710014 +237411 +710028 6 @@ -10743,17 +10738,17 @@ 1424 -2061 +2063 29 -2064 -2425 +2066 +2429 29 -2427 -2796 +2429 +2797 22 @@ -11336,18 +11331,18 @@ 35 -20304 -51564 +20305 +51570 35 -54934 +54937 117747 35 -117846 -185890 +117863 +185908 35 @@ -11408,12 +11403,12 @@ 1983 -2458 +2459 35 -2468 -2637 +2470 +2640 32 @@ -11469,7 +11464,7 @@ 2070 -5989 +5990 35 @@ -11616,7 +11611,7 @@ 2067 -5989 +5990 35 @@ -11647,23 +11642,23 @@ numlines -544741 +523603 element_id -537168 +516324 num_lines -10272 +9873 num_code -7938 +7630 num_comment -4364 +4194 @@ -11677,12 +11672,12 @@ 1 2 -529679 +509126 2 7 -7488 +7197 @@ -11698,12 +11693,12 @@ 1 2 -529740 +509184 2 7 -7427 +7139 @@ -11719,12 +11714,12 @@ 1 2 -537083 +516242 2 3 -85 +81 @@ -11740,42 +11735,42 @@ 1 2 -4655 +4475 2 3 -1325 +1273 3 4 -765 +736 4 6 -838 +806 6 12 -814 +782 12 24 -778 +747 24 118 -778 +747 118 7658 -316 +303 @@ -11791,42 +11786,42 @@ 1 2 -4728 +4545 2 3 -1337 +1285 3 4 -802 +771 4 6 -850 +817 6 11 -923 +888 11 18 -790 +759 18 29 -790 +759 29 32 -48 +46 @@ -11842,42 +11837,42 @@ 1 2 -4716 +4533 2 3 -1337 +1285 3 4 -826 +794 4 6 -838 +806 6 10 -802 +771 10 16 -899 +864 16 26 -814 +782 26 27 -36 +35 @@ -11893,42 +11888,42 @@ 1 2 -3184 +3061 2 3 -1239 +1191 3 4 -632 +607 4 6 -607 +584 6 10 -619 +595 10 21 -619 +595 21 67 -595 +572 68 7861 -437 +420 @@ -11944,42 +11939,42 @@ 1 2 -3209 +3084 2 3 -1264 +1215 3 4 -644 +619 4 6 -607 +584 6 10 -692 +666 10 21 -644 +619 21 34 -607 +584 34 42 -267 +257 @@ -11995,42 +11990,42 @@ 1 2 -3233 +3108 2 3 -1227 +1180 3 4 -680 +654 4 6 -619 +595 6 10 -680 +654 10 19 -668 +642 19 28 -595 +572 28 33 -230 +222 @@ -12046,42 +12041,42 @@ 1 2 -2030 +1951 2 3 -559 +537 3 4 -328 +315 4 7 -340 +327 7 14 -340 +327 14 38 -328 +315 39 280 -328 +315 283 35679 -109 +105 @@ -12097,37 +12092,37 @@ 1 2 -2042 +1963 2 3 -571 +549 3 5 -389 +373 5 8 -364 +350 8 18 -364 +350 18 58 -328 +315 61 118 -303 +292 @@ -12143,37 +12138,37 @@ 1 2 -2042 +1963 2 3 -571 +549 3 5 -389 +373 5 8 -364 +350 8 17 -340 +327 17 52 -328 +315 56 108 -328 +315 @@ -12183,31 +12178,31 @@ diagnostics -76160 +73204 id -76160 +73204 severity -36 +35 error_tag -97 +93 error_message -121 +116 full_error_message -65948 +63389 location -145 +140 @@ -12221,7 +12216,7 @@ 1 2 -76160 +73204 @@ -12237,7 +12232,7 @@ 1 2 -76160 +73204 @@ -12253,7 +12248,7 @@ 1 2 -76160 +73204 @@ -12269,7 +12264,7 @@ 1 2 -76160 +73204 @@ -12285,7 +12280,7 @@ 1 2 -76160 +73204 @@ -12301,17 +12296,17 @@ 1 2 -12 +11 2 3 -12 +11 6262 6263 -12 +11 @@ -12327,12 +12322,12 @@ 1 2 -24 +23 6 7 -12 +11 @@ -12348,12 +12343,12 @@ 1 2 -24 +23 8 9 -12 +11 @@ -12369,17 +12364,17 @@ 1 2 -12 +11 2 3 -12 +11 5422 5423 -12 +11 @@ -12395,17 +12390,17 @@ 1 2 -12 +11 2 3 -12 +11 9 10 -12 +11 @@ -12421,32 +12416,32 @@ 1 2 -24 +23 2 3 -24 +23 5 6 -12 +11 417 418 -12 +11 841 842 -12 +11 4996 4997 -12 +11 @@ -12462,7 +12457,7 @@ 1 2 -97 +93 @@ -12478,12 +12473,12 @@ 1 2 -85 +81 3 4 -12 +11 @@ -12499,27 +12494,27 @@ 1 2 -36 +35 2 3 -24 +23 5 6 -12 +11 417 418 -12 +11 4996 4997 -12 +11 @@ -12535,17 +12530,17 @@ 1 2 -60 +58 2 3 -24 +23 5 6 -12 +11 @@ -12561,42 +12556,42 @@ 1 2 -24 +23 2 3 -24 +23 5 6 -12 +11 10 11 -12 +11 75 76 -12 +11 332 333 -12 +11 841 842 -12 +11 4996 4997 -12 +11 @@ -12612,7 +12607,7 @@ 1 2 -121 +116 @@ -12628,7 +12623,7 @@ 1 2 -121 +116 @@ -12644,37 +12639,37 @@ 1 2 -36 +35 2 3 -24 +23 5 6 -12 +11 10 11 -12 +11 75 76 -12 +11 332 333 -12 +11 4996 4997 -12 +11 @@ -12690,17 +12685,17 @@ 1 2 -85 +81 2 3 -24 +23 5 6 -12 +11 @@ -12716,12 +12711,12 @@ 1 2 -65936 +63377 841 842 -12 +11 @@ -12737,7 +12732,7 @@ 1 2 -65948 +63389 @@ -12753,7 +12748,7 @@ 1 2 -65948 +63389 @@ -12769,7 +12764,7 @@ 1 2 -65948 +63389 @@ -12785,7 +12780,7 @@ 1 2 -65948 +63389 @@ -12801,12 +12796,12 @@ 1 2 -133 +128 6254 6255 -12 +11 @@ -12822,7 +12817,7 @@ 1 2 -145 +140 @@ -12838,12 +12833,12 @@ 1 2 -133 +128 3 4 -12 +11 @@ -12859,12 +12854,12 @@ 1 2 -133 +128 5 6 -12 +11 @@ -12880,12 +12875,12 @@ 1 2 -133 +128 5414 5415 -12 +11 @@ -12895,27 +12890,27 @@ files -66167 +63599 id -66167 +63599 name -66167 +63599 simple -45148 +43397 ext -109 +105 fromSource -12 +11 @@ -12929,7 +12924,7 @@ 1 2 -66167 +63599 @@ -12945,7 +12940,7 @@ 1 2 -66167 +63599 @@ -12961,7 +12956,7 @@ 1 2 -66167 +63599 @@ -12977,7 +12972,7 @@ 1 2 -66167 +63599 @@ -12993,7 +12988,7 @@ 1 2 -66167 +63599 @@ -13009,7 +13004,7 @@ 1 2 -66167 +63599 @@ -13025,7 +13020,7 @@ 1 2 -66167 +63599 @@ -13041,7 +13036,7 @@ 1 2 -66167 +63599 @@ -13057,22 +13052,22 @@ 1 2 -34196 +32869 2 3 -6868 +6601 3 7 -3586 +3446 7 42 -498 +479 @@ -13088,22 +13083,22 @@ 1 2 -34196 +32869 2 3 -6868 +6601 3 7 -3586 +3446 7 42 -498 +479 @@ -13119,17 +13114,17 @@ 1 2 -40322 +38758 2 3 -4193 +4031 3 6 -632 +607 @@ -13145,7 +13140,7 @@ 1 2 -45148 +43397 @@ -13161,47 +13156,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 80 81 -12 +11 114 115 -12 +11 441 442 -12 +11 738 739 -12 +11 4013 4014 -12 +11 @@ -13217,47 +13212,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 80 81 -12 +11 114 115 -12 +11 441 442 -12 +11 738 739 -12 +11 4013 4014 -12 +11 @@ -13273,47 +13268,47 @@ 1 2 -12 +11 3 4 -12 +11 15 16 -12 +11 38 39 -12 +11 75 76 -12 +11 112 113 -12 +11 428 429 -12 +11 658 659 -12 +11 2838 2839 -12 +11 @@ -13329,7 +13324,7 @@ 1 2 -109 +105 @@ -13345,7 +13340,7 @@ 5443 5444 -12 +11 @@ -13361,7 +13356,7 @@ 5443 5444 -12 +11 @@ -13377,7 +13372,7 @@ 3714 3715 -12 +11 @@ -13393,7 +13388,7 @@ 9 10 -12 +11 @@ -13403,19 +13398,19 @@ folders -12107 +11637 id -12107 +11637 name -12107 +11637 simple -3476 +3341 @@ -13429,7 +13424,7 @@ 1 2 -12107 +11637 @@ -13445,7 +13440,7 @@ 1 2 -12107 +11637 @@ -13461,7 +13456,7 @@ 1 2 -12107 +11637 @@ -13477,7 +13472,7 @@ 1 2 -12107 +11637 @@ -13493,27 +13488,27 @@ 1 2 -1872 +1799 2 3 -741 +712 3 4 -498 +479 4 28 -279 +268 28 121 -85 +81 @@ -13529,27 +13524,27 @@ 1 2 -1872 +1799 2 3 -741 +712 3 4 -498 +479 4 28 -279 +268 28 121 -85 +81 @@ -13559,15 +13554,15 @@ containerparent -78250 +75214 parent -12107 +11637 child -78250 +75214 @@ -13581,42 +13576,42 @@ 1 2 -5506 +5293 2 3 -1568 +1507 3 4 -668 +642 4 6 -1118 +1074 6 10 -899 +864 10 14 -960 +923 14 30 -923 +888 30 153 -461 +444 @@ -13632,7 +13627,7 @@ 1 2 -78250 +75214 @@ -13642,23 +13637,23 @@ fileannotations -5688625 +5467887 id -5348 +5141 kind -24 +23 name -60186 +57851 value -49318 +47404 @@ -13672,12 +13667,12 @@ 1 2 -145 +140 2 3 -5202 +5001 @@ -13693,62 +13688,62 @@ 1 96 -401 +385 96 219 -401 +385 221 285 -401 +385 285 444 -401 +385 445 521 -401 +385 526 619 -425 +408 619 708 -401 +385 708 895 -401 +385 896 928 -97 +93 930 931 -1531 +1472 1076 1667 -401 +385 1689 2272 -85 +81 @@ -13764,57 +13759,57 @@ 1 108 -401 +385 108 269 -401 +385 269 356 -401 +385 371 630 -401 +385 630 729 -401 +385 733 948 -401 +385 948 1062 -401 +385 1079 1494 -279 +268 1495 1496 -1531 +1472 1496 1865 -401 +385 1963 4058 -328 +315 @@ -13830,12 +13825,12 @@ 428 429 -12 +11 440 441 -12 +11 @@ -13851,12 +13846,12 @@ 2 3 -12 +11 4949 4950 -12 +11 @@ -13872,12 +13867,12 @@ 1 2 -12 +11 4057 4058 -12 +11 @@ -13893,62 +13888,62 @@ 1 2 -9871 +9487 2 3 -6491 +6239 3 6 -4996 +4802 6 8 -4935 +4743 8 14 -4850 +4662 14 18 -4424 +4253 18 21 -4619 +4440 21 34 -4862 +4673 34 128 -4813 +4627 129 236 -4595 +4416 236 395 -4558 +4381 395 440 -1167 +1121 @@ -13964,7 +13959,7 @@ 1 2 -60186 +57851 @@ -13980,62 +13975,62 @@ 1 2 -11038 +10609 2 3 -8728 +8389 3 4 -2808 +2699 4 6 -4352 +4183 6 10 -5470 +5258 10 14 -3586 +3446 14 17 -4643 +4463 17 22 -4643 +4463 22 40 -4558 +4381 40 83 -4582 +4405 83 163 -4534 +4358 164 1933 -1239 +1191 @@ -14051,67 +14046,67 @@ 1 2 -7524 +7232 2 5 -2419 +2325 5 8 -3573 +3435 8 21 -3804 +3657 21 23 -2735 +2629 23 25 -4461 +4288 25 40 -3586 +3446 40 195 -3890 +3739 195 207 -3902 +3750 207 273 -4048 +3891 273 327 -3744 +3598 328 407 -4315 +4148 407 441 -1312 +1261 @@ -14127,12 +14122,12 @@ 1 2 -49306 +47393 2 3 -12 +11 @@ -14148,67 +14143,67 @@ 1 2 -7549 +7256 2 5 -2795 +2687 5 8 -3610 +3470 8 16 -4060 +3902 16 18 -3343 +3213 18 21 -4072 +3914 21 31 -4461 +4288 31 42 -4023 +3867 42 54 -3768 +3622 54 81 -3780 +3633 81 109 -3829 +3680 109 133 -3756 +3610 133 149 -267 +257 @@ -14218,15 +14213,15 @@ inmacroexpansion -57126596 +57160160 id -15544516 +15553649 inv -2493763 +2495229 @@ -14240,42 +14235,42 @@ 1 2 -3895411 +3897700 2 3 -2466113 +2467562 3 4 -2018102 +2019287 4 5 -1769908 +1770948 5 6 -1845270 +1846354 6 7 -884925 +885445 7 8 -1535759 +1536661 8 6265 -1129025 +1129688 @@ -14291,52 +14286,52 @@ 1 2 -651228 +651611 2 3 -350884 +351091 3 4 -145822 +145908 4 5 -276335 +276498 5 8 -230677 +230812 8 11 -202111 +202230 11 19 -210471 +210594 19 34 -192538 +192651 34 167 -188020 +188130 167 153127 -45673 +45699 @@ -14346,15 +14341,15 @@ affectedbymacroexpansion -35527526 +35548400 id -4083475 +4085874 inv -3282712 +3284641 @@ -14368,42 +14363,42 @@ 1 2 -1341531 +1342319 2 3 -719304 +719727 3 4 -682963 +683364 4 6 -320945 +321133 6 10 -313534 +313718 10 24 -308059 +308240 24 64 -309945 +310127 64 9803 -87190 +87242 @@ -14419,72 +14414,72 @@ 1 2 -253184 +253333 2 3 -209979 +210102 3 4 -202347 +202466 4 5 -258125 +258276 5 6 -301422 +301599 6 7 -247881 +248027 7 8 -231148 +231284 8 9 -228002 +228136 9 10 -182499 +182606 10 12 -285679 +285847 12 16 -297410 +297584 16 23 -275398 +275560 23 60 -248963 +249109 60 526 -60669 +60704 @@ -14494,23 +14489,23 @@ macroinvocations -40814994 +39320374 id -40814994 +39320374 macro_id -89374 +85906 location -836970 +804492 kind -24 +23 @@ -14524,7 +14519,7 @@ 1 2 -40814994 +39320374 @@ -14540,7 +14535,7 @@ 1 2 -40814994 +39320374 @@ -14556,7 +14551,7 @@ 1 2 -40814994 +39320374 @@ -14572,52 +14567,52 @@ 1 2 -19267 +18286 2 3 -16946 +16475 3 4 -3744 +3598 4 6 -7925 +7630 6 11 -7658 +7326 11 21 -7160 +6823 21 41 -6758 +6555 41 -104 -6710 +107 +6485 -104 -454 -6710 +107 +450 +6449 -454 -201153 -6491 +453 +201240 +6274 @@ -14633,37 +14628,37 @@ 1 2 -47483 +45640 2 3 -11803 +11345 3 4 -5895 +5667 4 6 -7682 +7384 6 13 -7403 +7115 13 65 -6734 +6473 65 3614 -2370 +2278 @@ -14679,12 +14674,12 @@ 1 2 -82566 +79362 2 3 -6807 +6543 @@ -14700,42 +14695,42 @@ 1 2 -314219 +299713 2 3 -186394 +180341 3 4 -44431 +42999 4 5 -58533 +56378 5 8 -67687 +65247 8 16 -64113 +61777 16 46 -64830 +62536 46 -262302 -36761 +262546 +35498 @@ -14751,12 +14746,12 @@ 1 2 -783044 +752659 2 353 -53925 +51833 @@ -14772,7 +14767,7 @@ 1 2 -836970 +804492 @@ -14788,12 +14783,12 @@ 37566 37567 -12 +11 -3319916 -3319917 -12 +3327545 +3327546 +11 @@ -14809,12 +14804,12 @@ 2199 2200 -12 +11 5713 5714 -12 +11 @@ -14830,12 +14825,12 @@ 6537 6538 -12 +11 62313 62314 -12 +11 @@ -14845,15 +14840,15 @@ macroparent -35822215 +34476404 id -35822215 +34476404 parent_id -27895299 +26856682 @@ -14867,7 +14862,7 @@ 1 2 -35822215 +34476404 @@ -14883,17 +14878,17 @@ 1 2 -21477676 +20687700 2 3 -5474478 +5262423 3 88 -943144 +906558 @@ -14903,15 +14898,15 @@ macrolocationbind -4016679 +4019039 id -2801506 +2803152 location -2004363 +2005541 @@ -14925,22 +14920,22 @@ 1 2 -2200726 +2202019 2 3 -339324 +339524 3 7 -231800 +231936 7 57 -29655 +29673 @@ -14956,22 +14951,22 @@ 1 2 -1602305 +1603246 2 3 -171008 +171108 3 8 -155504 +155595 8 723 -75546 +75590 @@ -14981,19 +14976,19 @@ macro_argument_unexpanded -104803767 +100941827 invocation -31131960 +30008413 argument_index -802 +771 text -345935 +332512 @@ -15007,22 +15002,22 @@ 1 2 -8804221 +8477672 2 3 -12965574 +12498009 3 4 -7092535 +6840222 4 67 -2269629 +2192508 @@ -15038,22 +15033,22 @@ 1 2 -8880284 +8550795 2 3 -13152746 +12678071 3 4 -6885304 +6640869 4 67 -2213625 +2138677 @@ -15069,17 +15064,17 @@ 51815 51816 -705 +677 52017 -186703 -60 +187640 +58 -770141 -2560947 -36 +773038 +2568177 +35 @@ -15095,17 +15090,17 @@ 2 3 -705 +677 13 1002 -60 +58 6617 19688 -36 +35 @@ -15121,62 +15116,62 @@ 1 2 -42535 +39868 2 3 -69291 +64826 3 4 -15621 +15435 4 5 -46376 +44296 5 8 -26513 +26980 8 12 -15560 +15447 12 16 -24531 +23275 16 22 -26403 +25414 22 -42 -26257 +41 +25075 -42 -113 -25978 +41 +101 +24970 -113 -51881 -25953 +101 +4363 +24958 -51881 -580841 -911 +4608 +581891 +1963 @@ -15192,17 +15187,17 @@ 1 2 -250082 +240378 2 3 -84450 +81173 3 9 -11402 +10960 @@ -15212,19 +15207,19 @@ macro_argument_expanded -104803767 +100941827 invocation -31131960 +30008413 argument_index -802 +771 text -209491 +201362 @@ -15238,22 +15233,22 @@ 1 2 -8804221 +8477672 2 3 -12965574 +12498009 3 4 -7092535 +6840222 4 67 -2269629 +2192508 @@ -15269,22 +15264,22 @@ 1 2 -12795323 +12315365 2 3 -11169279 +10770085 3 4 -5961987 +5753415 4 9 -1205370 +1169546 @@ -15300,17 +15295,17 @@ 51815 51816 -705 +677 52017 -186703 -60 +187640 +58 -770141 -2560947 -36 +773038 +2568177 +35 @@ -15326,17 +15321,17 @@ 1 2 -692 +666 2 75 -60 +58 867 13964 -48 +46 @@ -15352,62 +15347,57 @@ 1 2 -25820 +23871 2 3 -42583 +40791 3 4 -6758 +6636 4 -5 -15791 - - -5 6 -3367 +18450 6 7 -24555 +23743 7 9 -16702 +16475 9 15 -19146 +17597 15 31 -15851 +15984 31 -87 -15912 +86 +15108 -87 -393 -15742 +86 +365 +15225 -396 -1164221 -7257 +365 +1165688 +7478 @@ -15423,22 +15413,22 @@ 1 2 -105651 +101551 2 3 -87976 +84562 3 6 -15779 +15166 6 66 -85 +81 @@ -15448,19 +15438,19 @@ functions -3565918 +3552236 id -3565918 +3552236 name -315848 +303954 kind -85 +81 @@ -15474,7 +15464,7 @@ 1 2 -3565918 +3552236 @@ -15490,7 +15480,7 @@ 1 2 -3565918 +3552236 @@ -15506,27 +15496,27 @@ 1 2 -214682 +206387 2 3 -31266 +29924 3 5 -28360 +27435 5 13 -23826 +23100 13 -109484 -17711 +118759 +17106 @@ -15542,12 +15532,12 @@ 1 2 -314231 +302400 2 3 -1616 +1554 @@ -15563,37 +15553,37 @@ 32 33 -12 +11 -477 -478 -12 +478 +479 +11 2735 2736 -12 +11 -5928 -5929 -12 +6052 +6053 +11 -43779 -43780 -12 +43879 +43880 +11 -108979 -108980 -12 +109948 +109949 +11 -131406 -131407 -12 +140883 +140884 +11 @@ -15609,37 +15599,37 @@ 11 12 -12 +11 42 43 -12 +11 -228 -229 -12 +229 +230 +11 -1485 -1486 -12 +1494 +1495 +11 2735 2736 -12 +11 -2858 -2859 -12 +2879 +2880 +11 18756 18757 -12 +11 @@ -15649,15 +15639,15 @@ function_entry_point -1068501 +1030977 id -1065255 +1027857 entry_point -1068501 +1030977 @@ -15671,12 +15661,12 @@ 1 2 -1062313 +1025030 2 9 -2941 +2827 @@ -15692,7 +15682,7 @@ 1 2 -1068501 +1030977 @@ -15702,15 +15692,15 @@ function_return_type -3577065 +3562951 id -3565347 +3551686 return_type -1033588 +1048715 @@ -15724,12 +15714,12 @@ 1 2 -3554126 +3540901 2 6 -11220 +10784 @@ -15745,17 +15735,17 @@ 1 2 -319945 +309177 2 3 -649566 +677865 3 -81742 -64076 +82133 +61671 @@ -15765,60 +15755,60 @@ purefunctions -21018 +20805 id -21018 +20805 function_deleted -51251 +49379 id -51251 +49379 function_defaulted -9554 +9184 id -9554 +9184 fun_decls -3668324 +3646017 id -3657006 +3635139 function -3484737 +3469555 type_id -1026294 +1041634 name -281968 +271389 location -875943 +843835 @@ -15832,7 +15822,7 @@ 1 2 -3657006 +3635139 @@ -15848,12 +15838,12 @@ 1 2 -3646053 +3624611 2 6 -10952 +10527 @@ -15869,7 +15859,7 @@ 1 2 -3657006 +3635139 @@ -15885,7 +15875,7 @@ 1 2 -3657006 +3635139 @@ -15901,12 +15891,12 @@ 1 2 -3343699 +3333988 2 9 -141038 +135566 @@ -15922,12 +15912,12 @@ 1 2 -3466345 +3451876 2 6 -18392 +17678 @@ -15943,7 +15933,7 @@ 1 2 -3484737 +3469555 @@ -15959,12 +15949,12 @@ 1 2 -3389832 +3378332 2 9 -94905 +91222 @@ -15980,17 +15970,17 @@ 1 2 -305953 +295716 2 3 -648059 +676381 3 -87017 -72282 +87408 +69535 @@ -16006,17 +15996,17 @@ 1 2 -318972 +308231 2 3 -644096 +672572 3 -80918 -63225 +81309 +60830 @@ -16032,12 +16022,12 @@ 1 2 -956638 +974669 2 -7429 -69656 +7459 +66965 @@ -16053,17 +16043,17 @@ 1 2 -921129 +940538 2 5 -81642 +78474 5 -22296 -23522 +22349 +22621 @@ -16079,32 +16069,32 @@ 1 2 -169351 +162826 2 3 -32554 +31420 3 4 -18866 +17994 4 7 -25650 +24841 7 19 -21261 +20518 19 -109747 -14283 +119022 +13787 @@ -16120,32 +16110,32 @@ 1 2 -181155 +174172 2 3 -31412 +30099 3 4 -16654 +16171 4 7 -22623 +21862 7 -26 -21383 +25 +20366 -26 -109468 -8740 +25 +118743 +8716 @@ -16161,17 +16151,17 @@ 1 2 -246046 +236860 2 5 -23170 +22271 5 -56245 -12752 +60936 +12257 @@ -16187,27 +16177,27 @@ 1 2 -180486 +173599 2 3 -47823 +46213 3 4 -18040 +17340 4 8 -22696 +21815 8 -8793 -12922 +8910 +12420 @@ -16223,27 +16213,27 @@ 1 2 -589769 +567012 2 3 -147895 +142319 3 5 -69790 +67350 5 -179 -65766 +141 +63307 -179 -3027 -2723 +142 +3039 +3844 @@ -16259,22 +16249,22 @@ 1 2 -602727 +579468 2 3 -164743 +158514 3 9 -69753 +67747 9 -3027 -38718 +3039 +38103 @@ -16290,17 +16280,17 @@ 1 2 -773854 +744445 2 4 -68209 +65890 4 -1514 -33879 +1520 +33500 @@ -16316,12 +16306,12 @@ 1 2 -848299 +817018 2 134 -27643 +26816 @@ -16331,22 +16321,22 @@ fun_def -1296860 +1250592 id -1296860 +1250592 fun_specialized -6505 +6439 id -6505 +6439 @@ -16364,11 +16354,11 @@ fun_decl_specifiers -512313 +512614 id -274687 +274848 name @@ -16386,17 +16376,17 @@ 1 2 -72048 +72090 2 3 -167651 +167750 3 4 -34987 +35007 @@ -16583,26 +16573,26 @@ fun_decl_empty_throws -1416734 +1471304 fun_decl -1416734 +1471304 fun_decl_noexcept -16569 +15937 fun_decl -15693 +15096 constant -16435 +15809 @@ -16616,12 +16606,12 @@ 1 2 -14818 +14255 2 3 -875 +841 @@ -16637,12 +16627,12 @@ 1 2 -16301 +15680 2 3 -133 +128 @@ -16652,26 +16642,26 @@ fun_decl_empty_noexcept -364559 +350681 fun_decl -364559 +350681 fun_decl_typedef_type -194 +186 fun_decl -194 +186 typedeftype_id -97 +93 @@ -16685,7 +16675,7 @@ 1 2 -194 +186 @@ -16701,7 +16691,7 @@ 2 3 -97 +93 @@ -16711,19 +16701,19 @@ param_decl_bind -4830661 +4766932 id -4830661 +4766932 index -389 +373 fun_decl -3158896 +3153051 @@ -16737,7 +16727,7 @@ 1 2 -4830661 +4766932 @@ -16753,7 +16743,7 @@ 1 2 -4830661 +4766932 @@ -16769,57 +16759,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 885 1215 -24 +23 1695 2656 -24 +23 4907 -13240 -24 +13252 +23 -34828 -76062 -24 +34902 +76574 +23 -259854 -259855 -12 +269844 +269845 +11 @@ -16835,57 +16825,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 885 1215 -24 +23 1695 2656 -24 +23 4907 -13240 -24 +13252 +23 -34828 -76062 -24 +34902 +76574 +23 -259854 -259855 -12 +269844 +269845 +11 @@ -16901,22 +16891,22 @@ 1 2 -2234266 +2258317 2 3 -501246 +486913 3 4 -262445 +252985 4 33 -160938 +154834 @@ -16932,22 +16922,22 @@ 1 2 -2234266 +2258317 2 3 -501246 +486913 3 4 -262445 +252985 4 33 -160938 +154834 @@ -16957,27 +16947,27 @@ var_decls -5602108 +5518014 id -5579181 +5495954 variable -5340611 +5266618 type_id -2038268 +2068405 name -139592 +134175 location -1358468 +1305755 @@ -16991,7 +16981,7 @@ 1 2 -5579181 +5495954 @@ -17007,12 +16997,12 @@ 1 2 -5556716 +5474337 2 7 -22465 +21616 @@ -17028,7 +17018,7 @@ 1 2 -5579181 +5495954 @@ -17044,12 +17034,12 @@ 1 2 -5579132 +5495907 2 3 -48 +46 @@ -17065,12 +17055,12 @@ 1 2 -5146145 +5079674 2 9 -194466 +186943 @@ -17086,12 +17076,12 @@ 1 2 -5290709 +5218605 2 7 -49902 +48012 @@ -17107,12 +17097,12 @@ 1 2 -5321866 +5248600 2 3 -18745 +18017 @@ -17128,12 +17118,12 @@ 1 2 -5225490 +5155963 2 9 -115121 +110654 @@ -17149,22 +17139,22 @@ 1 2 -1580700 +1627085 2 3 -244952 +236522 3 -9 -154629 +10 +155430 -9 -5708 -57986 +10 +5721 +49367 @@ -17180,22 +17170,22 @@ 1 2 -1607080 +1652441 2 3 -234777 +226741 3 -11 -155359 +13 +156353 -11 -5254 -41052 +13 +5267 +32869 @@ -17211,17 +17201,17 @@ 1 2 -1850925 +1888086 2 5 -162458 +156341 5 770 -24884 +23977 @@ -17237,17 +17227,17 @@ 1 2 -1771751 +1811867 2 4 -165132 +159052 4 3604 -101384 +97485 @@ -17263,42 +17253,42 @@ 1 2 -58861 +56530 2 3 -20860 +20039 3 4 -12290 +11801 4 6 -12715 +12268 6 10 -11524 +11088 10 22 -10673 +10270 22 255 -10490 +10083 263 -149390 -2176 +159500 +2091 @@ -17314,37 +17304,37 @@ 1 2 -62277 +59814 2 3 -20118 +19314 3 4 -13359 +12841 4 6 -11949 +11532 6 11 -11499 +11077 11 28 -10515 +10095 28 -148426 -9871 +158536 +9499 @@ -17360,32 +17350,32 @@ 1 2 -84973 +81606 2 3 -18149 +17445 3 4 -9676 +9347 4 7 -11706 +11275 7 28 -10576 +10165 28 -111448 -4510 +120730 +4335 @@ -17401,32 +17391,32 @@ 1 2 -80329 +77212 2 3 -21273 +20448 3 4 -7780 +7478 4 7 -12423 +11941 7 21 -10563 +10154 21 9993 -7220 +6940 @@ -17442,22 +17432,22 @@ 1 2 -1008108 +967927 2 3 -144734 +139422 3 6 -124044 +119546 6 -114124 -81581 +123459 +78860 @@ -17473,22 +17463,22 @@ 1 2 -1060320 +1018112 2 3 -107961 +103970 3 6 -111863 +107943 6 -113877 -78323 +123212 +75728 @@ -17504,17 +17494,17 @@ 1 2 -1166129 +1119863 2 3 -93045 +89797 3 -104379 -99293 +113652 +96095 @@ -17530,12 +17520,12 @@ 1 2 -1348524 +1296197 2 52 -9943 +9558 @@ -17545,11 +17535,11 @@ var_def -2573394 +2477557 id -2573394 +2477557 @@ -17619,19 +17609,19 @@ type_decls -1469165 +1413769 id -1469165 +1413769 type_id -1433996 +1379965 location -1203571 +1156868 @@ -17645,7 +17635,7 @@ 1 2 -1469165 +1413769 @@ -17661,7 +17651,7 @@ 1 2 -1469165 +1413769 @@ -17677,12 +17667,12 @@ 1 2 -1408431 +1355392 2 24 -25564 +24572 @@ -17698,12 +17688,12 @@ 1 2 -1409866 +1356771 2 24 -24130 +23194 @@ -17719,12 +17709,12 @@ 1 2 -1142582 +1098234 2 469 -60988 +58633 @@ -17740,12 +17730,12 @@ 1 2 -1144223 +1099812 2 469 -59347 +57056 @@ -17755,45 +17745,45 @@ type_def -1035654 +995467 id -1035654 +995467 type_decl_top -297552 +286006 type_decl -297552 +286006 namespace_decls -151627 +145743 id -151627 +145743 namespace_id -8485 +8155 location -135422 +130167 bodylocation -135787 +130518 @@ -17807,7 +17797,7 @@ 1 2 -151627 +145743 @@ -17823,7 +17813,7 @@ 1 2 -151627 +145743 @@ -17839,7 +17829,7 @@ 1 2 -151627 +145743 @@ -17855,42 +17845,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3743 -158 +151 @@ -17906,42 +17896,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3743 -158 +151 @@ -17957,42 +17947,42 @@ 1 2 -4011 +3855 2 3 -1191 +1145 3 4 -449 +432 4 7 -717 +689 7 13 -656 +630 13 27 -656 +630 28 163 -644 +619 172 3742 -158 +151 @@ -18008,12 +17998,12 @@ 1 2 -126135 +121240 2 8 -9287 +8927 @@ -18029,12 +18019,12 @@ 1 2 -126135 +121240 2 8 -9287 +8927 @@ -18050,12 +18040,12 @@ 1 2 -134595 +129373 2 3 -826 +794 @@ -18071,12 +18061,12 @@ 1 2 -126900 +121976 2 11 -8886 +8541 @@ -18092,12 +18082,12 @@ 1 2 -126900 +121976 2 9 -8886 +8541 @@ -18113,12 +18103,12 @@ 1 2 -135349 +130097 2 5 -437 +420 @@ -18128,19 +18118,19 @@ usings -320601 +308161 id -320601 +308161 element_id -49002 +47101 location -26464 +25437 @@ -18154,7 +18144,7 @@ 1 2 -320601 +308161 @@ -18170,7 +18160,7 @@ 1 2 -320601 +308161 @@ -18186,17 +18176,17 @@ 1 2 -41234 +39634 2 4 -4169 +4007 4 127 -3598 +3458 @@ -18212,17 +18202,17 @@ 1 2 -41234 +39634 2 4 -4169 +4007 4 127 -3598 +3458 @@ -18238,22 +18228,22 @@ 1 2 -20033 +19256 2 3 -2540 +2442 3 21 -2054 +1974 21 347 -1835 +1764 @@ -18269,22 +18259,22 @@ 1 2 -20033 +19256 2 3 -2540 +2442 3 21 -2054 +1974 21 347 -1835 +1764 @@ -18294,15 +18284,15 @@ using_container -485187 +466360 parent -8667 +8331 child -301029 +289348 @@ -18316,47 +18306,47 @@ 1 2 -3379 +3248 2 3 -559 +537 3 6 -668 +642 6 15 -656 +630 16 31 -705 +677 31 143 -291 +280 178 179 -1397 +1343 179 182 -765 +736 182 501 -243 +233 @@ -18372,22 +18362,22 @@ 1 2 -217478 +209039 2 3 -55773 +53609 3 6 -22659 +21780 6 47 -5117 +4919 @@ -18397,23 +18387,23 @@ static_asserts -132358 +131017 id -132358 +131017 condition -132358 +131017 message -30094 +29789 location -16938 +16766 @@ -18427,7 +18417,7 @@ 1 2 -132358 +131017 @@ -18443,7 +18433,7 @@ 1 2 -132358 +131017 @@ -18459,7 +18449,7 @@ 1 2 -132358 +131017 @@ -18475,7 +18465,7 @@ 1 2 -132358 +131017 @@ -18491,7 +18481,7 @@ 1 2 -132358 +131017 @@ -18507,7 +18497,7 @@ 1 2 -132358 +131017 @@ -18523,32 +18513,32 @@ 1 2 -22395 +22168 2 3 -428 +424 3 4 -2867 +2837 4 11 -1463 +1448 12 17 -2379 +2355 17 513 -560 +554 @@ -18564,32 +18554,32 @@ 1 2 -22395 +22168 2 3 -428 +424 3 4 -2867 +2837 4 11 -1463 +1448 12 17 -2379 +2355 17 513 -560 +554 @@ -18605,12 +18595,12 @@ 1 2 -27912 +27629 2 33 -2181 +2159 @@ -18626,32 +18616,32 @@ 1 2 -2939 +2909 2 3 -2801 +2772 3 4 -1344 +1330 5 6 -3776 +3738 6 7 -177 +176 14 15 -2062 +2042 16 @@ -18661,12 +18651,12 @@ 17 18 -3447 +3412 19 52 -349 +345 @@ -18682,32 +18672,32 @@ 1 2 -2939 +2909 2 3 -2801 +2772 3 4 -1344 +1330 5 6 -3776 +3738 6 7 -177 +176 14 15 -2062 +2042 16 @@ -18717,12 +18707,12 @@ 17 18 -3447 +3412 19 52 -349 +345 @@ -18738,22 +18728,22 @@ 1 2 -4475 +4429 2 3 -6063 +6002 3 4 -6208 +6145 4 7 -191 +189 @@ -18763,23 +18753,23 @@ params -4803552 +4749557 id -4779409 +4724692 function -3118318 +3117564 index -389 +373 type_id -1865866 +1906163 @@ -18793,12 +18783,12 @@ 1 2 -4778668 +4723979 2 69 -741 +712 @@ -18814,7 +18804,7 @@ 1 2 -4779409 +4724692 @@ -18830,12 +18820,12 @@ 1 2 -4757747 +4702211 2 7 -21662 +22481 @@ -18851,22 +18841,22 @@ 1 2 -2207692 +2232786 2 3 -482853 +472740 3 4 -264220 +254691 4 33 -163552 +157346 @@ -18882,22 +18872,22 @@ 1 2 -2207692 +2232786 2 3 -482853 +472740 3 4 -264220 +254691 4 33 -163552 +157346 @@ -18913,22 +18903,22 @@ 1 2 -2314438 +2335471 2 3 -493113 +480884 3 5 -270978 +262941 5 20 -39787 +38267 @@ -18944,57 +18934,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 883 1209 -24 +23 1659 2596 -24 +23 4880 -13455 -24 +13467 +23 -35189 -74910 -24 +35263 +75722 +23 -256345 -256346 -12 +266636 +266637 +11 @@ -19010,57 +19000,57 @@ 2 3 -158 +151 4 10 -24 +23 15 44 -24 +23 115 191 -24 +23 263 337 -24 +23 422 615 -24 +23 883 1209 -24 +23 1659 2596 -24 +23 4880 -13455 -24 +13467 +23 -35189 -74910 -24 +35263 +75722 +23 -256516 -256517 -12 +266807 +266808 +11 @@ -19076,57 +19066,57 @@ 1 2 -158 +151 3 7 -24 +23 8 20 -24 +23 36 40 -24 +23 42 45 -24 +23 61 105 -24 +23 173 257 -24 +23 406 661 -24 +23 1178 2710 -24 +23 -7491 -16702 -24 +7492 +16795 +23 -135733 -135734 -12 +145286 +145287 +11 @@ -19142,22 +19132,22 @@ 1 2 -1495095 +1547921 2 3 -199608 +193171 3 -13 -141671 +18 +144002 -13 -5275 -29491 +18 +5288 +21067 @@ -19173,22 +19163,22 @@ 1 2 -1517195 +1569164 2 3 -187245 +181276 3 -17 -140893 +25 +143324 -17 -4798 -20532 +25 +4811 +12397 @@ -19204,12 +19194,12 @@ 1 2 -1751170 +1795906 2 33 -114695 +110257 @@ -19219,15 +19209,15 @@ overrides -161127 +159494 new -126169 +124890 old -15666 +15507 @@ -19241,12 +19231,12 @@ 1 2 -91218 +90293 2 3 -34944 +34590 3 @@ -19267,37 +19257,37 @@ 1 2 -8232 +8148 2 3 -2043 +2022 3 4 -883 +874 4 5 -1278 +1265 5 10 -1245 +1233 10 43 -1179 +1167 44 218 -804 +795 @@ -19307,19 +19297,19 @@ membervariables -329658 +325582 id -325099 +321201 type_id -145086 +139772 name -59068 +56776 @@ -19333,12 +19323,12 @@ 1 2 -320637 +316912 2 7 -4461 +4288 @@ -19354,7 +19344,7 @@ 1 2 -325099 +321201 @@ -19370,22 +19360,22 @@ 1 2 -118391 +113949 2 3 -13396 +12934 3 11 -10989 +10656 11 -1212 -2309 +1715 +2231 @@ -19401,17 +19391,17 @@ 1 2 -125916 +121310 2 3 -9883 +9511 3 266 -9287 +8950 @@ -19427,32 +19417,32 @@ 1 2 -31217 +29971 2 3 -9056 +8705 3 4 -5944 +5725 4 6 -4485 +4311 6 15 -4534 +4358 15 -1317 -3829 +1953 +3704 @@ -19468,32 +19458,32 @@ 1 2 -38256 +36736 2 3 -7524 +7232 3 4 -4035 +3891 4 7 -4765 +4592 7 -319 -4437 +291 +4264 -323 +318 605 -48 +58 @@ -19674,19 +19664,19 @@ localvariables -527180 +521836 id -527101 +521758 type_id -48087 +47599 name -76217 +75444 @@ -19700,12 +19690,12 @@ 1 2 -527022 +521680 2 3 -79 +78 @@ -19721,7 +19711,7 @@ 1 2 -527101 +521758 @@ -19737,32 +19727,32 @@ 1 2 -26759 +26487 2 3 -6841 +6772 3 4 -2893 +2864 4 6 -4119 +4077 6 13 -3862 +3823 13 4908 -3611 +3575 @@ -19778,22 +19768,22 @@ 1 2 -36072 +35706 2 3 -4969 +4919 3 5 -4323 +4279 5 1158 -2722 +2694 @@ -19809,32 +19799,32 @@ 1 2 -43526 +43085 2 3 -13096 +12963 3 4 -5140 +5088 4 7 -6821 +6752 7 31 -5767 +5708 31 6112 -1865 +1846 @@ -19850,17 +19840,17 @@ 1 2 -64564 +63910 2 3 -6472 +6406 3 819 -5180 +5127 @@ -19870,11 +19860,11 @@ autoderivation -19759 +19559 var -19759 +19559 derivation_type @@ -19892,7 +19882,7 @@ 1 2 -19759 +19559 @@ -19938,31 +19928,31 @@ enumconstants -94487 +94097 id -94487 +94097 parent -7539 +8031 index -7678 +7600 type_id -7394 +7887 name -73851 +73102 location -76856 +76077 @@ -19976,7 +19966,7 @@ 1 2 -94487 +94097 @@ -19992,7 +19982,7 @@ 1 2 -94487 +94097 @@ -20008,7 +19998,7 @@ 1 2 -94487 +94097 @@ -20024,7 +20014,7 @@ 1 2 -94487 +94097 @@ -20040,7 +20030,7 @@ 1 2 -94487 +94097 @@ -20056,47 +20046,47 @@ 1 2 -1041 +1598 2 3 -830 +822 3 4 -2484 +2459 4 5 -586 +580 5 6 -586 +580 6 -8 -540 +9 +730 -8 -13 -659 +9 +16 +613 -13 -46 -573 +16 +392 +606 -46 +426 1166 -237 +39 @@ -20112,47 +20102,42 @@ 1 2 -1041 +1598 2 3 -843 +835 3 4 -2530 +2505 4 5 -579 +574 5 6 -593 +587 6 -8 -527 - - -8 -13 -632 +9 +704 -13 -49 -566 +9 +17 +626 -50 +17 1166 -224 +600 @@ -20168,12 +20153,12 @@ 1 2 -6788 +7287 2 3 -751 +743 @@ -20189,47 +20174,42 @@ 1 2 -1041 +1598 2 3 -843 +835 3 4 -2530 +2505 4 5 -579 +574 5 6 -593 +587 6 -8 -527 - - -8 -13 -632 +9 +704 -13 -49 -566 +9 +17 +626 -50 +17 1166 -224 +600 @@ -20245,47 +20225,47 @@ 1 2 -1080 +1637 2 3 -843 +835 3 4 -2484 +2459 4 5 -586 +580 5 6 -566 +561 6 -8 -514 +9 +704 -8 -13 -659 +9 +16 +613 -13 -46 -566 +16 +427 +606 -46 +466 1166 -237 +32 @@ -20301,47 +20281,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 30 -606 +600 30 -1166 -355 +1253 +352 @@ -20357,47 +20337,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 9 -685 +678 9 11 -369 +365 11 12 -560 +554 12 29 -606 +600 29 -1145 -355 +1232 +352 @@ -20413,47 +20393,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 9 -685 +678 9 11 -369 +365 11 12 -560 +554 12 28 -606 +600 28 -1123 -355 +1210 +352 @@ -20469,47 +20449,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 28 -606 +600 28 674 -355 +352 @@ -20525,47 +20505,47 @@ 1 2 -2642 +2616 2 3 -942 +932 3 4 -935 +926 4 7 -579 +574 7 10 -698 +691 10 11 -355 +352 11 12 -560 +554 12 28 -606 +600 28 774 -355 +352 @@ -20581,47 +20561,47 @@ 1 2 -1041 +1598 2 3 -810 +802 3 4 -2458 +2433 4 5 -566 +561 5 6 -566 +561 6 -8 -520 +9 +704 -8 -13 -639 +9 +16 +600 -13 -46 -560 +16 +470 +593 -46 +479 1166 -230 +32 @@ -20637,7 +20617,7 @@ 1 2 -7388 +7881 137 @@ -20658,47 +20638,42 @@ 1 2 -1041 +1598 2 3 -823 +815 3 4 -2504 +2479 4 5 -560 +554 5 6 -573 +567 6 -8 -507 - - -8 -13 -612 +9 +678 -13 -51 -560 +9 +17 +613 -52 +17 1166 -210 +580 @@ -20714,47 +20689,42 @@ 1 2 -1041 +1598 2 3 -823 +815 3 4 -2504 +2479 4 5 -560 +554 5 6 -573 +567 6 -8 -507 - - -8 -13 -612 +9 +678 -13 -51 -560 +9 +17 +613 -52 +17 1166 -210 +580 @@ -20770,47 +20740,47 @@ 1 2 -1080 +1637 2 3 -823 +815 3 4 -2458 +2433 4 5 -566 +561 5 6 -547 +541 6 -8 -494 +9 +678 -8 -13 -639 +9 +16 +600 -13 -47 -560 +16 +470 +593 -48 +621 1166 -224 +26 @@ -20826,17 +20796,17 @@ 1 2 -66396 +65723 2 3 -6927 +6856 3 239 -527 +521 @@ -20852,17 +20822,17 @@ 1 2 -67049 +66369 2 3 -6274 +6210 3 239 -527 +521 @@ -20878,12 +20848,12 @@ 1 2 -68762 +68065 2 13 -5088 +5036 @@ -20899,17 +20869,17 @@ 1 2 -61941 +61313 2 3 -11382 +11267 3 239 -527 +521 @@ -20925,12 +20895,12 @@ 1 2 -71346 +70623 2 23 -2504 +2479 @@ -20946,12 +20916,12 @@ 1 2 -71531 +70773 2 229 -5325 +5304 @@ -20967,12 +20937,12 @@ 1 2 -71643 +70884 2 229 -5213 +5193 @@ -20988,12 +20958,12 @@ 1 2 -73211 +72469 2 17 -3644 +3607 @@ -21009,17 +20979,17 @@ 1 2 -66535 +65828 2 3 -10090 +9994 3 229 -230 +254 @@ -21035,12 +21005,12 @@ 1 2 -76685 +75907 2 27 -171 +169 @@ -21050,31 +21020,31 @@ builtintypes -559 +537 id -559 +537 name -559 +537 kind -559 +537 size -85 +81 sign -36 +35 alignment -60 +58 @@ -21088,7 +21058,7 @@ 1 2 -559 +537 @@ -21104,7 +21074,7 @@ 1 2 -559 +537 @@ -21120,7 +21090,7 @@ 1 2 -559 +537 @@ -21136,7 +21106,7 @@ 1 2 -559 +537 @@ -21152,7 +21122,7 @@ 1 2 -559 +537 @@ -21168,7 +21138,7 @@ 1 2 -559 +537 @@ -21184,7 +21154,7 @@ 1 2 -559 +537 @@ -21200,7 +21170,7 @@ 1 2 -559 +537 @@ -21216,7 +21186,7 @@ 1 2 -559 +537 @@ -21232,7 +21202,7 @@ 1 2 -559 +537 @@ -21248,7 +21218,7 @@ 1 2 -559 +537 @@ -21264,7 +21234,7 @@ 1 2 -559 +537 @@ -21280,7 +21250,7 @@ 1 2 -559 +537 @@ -21296,7 +21266,7 @@ 1 2 -559 +537 @@ -21312,7 +21282,7 @@ 1 2 -559 +537 @@ -21328,37 +21298,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21374,37 +21344,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21420,37 +21390,37 @@ 1 2 -12 +11 2 3 -12 +11 4 5 -12 +11 6 7 -12 +11 9 10 -12 +11 11 12 -12 +11 13 14 -12 +11 @@ -21466,12 +21436,12 @@ 1 2 -24 +23 3 4 -60 +58 @@ -21487,12 +21457,12 @@ 1 2 -60 +58 2 3 -24 +23 @@ -21508,17 +21478,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21534,17 +21504,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21560,17 +21530,17 @@ 6 7 -12 +11 12 13 -12 +11 28 29 -12 +11 @@ -21586,12 +21556,12 @@ 5 6 -24 +23 7 8 -12 +11 @@ -21607,7 +21577,7 @@ 5 6 -36 +35 @@ -21623,27 +21593,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21659,27 +21629,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21695,27 +21665,27 @@ 4 5 -12 +11 7 8 -12 +11 10 11 -12 +11 12 13 -12 +11 13 14 -12 +11 @@ -21731,12 +21701,12 @@ 1 2 -12 +11 2 3 -48 +46 @@ -21752,7 +21722,7 @@ 3 4 -60 +58 @@ -21762,23 +21732,23 @@ derivedtypes -4572495 +4651908 id -4572495 +4651908 name -2240442 +2328554 kind -97 +93 type_id -2743147 +2780308 @@ -21792,7 +21762,7 @@ 1 2 -4572495 +4651908 @@ -21808,7 +21778,7 @@ 1 2 -4572495 +4651908 @@ -21824,7 +21794,7 @@ 1 2 -4572495 +4651908 @@ -21840,17 +21810,17 @@ 1 2 -1640327 +1709696 2 3 -479376 +500222 3 -42612 -120737 +43371 +118634 @@ -21866,12 +21836,12 @@ 1 2 -2240417 +2328530 2 3 -24 +23 @@ -21887,17 +21857,17 @@ 1 2 -1640607 +1709965 2 3 -479097 +499954 3 -42594 -120737 +43353 +118634 @@ -21913,42 +21883,42 @@ 21 22 -12 +11 61 62 -12 +11 2051 2052 -12 +11 -25122 -25123 -12 +27346 +27347 +11 -42664 -42665 -12 +43423 +43424 +11 -53936 -53937 -12 +58521 +58522 +11 -97759 -97760 -12 +102765 +102766 +11 -154522 -154523 -12 +163929 +163930 +11 @@ -21964,42 +21934,42 @@ 1 2 -12 +11 13 14 -12 +11 38 39 -12 +11 1152 1153 -12 +11 -13367 -13368 -12 +15027 +15028 +11 -36098 -36099 -12 +39331 +39332 +11 -50248 -50249 -12 +53789 +53790 +11 -83386 -83387 -12 +89933 +89934 +11 @@ -22015,42 +21985,42 @@ 12 13 -12 +11 21 22 -12 +11 969 970 -12 +11 -25122 -25123 -12 +27346 +27347 +11 -42664 -42665 -12 +43423 +43424 +11 -53936 -53937 -12 +58521 +58522 +11 -97431 -97432 -12 +102434 +102435 +11 -154522 -154523 -12 +163929 +163930 +11 @@ -22066,22 +22036,22 @@ 1 2 -1661856 +1683160 2 3 -405550 +392781 3 4 -615674 +646083 4 202 -60064 +58283 @@ -22097,22 +22067,22 @@ 1 2 -1663206 +1684457 2 3 -405380 +392618 3 4 -614495 +644949 4 198 -60064 +58283 @@ -22128,22 +22098,22 @@ 1 2 -1663534 +1684784 2 3 -406814 +393985 3 4 -614446 +644902 4 7 -58350 +56635 @@ -22153,19 +22123,19 @@ pointerishsize -3358396 +3426426 id -3358396 +3426426 size -24 +23 alignment -12 +11 @@ -22179,7 +22149,7 @@ 1 2 -3358396 +3426426 @@ -22195,7 +22165,7 @@ 1 2 -3358396 +3426426 @@ -22211,12 +22181,12 @@ 21 22 -12 +11 -276244 -276245 -12 +293219 +293220 +11 @@ -22232,7 +22202,7 @@ 1 2 -24 +23 @@ -22246,9 +22216,9 @@ 12 -276265 -276266 -12 +293240 +293241 +11 @@ -22264,7 +22234,7 @@ 2 3 -12 +11 @@ -22274,23 +22244,23 @@ arraysizes -18830 +18099 id -18830 +18099 num_elements -2394 +2301 bytesize -2783 +2675 alignment -85 +81 @@ -22304,7 +22274,7 @@ 1 2 -18830 +18099 @@ -22320,7 +22290,7 @@ 1 2 -18830 +18099 @@ -22336,7 +22306,7 @@ 1 2 -18830 +18099 @@ -22352,37 +22322,37 @@ 1 2 -182 +175 2 3 -1422 +1367 3 4 -85 +81 4 5 -182 +175 5 13 -182 +175 13 25 -182 +175 38 116 -158 +151 @@ -22398,27 +22368,27 @@ 1 2 -1762 +1694 2 3 -243 +233 3 4 -133 +128 4 6 -182 +175 6 11 -72 +70 @@ -22434,27 +22404,27 @@ 1 2 -1774 +1705 2 3 -255 +245 3 4 -158 +151 4 7 -182 +175 7 8 -24 +23 @@ -22470,42 +22440,42 @@ 1 2 -170 +163 2 3 -1556 +1495 3 4 -133 +128 4 6 -218 +210 6 9 -218 +210 9 17 -218 +210 17 53 -218 +210 55 75 -48 +46 @@ -22521,22 +22491,22 @@ 1 2 -2115 +2033 2 3 -389 +373 3 6 -243 +233 6 7 -36 +35 @@ -22552,22 +22522,22 @@ 1 2 -2176 +2091 2 3 -303 +292 3 5 -255 +245 5 7 -48 +46 @@ -22583,37 +22553,37 @@ 17 18 -12 +11 18 19 -12 +11 33 34 -12 +11 50 51 -12 +11 181 182 -12 +11 389 390 -12 +11 861 862 -12 +11 @@ -22629,37 +22599,37 @@ 4 5 -12 +11 5 6 -12 +11 13 14 -12 +11 16 17 -12 +11 39 40 -12 +11 40 41 -12 +11 190 191 -12 +11 @@ -22675,37 +22645,37 @@ 1 2 -12 +11 2 3 -12 +11 14 15 -12 +11 17 18 -12 +11 41 42 -12 +11 53 54 -12 +11 191 192 -12 +11 @@ -22715,15 +22685,15 @@ typedefbase -1919913 +1867884 id -1919913 +1867884 type_id -899600 +871937 @@ -22737,7 +22707,7 @@ 1 2 -1919913 +1867884 @@ -22753,22 +22723,22 @@ 1 2 -698168 +676919 2 3 -93312 +90264 3 6 -72975 +70856 6 -5423 -35144 +5485 +33897 @@ -22778,23 +22748,23 @@ decltypes -45841 +44063 id -45841 +44063 expr -43325 +41644 base_type -6479 +6227 parentheses_would_change_meaning -24 +23 @@ -22808,7 +22778,7 @@ 1 2 -45841 +44063 @@ -22824,7 +22794,7 @@ 1 2 -45841 +44063 @@ -22840,7 +22810,7 @@ 1 2 -45841 +44063 @@ -22856,12 +22826,12 @@ 1 2 -40809 +39225 2 3 -2516 +2418 @@ -22877,12 +22847,12 @@ 1 2 -40809 +39225 2 3 -2516 +2418 @@ -22898,7 +22868,7 @@ 1 2 -43325 +41644 @@ -22914,17 +22884,17 @@ 1 2 -3622 +3482 2 3 -2552 +2453 3 277 -303 +292 @@ -22940,22 +22910,22 @@ 1 2 -2540 +2442 2 3 -3282 +3154 3 12 -522 +502 13 2445 -133 +128 @@ -22971,7 +22941,7 @@ 1 2 -6479 +6227 @@ -22987,12 +22957,12 @@ 8 9 -12 +11 1082 1083 -12 +11 @@ -23008,12 +22978,12 @@ 8 9 -12 +11 3556 3557 -12 +11 @@ -23029,12 +22999,12 @@ 8 9 -12 +11 525 526 -12 +11 @@ -23044,19 +23014,19 @@ usertypes -4363319 +4337028 id -4363319 +4337028 name -899429 +917472 kind -133 +128 @@ -23070,7 +23040,7 @@ 1 2 -4363319 +4337028 @@ -23086,7 +23056,7 @@ 1 2 -4363319 +4337028 @@ -23102,22 +23072,22 @@ 1 2 -596127 +606962 2 3 -199888 +203676 3 8 -67589 +69886 8 -31201 -35824 +32070 +36947 @@ -23133,12 +23103,12 @@ 1 2 -842355 +861619 2 10 -57074 +55852 @@ -23154,57 +23124,57 @@ 23 24 -12 +11 372 373 -12 +11 773 774 -12 +11 -1526 -1527 -12 +1856 +1857 +11 -4123 -4124 -12 +4195 +4196 +11 14604 14605 -12 +11 -17528 -17529 -12 +17544 +17545 +11 -20287 -20288 -12 +20425 +20426 +11 -75247 -75248 -12 +75551 +75552 +11 -81118 -81119 -12 +90575 +90576 +11 -143330 -143331 -12 +145253 +145254 +11 @@ -23220,52 +23190,52 @@ 16 17 -12 +11 38 39 -24 +23 404 405 -12 +11 548 549 -12 +11 -776 -777 -12 +777 +778 +11 -2846 -2847 -12 +2848 +2849 +11 4545 4546 -12 +11 -9121 -9122 -12 +9129 +9130 +11 11659 11660 -12 +11 -49218 -49219 -12 +53824 +53825 +11 @@ -23275,19 +23245,19 @@ usertypesize -1364814 +1420908 id -1364814 +1420908 size -1641 +1577 alignment -97 +93 @@ -23301,7 +23271,7 @@ 1 2 -1364814 +1420908 @@ -23317,7 +23287,7 @@ 1 2 -1364814 +1420908 @@ -23333,52 +23303,52 @@ 1 2 -474 +455 2 3 -218 +210 3 4 -72 +70 4 5 -109 +105 5 8 -121 +116 8 12 -109 +105 12 16 -133 +128 16 36 -133 +128 37 170 -133 +128 260 -86086 -133 +95028 +128 @@ -23394,17 +23364,17 @@ 1 2 -1349 +1297 2 3 -194 +186 3 6 -97 +93 @@ -23420,42 +23390,42 @@ 1 2 -12 +11 3 4 -12 +11 7 8 -12 +11 50 51 -12 +11 54 55 -12 +11 -1916 -1917 -12 +2246 +2247 +11 -9656 -9657 -12 +9717 +9718 +11 -100584 -100585 -12 +109526 +109527 +11 @@ -23471,37 +23441,37 @@ 1 2 -24 +23 3 4 -12 +11 8 9 -12 +11 12 13 -12 +11 17 18 -12 +11 25 26 -12 +11 106 107 -12 +11 @@ -23511,26 +23481,26 @@ usertype_final -1331 +1317 id -1331 +1317 usertype_uuid -4897 +4847 id -4897 +4847 uuid -4897 +4847 @@ -23544,7 +23514,7 @@ 1 2 -4897 +4847 @@ -23560,7 +23530,7 @@ 1 2 -4897 +4847 @@ -23570,15 +23540,15 @@ mangled_name -4359684 +4333558 id -4359684 +4333558 mangled_name -532986 +514256 @@ -23592,7 +23562,7 @@ 1 2 -4359684 +4333558 @@ -23608,32 +23578,32 @@ 1 2 -325269 +310895 2 3 -68246 +66497 3 4 -35958 +35217 4 -8 -45307 +7 +39225 -8 -34 -40237 +7 +23 +38664 -34 -8470 -17967 +23 +8589 +23755 @@ -23643,59 +23613,59 @@ is_pod_class -1041477 +1104649 id -1041477 +1104649 is_standard_layout_class -1118962 +1180366 id -1118962 +1180366 is_complete -1345984 +1398952 id -1345984 +1398952 is_class_template -246617 +238660 id -246617 +238660 class_instantiation -1108921 +1176522 to -1107195 +1174863 from -72513 +72363 @@ -23709,12 +23679,12 @@ 1 2 -1105566 +1173297 2 4 -1628 +1565 @@ -23730,47 +23700,47 @@ 1 2 -21601 +21289 2 3 -12897 +12771 3 4 -7488 +7314 4 5 -4789 +4942 5 7 -5871 +5994 7 11 -6503 +6438 11 20 -5555 +5585 20 -89 -5470 +87 +5456 -89 -2079 -2334 +87 +3629 +2570 @@ -23780,19 +23750,19 @@ class_template_argument -2800063 +3135757 type_id -1339675 +1428725 index -1361 +1308 arg_type -921287 +904899 @@ -23806,27 +23776,27 @@ 1 2 -593732 +586000 2 3 -438105 +428957 3 4 -175599 +258501 4 7 -108629 +129501 7 113 -23607 +25764 @@ -23842,22 +23812,22 @@ 1 2 -619710 +613658 2 3 -445691 +442173 3 4 -187999 +272382 4 113 -86274 +100511 @@ -23873,37 +23843,37 @@ 1 2 -12 +11 2 3 -863 +829 3 26 -109 +105 29 64 -109 +105 69 -427 -109 +435 +105 -594 -8438 -109 +616 +9263 +105 -11951 -101100 -48 +13601 +119714 +46 @@ -23919,37 +23889,37 @@ 1 2 -12 +11 2 3 -863 +829 3 14 -121 +116 14 26 -109 +105 29 -147 -109 +148 +105 -191 -3560 -109 +198 +3591 +105 -11321 -39550 -36 +11582 +41130 +35 @@ -23965,22 +23935,27 @@ 1 2 -571096 +550198 2 3 -205784 +200100 3 -5 -75369 +4 +54918 -5 -5259 -69036 +4 +10 +70727 + + +10 +11421 +28954 @@ -23996,17 +23971,253 @@ 1 2 -805922 +786767 + + +2 +3 +98069 + + +3 +22 +20062 + + + + + + + + +class_template_argument_value +362635 + + +type_id +233565 + + +index +163 + + +arg_value +345447 + + + + +type_id +index + + +12 + + +1 +2 +209845 2 3 -96011 +14512 + + +3 +14 +9207 + + + + + + +type_id +arg_value + + +12 + + +1 +2 +197436 + + +2 +3 +17971 3 22 -19353 +17527 + + +24 +173 +630 + + + + + + +index +type_id + + +12 + + +8 +9 +58 + + +20 +21 +11 + + +25 +26 +11 + + +206 +207 +11 + + +389 +390 +11 + + +552 +553 +11 + + +1312 +1313 +11 + + +5393 +5394 +11 + + +5423 +5424 +11 + + +9668 +9669 +11 + + + + + + +index +arg_value + + +12 + + +8 +9 +58 + + +20 +21 +11 + + +42 +43 +11 + + +311 +312 +11 + + +514 +515 +11 + + +715 +716 +11 + + +1585 +1586 +11 + + +6302 +6303 +11 + + +8160 +8161 +11 + + +11875 +11876 +11 + + + + + + +arg_value +type_id + + +12 + + +1 +2 +328387 + + +2 +4 +17059 + + + + + + +arg_value +index + + +12 + + +1 +2 +345447 @@ -24016,15 +24227,15 @@ is_proxy_class_for -50120 +49017 id -50120 +49017 templ_param_id -50120 +49017 @@ -24038,7 +24249,7 @@ 1 2 -50120 +49017 @@ -24054,7 +24265,7 @@ 1 2 -50120 +49017 @@ -24064,19 +24275,19 @@ type_mentions -1699359 +1682135 id -1699359 +1682135 type_id -68077 +67387 location -1668455 +1651543 kind @@ -24094,7 +24305,7 @@ 1 2 -1699359 +1682135 @@ -24110,7 +24321,7 @@ 1 2 -1699359 +1682135 @@ -24126,7 +24337,7 @@ 1 2 -1699359 +1682135 @@ -24142,37 +24353,37 @@ 1 2 -30463 +30154 2 3 -12463 +12337 3 4 -3684 +3646 4 7 -6142 +6080 7 13 -5213 +5160 13 35 -5259 +5206 35 9490 -4850 +4801 @@ -24188,37 +24399,37 @@ 1 2 -30463 +30154 2 3 -12463 +12337 3 4 -3684 +3646 4 7 -6142 +6080 7 13 -5213 +5160 13 35 -5259 +5206 35 9490 -4850 +4801 @@ -24234,12 +24445,12 @@ 1 2 -66818 +66141 2 3 -1258 +1246 @@ -24255,12 +24466,12 @@ 1 2 -1637892 +1621291 2 5 -30562 +30252 @@ -24276,12 +24487,12 @@ 1 2 -1637892 +1621291 2 5 -30562 +30252 @@ -24297,7 +24508,7 @@ 1 2 -1668455 +1651543 @@ -24370,26 +24581,26 @@ is_function_template -1058083 +1023581 id -1058083 +1023581 function_instantiation -739463 +719194 to -739463 +719194 from -136103 +134923 @@ -24403,7 +24614,7 @@ 1 2 -739463 +719194 @@ -24419,37 +24630,32 @@ 1 2 -63018 +64125 2 3 -32396 +31385 3 4 -8193 +7898 4 -5 -9299 - - -5 -10 -10940 +6 +12467 -10 -57 -10223 +6 +15 +10434 -58 +15 645 -2030 +8611 @@ -24459,19 +24665,19 @@ function_template_argument -1910796 +1981225 function_id -1112422 +1088560 index -243 +233 arg_type -369847 +359386 @@ -24485,22 +24691,22 @@ 1 2 -634796 +600045 2 3 -361033 +302330 3 -5 -84645 +4 +131242 -5 +4 21 -31947 +54941 @@ -24516,22 +24722,22 @@ 1 2 -657966 +618530 2 3 -332393 +293520 3 -5 -90905 +4 +116683 -5 +4 21 -31156 +59825 @@ -24547,102 +24753,102 @@ 4 5 -12 +11 7 8 -12 +11 17 18 -12 +11 39 40 -12 +11 65 66 -12 +11 152 153 -12 +11 -238 -239 -12 +241 +242 +11 -325 -326 -12 +328 +329 +11 -422 -423 -12 +425 +426 +11 -520 -521 -12 +523 +524 +11 -754 -755 -12 +758 +759 +11 -1007 -1008 -12 +1011 +1012 +11 -1259 -1260 -12 +1520 +1521 +11 -1514 -1515 -12 +1701 +1702 +11 -2559 -2560 -12 +2566 +2567 +11 -2804 -2805 -12 +2917 +2918 +11 -4818 -4819 -12 +5686 +5687 +11 -13309 -13310 -12 +17602 +17603 +11 -40569 -40570 -12 +42858 +42859 +11 -84931 -84932 -12 +88286 +88287 +11 @@ -24658,102 +24864,102 @@ 4 5 -12 +11 7 8 -12 +11 14 15 -12 +11 22 23 -12 +11 32 33 -12 +11 54 55 -12 +11 -57 -58 -12 +60 +61 +11 -61 -62 -12 +62 +63 +11 -75 -76 -12 +78 +79 +11 -90 -91 -12 +91 +92 +11 -137 -138 -12 +140 +141 +11 214 215 -12 +11 -238 -239 -12 +242 +243 +11 -316 -317 -12 +317 +318 +11 -517 -518 -12 +521 +522 +11 -695 -696 -12 +700 +701 +11 -1468 -1469 -12 +1491 +1492 +11 -3652 -3653 -12 +3698 +3699 +11 -8773 -8774 -12 +8798 +8799 +11 -17388 -17389 -12 +17653 +17654 +11 @@ -24769,27 +24975,27 @@ 1 2 -249547 +242738 2 3 -48698 +46902 3 6 -29783 +28756 6 -19 -27996 +20 +27704 -19 -906 -13821 +20 +1989 +13285 @@ -24805,17 +25011,238 @@ 1 2 -341230 +331740 2 5 -28129 +27131 5 -10 -486 +12 +514 + + + + + + + + +function_template_argument_value +209892 + + +function_id +113037 + + +index +163 + + +arg_value +181755 + + + + +function_id +index + + +12 + + +1 +2 +107207 + + +2 +14 +5830 + + + + + + +function_id +arg_value + + +12 + + +1 +2 +89610 + + +2 +3 +17106 + + +3 +113 +6321 + + + + + + +index +function_id + + +12 + + +3 +4 +70 + + +5 +6 +11 + + +6 +7 +11 + + +111 +112 +11 + + +441 +442 +11 + + +857 +858 +11 + + +2136 +2137 +11 + + +2428 +2429 +11 + + +4217 +4218 +11 + + + + + + +index +arg_value + + +12 + + +5 +6 +70 + + +7 +8 +11 + + +8 +9 +11 + + +157 +158 +11 + + +405 +406 +11 + + +973 +974 +11 + + +2523 +2524 +11 + + +4848 +4849 +11 + + +6604 +6605 +11 + + + + + + +arg_value +function_id + + +12 + + +1 +2 +153712 + + +2 +3 +27949 + + +3 +4 +93 + + + + + + +arg_value +index + + +12 + + +1 +2 +181755 @@ -24825,26 +25252,26 @@ is_variable_template -19778 +19011 id -19778 +19011 variable_instantiation -31837 +38057 to -31837 +38057 from -6734 +6929 @@ -24858,7 +25285,7 @@ 1 2 -31837 +38057 @@ -24874,37 +25301,37 @@ 1 2 -2382 +2383 2 3 -2030 +2033 3 4 -449 +432 4 5 -692 +782 5 9 -534 +560 9 -29 -534 +21 +525 -42 -214 -109 +24 +286 +210 @@ -24914,11 +25341,11 @@ variable_template_argument -5529 +5499 variable_id -843 +848 index @@ -24926,7 +25353,7 @@ arg_type -4257 +4214 @@ -24940,12 +25367,12 @@ 1 2 -692 +685 2 3 -112 +123 3 @@ -24966,12 +25393,12 @@ 1 2 -369 +371 2 3 -125 +130 3 @@ -24981,12 +25408,12 @@ 4 6 -72 +71 6 8 -72 +71 8 @@ -25025,13 +25452,13 @@ 6 -9 -10 +10 +11 6 -17 -18 +20 +21 6 @@ -25066,8 +25493,8 @@ 6 -137 -138 +139 +140 6 @@ -25089,17 +25516,17 @@ 1 2 -3532 +3490 2 3 -481 +476 3 11 -243 +247 @@ -25115,12 +25542,148 @@ 1 2 -4046 +3999 + + +2 +4 +215 + + + + + + + + +variable_template_argument_value +137 + + +variable_id +19 + + +index +13 + + +arg_value +137 + + + + +variable_id +index + + +12 + + +1 +2 +13 2 3 -210 +6 + + + + + + +variable_id +arg_value + + +12 + + +3 +4 +13 + + +15 +16 +6 + + + + + + +index +variable_id + + +12 + + +1 +2 +6 + + +3 +4 +6 + + + + + + +index +arg_value + + +12 + + +6 +7 +6 + + +15 +16 +6 + + + + + + +arg_value +variable_id + + +12 + + +1 +2 +137 + + + + + + +arg_value +index + + +12 + + +1 +2 +137 @@ -25130,15 +25693,15 @@ routinetypes -444572 +436132 id -444572 +436132 return_type -184814 +178086 @@ -25152,7 +25715,7 @@ 1 2 -444572 +436132 @@ -25168,22 +25731,22 @@ 1 2 -148344 +142985 2 3 -21030 +20191 3 -18 -13943 +17 +13367 -18 -7709 -1495 +17 +8001 +1542 @@ -25193,19 +25756,19 @@ routinetypeargs -741201 +726544 routine -362760 +357377 index -389 +373 type_id -209394 +208724 @@ -25219,27 +25782,27 @@ 1 2 -169412 +166448 2 3 -95355 +96574 3 4 -58144 +55888 4 6 -31351 +30298 6 33 -8497 +8167 @@ -25255,22 +25818,22 @@ 1 2 -194831 +190916 2 3 -95853 +97018 3 4 -49707 +47778 4 22 -22367 +21663 @@ -25286,62 +25849,62 @@ 1 2 -133 +128 2 7 -24 +23 10 16 -24 +23 19 33 -24 +23 52 74 -24 +23 93 115 -24 +23 139 199 -24 +23 269 364 -24 +23 473 700 -24 +23 1319 -3279 -24 +3293 +23 -8061 -15906 -24 +8075 +16341 +23 -29841 -29842 -12 +30585 +30586 +11 @@ -25357,62 +25920,62 @@ 1 2 -133 +128 2 5 -24 +23 6 10 -24 +23 11 22 -24 +23 33 37 -24 +23 38 42 -24 +23 44 83 -24 +23 124 183 -24 +23 248 346 -24 +23 463 950 -24 +23 -2463 -5546 -24 +2464 +5642 +23 -12306 -12307 -12 +12850 +12851 +11 @@ -25428,27 +25991,27 @@ 1 2 -123691 +124231 2 3 -40869 +41258 3 4 -13505 +13016 4 7 -17942 +17293 7 -1097 -13384 +1099 +12923 @@ -25464,17 +26027,17 @@ 1 2 -156830 +158176 2 3 -41161 +39576 3 33 -11402 +10971 @@ -25484,19 +26047,19 @@ ptrtomembers -12180 +13227 id -12180 +13227 type_id -10247 +10013 class_id -5519 +6601 @@ -25510,7 +26073,7 @@ 1 2 -12180 +13227 @@ -25526,7 +26089,7 @@ 1 2 -12180 +13227 @@ -25542,12 +26105,12 @@ 1 2 -9895 +9628 2 -65 -352 +100 +385 @@ -25563,12 +26126,12 @@ 1 2 -9895 +9628 2 -65 -352 +100 +385 @@ -25584,22 +26147,22 @@ 1 2 -4619 +5573 2 -7 -352 +3 +490 8 -9 -461 +17 +502 -16 +64 65 -85 +35 @@ -25615,22 +26178,22 @@ 1 2 -4619 +5573 2 -7 -352 +3 +490 8 -9 -461 +17 +502 -16 +64 65 -85 +35 @@ -25640,15 +26203,15 @@ specifiers -547 +525 id -547 +525 str -547 +525 @@ -25662,7 +26225,7 @@ 1 2 -547 +525 @@ -25678,7 +26241,7 @@ 1 2 -547 +525 @@ -25688,15 +26251,15 @@ typespecifiers -1464874 +1479986 type_id -1460193 +1472695 spec_id -85 +81 @@ -25710,12 +26273,12 @@ 1 2 -1455513 +1465403 2 3 -4680 +7291 @@ -25731,37 +26294,37 @@ 102 103 -12 +11 222 223 -12 +11 518 519 -12 +11 -718 -719 -12 +957 +958 +11 2323 2324 -12 +11 -19328 -19329 -12 +20241 +20242 +11 -97291 -97292 -12 +102297 +102298 +11 @@ -25771,15 +26334,15 @@ funspecifiers -11370456 +11412148 func_id -3511992 +3500391 spec_id -194 +186 @@ -25793,27 +26356,27 @@ 1 2 -342616 +329999 2 3 -464083 +448167 3 4 -909155 +883458 4 5 -1670402 +1717910 5 8 -125733 +120855 @@ -25829,82 +26392,82 @@ 22 23 -12 +11 169 170 -12 +11 491 492 -12 +11 -506 -507 -12 +598 +599 +11 632 633 -12 +11 5650 5651 -12 +11 9530 9531 -12 +11 10451 10452 -12 +11 -11821 -11822 -12 +11834 +11835 +11 14848 14849 -12 +11 -25330 -25331 -12 +26196 +26197 +11 -33532 -33533 -12 +33724 +33725 +11 -122462 -122463 -12 +131801 +131802 +11 -204591 -204592 -12 +214925 +214926 +11 -232301 -232302 -12 +242884 +242885 +11 -263009 -263010 -12 +272918 +272919 +11 @@ -25914,11 +26477,11 @@ varspecifiers -1124158 +1113938 var_id -935091 +926194 spec_id @@ -25936,17 +26499,17 @@ 1 2 -795258 +787198 2 3 -92279 +91911 3 5 -47553 +47084 @@ -25980,13 +26543,13 @@ 6 -8409 -8410 +8411 +8412 6 -8751 -8752 +8753 +8754 6 @@ -25995,13 +26558,13 @@ 6 -13352 -13353 +13439 +13440 6 -42323 -42324 +42412 +42413 6 @@ -26590,11 +27153,11 @@
    attribute_args -118319 +118389 id -118319 +118389 kind @@ -26602,7 +27165,7 @@ attribute -116952 +117020 index @@ -26610,7 +27173,7 @@ location -58256 +58290 @@ -26624,7 +27187,7 @@ 1 2 -118319 +118389 @@ -26640,7 +27203,7 @@ 1 2 -118319 +118389 @@ -26656,7 +27219,7 @@ 1 2 -118319 +118389 @@ -26672,7 +27235,7 @@ 1 2 -118319 +118389 @@ -26772,12 +27335,12 @@ 1 2 -116132 +116200 2 4 -819 +820 @@ -26793,7 +27356,7 @@ 1 2 -116431 +116499 2 @@ -26814,12 +27377,12 @@ 1 2 -116132 +116200 2 4 -819 +820 @@ -26835,7 +27398,7 @@ 1 2 -116137 +116205 2 @@ -26955,22 +27518,22 @@ 1 2 -28468 +28485 2 3 -7516 +7521 3 4 -19458 +19469 4 25 -2812 +2814 @@ -26986,12 +27549,12 @@ 1 2 -52020 +52051 2 3 -6235 +6239 @@ -27007,22 +27570,22 @@ 1 2 -28452 +28469 2 3 -7534 +7539 3 4 -19454 +19466 4 25 -2814 +2815 @@ -27038,7 +27601,7 @@ 1 2 -58250 +58285 3 @@ -27053,15 +27616,15 @@ attribute_arg_value -118292 +118362 arg -118292 +118362 value -2257 +2258 @@ -27075,7 +27638,7 @@ 1 2 -118292 +118362 @@ -27091,7 +27654,7 @@ 1 2 -1808 +1809 2 @@ -27116,15 +27679,15 @@ attribute_arg_type -60 +58 arg -60 +58 type_id -36 +35 @@ -27138,7 +27701,7 @@ 1 2 -60 +58 @@ -27154,12 +27717,12 @@ 1 2 -12 +11 2 3 -24 +23 @@ -27222,15 +27785,15 @@ typeattributes -12119 +12701 type_id -10831 +11462 spec_id -12119 +12701 @@ -27244,12 +27807,12 @@ 1 2 -10296 +10948 2 34 -534 +514 @@ -27265,7 +27828,7 @@ 1 2 -12119 +12701 @@ -27275,15 +27838,15 @@ funcattributes -327044 +314529 func_id -174943 +168330 spec_id -327044 +314529 @@ -27297,22 +27860,22 @@ 1 2 -94078 +90603 2 3 -13554 +13028 3 4 -65134 +62606 4 14 -2176 +2091 @@ -27328,7 +27891,7 @@ 1 2 -327044 +314529 @@ -27444,15 +28007,15 @@ unspecifiedtype -9406353 +9451546 type_id -9406353 +9451546 unspecified_type_id -5062897 +5133540 @@ -27466,7 +28029,7 @@ 1 2 -9406353 +9451546 @@ -27482,22 +28045,17 @@ 1 2 -2733810 +2776289 2 3 -1943594 +1978655 3 -30 -379779 - - -30 -7873 -5713 +7936 +378596 @@ -27507,19 +28065,19 @@ member -5112192 +5066844 parent -809800 +833190 index -2966 +2851 child -5095258 +5050544 @@ -27533,47 +28091,47 @@ 1 2 -46948 +45126 2 3 -191658 +219789 3 4 -208336 +209109 4 5 -90285 +90638 5 7 -65073 +67210 7 9 -67212 +65539 9 15 -68221 +66497 15 -39 -62471 +45 +62758 -39 +45 245 -9591 +6520 @@ -27589,47 +28147,47 @@ 1 2 -46218 +44425 2 3 -191719 +219824 3 4 -202769 +203723 4 5 -93154 +93454 5 7 -65766 +67876 7 9 -67346 +65668 9 15 -68999 +67245 15 -38 -61462 +41 +62641 -38 +41 281 -12363 +8331 @@ -27645,62 +28203,62 @@ 1 2 -547 +525 2 5 -267 +257 5 9 -255 +245 9 18 -230 +222 23 100 -230 +222 122 186 -230 +222 188 293 -230 +222 296 374 -230 +222 375 542 -230 +222 572 3257 -230 +222 3427 -21556 -230 +22111 +222 -29162 -65993 -48 +30337 +70680 +46 @@ -27716,62 +28274,62 @@ 1 2 -534 +514 2 5 -218 +210 5 7 -230 +222 7 13 -230 +222 13 70 -230 +222 71 160 -230 +222 160 256 -230 +222 263 345 -230 +222 346 476 -243 +233 492 1685 -230 +222 1926 -8765 -230 +8775 +222 -10213 -66838 -121 +10226 +71530 +116 @@ -27787,7 +28345,7 @@ 1 2 -5095258 +5050544 @@ -27803,12 +28361,12 @@ 1 2 -5078555 +5034466 2 7 -16702 +16078 @@ -27818,15 +28376,15 @@ enclosingfunction -131751 +127164 child -131751 +127164 parent -74239 +71639 @@ -27840,7 +28398,7 @@ 1 2 -131751 +127164 @@ -27856,27 +28414,27 @@ 1 2 -39240 +37811 2 3 -21930 +21231 3 4 -7208 +6952 4 6 -5652 +5445 6 45 -206 +198 @@ -27886,27 +28444,27 @@ derivations -370309 +392220 derivation -370309 +392220 sub -346555 +367484 index -72 +70 super -237840 +236475 location -96351 +92613 @@ -27920,7 +28478,7 @@ 1 2 -370309 +392220 @@ -27936,7 +28494,7 @@ 1 2 -370309 +392220 @@ -27952,7 +28510,7 @@ 1 2 -370309 +392220 @@ -27968,7 +28526,7 @@ 1 2 -370309 +392220 @@ -27984,12 +28542,12 @@ 1 2 -326108 +345926 2 7 -20447 +21558 @@ -28005,12 +28563,12 @@ 1 2 -334933 +356161 2 7 -11621 +11322 @@ -28026,12 +28584,12 @@ 1 2 -326120 +345937 2 7 -20434 +21546 @@ -28047,12 +28605,12 @@ 1 2 -334921 +356150 2 7 -11633 +11334 @@ -28068,32 +28626,32 @@ 1 2 -12 +11 4 5 -12 +11 44 45 -12 +11 220 221 -12 +11 -957 -958 -12 +970 +971 +11 -29236 -29237 -12 +32328 +32329 +11 @@ -28109,32 +28667,32 @@ 1 2 -12 +11 4 5 -12 +11 44 45 -12 +11 220 221 -12 +11 -956 -957 -12 +969 +970 +11 -28508 -28509 -12 +31450 +31451 +11 @@ -28150,32 +28708,32 @@ 1 2 -12 +11 3 4 -12 +11 29 30 -12 +11 84 85 -12 +11 -441 -442 -12 +452 +453 +11 -19051 -19052 -12 +19713 +19714 +11 @@ -28191,32 +28749,32 @@ 1 2 -12 +11 4 5 -12 +11 17 18 -12 +11 51 52 -12 +11 254 255 -12 +11 7602 7603 -12 +11 @@ -28232,12 +28790,12 @@ 1 2 -222438 +221343 2 -766 -15402 +1134 +15131 @@ -28253,12 +28811,12 @@ 1 2 -222450 +221355 2 -766 -15390 +1134 +15120 @@ -28274,12 +28832,12 @@ 1 2 -237342 +235996 2 4 -498 +479 @@ -28295,12 +28853,12 @@ 1 2 -229780 +228634 2 439 -8059 +7840 @@ -28316,22 +28874,22 @@ 1 2 -74652 +70786 2 3 -9336 +8985 3 8 -7306 +7606 8 -682 -5057 +698 +5234 @@ -28347,22 +28905,22 @@ 1 2 -77193 +73146 2 3 -7002 +6858 3 -9 -7609 +8 +7443 -9 -682 -4546 +8 +698 +5164 @@ -28378,12 +28936,12 @@ 1 2 -96327 +92589 2 4 -24 +23 @@ -28399,22 +28957,22 @@ 1 2 -77655 +73882 2 3 -9056 +8833 3 -11 -7269 +10 +7326 -11 -682 -2370 +10 +698 +2570 @@ -28424,15 +28982,15 @@ derspecifiers -372947 +394756 der_id -370272 +392185 spec_id -48 +46 @@ -28446,12 +29004,12 @@ 1 2 -367598 +389615 2 3 -2674 +2570 @@ -28467,22 +29025,22 @@ 220 221 -12 +11 242 243 -12 +11 979 980 -12 +11 -29238 -29239 -12 +32343 +32344 +11 @@ -28492,15 +29050,15 @@ direct_base_offsets -282029 +307366 der_id -282029 +307366 offset -206 +210 @@ -28514,7 +29072,7 @@ 1 2 -282029 +307366 @@ -28530,62 +29088,67 @@ 1 2 -36 +46 2 3 -12 +11 4 5 -24 +23 5 6 -12 +11 6 7 -24 +11 7 8 -12 +23 8 9 -24 +11 + + +10 +11 +11 11 12 -12 +11 21 22 -12 +11 -78 -79 -12 +85 +86 +11 200 201 -12 +11 -22837 -22838 -12 +25931 +25932 +11 @@ -28595,19 +29158,19 @@ virtual_base_offsets -7026 +6753 sub -3890 +3739 super -534 +514 offset -267 +257 @@ -28621,22 +29184,22 @@ 1 2 -3063 +2944 2 4 -340 +327 4 7 -279 +268 7 11 -206 +198 @@ -28652,17 +29215,17 @@ 1 2 -3282 +3154 2 4 -328 +315 4 8 -279 +268 @@ -28678,52 +29241,52 @@ 1 2 -85 +81 2 3 -48 +46 3 4 -60 +58 4 5 -97 +93 5 7 -36 +35 8 13 -48 +46 13 15 -48 +46 15 23 -48 +46 24 60 -48 +46 196 197 -12 +11 @@ -28739,32 +29302,32 @@ 1 2 -303 +292 2 3 -85 +81 4 6 -36 +35 6 8 -48 +46 8 10 -48 +46 14 15 -12 +11 @@ -28780,57 +29343,57 @@ 2 3 -36 +35 4 5 -12 +11 5 6 -24 +23 6 8 -24 +23 8 9 -36 +35 10 12 -24 +23 14 19 -24 +23 20 27 -24 +23 28 31 -24 +23 36 97 -24 +23 97 98 -12 +11 @@ -28846,37 +29409,37 @@ 1 2 -85 +81 2 3 -36 +35 3 4 -48 +46 5 7 -24 +23 7 10 -24 +23 12 14 -24 +23 21 29 -24 +23 @@ -28886,23 +29449,23 @@ frienddecls -231178 +222208 id -231178 +222208 type_id -19511 +18753 decl_id -28810 +27692 location -8096 +7782 @@ -28916,7 +29479,7 @@ 1 2 -231178 +222208 @@ -28932,7 +29495,7 @@ 1 2 -231178 +222208 @@ -28948,7 +29511,7 @@ 1 2 -231178 +222208 @@ -28964,47 +29527,47 @@ 1 2 -6856 +6590 2 3 -2467 +2371 3 4 -1191 +1145 4 6 -1714 +1647 6 10 -1556 +1495 10 16 -1470 +1413 16 34 -1786 +1717 36 59 -1470 +1413 59 129 -996 +958 @@ -29020,47 +29583,47 @@ 1 2 -6856 +6590 2 3 -2467 +2371 3 4 -1191 +1145 4 6 -1714 +1647 6 10 -1556 +1495 10 16 -1470 +1413 16 34 -1786 +1717 36 59 -1470 +1413 59 129 -996 +958 @@ -29076,17 +29639,17 @@ 1 2 -17748 +17059 2 5 -1543 +1483 5 31 -218 +210 @@ -29102,37 +29665,37 @@ 1 2 -15815 +15201 2 3 -2261 +2173 3 5 -2479 +2383 5 9 -2188 +2103 9 20 -2030 +1951 20 28 -2467 +2371 28 390 -1568 +1507 @@ -29148,37 +29711,37 @@ 1 2 -15815 +15201 2 3 -2261 +2173 3 5 -2479 +2383 5 9 -2188 +2103 9 20 -2030 +1951 20 28 -2467 +2371 28 390 -1568 +1507 @@ -29194,12 +29757,12 @@ 1 2 -28215 +27120 2 46 -595 +572 @@ -29215,17 +29778,17 @@ 1 2 -6917 +6648 2 3 -1045 +1004 3 18239 -133 +128 @@ -29241,12 +29804,12 @@ 1 2 -7609 +7314 2 1215 -486 +467 @@ -29262,17 +29825,17 @@ 1 2 -6929 +6660 2 3 -1033 +993 3 1734 -133 +128 @@ -29282,19 +29845,19 @@ comments -1743633 +1675974 id -1743633 +1675974 contents -864492 +830947 location -1743633 +1675974 @@ -29308,7 +29871,7 @@ 1 2 -1743633 +1675974 @@ -29324,7 +29887,7 @@ 1 2 -1743633 +1675974 @@ -29340,17 +29903,17 @@ 1 2 -731525 +703139 2 3 -83149 +79923 3 10736 -49817 +47883 @@ -29366,17 +29929,17 @@ 1 2 -731525 +703139 2 3 -83149 +79923 3 10736 -49817 +47883 @@ -29392,7 +29955,7 @@ 1 2 -1743633 +1675974 @@ -29408,7 +29971,7 @@ 1 2 -1743633 +1675974 @@ -29418,15 +29981,15 @@ commentbinding -778436 +748230 id -679021 +652673 element -747438 +718434 @@ -29440,17 +30003,17 @@ 1 2 -616002 +592099 2 4 -58545 +56273 4 97 -4473 +4299 @@ -29466,12 +30029,12 @@ 1 2 -716439 +688638 2 3 -30998 +29796 @@ -29481,15 +30044,15 @@ exprconv -6445331 +6446816 converted -6445038 +6446523 conversion -6445331 +6446816 @@ -29503,7 +30066,7 @@ 1 2 -6444746 +6446231 2 @@ -29524,7 +30087,7 @@ 1 2 -6445331 +6446816 @@ -29534,30 +30097,30 @@ compgenerated -6720341 +6652484 id -6720341 +6652484 synthetic_destructor_call -59493 +57185 element -47422 +45582 i -340 +327 destructor_call -49573 +47650 @@ -29571,17 +30134,17 @@ 1 2 -38791 +37285 2 3 -6321 +6076 3 29 -2309 +2220 @@ -29597,17 +30160,17 @@ 1 2 -38791 +37285 2 3 -6321 +6076 3 29 -2309 +2220 @@ -29623,27 +30186,27 @@ 1 2 -255 +245 2 7 -24 +23 22 43 -24 +23 190 711 -24 +23 3901 3902 -12 +11 @@ -29659,27 +30222,27 @@ 1 2 -255 +245 2 7 -24 +23 21 37 -24 +23 146 550 -24 +23 3297 3298 -12 +11 @@ -29695,17 +30258,17 @@ 1 2 -43823 +42123 2 3 -3719 +3575 3 26 -2030 +1951 @@ -29721,7 +30284,7 @@ 1 2 -49573 +47650 @@ -29731,15 +30294,15 @@ namespaces -8497 +8167 id -8497 +8167 name -4570 +4393 @@ -29753,7 +30316,7 @@ 1 2 -8497 +8167 @@ -29769,17 +30332,17 @@ 1 2 -3841 +3692 2 3 -461 +444 3 139 -267 +257 @@ -29789,26 +30352,26 @@ namespace_inline -170 +163 id -170 +163 namespacembrs -1570027 +1616300 parentid -7913 +7606 memberid -1570027 +1616300 @@ -29822,62 +30385,67 @@ 1 2 -875 +829 2 3 -826 +794 3 4 -644 +385 4 -6 -680 +5 +607 -6 -9 -607 +5 +8 +666 -9 -16 -680 +8 +14 +677 -16 -27 -607 +14 +22 +595 -27 -46 -619 +22 +42 +595 -46 -85 -607 +42 +63 +572 -85 -169 -607 +63 +127 +572 -169 -444 -595 +127 +304 +572 -475 -29073 -559 +321 +1041 +572 + + +1101 +32701 +163 @@ -29893,7 +30461,7 @@ 1 2 -1570027 +1616300 @@ -29903,19 +30471,19 @@ exprparents -13615303 +13481241 expr_id -13615112 +13481052 child_index -3163 +3131 parent_id -9644209 +9549204 @@ -29929,7 +30497,7 @@ 1 2 -13615105 +13481045 2 @@ -29950,12 +30518,12 @@ 1 2 -13614927 +13480869 2 4 -184 +182 @@ -29971,37 +30539,37 @@ 1 2 -72 +71 2 3 -652 +645 3 4 -1674 +1657 4 46 -243 +241 46 56 -237 +234 56 3660 -237 +234 6434 -1187727 -46 +1188148 +45 @@ -30017,37 +30585,37 @@ 1 2 -72 +71 2 3 -652 +645 3 4 -1674 +1657 4 31 -243 +241 31 41 -237 +234 41 3645 -237 +234 6419 -1187740 -46 +1188161 +45 @@ -30063,17 +30631,17 @@ 1 2 -6840662 +6772879 2 3 -2212086 +2190858 3 1681 -591461 +585466 @@ -30089,17 +30657,17 @@ 1 2 -6840682 +6772898 2 3 -2212066 +2190839 3 480 -591461 +585466 @@ -30109,22 +30677,22 @@ expr_isload -5063114 +5014574 expr_id -5063114 +5014574 conversionkinds -4254113 +4255501 expr_id -4254113 +4255501 kind @@ -30142,7 +30710,7 @@ 1 2 -4254113 +4255501 @@ -30166,8 +30734,8 @@ 1 -13109 -13110 +13672 +13673 1 @@ -30181,8 +30749,8 @@ 1 -4161592 -4161593 +4162417 +4162418 1 @@ -30193,15 +30761,15 @@ iscall -2365240 +2284876 caller -2365240 +2284876 kind -36 +35 @@ -30215,7 +30783,7 @@ 1 2 -2365240 +2284876 @@ -30231,17 +30799,17 @@ 1319 1320 -12 +11 -5604 -5605 -12 +5643 +5644 +11 -187644 -187645 -12 +188582 +188583 +11 @@ -30251,15 +30819,15 @@ numtemplatearguments -157948 +152181 expr_id -157948 +152181 num -48 +46 @@ -30273,7 +30841,7 @@ 1 2 -157948 +152181 @@ -30289,22 +30857,22 @@ 3 4 -12 +11 41 42 -12 +11 651 652 -12 +11 -12298 -12299 -12 +12329 +12330 +11 @@ -30314,15 +30882,15 @@ specialnamequalifyingelements -12 +11 id -12 +11 name -12 +11 @@ -30336,7 +30904,7 @@ 1 2 -12 +11 @@ -30352,7 +30920,7 @@ 1 2 -12 +11 @@ -30362,23 +30930,23 @@ namequalifiers -1125621 +1116919 id -1125621 +1116919 qualifiableelement -1125621 +1116919 qualifyingelement -37001 +38961 location -509589 +506087 @@ -30392,7 +30960,7 @@ 1 2 -1125621 +1116919 @@ -30408,7 +30976,7 @@ 1 2 -1125621 +1116919 @@ -30424,7 +30992,7 @@ 1 2 -1125621 +1116919 @@ -30440,7 +31008,7 @@ 1 2 -1125621 +1116919 @@ -30456,7 +31024,7 @@ 1 2 -1125621 +1116919 @@ -30472,7 +31040,7 @@ 1 2 -1125621 +1116919 @@ -30488,32 +31056,32 @@ 1 2 -17109 +18965 2 3 -7935 +8142 3 4 -5081 +5043 4 -10 -2860 +11 +3027 -10 -86 -2781 +11 +129 +2935 -86 +132 24926 -1232 +848 @@ -30529,32 +31097,32 @@ 1 2 -17109 +18965 2 3 -7935 +8142 3 4 -5081 +5043 4 -10 -2860 +11 +3027 -10 -86 -2781 +11 +129 +2935 -86 +132 24926 -1232 +848 @@ -30570,27 +31138,27 @@ 1 2 -22745 +24850 2 3 -4817 +4762 3 4 -3802 +3770 4 11 -3018 +2974 11 16728 -2616 +2603 @@ -30606,22 +31174,22 @@ 1 2 -387650 +384719 2 3 -57004 +56877 3 7 -39037 +38851 7 381 -25895 +25639 @@ -30637,22 +31205,22 @@ 1 2 -387650 +384719 2 3 -57004 +56877 3 7 -39037 +38851 7 381 -25895 +25639 @@ -30668,17 +31236,17 @@ 1 2 -452478 +449080 2 3 -44785 +44650 3 190 -12324 +12356 @@ -30688,15 +31256,15 @@ varbind -5497554 +5445518 expr -5497428 +5445394 var -1549133 +1534266 @@ -30710,12 +31278,12 @@ 1 2 -5497303 +5445270 2 3 -125 +123 @@ -30731,32 +31299,32 @@ 1 2 -685882 +679661 2 3 -311295 +308179 3 4 -236831 +234430 4 5 -93953 +93020 5 9 -134777 +133430 9 6150 -86393 +85544 @@ -30766,15 +31334,15 @@ funbind -2442767 +2419854 expr -2142538 +2122577 fun -438611 +434205 @@ -30788,17 +31356,17 @@ 1 2 -1842553 +1825541 2 3 -299807 +296859 3 5 -177 +176 @@ -30814,32 +31382,32 @@ 1 2 -255153 +252065 2 3 -76151 +75516 3 4 -31642 +31302 4 7 -33910 +33957 7 37 -33831 +33520 37 6664 -7922 +7841 @@ -30849,19 +31417,19 @@ expr_allocator -27692 +26617 expr -27692 +26617 func -133 +128 form -12 +11 @@ -30875,7 +31443,7 @@ 1 2 -27692 +26617 @@ -30891,7 +31459,7 @@ 1 2 -27692 +26617 @@ -30907,42 +31475,42 @@ 1 2 -36 +35 3 4 -12 +11 4 5 -12 +11 5 6 -12 +11 7 8 -24 +23 39 40 -12 +11 973 974 -12 +11 1237 1238 -12 +11 @@ -30958,7 +31526,7 @@ 1 2 -133 +128 @@ -30974,7 +31542,7 @@ 2278 2279 -12 +11 @@ -30990,7 +31558,7 @@ 11 12 -12 +11 @@ -31000,19 +31568,19 @@ expr_deallocator -30998 +29796 expr -30998 +29796 func -145 +140 form -24 +23 @@ -31026,7 +31594,7 @@ 1 2 -30998 +29796 @@ -31042,7 +31610,7 @@ 1 2 -30998 +29796 @@ -31058,42 +31626,42 @@ 1 2 -36 +35 2 3 -24 +23 3 4 -12 +11 4 5 -12 +11 7 8 -24 +23 118 119 -12 +11 883 884 -12 +11 1521 1522 -12 +11 @@ -31109,7 +31677,7 @@ 1 2 -145 +140 @@ -31125,12 +31693,12 @@ 891 892 -12 +11 1659 1660 -12 +11 @@ -31146,12 +31714,12 @@ 4 5 -12 +11 8 9 -12 +11 @@ -31161,26 +31729,26 @@ expr_cond_two_operand -610 +611 cond -610 +611 expr_cond_guard -154429 +154519 cond -154429 +154519 guard -154429 +154519 @@ -31194,7 +31762,7 @@ 1 2 -154429 +154519 @@ -31210,7 +31778,7 @@ 1 2 -154429 +154519 @@ -31220,15 +31788,15 @@ expr_cond_true -154429 +154519 cond -154429 +154519 true -154429 +154519 @@ -31242,7 +31810,7 @@ 1 2 -154429 +154519 @@ -31258,7 +31826,7 @@ 1 2 -154429 +154519 @@ -31268,15 +31836,15 @@ expr_cond_false -154429 +154519 cond -154429 +154519 false -154429 +154519 @@ -31290,7 +31858,7 @@ 1 2 -154429 +154519 @@ -31306,7 +31874,7 @@ 1 2 -154429 +154519 @@ -31316,15 +31884,15 @@ values -8776796 +8788031 id -8776796 +8788031 str -651390 +651491 @@ -31338,7 +31906,7 @@ 1 2 -8776796 +8788031 @@ -31354,17 +31922,17 @@ 1 2 -540103 +540120 2 3 -65463 +65472 3 -4044535 -45824 +4046841 +45899 @@ -31374,15 +31942,15 @@ valuetext -4759381 +4766569 id -4759381 +4766569 text -704971 +705085 @@ -31396,7 +31964,7 @@ 1 2 -4759381 +4766569 @@ -31412,22 +31980,22 @@ 1 2 -528095 +528108 2 3 -102815 +102830 3 7 -56849 +56879 7 427516 -17212 +17268 @@ -31437,15 +32005,15 @@ valuebind -9499071 +9509366 val -8769631 +8779926 expr -9499071 +9509366 @@ -31459,7 +32027,7 @@ 1 2 -8040923 +8051218 2 @@ -31485,7 +32053,7 @@ 1 2 -9499071 +9509366 @@ -31495,19 +32063,19 @@ fieldoffsets -259539 +251575 id -259539 +251575 byteoffset -3914 +9022 bitoffset -85 +52 @@ -31521,7 +32089,7 @@ 1 2 -259539 +251575 @@ -31537,7 +32105,7 @@ 1 2 -259539 +251575 @@ -31553,42 +32121,27 @@ 1 2 -1689 +6132 2 3 -534 +782 3 -4 -194 - - -4 6 -340 +750 6 -11 -328 - - -11 -23 -328 - - -23 -84 -303 +17 +678 -90 -12369 -194 +17 +11685 +678 @@ -31604,12 +32157,12 @@ 1 2 -3853 +8579 2 -8 -60 +9 +443 @@ -31623,29 +32176,44 @@ 12 -1 -2 -36 +83 +84 +6 -2 -3 -12 +87 +88 +6 -3 -4 -12 +102 +103 +6 -4 -5 -12 +122 +123 +6 -21338 -21339 -12 +127 +128 +6 + + +153 +154 +6 + + +195 +196 +6 + + +37692 +37693 +6 @@ -31659,24 +32227,44 @@ 12 -1 -2 -36 +40 +41 +6 -2 -3 -24 +44 +45 +6 -3 -4 -12 +45 +46 +6 -322 -323 -12 +52 +53 +6 + + +54 +55 +6 + + +58 +59 +6 + + +66 +67 +6 + + +1383 +1384 +6 @@ -31686,11 +32274,11 @@ bitfield -13357 +13365 id -13357 +13365 bits @@ -31712,7 +32300,7 @@ 1 2 -13357 +13365 @@ -31728,7 +32316,7 @@ 1 2 -13357 +13365 @@ -31892,23 +32480,23 @@ initialisers -1685017 +1668506 init -1685017 +1668506 var -649685 +643667 expr -1685017 +1668506 location -321906 +318643 @@ -31922,7 +32510,7 @@ 1 2 -1685017 +1668506 @@ -31938,7 +32526,7 @@ 1 2 -1685017 +1668506 @@ -31954,7 +32542,7 @@ 1 2 -1685017 +1668506 @@ -31970,22 +32558,22 @@ 1 2 -562000 +556871 2 16 -29079 +28784 16 17 -49688 +49185 17 53 -8917 +8827 @@ -32001,22 +32589,22 @@ 1 2 -562000 +556871 2 16 -29079 +28784 16 17 -49688 +49185 17 53 -8917 +8827 @@ -32032,7 +32620,7 @@ 1 2 -649672 +643654 2 @@ -32053,7 +32641,7 @@ 1 2 -1685017 +1668506 @@ -32069,7 +32657,7 @@ 1 2 -1685017 +1668506 @@ -32085,7 +32673,7 @@ 1 2 -1685017 +1668506 @@ -32101,27 +32689,27 @@ 1 2 -248450 +245906 2 3 -24096 +23845 3 7 -24485 +24243 7 65 -24346 +24126 67 109238 -527 +521 @@ -32137,22 +32725,22 @@ 1 2 -271334 +268551 2 3 -25342 +25091 3 -24 -24155 +23 +23904 -24 +23 12632 -1074 +1096 @@ -32168,27 +32756,27 @@ 1 2 -248450 +245906 2 3 -24096 +23845 3 7 -24485 +24243 7 65 -24346 +24126 67 109238 -527 +521 @@ -32198,15 +32786,15 @@ expr_ancestor -67772 +68706 exp -67176 +68133 ancestor -49695 +51330 @@ -32220,12 +32808,12 @@ 1 2 -66605 +67584 2 4 -571 +549 @@ -32241,17 +32829,17 @@ 1 2 -37405 +39517 2 3 -10150 +9756 3 29 -2139 +2056 @@ -32261,19 +32849,19 @@ exprs -18449753 +18460593 id -18449753 +18460593 kind -393 +1168 location -6150603 +3836046 @@ -32287,7 +32875,7 @@ 1 2 -18449753 +18460593 @@ -32303,7 +32891,7 @@ 1 2 -18449753 +18460593 @@ -32317,69 +32905,69 @@ 12 -5 -28 -30 +1 +14 +105 -71 -82 -30 +15 +44 +93 -94 -255 -30 +47 +86 +93 -271 -627 -30 +90 +223 +93 -858 -1879 -30 +296 +463 +93 -2191 -3716 -30 +483 +715 +93 -4305 -6068 -30 +788 +2129 +93 -7004 -11661 -30 +2165 +2950 +93 -12107 -20202 -30 +3030 +4378 +93 -21965 -29561 -30 +4477 +6077 +93 -32830 -41032 -30 +6490 +17249 +93 -44670 -145995 -30 +19347 +188353 +93 -447805 -725766 -24 +191022 +403956 +35 @@ -32394,68 +32982,68 @@ 1 -24 -30 +4 +105 -27 -72 -30 +6 +13 +105 -77 -157 -30 +13 +24 +93 -171 -402 -30 +24 +38 +93 -422 -1083 -30 +38 +134 +93 -1179 -1862 -30 +144 +259 +93 -2201 -4268 -30 +269 +480 +93 -4679 -6584 -30 +481 +1074 +93 -6624 -11083 -30 +1095 +1411 +93 -11359 -12983 -30 +1422 +2045 +93 -17158 -28621 -30 +2059 +4557 +93 -29980 -88945 -30 +5888 +59687 +93 -128315 -425042 -24 +72153 +117893 +23 @@ -32471,22 +33059,37 @@ 1 2 -4450587 +1838158 2 3 -874643 +753582 3 -6 -496205 +4 +356208 -6 -22445 -329167 +4 +5 +276250 + + +5 +9 +301489 + + +9 +72 +287759 + + +72 +136887 +22598 @@ -32502,22 +33105,17 @@ 1 2 -4599301 +2734142 2 3 -812812 +859259 3 -5 -498909 - - -5 -33 -239579 +30 +242644 @@ -32527,19 +33125,19 @@ expr_types -18617706 +18629051 id -18444987 +18456012 typeid -1372691 +1345343 value_category -36 +35 @@ -32553,12 +33151,12 @@ 1 2 -18272500 +18283254 2 4 -172487 +172758 @@ -32574,7 +33172,7 @@ 1 2 -18444987 +18456012 @@ -32590,42 +33188,42 @@ 1 2 -530591 +526443 2 3 -259102 +254107 3 4 -113553 +110864 4 5 -95427 +92110 5 8 -122925 +118483 8 14 -105736 +102381 14 -46 -103864 +47 +101797 -46 -111456 -41489 +47 +123210 +39155 @@ -32641,17 +33239,17 @@ 1 2 -1207109 +1185928 2 3 -157753 +151877 3 4 -7828 +7536 @@ -32667,17 +33265,17 @@ 4533 4534 -12 +11 -340895 -340896 -12 +342547 +342548 +11 -1171875 -1171876 -12 +1232420 +1232421 +11 @@ -32691,19 +33289,19 @@ 12 -1340 -1341 -12 +1341 +1342 +11 -29733 -29734 -12 +29841 +29842 +11 -96111 -96112 -12 +98243 +98244 +11 @@ -32713,15 +33311,15 @@ new_allocated_type -29527 +28382 expr -29527 +28382 type_id -18234 +17527 @@ -32735,7 +33333,7 @@ 1 2 -29527 +28382 @@ -32751,22 +33349,22 @@ 1 2 -12667 +12175 2 3 -4035 +3879 3 9 -1446 +1390 10 92 -85 +81 @@ -32776,15 +33374,15 @@ new_array_allocated_type -5364 +5310 expr -5364 +5310 type_id -2306 +2283 @@ -32798,7 +33396,7 @@ 1 2 -5364 +5310 @@ -32819,12 +33417,12 @@ 2 3 -2043 +2022 3 7 -177 +176 8 @@ -33376,15 +33974,15 @@ condition_decl_bind -7646 +7349 expr -7646 +7349 decl -7646 +7349 @@ -33398,7 +33996,7 @@ 1 2 -7646 +7349 @@ -33414,7 +34012,7 @@ 1 2 -7646 +7349 @@ -33424,15 +34022,15 @@ typeid_bind -4899 +4708 expr -4899 +4708 type_id -2601 +2500 @@ -33446,7 +34044,7 @@ 1 2 -4899 +4708 @@ -33462,22 +34060,22 @@ 1 2 -1300 +1250 2 3 -996 +958 3 6 -230 +222 6 17 -72 +70 @@ -33487,15 +34085,15 @@ uuidof_bind -856 +848 expr -856 +848 type_id -652 +645 @@ -33509,7 +34107,7 @@ 1 2 -856 +848 @@ -33525,12 +34123,12 @@ 1 2 -481 +476 2 3 -138 +137 3 @@ -33545,15 +34143,15 @@ sizeof_bind -156997 +157089 expr -156997 +157089 type_id -2673 +2674 @@ -33567,7 +34165,7 @@ 1 2 -156997 +157089 @@ -33583,7 +34181,7 @@ 1 2 -1044 +1045 2 @@ -33681,11 +34279,11 @@ lambdas -12641 +12513 expr -12641 +12513 default_capture @@ -33707,7 +34305,7 @@ 1 2 -12641 +12513 @@ -33723,7 +34321,7 @@ 1 2 -12641 +12513 @@ -33812,23 +34410,23 @@ lambda_capture -21730 +21509 id -21730 +21509 lambda -10097 +9994 index -112 +110 field -21730 +21509 captured_by_reference @@ -33840,7 +34438,7 @@ location -14051 +13909 @@ -33854,7 +34452,7 @@ 1 2 -21730 +21509 @@ -33870,7 +34468,7 @@ 1 2 -21730 +21509 @@ -33886,7 +34484,7 @@ 1 2 -21730 +21509 @@ -33902,7 +34500,7 @@ 1 2 -21730 +21509 @@ -33918,7 +34516,7 @@ 1 2 -21730 +21509 @@ -33934,7 +34532,7 @@ 1 2 -21730 +21509 @@ -33950,27 +34548,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -33986,27 +34584,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -34022,27 +34620,27 @@ 1 2 -5002 +4951 2 3 -2379 +2355 3 4 -1265 +1252 4 6 -922 +913 6 18 -527 +521 @@ -34058,12 +34656,12 @@ 1 2 -9629 +9531 2 3 -467 +463 @@ -34079,7 +34677,7 @@ 1 2 -10077 +9975 2 @@ -34100,27 +34698,27 @@ 1 2 -5483 +5428 2 3 -2504 +2479 3 4 -1041 +1030 4 7 -823 +815 7 18 -243 +241 @@ -34429,7 +35027,7 @@ 2 3 -85 +84 @@ -34450,7 +35048,7 @@ 2 3 -46 +45 @@ -34562,7 +35160,7 @@ 1 2 -21730 +21509 @@ -34578,7 +35176,7 @@ 1 2 -21730 +21509 @@ -34594,7 +35192,7 @@ 1 2 -21730 +21509 @@ -34610,7 +35208,7 @@ 1 2 -21730 +21509 @@ -34626,7 +35224,7 @@ 1 2 -21730 +21509 @@ -34642,7 +35240,7 @@ 1 2 -21730 +21509 @@ -34900,17 +35498,17 @@ 1 2 -12667 +12539 2 6 -1061 +1050 6 68 -322 +319 @@ -34926,12 +35524,12 @@ 1 2 -13115 +12982 2 68 -935 +926 @@ -34947,12 +35545,12 @@ 1 2 -13511 +13374 2 8 -540 +534 @@ -34968,17 +35566,17 @@ 1 2 -12667 +12539 2 6 -1061 +1050 6 68 -322 +319 @@ -34994,7 +35592,7 @@ 1 2 -14032 +13889 2 @@ -35015,7 +35613,7 @@ 1 2 -14051 +13909 @@ -35141,19 +35739,19 @@ stmts -4943740 +4765273 id -4943740 +4765273 kind -230 +222 location -1317574 +1266448 @@ -35167,7 +35765,7 @@ 1 2 -4943740 +4765273 @@ -35183,7 +35781,7 @@ 1 2 -4943740 +4765273 @@ -35199,97 +35797,97 @@ 2 3 -12 +11 28 29 -12 +11 338 339 -12 +11 473 474 -12 +11 690 691 -12 +11 1560 1561 -12 +11 1757 1758 -12 +11 -2076 -2077 -12 +2080 +2081 +11 -2191 -2192 -12 +2193 +2194 +11 2707 2708 -12 +11 2748 2749 -12 +11 -2944 -2945 -12 +2946 +2947 +11 3296 3297 -12 +11 4540 4541 -12 +11 -28688 -28689 -12 +28694 +28695 +11 -53254 -53255 -12 +53369 +53370 +11 -85878 -85879 -12 +86211 +86212 +11 -98483 -98484 -12 +98824 +98825 +11 -115024 -115025 -12 +115365 +115366 +11 @@ -35305,97 +35903,97 @@ 2 3 -12 +11 23 24 -12 +11 106 107 -12 +11 112 113 -12 +11 178 179 -12 +11 252 253 -12 +11 296 297 -12 +11 661 662 -12 +11 663 664 -12 +11 991 992 -12 +11 1030 1031 -12 +11 1408 1409 -12 +11 1918 1919 -12 +11 2676 2677 -12 +11 10172 10173 -12 +11 10231 10232 -12 +11 22268 22269 -12 +11 26534 26535 -12 +11 31957 31958 -12 +11 @@ -35411,32 +36009,32 @@ 1 2 -779628 +747015 2 3 -179173 +173050 3 4 -120275 +116169 4 6 -106891 +103199 6 19 -102794 +99168 19 -4895 -28810 +4923 +27844 @@ -35452,12 +36050,12 @@ 1 2 -1291693 +1241571 2 9 -25881 +24876 @@ -35563,15 +36161,15 @@ if_then -524558 +524866 if_stmt -524558 +524866 then_id -524558 +524866 @@ -35585,7 +36183,7 @@ 1 2 -524558 +524866 @@ -35601,7 +36199,7 @@ 1 2 -524558 +524866 @@ -35611,15 +36209,15 @@ if_else -148234 +148322 if_stmt -148234 +148322 else_id -148234 +148322 @@ -35633,7 +36231,7 @@ 1 2 -148234 +148322 @@ -35649,7 +36247,7 @@ 1 2 -148234 +148322 @@ -35755,15 +36353,15 @@ while_body -32907 +31630 while_stmt -32907 +31630 body_id -32907 +31630 @@ -35777,7 +36375,7 @@ 1 2 -32907 +31630 @@ -35793,7 +36391,7 @@ 1 2 -32907 +31630 @@ -35803,15 +36401,15 @@ do_body -149900 +149988 do_stmt -149900 +149988 body_id -149900 +149988 @@ -35825,7 +36423,7 @@ 1 2 -149900 +149988 @@ -35841,7 +36439,7 @@ 1 2 -149900 +149988 @@ -35851,11 +36449,11 @@ switch_case -281530 +281695 switch_stmt -55225 +55258 index @@ -35863,7 +36461,7 @@ case_id -281530 +281695 @@ -35877,17 +36475,17 @@ 1 5 -4288 +4290 5 6 -48725 +48753 6 156 -2212 +2213 @@ -35903,17 +36501,17 @@ 1 5 -4288 +4290 5 6 -48725 +48753 6 156 -2212 +2213 @@ -36031,7 +36629,7 @@ 1 2 -281530 +281695 @@ -36047,7 +36645,7 @@ 1 2 -281530 +281695 @@ -36057,15 +36655,15 @@ switch_body -55225 +55258 switch_stmt -55225 +55258 body_id -55225 +55258 @@ -36079,7 +36677,7 @@ 1 2 -55225 +55258 @@ -36095,7 +36693,7 @@ 1 2 -55225 +55258 @@ -36105,15 +36703,15 @@ for_initialization -29922 +29619 for_stmt -29922 +29619 init_id -29922 +29619 @@ -36127,7 +36725,7 @@ 1 2 -29922 +29619 @@ -36143,7 +36741,7 @@ 1 2 -29922 +29619 @@ -36153,15 +36751,15 @@ for_condition -31781 +31459 for_stmt -31781 +31459 condition_id -31781 +31459 @@ -36175,7 +36773,7 @@ 1 2 -31781 +31459 @@ -36191,7 +36789,7 @@ 1 2 -31781 +31459 @@ -36201,15 +36799,15 @@ for_update -29659 +29358 for_stmt -29659 +29358 update_id -29659 +29358 @@ -36223,7 +36821,7 @@ 1 2 -29659 +29358 @@ -36239,7 +36837,7 @@ 1 2 -29659 +29358 @@ -36249,15 +36847,15 @@ for_body -32387 +32059 for_stmt -32387 +32059 body_id -32387 +32059 @@ -36271,7 +36869,7 @@ 1 2 -32387 +32059 @@ -36287,7 +36885,7 @@ 1 2 -32387 +32059 @@ -36297,19 +36895,19 @@ stmtparents -4168478 +4131960 id -4168478 +4131960 index -12799 +836 parent -1762006 +1583254 @@ -36323,7 +36921,7 @@ 1 2 -4168478 +4131960 @@ -36339,7 +36937,7 @@ 1 2 -4168478 +4131960 @@ -36355,52 +36953,57 @@ 1 2 -4020 +182 2 3 -1094 +149 3 -4 -520 +5 +41 -4 -5 -1496 +5 +7 +72 7 -8 -1047 +9 +68 -8 -12 -830 +9 +18 +63 -12 -29 -1127 +18 +39 +64 -29 -37 -909 +39 +111 +63 -37 -74 -975 +112 +836 +63 -74 -191996 -777 +920 +136298 +63 + + +254134 +706946 +5 @@ -36416,52 +37019,57 @@ 1 2 -4020 +182 2 3 -1094 +149 3 -4 -520 +5 +41 -4 -5 -1496 +5 +7 +72 7 -8 -1047 +9 +68 -8 -12 -830 +9 +18 +63 -12 -29 -1127 +18 +39 +64 -29 -37 -909 +39 +111 +63 -37 -74 -975 +112 +836 +63 -74 -191996 -777 +920 +136298 +63 + + +254134 +706946 +5 @@ -36477,32 +37085,27 @@ 1 2 -1004414 +841847 2 3 -386602 +376317 3 4 -109343 +145318 4 -6 -115439 - - -6 -17 -133386 +9 +119501 -17 -1943 -12819 +9 +465 +100269 @@ -36518,32 +37121,27 @@ 1 2 -1004414 +841847 2 3 -386602 +376317 3 4 -109343 +145318 4 -6 -115439 - - -6 -17 -133386 +9 +119501 -17 -1943 -12819 +9 +465 +100269 @@ -36553,26 +37151,26 @@ ishandler -21888 +21666 block -21888 +21666 successors -17214104 +17224218 from -16042874 +16052300 to -16040997 +16050421 @@ -36586,12 +37184,12 @@ 1 2 -15044821 +15053661 2 156 -998052 +998638 @@ -36607,12 +37205,12 @@ 1 2 -15328885 +15337891 2 419 -712111 +712530 @@ -36622,15 +37220,15 @@ truecond -966805 +967373 from -966805 +967373 to -937112 +937663 @@ -36644,7 +37242,7 @@ 1 2 -966805 +967373 @@ -36660,12 +37258,12 @@ 1 2 -913540 +914077 2 21 -23572 +23585 @@ -36675,15 +37273,15 @@ falsecond -966805 +967373 from -966805 +967373 to -812105 +812583 @@ -36697,7 +37295,7 @@ 1 2 -966805 +967373 @@ -36713,17 +37311,17 @@ 1 2 -698749 +699160 2 3 -87006 +87057 3 25 -26349 +26365 @@ -36733,11 +37331,11 @@ stmt_decl_bind -538233 +532777 stmt -531279 +525894 num @@ -36745,7 +37343,7 @@ decl -538233 +532777 @@ -36759,12 +37357,12 @@ 1 2 -525776 +520447 2 9 -5503 +5447 @@ -36780,12 +37378,12 @@ 1 2 -525756 +520427 2 9 -5523 +5467 @@ -36903,7 +37501,7 @@ 1 2 -538233 +532777 @@ -36919,7 +37517,7 @@ 1 2 -538233 +532777 @@ -36929,19 +37527,19 @@ stmt_decl_entry_bind -519726 +520031 stmt -474524 +474803 num -491 +492 decl_entry -495657 +495948 @@ -36955,12 +37553,12 @@ 1 2 -441842 +442101 2 274 -32682 +32702 @@ -36976,12 +37574,12 @@ 1 2 -441842 +442101 2 15 -32682 +32702 @@ -37064,12 +37662,12 @@ 1 2 -483634 +483918 2 85 -12022 +12029 @@ -37085,7 +37683,7 @@ 1 2 -495588 +495879 2 @@ -37100,15 +37698,15 @@ blockscope -1398256 +1347984 block -1398256 +1347984 enclosing -1254288 +1209602 @@ -37122,7 +37720,7 @@ 1 2 -1398256 +1347984 @@ -37138,12 +37736,12 @@ 1 2 -1171636 +1130157 2 509 -82651 +79444 @@ -37153,19 +37751,19 @@ jumpinfo -366503 +366719 id -366503 +366719 str -6361 +6365 target -85508 +85558 @@ -37179,7 +37777,7 @@ 1 2 -366503 +366719 @@ -37195,7 +37793,7 @@ 1 2 -366503 +366719 @@ -37216,12 +37814,12 @@ 2 3 -3507 +3509 3 4 -835 +836 4 @@ -37231,12 +37829,12 @@ 5 7 -491 +492 7 15 -500 +501 15 @@ -37257,12 +37855,12 @@ 1 2 -5095 +5098 2 3 -700 +701 3 @@ -37293,32 +37891,32 @@ 2 3 -21251 +21263 3 4 -7559 +7564 4 5 -3816 +3818 5 6 -39695 +39718 6 7 -11019 +11025 7 162 -1880 +1882 @@ -37334,7 +37932,7 @@ 1 2 -85508 +85558 @@ -37344,19 +37942,19 @@ preprocdirects -1456121 +1399618 id -1456121 +1399618 kind -158 +151 location -1449131 +1392900 @@ -37370,7 +37968,7 @@ 1 2 -1456121 +1399618 @@ -37386,7 +37984,7 @@ 1 2 -1456121 +1399618 @@ -37402,67 +38000,67 @@ 4 5 -12 +11 8 9 -12 +11 500 501 -12 +11 929 930 -12 +11 1740 1741 -12 +11 1873 1874 -12 +11 5235 5236 -12 +11 5497 5498 -12 +11 7551 7552 -12 +11 14073 14074 -12 +11 26464 26465 -12 +11 27121 27122 -12 +11 28787 28788 -12 +11 @@ -37478,67 +38076,67 @@ 4 5 -12 +11 7 8 -12 +11 500 501 -12 +11 929 930 -12 +11 1740 1741 -12 +11 1873 1874 -12 +11 5235 5236 -12 +11 5497 5498 -12 +11 7551 7552 -12 +11 14073 14074 -12 +11 26122 26123 -12 +11 27121 27122 -12 +11 28555 28556 -12 +11 @@ -37554,12 +38152,12 @@ 1 2 -1448766 +1392549 2 234 -364 +350 @@ -37575,7 +38173,7 @@ 1 2 -1449131 +1392900 @@ -37585,15 +38183,15 @@ preprocpair -416102 +399956 begin -329694 +316901 elseelifend -416102 +399956 @@ -37607,17 +38205,17 @@ 1 2 -261399 +251256 2 3 -60247 +57909 3 53 -8047 +7735 @@ -37633,7 +38231,7 @@ 1 2 -416102 +399956 @@ -37643,41 +38241,41 @@ preproctrue -183112 +176006 branch -183112 +176006 preprocfalse -130000 +124956 branch -130000 +124956 preproctext -1062775 +1021536 id -1062775 +1021536 head -510083 +490290 body -192959 +185471 @@ -37691,7 +38289,7 @@ 1 2 -1062775 +1021536 @@ -37707,7 +38305,7 @@ 1 2 -1062775 +1021536 @@ -37723,22 +38321,22 @@ 1 2 -380459 +365696 2 3 -86116 +82774 3 19 -38414 +36923 19 752 -5093 +4895 @@ -37754,12 +38352,12 @@ 1 2 -486208 +467341 2 38 -23875 +22948 @@ -37775,12 +38373,12 @@ 1 2 -181252 +174219 2 64395 -11706 +11252 @@ -37796,12 +38394,12 @@ 1 2 -182893 +175796 2 21671 -10065 +9674 @@ -37811,15 +38409,15 @@ includes -321805 +309317 id -321805 +309317 included -60162 +57827 @@ -37833,7 +38431,7 @@ 1 2 -321805 +309317 @@ -37849,37 +38447,37 @@ 1 2 -29503 +28358 2 3 -9895 +9511 3 4 -5117 +4919 4 6 -5348 +5141 6 11 -4643 +4463 11 41 -4558 +4381 41 763 -1094 +1051 @@ -37889,15 +38487,15 @@ link_targets -644 +619 id -644 +619 binary -644 +619 @@ -37911,7 +38509,7 @@ 1 2 -644 +619 @@ -37927,7 +38525,7 @@ 1 2 -644 +619 @@ -37937,15 +38535,15 @@ link_parent -19143690 +19072521 element -5076549 +5117392 link_target -644 +619 @@ -37959,32 +38557,32 @@ 1 2 -1439430 +1455425 2 3 -1904730 +1924496 3 4 -772395 +779113 4 6 -426167 +434215 6 -27 -383109 +28 +394382 -27 +28 45 -150715 +129758 @@ -38000,67 +38598,67 @@ 2 3 -97 +93 5 557 -48 +46 -2555 -5912 -48 +2662 +6059 +46 -6322 -8240 -48 +6479 +8402 +46 -9873 -12705 -48 +10060 +12929 +46 -12726 -19568 -48 +13044 +20082 +46 -24613 -26319 -48 +24978 +26985 +46 -26410 -31881 -48 +27088 +32537 +46 -32502 -37729 -48 +33104 +38465 +46 -39858 -40615 -48 +41123 +42511 +46 -43096 -52498 -48 +44410 +55889 +46 -53361 -126529 -48 +55937 +132605 +46 -345660 -345661 -12 +362472 +362473 +11 From afe666500f54db4dc7aa7c688bcab1c1a12b7264 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 5 Nov 2019 11:34:37 +0000 Subject: [PATCH 0200/2538] C++: Simplify getTemplateArgument*() impl. --- cpp/ql/src/semmle/code/cpp/Class.qll | 18 ------------ cpp/ql/src/semmle/code/cpp/Declaration.qll | 33 ++++++++++------------ cpp/ql/src/semmle/code/cpp/Function.qll | 19 ------------- cpp/ql/src/semmle/code/cpp/Variable.qll | 18 ------------ 4 files changed, 15 insertions(+), 73 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Class.qll b/cpp/ql/src/semmle/code/cpp/Class.qll index 5ccf6193c4ff..297654a1afaa 100644 --- a/cpp/ql/src/semmle/code/cpp/Class.qll +++ b/cpp/ql/src/semmle/code/cpp/Class.qll @@ -605,24 +605,6 @@ class Class extends UserType { class_instantiation(underlyingElement(this), unresolveElement(c)) } - /** - * Gets the `i`th template argument used to instantiate this class from a - * class template. When called on a class template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgumentType(int i) { - class_template_argument(underlyingElement(this), i, unresolveElement(result)) - } - - /** - * Gets the `i`th template argument value used to instantiate this class from a - * class template. When called on a class template, this will return the - * `i`th template parameter value. - */ - override Expr getTemplateArgumentValue(int i) { - class_template_argument_value(underlyingElement(this), i, unresolveElement(result)) - } - /** * Holds if this class/struct is polymorphic (has a virtual function, or * inherits one). diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 9c8ce250d8d6..89f52f174deb 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -255,25 +255,22 @@ abstract class Declaration extends Locatable, @declaration { result = count(int i | exists(getTemplateArgument(i))) } - /** - * INTERNAL: Do not use. - * - * Gets a Type for a template argument. May be the template argument itself - * or the type of a non-type template argument. - * - * Use `getTemplateArgument` or `getTemplateKind` instead. - */ - Type getTemplateArgumentType(int index) { none() } + private Type getTemplateArgumentType(int index) { + class_template_argument(underlyingElement(this), index, unresolveElement(result)) + or + function_template_argument(underlyingElement(this), index, unresolveElement(result)) + or + variable_template_argument(underlyingElement(this), index, unresolveElement(result)) + } - /** - * INTERNAL: Do not use. - * - * Gets an Expression representing the value of a non-type template - * argument. - * - * Use `getTemplateArgument` or `getTemplateKind` instead. - */ - Expr getTemplateArgumentValue(int index) { none() } + + private Expr getTemplateArgumentValue(int index) { + class_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + or + function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + or + variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) + } } /** diff --git a/cpp/ql/src/semmle/code/cpp/Function.qll b/cpp/ql/src/semmle/code/cpp/Function.qll index 5436c3ba2183..14edf014b212 100644 --- a/cpp/ql/src/semmle/code/cpp/Function.qll +++ b/cpp/ql/src/semmle/code/cpp/Function.qll @@ -343,25 +343,6 @@ class Function extends Declaration, ControlFlowNode, AccessHolder, @function { function_instantiation(underlyingElement(this), unresolveElement(f)) } - /** - * Gets the `i`th template argument used to instantiate this function from a - * function template. When called on a function template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgumentType(int index) { - function_template_argument(underlyingElement(this), index, unresolveElement(result)) - } - - /** - * Gets the value of the `i`th template argument used to instantiate this - * function from a function template if that argument was a 'non-type' - * argument. When called on a function template, this with return the value - * of the `i`th template parameter. - */ - override Expr getTemplateArgumentValue(int index) { - function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - } - /** * Holds if this function is defined in several files. This is illegal in * C (though possible in some C++ compilers), and likely indicates that diff --git a/cpp/ql/src/semmle/code/cpp/Variable.qll b/cpp/ql/src/semmle/code/cpp/Variable.qll index 689f1c3bfa51..194cc5333c7d 100644 --- a/cpp/ql/src/semmle/code/cpp/Variable.qll +++ b/cpp/ql/src/semmle/code/cpp/Variable.qll @@ -155,24 +155,6 @@ class Variable extends Declaration, @variable { variable_instantiation(underlyingElement(this), unresolveElement(v)) } - /** - * Gets the `i`th template argument used to instantiate this variable from a - * variable template. When called on a variable template, this will return the - * `i`th template parameter. - */ - override Type getTemplateArgumentType(int index) { - variable_template_argument(underlyingElement(this), index, unresolveElement(result)) - } - - /** - * Gets the `i`th template argument value used to instantiate this variable from a - * variable template. When called on a variable template, this will return the - * `i`th template parameter value. - */ - override Expr getTemplateArgumentValue(int index) { - variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - } - /** * Holds if this is a compiler-generated variable. For example, a * [range-based for loop](http://en.cppreference.com/w/cpp/language/range-for) From 8eef953cd75ee10c1292a467fff3297202e5cbc1 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 5 Nov 2019 11:35:35 +0000 Subject: [PATCH 0201/2538] C++: Update 1.23 change notes --- change-notes/1.23/analysis-cpp.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/change-notes/1.23/analysis-cpp.md b/change-notes/1.23/analysis-cpp.md index f22436f55cb5..a92f78ca2f7b 100644 --- a/change-notes/1.23/analysis-cpp.md +++ b/change-notes/1.23/analysis-cpp.md @@ -54,3 +54,8 @@ The following changes in version 1.23 affect C/C++ analysis in all applications. lead to regressions (or improvements) in how queries are optimized because optimization in QL relies on static size estimates, and the control-flow edge relations will now have different size estimates than before. +* Support has been added for non-type template arguments. This means that the + return type of `Declaration::getTemplateArgument()` and + `Declaration::getATemplateArgument` have changed to `Locatable`. See the + documentation for `Declaration::getTemplateArgument()` and + `Declaration::getTemplateArgumentKind()` for details. From 5106626bd07d613f8e2f08193921b14f8539581d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Nov 2019 13:06:43 +0000 Subject: [PATCH 0202/2538] CPP: QLDoc helper predicates. --- .../CWE/CWE-457/InitializationFunctions.qll | 30 +++++++++++-------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 720cf11950b4..52b251bad00d 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -619,35 +619,41 @@ Function getAPossibleDefinition(Function undefinedFunction) { result.isDefined() } +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * If there is at least one defined target after performing some simple virtual dispatch + * resolution, then the result is all the defined targets. + */ private Function getTarget1(Call c) { - /* - * If there is at least one defined target after performing some simple virtual dispatch - * resolution, then the result is all the defined targets. - */ - result = VirtualDispatch::getAViableTarget(c) and result.isDefined() } +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * If we can use the heuristic matching of functions to find definitions for some of the viable + * targets, return those. + */ private Function getTarget2(Call c) { - /* - * If we can use the heuristic matching of functions to find definitions for some of the viable - * targets, return those. - */ - not exists(getTarget1(c)) and result = getAPossibleDefinition(VirtualDispatch::getAViableTarget(c)) } +/** + * Helper predicate for `getTarget`, that computes possible targets of a `Call`. + * + * Otherwise, the result is the undefined `Function` instances. + */ private Function getTarget3(Call c) { not exists(getTarget1(c)) and not exists(getTarget2(c)) and - // Otherwise, the result is the undefined `Function` instances. result = VirtualDispatch::getAViableTarget(c) } /** - * Gets a possible target for the Call, using the name and parameter matching if we did not associate + * Gets a possible target for the `Call`, using the name and parameter matching if we did not associate * this call with a specific definition at link or compile time, and performing simple virtual * dispatch resolution. */ From 7456a92d6dc5e45f449bf485faba572dfc5a1324 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Nov 2019 13:10:19 +0000 Subject: [PATCH 0203/2538] CPP: Autoformat. --- cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 52b251bad00d..86102008e2b6 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -618,7 +618,7 @@ Function getAPossibleDefinition(Function undefinedFunction) { ) and result.isDefined() } - + /** * Helper predicate for `getTarget`, that computes possible targets of a `Call`. * From df2fbfb3d02485b5a568769ff78d49c6841282b5 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Fri, 1 Nov 2019 13:16:45 +0100 Subject: [PATCH 0204/2538] C++: localInstruction{Flow,Taint} helpers These are analogous to the existing `localExpr{Flow,Taint}` predicates. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 8 ++++++++ .../code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll | 8 ++++++++ 2 files changed, 16 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index f824e0b6bf25..cd989c947103 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -214,6 +214,14 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction */ predicate localFlow(Node source, Node sink) { localFlowStep*(source, sink) } +/** + * Holds if data can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +predicate localInstructionFlow(Instruction e1, Instruction e2) { + localFlow(instructionNode(e1), instructionNode(e2)) +} + /** * Holds if data can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll index e34709e94ec1..8d7c9194f4f8 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/TaintTrackingUtil.qll @@ -53,6 +53,14 @@ private predicate localInstructionTaintStep(Instruction nodeFrom, Instruction no */ predicate localTaint(DataFlow::Node source, DataFlow::Node sink) { localTaintStep*(source, sink) } +/** + * Holds if taint can flow from `i1` to `i2` in zero or more + * local (intra-procedural) steps. + */ +predicate localInstructionTaint(Instruction i1, Instruction i2) { + localTaint(DataFlow::instructionNode(i1), DataFlow::instructionNode(i2)) +} + /** * Holds if taint can flow from `e1` to `e2` in zero or more * local (intra-procedural) steps. From 20ae183c16437c57ebdc651078caa39375103277 Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Tue, 5 Nov 2019 14:18:29 +0000 Subject: [PATCH 0205/2538] C++: Tidy up formatting --- cpp/ql/src/semmle/code/cpp/Declaration.qll | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Declaration.qll b/cpp/ql/src/semmle/code/cpp/Declaration.qll index 89f52f174deb..04135880129c 100644 --- a/cpp/ql/src/semmle/code/cpp/Declaration.qll +++ b/cpp/ql/src/semmle/code/cpp/Declaration.qll @@ -257,18 +257,17 @@ abstract class Declaration extends Locatable, @declaration { private Type getTemplateArgumentType(int index) { class_template_argument(underlyingElement(this), index, unresolveElement(result)) - or + or function_template_argument(underlyingElement(this), index, unresolveElement(result)) - or + or variable_template_argument(underlyingElement(this), index, unresolveElement(result)) } - private Expr getTemplateArgumentValue(int index) { class_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - or + or function_template_argument_value(underlyingElement(this), index, unresolveElement(result)) - or + or variable_template_argument_value(underlyingElement(this), index, unresolveElement(result)) } } From 16b63b3d01a68b8065f463002f43254aa9cdb369 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 5 Nov 2019 15:45:17 +0100 Subject: [PATCH 0206/2538] move deferred model to the query where it is used --- .../src/Statements/UseOfReturnlessFunction.ql | 51 +++++++++++++++++++ .../ql/src/semmle/javascript/Promises.qll | 42 --------------- .../TaintTracking/BasicTaintTracking.expected | 1 - .../library-tests/TaintTracking/promise.js | 11 ---- .../Statements/UseOfReturnlessFunction/tst.js | 6 +++ 5 files changed, 57 insertions(+), 54 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index f8f459cc84d0..48af33b8e436 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -149,6 +149,57 @@ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { ) } + +/** + * Provides classes for working with various Deferred implementations. + * It is a heuristic. The heuristic assume that a class is a promise defintion + * if the class is called "Deferred" and the method `resolve` is called on an instance. + * + * Removes some false positives in the js/use-of-returnless-function query. + */ +module Deferred { + /** + * An instance of a `Deferred` class. + * E.g. the result from `new Deferred()` or `new $.Deferred()`. + */ + class DeferredInstance extends DataFlow::NewNode { + // Describes both `new Deferred()`, `new $.Deferred` and other variants. + DeferredInstance() { this.getCalleeName() = "Deferred" } + + private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { + t.start() and + result = this + or + exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) + } + + DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } + } + + /** + * A promise object created by a Deferred constructor + */ + private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { + DeferredPromiseDefinition() { + // hardening of the "Deferred" heuristic: a method call to `resolve`. + exists(ref().getAMethodCall("resolve")) + } + + override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } + } + + /** + * A resolved promise created by a `new Deferred().resolve()` call. + */ + class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { + ResolvedDeferredPromiseDefinition() { + this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") + } + + override DataFlow::Node getValue() { result = getArgument(0) } + } +} + from DataFlow::CallNode call, Function func, string name, string msg where ( diff --git a/javascript/ql/src/semmle/javascript/Promises.qll b/javascript/ql/src/semmle/javascript/Promises.qll index ae8554c1a0a3..858064e85a0d 100644 --- a/javascript/ql/src/semmle/javascript/Promises.qll +++ b/javascript/ql/src/semmle/javascript/Promises.qll @@ -32,48 +32,6 @@ module Bluebird { } } -/** - * Provides classes for working with various Deferred implementations - */ -module Deferred { - class DeferredInstance extends DataFlow::NewNode { - // Describes both `new Deferred()`, `new $.Deferred` and other variants. - DeferredInstance() { this.getCalleeName() = "Deferred" } - - private DataFlow::SourceNode ref(DataFlow::TypeTracker t) { - t.start() and - result = this - or - exists(DataFlow::TypeTracker t2 | result = ref(t2).track(t2, t)) - } - - DataFlow::SourceNode ref() { result = ref(DataFlow::TypeTracker::end()) } - } - - /** - * A promise object created by a Deferred constructor - */ - private class DeferredPromiseDefinition extends PromiseDefinition, DeferredInstance { - DeferredPromiseDefinition() { - // hardening of the "Deferred" heuristic: a method call to `resolve`. - exists(ref().getAMethodCall("resolve")) - } - - override DataFlow::FunctionNode getExecutor() { result = getCallback(0) } - } - - /** - * A resolved promise created by a `new Deferred().resolve()` call. - */ - class ResolvedDeferredPromiseDefinition extends ResolvedPromiseDefinition { - ResolvedDeferredPromiseDefinition() { - this = any(DeferredPromiseDefinition def).ref().getAMethodCall("resolve") - } - - override DataFlow::Node getValue() { result = getArgument(0) } - } -} - /** * Provides classes for working with the `q` library (https://github.com/kriskowal/q). */ diff --git a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected index 77592a2e855c..2722f67d6fdf 100644 --- a/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected +++ b/javascript/ql/test/library-tests/TaintTracking/BasicTaintTracking.expected @@ -69,7 +69,6 @@ typeInferenceMismatch | promise.js:5:25:5:32 | source() | promise.js:5:8:5:33 | bluebir ... urce()) | | promise.js:10:24:10:31 | source() | promise.js:10:8:10:32 | Promise ... urce()) | | promise.js:12:20:12:27 | source() | promise.js:13:8:13:23 | resolver.promise | -| promise.js:22:23:22:30 | source() | promise.js:22:7:22:31 | promise ... urce()) | | sanitizer-guards.js:2:11:2:18 | source() | sanitizer-guards.js:4:8:4:8 | x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:15:10:15:15 | this.x | | sanitizer-guards.js:13:14:13:21 | source() | sanitizer-guards.js:21:14:21:19 | this.x | diff --git a/javascript/ql/test/library-tests/TaintTracking/promise.js b/javascript/ql/test/library-tests/TaintTracking/promise.js index d16e57241e8d..9714d258df5d 100644 --- a/javascript/ql/test/library-tests/TaintTracking/promise.js +++ b/javascript/ql/test/library-tests/TaintTracking/promise.js @@ -11,15 +11,4 @@ function closure() { let resolver = Promise.withResolver(); resolver.resolve(source()); sink(resolver.promise); // NOT OK -} - -class Deferred { - -} - -function deferred() { - var promise = new Deferred(); - sink(promise.resolve(source())); // NOT OK - - new Deferred().reject("foo") // <- a reject has to exist. } \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js index 8a6a44707edd..90a52153dead 100644 --- a/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js +++ b/javascript/ql/test/query-tests/Statements/UseOfReturnlessFunction/tst.js @@ -82,4 +82,10 @@ var baz = [1,2,3].filter(n => {n === 3}) // OK console.log(baz); + + class Deferred { + + } + + new Deferred().resolve(onlySideEffects()); // OK })(); \ No newline at end of file From 3e92d0ffb5cb1a3faf930570b46505f8ef42c53f Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 15:49:42 +0000 Subject: [PATCH 0207/2538] JavaScript: Remove redundant `--experimental` extractor options. --- .../library-tests/PropWrite/tests.expected | 396 +++++++++--------- .../ql/test/library-tests/PropWrite/tst.js | 1 - .../library-tests/SpreadRestProperties/tst.js | 2 - .../library-tests/TaintTracking/exceptions.js | 2 - .../Templates/templates-revised.js | 2 - .../TrailingFunctionCommas/tst.js | 2 - .../library-tests/frameworks/SQL/mssql1.js | 2 - .../RedeclaredVariable/restprops.js | 2 - .../Declarations/UnusedParameter/restprops.js | 2 - .../Expressions/SelfAssignment/jsdoc.js | 2 - .../LanguageFeatures/IllegalInvocation/tst.js | 2 - .../query-tests/NodeJS/DubiousImport/m.js | 2 - .../test/query-tests/Performance/ReDoS/tst.js | 2 - .../Security/CWE-089/untyped/tst2.js | 2 - 14 files changed, 198 insertions(+), 223 deletions(-) diff --git a/javascript/ql/test/library-tests/PropWrite/tests.expected b/javascript/ql/test/library-tests/PropWrite/tests.expected index 33eff9b06287..beb4916f397a 100644 --- a/javascript/ql/test/library-tests/PropWrite/tests.expected +++ b/javascript/ql/test/library-tests/PropWrite/tests.expected @@ -1,55 +1,55 @@ test_getAPropertyRead -| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state | -| tst.js:14:5:14:11 | console | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | tst.js:17:5:17:15 | console.log | -| tst.js:23:15:23:29 | this.someMethod | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:36:24:45 | this.state | tst.js:24:36:24:50 | this.state.name | -| tst.js:34:6:34:7 | vv | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | tst.js:45:3:45:13 | console.log | -| tst.js:45:15:45:17 | obj | tst.js:45:15:45:20 | obj[p] | +| tst.js:1:1:1:0 | this | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | tst.js:23:36:23:45 | this.state | +| tst.js:13:5:13:11 | console | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | tst.js:16:5:16:15 | console.log | +| tst.js:22:15:22:29 | this.someMethod | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:36:23:45 | this.state | tst.js:23:36:23:50 | this.state.name | +| tst.js:33:6:33:7 | vv | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | tst.js:44:3:44:13 | console.log | +| tst.js:44:15:44:17 | obj | tst.js:44:15:44:20 | obj[p] | test_getAPropertyReference | classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField | -| tst.js:1:1:1:0 | this | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | tst.js:24:36:24:45 | this.state | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:14:5:14:11 | console | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | tst.js:17:5:17:15 | console.log | -| tst.js:21:1:21:1 | C | tst.js:21:1:21:6 | C.prop | -| tst.js:23:15:23:29 | this.someMethod | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:8:24:57 |
    | tst.js:24:13:24:27 | onClick={click} | -| tst.js:24:36:24:45 | this.state | tst.js:24:36:24:50 | this.state.name | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:8 | n: 1 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:10 | [v]: 2 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | -| tst.js:34:6:34:7 | vv | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:13:38:15 | "a" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:18:38:20 | "b" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:23:38:25 | "c" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:13:39:15 | "a" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:20:39:22 | "c" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:15:40:17 | "b" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:20:40:22 | "c" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:13:41:15 | "a" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:18:41:20 | "b" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:13:42:15 | "a" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:27:42:29 | "d" | -| tst.js:45:3:45:9 | console | tst.js:45:3:45:13 | console.log | -| tst.js:45:15:45:17 | obj | tst.js:45:15:45:20 | obj[p] | +| tst.js:1:1:1:0 | this | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | tst.js:23:36:23:45 | this.state | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:2:5:2:8 | x: 4 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:13:5:13:11 | console | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | tst.js:16:5:16:15 | console.log | +| tst.js:20:1:20:1 | C | tst.js:20:1:20:6 | C.prop | +| tst.js:22:15:22:29 | this.someMethod | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:8:23:57 |
    | tst.js:23:13:23:27 | onClick={click} | +| tst.js:23:36:23:45 | this.state | tst.js:23:36:23:50 | this.state.name | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:31:5:31:8 | n: 1 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:10 | [v]: 2 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:33:6:33:7 | vv | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:13:37:15 | "a" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:18:37:20 | "b" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:23:37:25 | "c" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:13:38:15 | "a" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:20:38:22 | "c" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:15:39:17 | "b" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:20:39:22 | "c" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:13:40:15 | "a" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:18:40:20 | "b" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:13:41:15 | "a" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:27:41:29 | "d" | +| tst.js:44:3:44:9 | console | tst.js:44:3:44:13 | console.log | +| tst.js:44:15:44:17 | obj | tst.js:44:15:44:20 | obj[p] | test_getAPropertySource | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField | @@ -57,10 +57,10 @@ test_getAPropertySource | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:41:12:42 | {} | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:22:24:26 | click | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:22:23:26 | click | test_PropWritePropName | classes.ts:3:21:3:20 | constructor() {} | constructor | | classes.ts:4:3:4:24 | instanc ... foo(); | instanceField | @@ -70,123 +70,123 @@ test_PropWritePropName | classes.ts:12:17:12:37 | public ... erField | parameterField | | classes.ts:16:5:16:46 | constru ... {}) {} | constructor | | classes.ts:16:17:16:37 | public ... erField | parameterField | -| tst.js:3:5:3:8 | x: 4 | x | -| tst.js:4:5:6:5 | func: f ... ;\\n } | func | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | f | -| tst.js:12:9:12:8 | constructor() {} | constructor | -| tst.js:13:3:15:3 | static ... x);\\n } | func | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | f | -| tst.js:21:1:21:6 | C.prop | prop | -| tst.js:24:13:24:27 | onClick={click} | onClick | -| tst.js:27:3:27:26 | get x() ... null; } | x | -| tst.js:28:3:28:13 | set y(v) {} | y | -| tst.js:32:5:32:8 | n: 1 | n | +| tst.js:2:5:2:8 | x: 4 | x | +| tst.js:3:5:5:5 | func: f ... ;\\n } | func | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | f | +| tst.js:11:9:11:8 | constructor() {} | constructor | +| tst.js:12:3:14:3 | static ... x);\\n } | func | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | f | +| tst.js:20:1:20:6 | C.prop | prop | +| tst.js:23:13:23:27 | onClick={click} | onClick | +| tst.js:26:3:26:26 | get x() ... null; } | x | +| tst.js:27:3:27:13 | set y(v) {} | y | +| tst.js:31:5:31:8 | n: 1 | n | test_getAPropertyRead2 -| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state | -| tst.js:14:5:14:11 | console | log | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | log | tst.js:17:5:17:15 | console.log | -| tst.js:23:15:23:29 | this.someMethod | bind | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:36:24:45 | this.state | name | tst.js:24:36:24:50 | this.state.name | -| tst.js:34:6:34:7 | vv | pp | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | ppp | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | qqq | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | log | tst.js:45:3:45:13 | console.log | +| tst.js:1:1:1:0 | this | someMethod | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | state | tst.js:23:36:23:45 | this.state | +| tst.js:13:5:13:11 | console | log | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | log | tst.js:16:5:16:15 | console.log | +| tst.js:22:15:22:29 | this.someMethod | bind | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:36:23:45 | this.state | name | tst.js:23:36:23:50 | this.state.name | +| tst.js:33:6:33:7 | vv | pp | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | ppp | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | qqq | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | log | tst.js:44:3:44:13 | console.log | test_getAPropertyReference2 | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField | -| tst.js:1:1:1:0 | this | someMethod | tst.js:23:15:23:29 | this.someMethod | -| tst.js:1:1:1:0 | this | state | tst.js:24:36:24:45 | this.state | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:14:5:14:11 | console | log | tst.js:14:5:14:15 | console.log | -| tst.js:17:5:17:11 | console | log | tst.js:17:5:17:15 | console.log | -| tst.js:21:1:21:1 | C | prop | tst.js:21:1:21:6 | C.prop | -| tst.js:23:15:23:29 | this.someMethod | bind | tst.js:23:15:23:34 | this.someMethod.bind | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:13:24:27 | onClick={click} | -| tst.js:24:36:24:45 | this.state | name | tst.js:24:36:24:50 | this.state.name | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | x | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | y | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:5:32:8 | n: 1 | -| tst.js:34:6:34:7 | vv | pp | tst.js:34:6:34:10 | vv.pp | -| tst.js:35:6:35:8 | vvv | ppp | tst.js:35:6:35:12 | vvv.ppp | -| tst.js:35:6:35:12 | vvv.ppp | qqq | tst.js:35:6:35:16 | vvv.ppp.qqq | -| tst.js:45:3:45:9 | console | log | tst.js:45:3:45:13 | console.log | +| tst.js:1:1:1:0 | this | someMethod | tst.js:22:15:22:29 | this.someMethod | +| tst.js:1:1:1:0 | this | state | tst.js:23:36:23:45 | this.state | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:5:2:8 | x: 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:13:5:13:11 | console | log | tst.js:13:5:13:15 | console.log | +| tst.js:16:5:16:11 | console | log | tst.js:16:5:16:15 | console.log | +| tst.js:20:1:20:1 | C | prop | tst.js:20:1:20:6 | C.prop | +| tst.js:22:15:22:29 | this.someMethod | bind | tst.js:22:15:22:34 | this.someMethod.bind | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:13:23:27 | onClick={click} | +| tst.js:23:36:23:45 | this.state | name | tst.js:23:36:23:50 | this.state.name | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | x | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | y | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:5:31:8 | n: 1 | +| tst.js:33:6:33:7 | vv | pp | tst.js:33:6:33:10 | vv.pp | +| tst.js:34:6:34:8 | vvv | ppp | tst.js:34:6:34:12 | vvv.ppp | +| tst.js:34:6:34:12 | vvv.ppp | qqq | tst.js:34:6:34:16 | vvv.ppp.qqq | +| tst.js:44:3:44:9 | console | log | tst.js:44:3:44:13 | console.log | test_hasPropertyWrite | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:19:4:23 | foo() | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:22:8:35 | parameterField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:24:12:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:41:16:42 | {} | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:8:3:8 | 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:21:1:21:1 | C | prop | tst.js:21:10:21:11 | 56 | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:22:24:26 | click | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:8:32:8 | 1 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:8:2:8 | 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:20:1:20:1 | C | prop | tst.js:20:10:20:11 | 56 | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:22:23:26 | click | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:8:31:8 | 1 | test_PropWriteBase | classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:3:21:3:20 | this | | classes.ts:8:15:8:35 | public ... erField | classes.ts:8:3:8:2 | this | | classes.ts:12:17:12:37 | public ... erField | classes.ts:12:5:12:4 | this | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:5:16:4 | this | -| tst.js:3:5:3:8 | x: 4 | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:2:11:10:1 | {\\n x ... }\\n} | -| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:12:1:19:1 | class C ... ;\\n }\\n} | -| tst.js:21:1:21:6 | C.prop | tst.js:21:1:21:1 | C | -| tst.js:24:13:24:27 | onClick={click} | tst.js:24:8:24:57 |
    | -| tst.js:27:3:27:26 | get x() ... null; } | tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | -| tst.js:28:3:28:13 | set y(v) {} | tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | -| tst.js:32:5:32:8 | n: 1 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:33:5:33:10 | [v]: 2 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:34:5:34:14 | [vv.pp]: 3 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | -| tst.js:38:13:38:15 | "a" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:38:18:38:20 | "b" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:38:23:38:25 | "c" | tst.js:38:12:38:26 | ["a", "b", "c"] | -| tst.js:39:13:39:15 | "a" | tst.js:39:12:39:23 | ["a", , "c"] | -| tst.js:39:20:39:22 | "c" | tst.js:39:12:39:23 | ["a", , "c"] | -| tst.js:40:15:40:17 | "b" | tst.js:40:12:40:23 | [, "b", "c"] | -| tst.js:40:20:40:22 | "c" | tst.js:40:12:40:23 | [, "b", "c"] | -| tst.js:41:13:41:15 | "a" | tst.js:41:12:41:22 | ["a", "b",] | -| tst.js:41:18:41:20 | "b" | tst.js:41:12:41:22 | ["a", "b",] | -| tst.js:42:13:42:15 | "a" | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | -| tst.js:42:18:42:24 | ...arr3 | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | -| tst.js:42:27:42:29 | "d" | tst.js:42:12:42:30 | ["a", ...arr3, "d"] | +| tst.js:2:5:2:8 | x: 4 | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:3:5:5:5 | func: f ... ;\\n } | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | tst.js:1:11:9:1 | {\\n x ... }\\n} | +| tst.js:12:3:14:3 | static ... x);\\n } | tst.js:11:1:18:1 | class C ... ;\\n }\\n} | +| tst.js:20:1:20:6 | C.prop | tst.js:20:1:20:1 | C | +| tst.js:23:13:23:27 | onClick={click} | tst.js:23:8:23:57 |
    | +| tst.js:26:3:26:26 | get x() ... null; } | tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | +| tst.js:27:3:27:13 | set y(v) {} | tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | +| tst.js:31:5:31:8 | n: 1 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:32:5:32:10 | [v]: 2 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:33:5:33:14 | [vv.pp]: 3 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | +| tst.js:37:13:37:15 | "a" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:37:18:37:20 | "b" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:37:23:37:25 | "c" | tst.js:37:12:37:26 | ["a", "b", "c"] | +| tst.js:38:13:38:15 | "a" | tst.js:38:12:38:23 | ["a", , "c"] | +| tst.js:38:20:38:22 | "c" | tst.js:38:12:38:23 | ["a", , "c"] | +| tst.js:39:15:39:17 | "b" | tst.js:39:12:39:23 | [, "b", "c"] | +| tst.js:39:20:39:22 | "c" | tst.js:39:12:39:23 | [, "b", "c"] | +| tst.js:40:13:40:15 | "a" | tst.js:40:12:40:22 | ["a", "b",] | +| tst.js:40:18:40:20 | "b" | tst.js:40:12:40:22 | ["a", "b",] | +| tst.js:41:13:41:15 | "a" | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | +| tst.js:41:18:41:24 | ...arr3 | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | +| tst.js:41:27:41:29 | "d" | tst.js:41:12:41:30 | ["a", ...arr3, "d"] | test_getAPropertyWrite | classes.ts:3:21:3:20 | this | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | classes.ts:16:17:16:37 | public ... erField | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:3:5:3:8 | x: 4 | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:21:1:21:1 | C | tst.js:21:1:21:6 | C.prop | -| tst.js:24:8:24:57 |
    | tst.js:24:13:24:27 | onClick={click} | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:8 | n: 1 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:10 | [v]: 2 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:13:38:15 | "a" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:18:38:20 | "b" | -| tst.js:38:12:38:26 | ["a", "b", "c"] | tst.js:38:23:38:25 | "c" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:13:39:15 | "a" | -| tst.js:39:12:39:23 | ["a", , "c"] | tst.js:39:20:39:22 | "c" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:15:40:17 | "b" | -| tst.js:40:12:40:23 | [, "b", "c"] | tst.js:40:20:40:22 | "c" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:13:41:15 | "a" | -| tst.js:41:12:41:22 | ["a", "b",] | tst.js:41:18:41:20 | "b" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:13:42:15 | "a" | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:12:42:30 | ["a", ...arr3, "d"] | tst.js:42:27:42:29 | "d" | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:2:5:2:8 | x: 4 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:20:1:20:1 | C | tst.js:20:1:20:6 | C.prop | +| tst.js:23:8:23:57 |
    | tst.js:23:13:23:27 | onClick={click} | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:31:5:31:8 | n: 1 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:32:5:32:10 | [v]: 2 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:13:37:15 | "a" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:18:37:20 | "b" | +| tst.js:37:12:37:26 | ["a", "b", "c"] | tst.js:37:23:37:25 | "c" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:13:38:15 | "a" | +| tst.js:38:12:38:23 | ["a", , "c"] | tst.js:38:20:38:22 | "c" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:15:39:17 | "b" | +| tst.js:39:12:39:23 | [, "b", "c"] | tst.js:39:20:39:22 | "c" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:13:40:15 | "a" | +| tst.js:40:12:40:22 | ["a", "b",] | tst.js:40:18:40:20 | "b" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:13:41:15 | "a" | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:12:41:30 | ["a", ...arr3, "d"] | tst.js:41:27:41:29 | "d" | test_PropWrite | classes.ts:3:21:3:20 | constructor() {} | | classes.ts:4:3:4:24 | instanc ... foo(); | @@ -196,46 +196,46 @@ test_PropWrite | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:46 | constru ... {}) {} | | classes.ts:16:17:16:37 | public ... erField | -| tst.js:3:5:3:8 | x: 4 | -| tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:12:9:12:8 | constructor() {} | -| tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | -| tst.js:21:1:21:6 | C.prop | -| tst.js:24:13:24:27 | onClick={click} | -| tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:28:3:28:13 | set y(v) {} | -| tst.js:32:5:32:8 | n: 1 | -| tst.js:33:5:33:10 | [v]: 2 | -| tst.js:34:5:34:14 | [vv.pp]: 3 | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | +| tst.js:2:5:2:8 | x: 4 | +| tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:11:9:11:8 | constructor() {} | +| tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | +| tst.js:20:1:20:6 | C.prop | +| tst.js:23:13:23:27 | onClick={click} | +| tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:27:3:27:13 | set y(v) {} | +| tst.js:31:5:31:8 | n: 1 | +| tst.js:32:5:32:10 | [v]: 2 | +| tst.js:33:5:33:14 | [vv.pp]: 3 | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | +| tst.js:37:13:37:15 | "a" | +| tst.js:37:18:37:20 | "b" | +| tst.js:37:23:37:25 | "c" | | tst.js:38:13:38:15 | "a" | -| tst.js:38:18:38:20 | "b" | -| tst.js:38:23:38:25 | "c" | -| tst.js:39:13:39:15 | "a" | +| tst.js:38:20:38:22 | "c" | +| tst.js:39:15:39:17 | "b" | | tst.js:39:20:39:22 | "c" | -| tst.js:40:15:40:17 | "b" | -| tst.js:40:20:40:22 | "c" | +| tst.js:40:13:40:15 | "a" | +| tst.js:40:18:40:20 | "b" | | tst.js:41:13:41:15 | "a" | -| tst.js:41:18:41:20 | "b" | -| tst.js:42:13:42:15 | "a" | -| tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:27:42:29 | "d" | +| tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:27:41:29 | "d" | test_getAPropertyWrite2 | classes.ts:3:21:3:20 | this | instanceField | classes.ts:4:3:4:24 | instanc ... foo(); | | classes.ts:8:3:8:2 | this | parameterField | classes.ts:8:15:8:35 | public ... erField | | classes.ts:12:5:12:4 | this | parameterField | classes.ts:12:17:12:37 | public ... erField | | classes.ts:16:5:16:4 | this | parameterField | classes.ts:16:17:16:37 | public ... erField | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | f | tst.js:7:5:9:5 | f() {\\n ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | func | tst.js:4:5:6:5 | func: f ... ;\\n } | -| tst.js:2:11:10:1 | {\\n x ... }\\n} | x | tst.js:3:5:3:8 | x: 4 | -| tst.js:12:1:19:1 | class C ... ;\\n }\\n} | func | tst.js:13:3:15:3 | static ... x);\\n } | -| tst.js:21:1:21:1 | C | prop | tst.js:21:1:21:6 | C.prop | -| tst.js:24:8:24:57 |
    | onClick | tst.js:24:13:24:27 | onClick={click} | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | x | tst.js:27:3:27:26 | get x() ... null; } | -| tst.js:26:2:29:1 | {\\n get ... v) {}\\n} | y | tst.js:28:3:28:13 | set y(v) {} | -| tst.js:31:2:36:1 | {\\n n ... q]: 4\\n} | n | tst.js:32:5:32:8 | n: 1 | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | f | tst.js:6:5:8:5 | f() {\\n ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | func | tst.js:3:5:5:5 | func: f ... ;\\n } | +| tst.js:1:11:9:1 | {\\n x ... }\\n} | x | tst.js:2:5:2:8 | x: 4 | +| tst.js:11:1:18:1 | class C ... ;\\n }\\n} | func | tst.js:12:3:14:3 | static ... x);\\n } | +| tst.js:20:1:20:1 | C | prop | tst.js:20:1:20:6 | C.prop | +| tst.js:23:8:23:57 |
    | onClick | tst.js:23:13:23:27 | onClick={click} | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | x | tst.js:26:3:26:26 | get x() ... null; } | +| tst.js:25:2:28:1 | {\\n get ... v) {}\\n} | y | tst.js:27:3:27:13 | set y(v) {} | +| tst.js:30:2:35:1 | {\\n n ... q]: 4\\n} | n | tst.js:31:5:31:8 | n: 1 | test_PropWriteRhs | classes.ts:3:21:3:20 | constructor() {} | classes.ts:3:21:3:20 | () {} | | classes.ts:4:3:4:24 | instanc ... foo(); | classes.ts:4:19:4:23 | foo() | @@ -246,27 +246,27 @@ test_PropWriteRhs | classes.ts:16:5:16:46 | constru ... {}) {} | classes.ts:16:5:16:46 | constru ... {}) {} | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:24:16:37 | parameterField | | classes.ts:16:17:16:37 | public ... erField | classes.ts:16:41:16:42 | {} | -| tst.js:3:5:3:8 | x: 4 | tst.js:3:8:3:8 | 4 | -| tst.js:4:5:6:5 | func: f ... ;\\n } | tst.js:4:11:6:5 | functio ... ;\\n } | -| tst.js:7:5:9:5 | f() {\\n ... ;\\n } | tst.js:7:6:9:5 | () {\\n ... ;\\n } | -| tst.js:12:9:12:8 | constructor() {} | tst.js:12:9:12:8 | () {} | -| tst.js:13:3:15:3 | static ... x);\\n } | tst.js:13:14:15:3 | (x) {\\n ... x);\\n } | -| tst.js:16:3:18:3 | f(x) {\\n ... x);\\n } | tst.js:16:4:18:3 | (x) {\\n ... x);\\n } | -| tst.js:21:1:21:6 | C.prop | tst.js:21:10:21:11 | 56 | -| tst.js:24:13:24:27 | onClick={click} | tst.js:24:22:24:26 | click | -| tst.js:32:5:32:8 | n: 1 | tst.js:32:8:32:8 | 1 | -| tst.js:33:5:33:10 | [v]: 2 | tst.js:33:10:33:10 | 2 | -| tst.js:34:5:34:14 | [vv.pp]: 3 | tst.js:34:14:34:14 | 3 | -| tst.js:35:5:35:20 | [vvv.ppp.qqq]: 4 | tst.js:35:20:35:20 | 4 | +| tst.js:2:5:2:8 | x: 4 | tst.js:2:8:2:8 | 4 | +| tst.js:3:5:5:5 | func: f ... ;\\n } | tst.js:3:11:5:5 | functio ... ;\\n } | +| tst.js:6:5:8:5 | f() {\\n ... ;\\n } | tst.js:6:6:8:5 | () {\\n ... ;\\n } | +| tst.js:11:9:11:8 | constructor() {} | tst.js:11:9:11:8 | () {} | +| tst.js:12:3:14:3 | static ... x);\\n } | tst.js:12:14:14:3 | (x) {\\n ... x);\\n } | +| tst.js:15:3:17:3 | f(x) {\\n ... x);\\n } | tst.js:15:4:17:3 | (x) {\\n ... x);\\n } | +| tst.js:20:1:20:6 | C.prop | tst.js:20:10:20:11 | 56 | +| tst.js:23:13:23:27 | onClick={click} | tst.js:23:22:23:26 | click | +| tst.js:31:5:31:8 | n: 1 | tst.js:31:8:31:8 | 1 | +| tst.js:32:5:32:10 | [v]: 2 | tst.js:32:10:32:10 | 2 | +| tst.js:33:5:33:14 | [vv.pp]: 3 | tst.js:33:14:33:14 | 3 | +| tst.js:34:5:34:20 | [vvv.ppp.qqq]: 4 | tst.js:34:20:34:20 | 4 | +| tst.js:37:13:37:15 | "a" | tst.js:37:13:37:15 | "a" | +| tst.js:37:18:37:20 | "b" | tst.js:37:18:37:20 | "b" | +| tst.js:37:23:37:25 | "c" | tst.js:37:23:37:25 | "c" | | tst.js:38:13:38:15 | "a" | tst.js:38:13:38:15 | "a" | -| tst.js:38:18:38:20 | "b" | tst.js:38:18:38:20 | "b" | -| tst.js:38:23:38:25 | "c" | tst.js:38:23:38:25 | "c" | -| tst.js:39:13:39:15 | "a" | tst.js:39:13:39:15 | "a" | +| tst.js:38:20:38:22 | "c" | tst.js:38:20:38:22 | "c" | +| tst.js:39:15:39:17 | "b" | tst.js:39:15:39:17 | "b" | | tst.js:39:20:39:22 | "c" | tst.js:39:20:39:22 | "c" | -| tst.js:40:15:40:17 | "b" | tst.js:40:15:40:17 | "b" | -| tst.js:40:20:40:22 | "c" | tst.js:40:20:40:22 | "c" | +| tst.js:40:13:40:15 | "a" | tst.js:40:13:40:15 | "a" | +| tst.js:40:18:40:20 | "b" | tst.js:40:18:40:20 | "b" | | tst.js:41:13:41:15 | "a" | tst.js:41:13:41:15 | "a" | -| tst.js:41:18:41:20 | "b" | tst.js:41:18:41:20 | "b" | -| tst.js:42:13:42:15 | "a" | tst.js:42:13:42:15 | "a" | -| tst.js:42:18:42:24 | ...arr3 | tst.js:42:18:42:24 | ...arr3 | -| tst.js:42:27:42:29 | "d" | tst.js:42:27:42:29 | "d" | +| tst.js:41:18:41:24 | ...arr3 | tst.js:41:18:41:24 | ...arr3 | +| tst.js:41:27:41:29 | "d" | tst.js:41:27:41:29 | "d" | diff --git a/javascript/ql/test/library-tests/PropWrite/tst.js b/javascript/ql/test/library-tests/PropWrite/tst.js index 8b2ad5aa3e2c..99e9d5ffb1c7 100644 --- a/javascript/ql/test/library-tests/PropWrite/tst.js +++ b/javascript/ql/test/library-tests/PropWrite/tst.js @@ -1,4 +1,3 @@ -// semmle-extractor-options: --experimental var obj = { x: 4, func: function() { diff --git a/javascript/ql/test/library-tests/SpreadRestProperties/tst.js b/javascript/ql/test/library-tests/SpreadRestProperties/tst.js index cbff84ef9b47..faa017a8bd3e 100644 --- a/javascript/ql/test/library-tests/SpreadRestProperties/tst.js +++ b/javascript/ql/test/library-tests/SpreadRestProperties/tst.js @@ -1,4 +1,2 @@ var q = { ...o, x: 42, ...p }; let { x, ...r } = q, { z } = {}; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/TaintTracking/exceptions.js b/javascript/ql/test/library-tests/TaintTracking/exceptions.js index b8946b5603ae..98e3e7ce0091 100644 --- a/javascript/ql/test/library-tests/TaintTracking/exceptions.js +++ b/javascript/ql/test/library-tests/TaintTracking/exceptions.js @@ -169,5 +169,3 @@ function throwThoughLibrary(xs) { sink(e); // OK - doesn't catch exception from event listener } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Templates/templates-revised.js b/javascript/ql/test/library-tests/Templates/templates-revised.js index 0ca81631fb43..7df488e53f91 100644 --- a/javascript/ql/test/library-tests/Templates/templates-revised.js +++ b/javascript/ql/test/library-tests/Templates/templates-revised.js @@ -1,3 +1 @@ tag `\unvalid escape sequence`; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js b/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js index 434f0d0ae61e..2257a74aa2a2 100644 --- a/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js +++ b/javascript/ql/test/library-tests/TrailingFunctionCommas/tst.js @@ -31,5 +31,3 @@ new h2(23, 42,); x => x; function f4(x = 42,) {} - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js b/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js index accf4713d71b..39a340ccf83e 100644 --- a/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js +++ b/javascript/ql/test/library-tests/frameworks/SQL/mssql1.js @@ -10,5 +10,3 @@ async () => { // ... error checks } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js index ffab5c805396..44cf825c3cde 100644 --- a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/restprops.js @@ -1,4 +1,2 @@ var f = ({...p}) => {}; var g = ({...p}) => {}; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js b/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js index 2a7d8c0b4e5d..43b3b2ebfb2e 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/restprops.js @@ -1,5 +1,3 @@ function f({ x, ...ys }) { return ys; } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js b/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js index 0329cdf038d1..03bfc0b5573b 100644 --- a/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js +++ b/javascript/ql/test/query-tests/Expressions/SelfAssignment/jsdoc.js @@ -11,5 +11,3 @@ class C extends Q { this.arg = this.arg; // NOT OK } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js index 6a489653379c..3ed85a709341 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/IllegalInvocation/tst.js @@ -60,5 +60,3 @@ function invoke(fn) { } invoke(C); invoke(function() {}); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js index ac41c9e8511d..9e1c24dfeccd 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/m.js @@ -5,5 +5,3 @@ var props = { module.exports = { ...props }; - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js index 9d4e7a7b8de3..4839b585eb44 100644 --- a/javascript/ql/test/query-tests/Performance/ReDoS/tst.js +++ b/javascript/ql/test/query-tests/Performance/ReDoS/tst.js @@ -84,5 +84,3 @@ var bad16 = /(.|\n)*!/s; // GOOD var good8 = /([\w.]+)*/; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js index 126745e94445..b28ddabc9ca6 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst2.js @@ -8,5 +8,3 @@ app.get('/post/:id', async function(req, res) { // NOT OK new sql.Request().query("select * from mytable where id = '" + req.params.id + "'"); }); - -// semmle-extractor-options: --experimental From 8661de11f2ff9c5651899095b3465f11faaf5216 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 5 Nov 2019 14:50:28 +0000 Subject: [PATCH 0208/2538] docs: update ql terminology --- docs/language/learn-ql/ql-training.rst | 52 +++++++++---------- .../ql-training/cpp/bad-overflow-guard.rst | 24 ++++----- .../ql-training/cpp/control-flow-cpp.rst | 4 +- .../ql-training/cpp/data-flow-cpp.rst | 4 +- .../ql-training/cpp/global-data-flow-cpp.rst | 4 +- .../language/ql-training/cpp/intro-ql-cpp.rst | 38 +++++++------- .../cpp/program-representation-cpp.rst | 10 ++-- docs/language/ql-training/cpp/snprintf.rst | 2 +- docs/language/ql-training/index.rst | 4 +- .../ql-training/java/apache-struts-java.rst | 2 +- .../java/global-data-flow-java.rst | 2 +- .../ql-training/java/intro-ql-java.rst | 36 ++++++------- .../java/program-representation-java.rst | 2 +- .../ql-training/java/query-injection-java.rst | 20 +++---- .../slide-snippets/abstract-syntax-tree.rst | 10 ++-- .../ql-training/slide-snippets/info.rst | 33 ------------ .../slide-snippets/intro-ql-general.rst | 16 +++--- 17 files changed, 115 insertions(+), 148 deletions(-) delete mode 100644 docs/language/ql-training/slide-snippets/info.rst diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index 66afa06d754e..757de7daed61 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -1,19 +1,19 @@ -QL training and variant analysis examples -######################################### +CodeQL training and variant analysis examples +============================================= QL and variant analysis -======================= +----------------------- `Variant analysis `__ is the process of using a known vulnerability as a seed to find similar problems in your code. Security engineers typically perform variant analysis to identify possible vulnerabilities and to ensure that these threats are properly fixed across multiple code bases. -`QL `__ is Semmle's variant analysis engine, and it is also the technology that underpins LGTM, Semmle's community driven security analysis platform. Together, QL and LGTM provide continuous monitoring and scalable variant analysis for your projects, even if you don’t have your own team of dedicated security engineers. You can read more about using QL and LGTM in variant analysis in the `Semmle blog `__. +`CodeQL `__ is the code analysis engine that underpins LGTM, Semmle's community driven security analysis platform. Together, CodeQL and LGTM provide continuous monitoring and scalable variant analysis for your projects, even if you don’t have your own team of dedicated security engineers. You can read more about using CodeQL and LGTM in variant analysis in the `Semmle blog `__. -The QL language is easy to learn, and exploring code using QL is the most efficient way to perform variant analysis. +CodeQL is easy to learn, and exploring code using CodeQL is the most efficient way to perform variant analysis. Learning QL for variant analysis -================================ +-------------------------------- -Start learning how to use QL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on the QL language, QL libraries, or an example variant discovered using QL. +Start learning how to use CodeQL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on CodeQL, its libraries, or an example variant discovered using CodeQL. .. |arrow-l| unicode:: U+2190 @@ -24,7 +24,7 @@ Start learning how to use QL in variant analysis for a specific language by look When you have selected a presentation, use |arrow-r| and |arrow-l| to navigate between slides. Press **p** to view the additional notes on slides that have an information icon |info| in the top right corner, and press **f** to enter full-screen mode. -The presentations contain a number of QL query examples. +The presentations contain a number of query examples. We recommend that you download `QL for Eclipse `__ and import the example snapshot for each presentation so that you can find the bugs mentioned in the slides. @@ -32,35 +32,35 @@ We recommend that you download `QL for Eclipse `__–an introduction to variant analysis and QL for C/C++ programmers. +- `Introduction to variant analysis: CodeQL for C/C++ <../ql-training/cpp/intro-ql-cpp.html>`__–an introduction to variant analysis and CodeQL for C/C++ programmers. - `Example: Bad overflow guard <../ql-training/cpp/bad-overflow-guard.html>`__–an example of iterative query development to find bad overflow guards in a C++ project. -- `Program representation: QL for C/C++ <../ql-training/cpp/program-representation-cpp.html>`__–information on how QL analysis represents C/C++ programs. -- `Introduction to local data flow <../ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using QL, including an example demonstrating how to develop a query to find a real CVE. +- `Program representation: CodeQL for C/C++ <../ql-training/cpp/program-representation-cpp.html>`__–information on how CodeQL analysis represents C/C++ programs. +- `Introduction to local data flow <../ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE. - `Exercise: snprintf overflow <../ql-training/cpp/snprintf.html>`__–an example demonstrating how to develop a data flow query. -- `Introduction to global data flow <../ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using QL. -- `Analyzing control flow: QL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using QL. +- `Introduction to global data flow <../ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using CodeQL. +- `Analyzing control flow: CodeQL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using QL. -QL and variant analysis for Java --------------------------------- +CodeQL and variant analysis for Java +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -- `Introduction to variant analysis: QL for Java <../ql-training/java/intro-ql-java.html>`__–an introduction to variant analysis and QL for Java programmers. +- `Introduction to variant analysis: CodeQL for Java <../ql-training/java/intro-ql-java.html>`__–an introduction to variant analysis and CodeQL for Java programmers. - `Example: Query injection <../ql-training/java/query-injection-java.html>`__–an example of iterative query development to find unsanitized SPARQL injections in a Java project. -- `Program representation: QL for Java <../ql-training/java/program-representation-java.html>`__–information on how QL analysis represents Java programs. -- `Introduction to local data flow <../ql-training/java/data-flow-java.html>`__–an introduction to analyzing local data flow in Java using QL, including an example demonstrating how to develop a query to find a real CVE. +- `Program representation: CodeQL for Java <../ql-training/java/program-representation-java.html>`__–information on how CodeQL analysis represents Java programs. +- `Introduction to local data flow <../ql-training/java/data-flow-java.html>`__–an introduction to analyzing local data flow in Java using CodeQL, including an example demonstrating how to develop a query to find a real CVE. - `Exercise: Apache Struts <../ql-training/java/apache-struts-java.html>`__–an example demonstrating how to develop a data flow query. -- `Introduction to global data flow <../ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using QL. +- `Introduction to global data flow <../ql-training/java/global-data-flow-java.html>`__–an introduction to analyzing global data flow in Java using CodeQL. More resources --------------- +~~~~~~~~~~~~~~ -- If you are completely new to QL, look at our introductory topics in :ref:`Getting started `. -- To find more detailed information about how to write QL queries for specific languages, visit the links in :ref:`Writing QL queries `. -- To read more about how QL queries have been used in Semmle's security research, and to read about new QL developments, visit the `Semmle blog `__. +- If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. +- To find more detailed information about how to write CodeQL queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. +- To read more about how CodeQL queries have been used in Semmle's security research, and to read about new CodeQL developments, visit the `Semmle blog `__. - Find more examples of queries written by Semmle's own security researchers in the `Semmle Demos repository `__ on GitHub. diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 12f35440906b..5e9fbcfc700c 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -2,7 +2,7 @@ Example: Bad overflow guard =========================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -127,13 +127,13 @@ This happens even though the overflow check passed! .. rst-class:: background2 -Developing a QL query -===================== +Developing a CodeQL query +========================= Finding bad overflow guards -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================== Let’s look for overflow guards of the form ``v + b < v``, using the classes ``AddExpr``, ``Variable`` and ``RelationalOperation`` from the ``cpp`` library. @@ -153,10 +153,10 @@ Let’s look for overflow guards of the form ``v + b < v``, using the classes - a ``RelationalOperation``: the overflow comparison check. - a ``Variable``: used as an argument to both the addition and comparison. - - The ``where`` part of the query ties these three QL variables together using `predicates `__ defined in the `standard QL for C/C++ library `__. + - The ``where`` part of the query ties these three variables together using `predicates `__ defined in the `standard CodeQL for C/C++ library `__. -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================= We want to ensure the operands being added have size less than 4 bytes. @@ -180,8 +180,8 @@ We can get the size (in bytes) of a type using the ``getSize()`` method. - We therefore write a helper predicate for small expressions. - This predicate effectively represents the set of all expressions in the database where the size of the type of the expression is less than 4 bytes, that is, less than 32-bits. -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================== We can ensure the operands being added have size less than 4 bytes, using our new predicate. @@ -216,8 +216,8 @@ Now our query becomes: - The “range” part, ``op = a.getAnOperand()``, restricts ``op`` to being one of the two operands to the addition. - The “condition” part, ``isSmall(op)``, says that the ``forall`` holds only if the condition (that the ``op`` is small) holds for everything in the range–that is, both the arguments to the addition. -QL query: bad overflow guards -============================= +CodeQL query: bad overflow guards +================================= Sometimes the result of the addition is cast to a small type of size less than 4 bytes, preventing automatic widening. We don’t want our query to flag these instances. diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index ea8e2c1b1582..a8171a44b5d1 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -2,7 +2,7 @@ Analyzing control flow ====================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -226,7 +226,7 @@ A ``GuardCondition`` is a ``Boolean`` condition that controls one or more basic Further materials ================= -- QL for C/C++: https://help.semmle.com/QL/learn-ql/ql/cpp/ql-for-cpp.html +- CodeQL for C/C++: https://help.semmle.com/QL/learn-ql/ql/cpp/ql-for-cpp.html - API reference: https://help.semmle.com/qldoc/cpp .. rst-class:: end-slide diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index 2b020499eb08..5377d8d52d16 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -86,9 +86,9 @@ Write a query that flags ``printf`` calls where the format argument is not a ``S .. note:: - This first query is about finding places where the format specifier is not a constant string. In QL for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. + This first query is about finding places where the format specifier is not a constant string. In CodeQL for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. - The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the QL for C/C++ standard library class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. + The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the CodeQL for C/C++ standard library class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. Meh... ====== diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index 6033581ffc3f..bc048ac59f4c 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -2,7 +2,7 @@ Introduction to global data flow ================================ -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -77,7 +77,7 @@ The library class ``SecurityOptions`` provides a (configurable) model of what co .. note:: - We first define what it means to be a *source* of tainted data for this particular problem. In this case, what we care about is whether the format string can be provided by an external user to our application or service. As there are many such ways external data could be introduced into the system, the standard QL libraries for C/C++ include an extensible API for modeling user input. In this case, we will simply use the predefined set of *user inputs*, which includes arguments provided to command line applications. + We first define what it means to be a *source* of tainted data for this particular problem. In this case, what we care about is whether the format string can be provided by an external user to our application or service. As there are many such ways external data could be introduced into the system, the standard CodeQL libraries for C/C++ include an extensible API for modeling user input. In this case, we will simply use the predefined set of *user inputs*, which includes arguments provided to command line applications. Defining sinks (exercise) diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 82eb62a3ba88..dddc86ca77fd 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -2,7 +2,7 @@ Introduction to variant analysis ================================ -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -56,14 +56,14 @@ Oops .. note:: - Here’s a simple (artificial) bug, which we’ll develop a QL query to catch. + Here’s a simple (artificial) bug, which we’ll develop a query to catch. This function writes a value to a given location in an array, first trying to do a bounds check to validate that the location is within bounds. However, the return statement has been commented out, leaving a redundant if statement and no bounds checking. This case can act as our “patient zero” in the variant analysis game. -A simple QL query -================= +A simple CodeQL query +===================== .. literalinclude:: ../query-examples/cpp/empty-if-cpp.ql :language: ql @@ -72,9 +72,9 @@ A simple QL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `QL query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `C/C++ standard QL library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL for C/C++ standard library `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -97,8 +97,8 @@ A simple QL query -Structure of a QL query -======================= +Structure of a query +==================== A **query file** has the extension ``.ql`` and contains a **query clause**, and optionally **predicates**, **classes**, and **modules**. @@ -110,14 +110,14 @@ Each query library also implicitly defines a module. .. note:: - QL queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary QL file in the background. + Queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary query file in the background. - Parts of queries can be lifted into `QL library files `__ with the extension ``qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. + Parts of queries can be lifted into `library files `__ with the extension ``qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. Logic can be encapsulated as user-defined `predicates `__ and `classes `__, and organized into `modules `__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later. -Predicates in QL -================ +Predicates +========== A predicate allows you to pull out and name parts of a query. @@ -135,14 +135,14 @@ A predicate allows you to pull out and name parts of a query. .. note:: - A QL predicate takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be recursive, simply by referring to themselves (directly or indirectly). + A `predicate `__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive `__, simply by referring to themselves (directly or indirectly). You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes in QL -============= +Classes +======= -A QL class allows you to name a set of values and define (member) predicates on them. +A class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -162,8 +162,8 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes in QL continued -======================= +Classes continued +================= .. container:: column-left @@ -198,7 +198,7 @@ Iterative query refinement .. note:: - QL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. + CodeQL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. As an exercise, refine the redundant-if query based on the observation that if the if-statement has an “else” clause, then even if the body of the “then” clause is empty, it’s not actually redundant. diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 1850e3e5671e..b21677fccab1 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -2,7 +2,7 @@ Program representation ====================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo @@ -25,8 +25,8 @@ Agenda .. resume slides -AST QL classes -============== +AST classes +=========== Important AST classes include: @@ -66,9 +66,9 @@ Working with variables Working with functions ====================== -Functions are represented by the Function QL class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. +Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by QL class Call and its subclasses: +Calls to functions are modeled by class Call and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index 77e46933fcbf..dafebc4a7204 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -2,7 +2,7 @@ Exercise: ``snprintf`` overflow =============================== -QL for C/C++ +CodeQL for C/C++ .. container:: semmle-logo diff --git a/docs/language/ql-training/index.rst b/docs/language/ql-training/index.rst index 0cc4ca9b024a..309fe92c052b 100644 --- a/docs/language/ql-training/index.rst +++ b/docs/language/ql-training/index.rst @@ -1,5 +1,5 @@ -QL training and variant analysis examples -========================================= +CodeQL training and variant analysis examples +============================================= .. container:: semmle-logo diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 7fcd2e003cdc..5c27ec73979b 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -67,7 +67,7 @@ RCE in Apache Struts Finding the RCE yourself ======================== -#. Create a QL class to find the interface ``org.apache.struts2.rest.handler.ContentTypeHandler`` +#. Create a class to find the interface ``org.apache.struts2.rest.handler.ContentTypeHandler`` **Hint**: Use predicate ``hasQualifiedName(...)`` diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index 665899f84590..f43c31e0f4f7 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -2,7 +2,7 @@ Introduction to global data flow ================================ -QL for Java +CodeQL for Java .. container:: semmle-logo diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 392c18309cb8..f80f878492dd 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -2,7 +2,7 @@ Introduction to variant analysis ================================ -QL for Java +CodeQL for Java .. container:: semmle-logo @@ -56,14 +56,14 @@ Oops .. note:: - Here’s a simple (artificial) bug, which we’ll develop a QL query to catch. + Here’s a simple (artificial) bug, which we’ll develop a query to catch. This function writes a value to a given location in an array, first trying to do a bounds check to validate that the location is within bounds. However, the return statement has been commented out, leaving a redundant if statement and no bounds checking. This case can act as our “patient zero” in the variant analysis game. -A simple QL query -================= +A simple CodeQL query +===================== .. literalinclude:: ../query-examples/java/empty-if-java.ql :language: ql @@ -72,9 +72,9 @@ A simple QL query We are going to write a simple query which finds “if statements” with empty “then” blocks, so we can highlight the results like those on the previous slide. The query can be run in the `query console on LGTM `__, or in your `IDE `__. - A `QL query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. + A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `Java standard QL library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL for Java library `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -96,8 +96,8 @@ A simple QL query Finally, we select a location, at which to report the problem, and a message, to explain what the problem is. -Structure of a QL query -======================= +Structure of a query +===================== A **query file** has the extension ``.ql`` and contains a **query clause**, and optionally **predicates**, **classes**, and **modules**. @@ -109,14 +109,14 @@ Each query library also implicitly defines a module. .. note:: - QL queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary QL file in the background. + Queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary QL file in the background. - Parts of queries can be lifted into `QL library files `__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using “import” statements, and similarly QLL files can import each other’s definitions using “import” statements. + Parts of queries can be lifted into `library files `__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using “import” statements, and similarly QLL files can import each other’s definitions using “import” statements. Logic can be encapsulated as user-defined `predicates `__ and `classes `__, and organized into `modules `__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later. -Predicates in QL -================ +Predicates +========== A predicate allows you to pull out and name parts of a query. @@ -134,15 +134,15 @@ A predicate allows you to pull out and name parts of a query. .. note:: - A `QL predicate `__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive `__, simply by referring to themselves (directly or indirectly). + A `predicate `__ takes zero or more parameters, and its body is a condition on those parameters. The predicate may (or may not) hold. Predicates may also be `recursive `__, simply by referring to themselves (directly or indirectly). You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes in QL -============= +Classes +======= -A QL class allows you to name a set of values and define (member) predicates on them. +A class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -162,7 +162,7 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes in QL continued +Classes in continued ======================= .. container:: column-left @@ -197,7 +197,7 @@ Iterative query refinement .. note:: - QL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. + CodeQL makes it very easy to experiment with analysis ideas. A common workflow is to start with a simple query (like our “redundant if-statement” example), examine a few results, refine the query based on any patterns that emerge and repeat. As an exercise, refine the redundant-if query based on the observation that if the if-statement has an “else” clause, then even if the body of the “then” clause is empty, it’s not actually redundant. diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index d090c30aebe2..ef078b53562e 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -2,7 +2,7 @@ Program representation ====================== -QL for Java +CodeQL for Java .. container:: semmle-logo diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index 67f7fe21a761..b3ef7d7e1820 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -2,7 +2,7 @@ Example: Query injection ======================== -QL for Java +CodeQL for Java .. container:: semmle-logo @@ -65,13 +65,13 @@ SPARQL injection .. rst-class:: background2 -Developing a QL query -====================== +Developing a query +=================== Finding a query concatenation -QL query: find SPARQL methods -============================= +CodeQL query: find SPARQL methods +================================= Let’s start by looking for calls to methods with names of the form ``sparql*Query``, using the classes ``Method`` and ``MethodAccess`` from the Java library. @@ -88,10 +88,10 @@ Let’s start by looking for calls to methods with names of the form ``sparql*Qu - a ``MethodAccess``: the call to a SPARQL query method - a ``Method``: the SPARQL query method. - - The ``where`` part of the query ties these three QL variables together using `predicates `__ defined in the `standard QL for Java library `__. + - The ``where`` part of the query ties these variables together using `predicates `__ defined in the `standard CodeQL for Java library `__. -QL query: find string concatenation -=================================== +CodeQL query: find string concatenation +======================================= - We now need to define what would make these API calls unsafe. - A simple heuristic would be to look for string concatenation used in the query argument. @@ -113,8 +113,8 @@ Looking at autocomplete suggestions, we see that we can get the type of an expre - We therefore write a helper predicate for finding string concatenation. - This predicate effectively represents the set of all ``add`` expressions in the database where the type of the expression is ``TypeString`` - that is, the addition produces a ``String`` value. -QL query: SPARQL injection -========================== +CodeQL query: SPARQL injection +============================== We can now combine our predicate with the existing query. Note that we do not need to specify that the argument of the method access is an ``AddExpr`` - this is implied by the ``isStringConcat`` requirement. diff --git a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst index c640aa7a16a9..6a26b5c74a41 100644 --- a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst +++ b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst @@ -35,9 +35,9 @@ The basic representation of an analyzed program is an *abstract syntax tree (AST .. note:: - When writing queries in QL it is important to have in mind the underlying representation of the program which is stored in the database. Typically queries make use of the “AST” representation of the program - a tree structure where program elements are nested within other program elements. + When writing queries it is important to have in mind the underlying representation of the program which is stored in the database. Typically queries make use of the “AST” representation of the program - a tree structure where program elements are nested within other program elements. - The following topics contain overviews of the important AST classes and QL libraries for C/C++, C#, and Java: + The following topics contain overviews of the important AST classes and CodeQL libraries for C/C++, C#, and Java: - `Introducing the C/C++ libraries `__ - `Introducing the C# libraries `__ @@ -47,19 +47,19 @@ The basic representation of an analyzed program is an *abstract syntax tree (AST Database representations of ASTs ================================ -AST nodes and other program elements are encoded in the database as *entity values*. Entities are implemented as integers, but in QL they are opaque - all one can do with them is to check their equality. +AST nodes and other program elements are encoded in the database as *entity values*. Entities are implemented as integers, but in QL they are opaque---all one can do with them is to check their equality. Each entity belongs to an entity type. Entity types have names starting with “@” and are defined in the database schema (not in QL). Properties of AST nodes and their relationships to each other are encoded by database relations, which are predicates defined in the database (not in QL). -Entity types are rarely used directly, the usual pattern is to define a QL class that extends the type and exposes properties of its entities through member predicates. +Entity types are rarely used directly, the usual pattern is to define a class that extends the type and exposes properties of its entities through member predicates. .. note:: ASTs are a typical example of the kind of data representation one finds in object-oriented programming, with data-carrying nodes that reference each other. At first glance, QL, which can only work with atomic values, does not seem to be well suited for working with this kind of data. However, ultimately all that we require of the nodes in an AST is that they have an identity. The relationships among nodes, usually implemented by reference-valued object fields in other languages, can just as well (and arguably more naturally) be represented as relations over nodes. Attaching data (such as strings or numbers) to nodes can also be represented with relations over nodes and primitive values. All we need is a way for relations to reference nodes. This is achieved in QL (as in other database languages) by means of *entity values* (or entities, for short), which are opaque atomic values, implemented as integers under the hood. - It is the job of the extractor to create entity values for all AST nodes and populate database relations that encode the relationship between AST nodes and any values associated with them. These relations are *extensional*, that is, explicitly stored in the database, unlike the relations described by QL predicates, which we also refer to as *intensional* relations. Entity values belong to *entity types*, whose name starts with “@” to set them apart from primitive types and classes. + It is the job of the extractor to create entity values for all AST nodes and populate database relations that encode the relationship between AST nodes and any values associated with them. These relations are *extensional*, that is, explicitly stored in the database, unlike the relations described by predicates, which we also refer to as *intensional* relations. Entity values belong to *entity types*, whose name starts with “@” to set them apart from primitive types and classes. The interface between entity types and extensional relations on the one hand and QL predicates and classes on the other hand is provided by the *database schema*, which defines the available entity types and the schema of each extensional relation, that is, how many columns the relation has, and which entity type or primitive type the values in each column come from. QL programs can refer to entity types and extensional relations just as they would refer to QL classes and predicates, with the restriction that entity types cannot be directly selected in a ``select`` clause, since they do not have a well-defined string representation. diff --git a/docs/language/ql-training/slide-snippets/info.rst b/docs/language/ql-training/slide-snippets/info.rst deleted file mode 100644 index 583a456207bb..000000000000 --- a/docs/language/ql-training/slide-snippets/info.rst +++ /dev/null @@ -1,33 +0,0 @@ -Information -=========== - -To try the examples in this presentation we recommend you download `QL for Eclipse `__. - -**QL language resources** - -- If you are new to QL, try the QL language tutorials at `Learning CodeQL `__. -- To learn more about the main features of QL, try looking at the `QL language handbook `__. -- For further information about writing queries in QL, see `Writing QL queries `__. - -**QL queries** - -The QL queries included in the latest Semmle release are open source. View them in the `semmle/ql repository `__. - -**Extra information** - -.. |arrow-l| unicode:: U+2190 - -.. |arrow-r| unicode:: U+2192 - -- Press |arrow-l| and |arrow-r| to navigate between slides -- Pressing **p** toggles between the slide and any extra notes (where they're available) -- Pressing **f** toggles full screen viewing on/off - -.. note:: - - To run the queries featured in this training presentation, we recommend you download the free-to-use `QL for Eclipse plugin `__. - - This plugin allows you to locally access the latest features of QL, including the standard QL libraries and queries. It also provides standard IDE features such as syntax highlighting, jump-to-definition, and tab completion. - - When you have setup QL for Eclipse we recommend increasing the “Memory for running queries” from the default setting of 4096MB to 8192MB, to ensure that all the queries complete quickly. - \ No newline at end of file diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index f0c00c131fc8..6fa68c7243e9 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -67,9 +67,9 @@ Complete text of the analysis (nothing left out!): .. note:: - Once the mission critical bug was discovered on Curiosity, JPL contacted Semmle for help discovering whether variants of the problem might exist elsewhere in the Curiosity control software. In 20 minutes, research engineers from Semmle produced a QL query and shared it with the JPL team. It finds all functions that are passed an array as an argument whose size is smaller than expected. + Once the mission critical bug was discovered on Curiosity, JPL contacted Semmle for help discovering whether variants of the problem might exist elsewhere in the Curiosity control software. In 20 minutes, research engineers from Semmle produced a CodeQL query and shared it with the JPL team. It finds all functions that are passed an array as an argument whose size is smaller than expected. - (The goal here is not to fully understand the QL, but to illustrate the power of the language and its standard libraries.) + (The goal here is not to fully understand the query, but to illustrate the power of the language and its standard libraries.) Find all instances! @@ -105,16 +105,16 @@ Analysis overview Semmle’s analysis works by extracting a queryable database from your project. For compiled languages, Semmle’s tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. - Once the extraction finishes, all this information is collected into a single `snapshot database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the snapshot so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. + Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the snapshot so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. - Queries are written in `QL `__ and usually depend on one or more of the `standard QL libraries `__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a snapshot database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine. + Queries are written in `QL `__ and usually depend on one or more of the `standard CodeQL libraries `__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a CodeQL database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine. Query results can be interpreted and presented in a variety of ways, including displaying them in an `IDE plugin `__ such as QL for Eclipse, or in a web dashboard as on `LGTM `__. Introducing QL ============== -QL is the query language running all Semmle analysis. +QL is the query language running all CodeQL analysis. QL is: @@ -126,12 +126,12 @@ QL is: .. note:: - QL is the high-level, object-oriented logic language that underpins all of Semmle’s libraries and analyses. You can learn lots more about QL by visiting `Introduction to the QL language `__ and `About QL `__. + QL is the high-level, object-oriented logic language that underpins all CodeQL libraries and analyses. You can learn lots more about QL by visiting `Introduction to the QL language `__ and `About QL `__. The key features of QL are: - All common logic connectives are available, including quantifiers like ``exist``, which can also introduce new variables. - The language is declarative–the user focuses on stating what they would like to find, and leaves the details of how to evaluate the query to the engine. - - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard QL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. + - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. - The database generated by Semmle’s tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. - You can start writing QL and running QL queries on open source projects in the `query console `__ on LGTM.com. You can also download snapshots from LGTM.com to query locally, by `running queries in your IDE `__ equipped with a QL plugin or extension. + You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download snapshots from LGTM.com to query locally, by `running queries in your IDE `__. From 69d7baa9bcfc4ac4ce72459e92bc66436197859c Mon Sep 17 00:00:00 2001 From: james Date: Tue, 5 Nov 2019 15:35:18 +0000 Subject: [PATCH 0209/2538] docs: update snapshot terminology --- docs/language/ql-training/cpp/bad-overflow-guard.rst | 8 ++++---- docs/language/ql-training/cpp/control-flow-cpp.rst | 6 +++--- docs/language/ql-training/cpp/data-flow-cpp.rst | 6 +++--- docs/language/ql-training/cpp/global-data-flow-cpp.rst | 6 +++--- docs/language/ql-training/cpp/intro-ql-cpp.rst | 6 +++--- .../ql-training/cpp/program-representation-cpp.rst | 4 ++-- docs/language/ql-training/cpp/snprintf.rst | 6 +++--- docs/language/ql-training/java/apache-struts-java.rst | 6 +++--- docs/language/ql-training/java/data-flow-java.rst | 6 +++--- docs/language/ql-training/java/global-data-flow-java.rst | 6 +++--- docs/language/ql-training/java/intro-ql-java.rst | 6 +++--- docs/language/ql-training/java/query-injection-java.rst | 6 +++--- .../ql-training/slide-snippets/abstract-syntax-tree.rst | 2 +- .../{snapshot-note.rst => database-note.rst} | 2 +- .../ql-training/slide-snippets/global-data-flow.rst | 6 +++--- .../ql-training/slide-snippets/intro-ql-general.rst | 6 +++--- .../ql-training/slide-snippets/local-data-flow.rst | 4 ++-- 17 files changed, 46 insertions(+), 46 deletions(-) rename docs/language/ql-training/slide-snippets/{snapshot-note.rst => database-note.rst} (66%) diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 5e9fbcfc700c..6937e9a1a4f7 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `ChakraCore snapshot `__ +- `ChakraCore database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides @@ -233,4 +233,4 @@ The final query .. literalinclude:: ../query-examples/cpp/bad-overflow-guard-3.ql :language: ql -This query finds a single result in our historic snapshot, which was `a genuine bug in ChakraCore `__. +This query finds a single result in our historic database, which was `a genuine bug in ChakraCore `__. diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index a8171a44b5d1..4e6ebbf42926 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -18,7 +18,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `ChakraCore snapshot `__ +- `ChakraCore database `__ .. note:: @@ -26,9 +26,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index 5377d8d52d16..cb7ed7b51331 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `dotnet/coreclr snapshot `__ +- `dotnet/coreclr database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index bc048ac59f4c..5a5e93aafdab 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `dotnet/coreclr snapshot `__ +- `dotnet/coreclr database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index dddc86ca77fd..e7d4b318b257 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `exiv2 snapshot `__ +- `exiv2 database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index b21677fccab1..077b36520f60 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -107,7 +107,7 @@ Working with macros #define square(x) x*x y = square(y0), z = square(z0) -is represented in the snapshot database as: +is represented in the CodeQL database database as: - A Macro entity representing the text of the *head* and *body* of the macro - Assignment nodes, representing the two assignments after preprocessing @@ -121,4 +121,4 @@ Useful predicates on ``Element``: ``isInMacroExpansion()``, ``isAffectedByMacro( .. note:: - The snapshot also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. \ No newline at end of file + The CodeQL database also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. \ No newline at end of file diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index dafebc4a7204..26c54708c0a3 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `rsyslog snapshot `__ +- `rsyslog database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 5c27ec73979b..73d0122b7ea2 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -20,7 +20,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `Apache Struts snapshot `__ +- `Apache Struts database `__ .. note:: @@ -28,9 +28,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/data-flow-java.rst b/docs/language/ql-training/java/data-flow-java.rst index be9ba98456e3..0b9026aadfb0 100644 --- a/docs/language/ql-training/java/data-flow-java.rst +++ b/docs/language/ql-training/java/data-flow-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `VIVO Vitro snapshot `__ +- `VIVO Vitro database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index f43c31e0f4f7..062ce30b04c5 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `Apache Struts snapshot `__ +- `Apache Struts database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index f80f878492dd..393e35cf5a84 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `Apache Struts snapshot `__ +- `Apache Struts database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index b3ef7d7e1820..dc345d3b39c3 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -16,7 +16,7 @@ Setup For this example you should download: - `QL for Eclipse `__ -- `VIVO Vitro snapshot `__ +- `VIVO Vitro database `__ .. note:: @@ -24,9 +24,9 @@ For this example you should download: You can also query the project in `the query console `__ on LGTM.com. - .. insert snapshot-note.rst to explain differences between snapshot available to download and the version available in the query console. + .. insert database-note.rst to explain differences between database available to download and the version available in the query console. - .. include:: ../slide-snippets/snapshot-note.rst + .. include:: ../slide-snippets/database-note.rst .. resume slides diff --git a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst index 6a26b5c74a41..aaa2cd23d717 100644 --- a/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst +++ b/docs/language/ql-training/slide-snippets/abstract-syntax-tree.rst @@ -63,7 +63,7 @@ Entity types are rarely used directly, the usual pattern is to define a class th The interface between entity types and extensional relations on the one hand and QL predicates and classes on the other hand is provided by the *database schema*, which defines the available entity types and the schema of each extensional relation, that is, how many columns the relation has, and which entity type or primitive type the values in each column come from. QL programs can refer to entity types and extensional relations just as they would refer to QL classes and predicates, with the restriction that entity types cannot be directly selected in a ``select`` clause, since they do not have a well-defined string representation. - For example, the database schemas for C/++, C#, and Java snapshot databases are here: + For example, the database schemas for C/++, C#, and Java CodeQL databases are here: - https://github.com/Semmle/ql/blob/master/cpp/ql/src/semmlecode.cpp.dbscheme - https://github.com/Semmle/ql/blob/master/csharp/ql/src/semmlecode.csharp.dbscheme diff --git a/docs/language/ql-training/slide-snippets/snapshot-note.rst b/docs/language/ql-training/slide-snippets/database-note.rst similarity index 66% rename from docs/language/ql-training/slide-snippets/snapshot-note.rst rename to docs/language/ql-training/slide-snippets/database-note.rst index 4a32243211b0..af6dce237289 100644 --- a/docs/language/ql-training/slide-snippets/snapshot-note.rst +++ b/docs/language/ql-training/slide-snippets/database-note.rst @@ -1 +1 @@ -Note that results generated in the query console are likely to differ to those generated in the QL plugin as LGTM.com analyzes the most recent revisions of each project that has been added–the snapshot available to download above is based on an historical version of the codebase. \ No newline at end of file +Note that results generated in the query console are likely to differ to those generated in the QL plugin as LGTM.com analyzes the most recent revisions of each project that has been added–the CodeQL database available to download above is based on an historical version of the codebase. \ No newline at end of file diff --git a/docs/language/ql-training/slide-snippets/global-data-flow.rst b/docs/language/ql-training/slide-snippets/global-data-flow.rst index f18dc22d1785..6cb52af0f847 100644 --- a/docs/language/ql-training/slide-snippets/global-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/global-data-flow.rst @@ -17,15 +17,15 @@ Global data flow and taint tracking - Recap: - - Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a snapshot - - Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a snapshot + - Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a CodeQL database + - Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a CodeQL database - For global data flow (and taint tracking), we must therefore provide restrictions to ensure the problem is tractable. - Typically, this involves specifying the *source* and *sink*. .. note:: - As we mentioned in the previous slide deck, while local data flow is feasible to compute for all functions in a snapshot, global data flow is not. This is because the number of paths becomes exponentially larger for global data flow. + As we mentioned in the previous slide deck, while local data flow is feasible to compute for all functions in a CodeQL database, global data flow is not. This is because the number of paths becomes exponentially larger for global data flow. The global data flow (and taint tracking) avoids this problem by requiring that the query author specifies which ``sources`` and ``sinks`` are applicable. This allows the implementation to compute paths between the restricted set of nodes, rather than the full graph. diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index 6fa68c7243e9..d559c5bbeb7d 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -105,7 +105,7 @@ Analysis overview Semmle’s analysis works by extracting a queryable database from your project. For compiled languages, Semmle’s tools observe an ordinary build of the source code. Each time a compiler is invoked to process a source file, a copy of that file is made, and all relevant information about the source code (syntactic data about the abstract syntax tree, semantic data like name binding and type information, data on the operation of the C preprocessor, etc.) is collected. For interpreted languages, the extractor gathers similar information by running directly on the source code. Multi-language code bases are analyzed one language at a time. - Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the snapshot so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. + Once the extraction finishes, all this information is collected into a single `CodeQL database `__, which is then ready to query, possibly on a different machine. A copy of the source files, made at the time the database was created, is also included in the CodeQL database so analysis results can be displayed at the correct location in the code. The database schema is (source) language specific. Queries are written in `QL `__ and usually depend on one or more of the `standard CodeQL libraries `__ (and of course you can write your own custom libraries). They are compiled into an efficiently executable format by the QL compiler and then run on a CodeQL database by the QL evaluator, either on a remote worker machine or locally on a developer’s machine. @@ -121,7 +121,7 @@ QL is: - a **logic** language based on first-order logic - a **declarative** language without side effects - an **object-oriented** language -- a **query** language working on a read-only snapshot database +- a **query** language working on a read-only CodeQL database database - equipped with rich standard libraries **for program analysis** .. note:: @@ -134,4 +134,4 @@ QL is: - The object-oriented layer allows Semmle to distribute rich standard libraries for program analysis. These model the common AST node types, control flow and name lookup, and define further layers on top–for example control flow or data flow analysis. The `standard CodeQL libraries and queries `__ ship as source and can be inspected by the user, and new abstractions are readily defined. - The database generated by Semmle’s tools is treated as read-only; queries cannot insert new data into it, though they can inspect its contents in various ways. - You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download snapshots from LGTM.com to query locally, by `running queries in your IDE `__. + You can start writing running queries on open source projects in the `query console `__ on LGTM.com. You can also download CodeQL databases from LGTM.com to query locally, by `running queries in your IDE `__. diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index 8a0eeac63747..068dfc9170ac 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -61,8 +61,8 @@ Data flow graphs Local vs global data flow ========================= -- Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a snapshot -- Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a snapshot +- Local (“intra-procedural”) data flow models flow within one function; feasible to compute for all functions in a CodeQL database +- Global (“inter-procedural”) data flow models flow across function calls; not feasible to compute for all functions in a CodeQL database - Different APIs, so discussed separately - This slide deck focuses on the former From 2d00ca5773b7773184b3beabbd3799876d3fc06b Mon Sep 17 00:00:00 2001 From: james Date: Fri, 4 Oct 2019 09:18:19 +0100 Subject: [PATCH 0210/2538] docs: semmle logo (cherry picked from commit 4a8e8fa0de4470aaeed94357f70b54b68c0b84a7) --- .../static/theme/css/default.css | 18 +-- .../_static-training/title-slide.svg | 149 +----------------- .../ql-training/cpp/bad-overflow-guard.rst | 4 - .../ql-training/cpp/control-flow-cpp.rst | 4 - .../ql-training/cpp/data-flow-cpp.rst | 4 - .../ql-training/cpp/global-data-flow-cpp.rst | 4 - .../language/ql-training/cpp/intro-ql-cpp.rst | 4 - .../cpp/program-representation-cpp.rst | 4 - docs/language/ql-training/cpp/snprintf.rst | 4 - docs/language/ql-training/index.rst | 4 - .../ql-training/java/apache-struts-java.rst | 4 - .../ql-training/java/data-flow-java.rst | 4 - .../java/global-data-flow-java.rst | 4 - .../ql-training/java/intro-ql-java.rst | 4 - .../java/program-representation-java.rst | 4 - .../ql-training/java/query-injection-java.rst | 4 - docs/language/ql-training/template.rst | 4 - 17 files changed, 4 insertions(+), 223 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index 2c05ea5e93b0..4f706120747d 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -1300,13 +1300,13 @@ aside.gdbar img { .title-slide hgroup h1 { font-size: 2em; line-height: 1.4; - /*letter-spacing: -3px;*/ color: white; margin: auto; display: block; position: absolute; top: 0; bottom: 10%; + left: 1.25em; height: 0; } /* line 898, ../scss/default.scss */ @@ -1430,31 +1430,19 @@ hgroup .pre { color: #5c31ff; } -/* title slide (deck title, subtitle, semmle logo)*/ +/* title slide (deck title, subtitle)*/ .title-slide { background-image: url("../../title-slide.svg"); background-size: cover; } -.semmle-logo sup { - vertical-align: super; - font-size: 0.3em; - font-weight: 100; -} - -.title-slide .semmle-logo { - color: white; - font-size: 1.2em; - position: absolute; - top: 10%; -} - .title-slide p { color: white; font-size: 1em; position: absolute; bottom: 30%; + left: 2.6em; } .title-slide hgroup .pre { diff --git a/docs/language/ql-training/_static-training/title-slide.svg b/docs/language/ql-training/_static-training/title-slide.svg index 6f9a19f4a1b8..13eb2d34fef2 100644 --- a/docs/language/ql-training/_static-training/title-slide.svg +++ b/docs/language/ql-training/_static-training/title-slide.svg @@ -1,148 +1 @@ - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + \ No newline at end of file diff --git a/docs/language/ql-training/cpp/bad-overflow-guard.rst b/docs/language/ql-training/cpp/bad-overflow-guard.rst index 6937e9a1a4f7..dceeec3320f1 100644 --- a/docs/language/ql-training/cpp/bad-overflow-guard.rst +++ b/docs/language/ql-training/cpp/bad-overflow-guard.rst @@ -4,10 +4,6 @@ Example: Bad overflow guard CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index 4e6ebbf42926..3fddc3f80728 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -4,10 +4,6 @@ Analyzing control flow CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Include information slides here .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index cb7ed7b51331..e78e8e86220e 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -4,10 +4,6 @@ Introduction to data flow Finding string formatting vulnerabilities in C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/global-data-flow-cpp.rst b/docs/language/ql-training/cpp/global-data-flow-cpp.rst index 5a5e93aafdab..aaa567e7a8e6 100644 --- a/docs/language/ql-training/cpp/global-data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/global-data-flow-cpp.rst @@ -3,10 +3,6 @@ Introduction to global data flow ================================ CodeQL for C/C++ - -.. container:: semmle-logo - - Semmle :sup:`TM` .. rst-class:: setup diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index e7d4b318b257..cbe29e6c520e 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -4,10 +4,6 @@ Introduction to variant analysis CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 077b36520f60..3c062089428c 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -4,10 +4,6 @@ Program representation CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/cpp/snprintf.rst b/docs/language/ql-training/cpp/snprintf.rst index 26c54708c0a3..c15bf74d2866 100644 --- a/docs/language/ql-training/cpp/snprintf.rst +++ b/docs/language/ql-training/cpp/snprintf.rst @@ -4,10 +4,6 @@ Exercise: ``snprintf`` overflow CodeQL for C/C++ -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/index.rst b/docs/language/ql-training/index.rst index 309fe92c052b..021bb58d3c44 100644 --- a/docs/language/ql-training/index.rst +++ b/docs/language/ql-training/index.rst @@ -1,10 +1,6 @@ CodeQL training and variant analysis examples ============================================= -.. container:: semmle-logo - - Semmle :sup:`TM` - .. toctree:: :glob: :maxdepth: 1 diff --git a/docs/language/ql-training/java/apache-struts-java.rst b/docs/language/ql-training/java/apache-struts-java.rst index 73d0122b7ea2..be071d41562b 100644 --- a/docs/language/ql-training/java/apache-struts-java.rst +++ b/docs/language/ql-training/java/apache-struts-java.rst @@ -8,10 +8,6 @@ Exercise: Apache Struts CVE-2017-9805 -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/data-flow-java.rst b/docs/language/ql-training/java/data-flow-java.rst index 0b9026aadfb0..93ccc87b7d1f 100644 --- a/docs/language/ql-training/java/data-flow-java.rst +++ b/docs/language/ql-training/java/data-flow-java.rst @@ -2,10 +2,6 @@ Introduction to data flow ========================= -.. container:: semmle-logo - - Semmle :sup:`TM` - Finding SPARQL injection vulnerabilities in Java .. rst-class:: setup diff --git a/docs/language/ql-training/java/global-data-flow-java.rst b/docs/language/ql-training/java/global-data-flow-java.rst index 062ce30b04c5..9edacde93c3d 100644 --- a/docs/language/ql-training/java/global-data-flow-java.rst +++ b/docs/language/ql-training/java/global-data-flow-java.rst @@ -4,10 +4,6 @@ Introduction to global data flow CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 393e35cf5a84..f7afe713c4ae 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -4,10 +4,6 @@ Introduction to variant analysis CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index ef078b53562e..ba9b1a9d80dd 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -4,10 +4,6 @@ Program representation CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: agenda Agenda diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index dc345d3b39c3..a5b46eabda5c 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -4,10 +4,6 @@ Example: Query injection CodeQL for Java -.. container:: semmle-logo - - Semmle :sup:`TM` - .. rst-class:: setup Setup diff --git a/docs/language/ql-training/template.rst b/docs/language/ql-training/template.rst index 0cce4a114358..21c5abef1449 100644 --- a/docs/language/ql-training/template.rst +++ b/docs/language/ql-training/template.rst @@ -27,10 +27,6 @@ Template slide deck Second subheading -.. container:: semmle-logo - - Semmle :sup:`TM` - .. Set up slide. Include link to QL4E snapshots required for examples .. rst-class:: setup From 0b6592f650421c5b5ff001674042577e038367bb Mon Sep 17 00:00:00 2001 From: james Date: Mon, 30 Sep 2019 11:51:17 +0100 Subject: [PATCH 0211/2538] docs: version number and small css tweaks (cherry picked from commit ff78feeeeaec99bdf779242c33e25f57c7bcab29) --- .../slides-semmle-2/static/theme/css/default.css | 6 ++++-- docs/language/ql-training/conf.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css index 4f706120747d..3f8a89c65555 100644 --- a/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css +++ b/docs/language/ql-training/_static-training/slides-semmle-2/static/theme/css/default.css @@ -485,6 +485,7 @@ ul { margin-left: 2.2em; margin-bottom: 1em; position: relative; + width: 90%; } /* line 300, ../scss/default.scss */ ul li { @@ -1452,6 +1453,7 @@ hgroup .pre { .subheading { position: absolute; top: 62.5%; + left: 0; } .subheading p { @@ -1557,7 +1559,7 @@ p.first.admonition-title { text-align: left; font-size: 0.8em; width: 100%; - overflow: scroll; + overflow: auto; border: 1px solid black; } @@ -1596,7 +1598,7 @@ p.first.admonition-title { display: block; position: fixed; top: 0; - right: -1%; + right: 0; font-size: 1.2em; } diff --git a/docs/language/ql-training/conf.py b/docs/language/ql-training/conf.py index de712cd06a44..8f8a13569b51 100644 --- a/docs/language/ql-training/conf.py +++ b/docs/language/ql-training/conf.py @@ -86,9 +86,9 @@ def setup(sphinx): # built documents. # # The short X.Y version. -version = u'1.21' +version = u'1.22' # The full version, including alpha/beta/rc tags. -release = u'1.21' +release = u'1.22' copyright = u'2019 Semmle Ltd' author = u'Semmle Ltd' From f3850e580c238440eddc99581319dcb208692624 Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 16:27:33 +0000 Subject: [PATCH 0212/2538] JS: Skip codeql databases in AutoBuild --- .../extractor/src/com/semmle/js/extractor/AutoBuild.java | 3 +++ .../src/com/semmle/js/extractor/test/AutoBuildTests.java | 8 ++++++++ 2 files changed, 11 insertions(+) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 55d3f8632a24..e67c4095e19d 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -666,6 +666,9 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { if (!dir.equals(currentRoot[0]) && (excludes.contains(dir) || dir.toFile().isHidden())) return FileVisitResult.SKIP_SUBTREE; + if (dir.resolve("codeql-database.yml").toFile().exists()) { + return FileVisitResult.SKIP_SUBTREE; + } return super.preVisitDirectory(dir, attrs); } }; diff --git a/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java b/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java index 28e618f45ea0..8db4ca22da5a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java +++ b/javascript/extractor/src/com/semmle/js/extractor/test/AutoBuildTests.java @@ -585,4 +585,12 @@ public void qhelpAsXmlAndAllXml() throws IOException { addFile(true, LGTM_SRC, "tst.qhelp"); runTest(); } + + @Test + public void skipCodeQLDatabases() throws IOException { + addFile(true, LGTM_SRC, "tst.js"); + addFile(false, LGTM_SRC, "db/codeql-database.yml"); + addFile(false, LGTM_SRC, "db/foo.js"); + runTest(); + } } From 488ce158887ed174a854730d81dd353c962a5c1d Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Tue, 5 Nov 2019 19:57:24 +0000 Subject: [PATCH 0213/2538] Apply suggestions from code review Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> Co-Authored-By: Felicity Chapman --- docs/language/learn-ql/ql-training.rst | 12 ++++++------ docs/language/ql-training/cpp/data-flow-cpp.rst | 4 ++-- docs/language/ql-training/cpp/intro-ql-cpp.rst | 2 +- .../ql-training/cpp/program-representation-cpp.rst | 6 +++--- docs/language/ql-training/java/intro-ql-java.rst | 2 +- .../ql-training/slide-snippets/intro-ql-general.rst | 2 +- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/language/learn-ql/ql-training.rst b/docs/language/learn-ql/ql-training.rst index 757de7daed61..4187ae621b53 100644 --- a/docs/language/learn-ql/ql-training.rst +++ b/docs/language/learn-ql/ql-training.rst @@ -1,8 +1,8 @@ CodeQL training and variant analysis examples ============================================= -QL and variant analysis ------------------------ +CodeQL and variant analysis +--------------------------- `Variant analysis `__ is the process of using a known vulnerability as a seed to find similar problems in your code. Security engineers typically perform variant analysis to identify possible vulnerabilities and to ensure that these threats are properly fixed across multiple code bases. @@ -10,8 +10,8 @@ QL and variant analysis CodeQL is easy to learn, and exploring code using CodeQL is the most efficient way to perform variant analysis. -Learning QL for variant analysis --------------------------------- +Learning CodeQL for variant analysis +------------------------------------ Start learning how to use CodeQL in variant analysis for a specific language by looking at the topics below. Each topic links to a short presentation on CodeQL, its libraries, or an example variant discovered using CodeQL. @@ -45,7 +45,7 @@ CodeQL and variant analysis for C/C++ - `Introduction to local data flow <../ql-training/cpp/data-flow-cpp.html>`__–an introduction to analyzing local data flow in C/C++ using CodeQL, including an example demonstrating how to develop a query to find a real CVE. - `Exercise: snprintf overflow <../ql-training/cpp/snprintf.html>`__–an example demonstrating how to develop a data flow query. - `Introduction to global data flow <../ql-training/cpp/global-data-flow-cpp.html>`__–an introduction to analyzing global data flow in C/C++ using CodeQL. -- `Analyzing control flow: CodeQL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using QL. +- `Analyzing control flow: CodeQL for C/C++ <../ql-training/cpp/control-flow-cpp.html>`__–an introduction to analyzing control flow in C/C++ using CodeQL. CodeQL and variant analysis for Java ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -61,6 +61,6 @@ More resources ~~~~~~~~~~~~~~ - If you are completely new to CodeQL, look at our introductory topics in :doc:`Learning CodeQL `. -- To find more detailed information about how to write CodeQL queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. +- To find more detailed information about how to write queries for specific languages, visit the links in :ref:`Writing CodeQL queries `. - To read more about how CodeQL queries have been used in Semmle's security research, and to read about new CodeQL developments, visit the `Semmle blog `__. - Find more examples of queries written by Semmle's own security researchers in the `Semmle Demos repository `__ on GitHub. diff --git a/docs/language/ql-training/cpp/data-flow-cpp.rst b/docs/language/ql-training/cpp/data-flow-cpp.rst index e78e8e86220e..32a3dfa233b6 100644 --- a/docs/language/ql-training/cpp/data-flow-cpp.rst +++ b/docs/language/ql-training/cpp/data-flow-cpp.rst @@ -82,9 +82,9 @@ Write a query that flags ``printf`` calls where the format argument is not a ``S .. note:: - This first query is about finding places where the format specifier is not a constant string. In CodeQL for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. + This first query is about finding places where the format specifier is not a constant string. In the CodeQL libraries for C/C++, constant strings are modeled as ``StringLiteral`` nodes, so we are looking for calls to format functions where the format specifier argument is not a string literal. - The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the CodeQL for C/C++ standard library class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. + The `C/C++ standard libraries `__ include many different formatting functions that may be vulnerable to this particular attack–including ``printf``, ``snprintf``, and others. Furthermore, each of these different formatting functions may include the format string in a different position in the argument list. Instead of laboriously listing all these different variants, we can make use of the standard CodeQL class ``FormattingFunction``, which provides an interface that models common formatting functions in C/C++. Meh... ====== diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index cbe29e6c520e..9cfb1d3b442c 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -108,7 +108,7 @@ Each query library also implicitly defines a module. Queries are always contained in query files with the file extension ``.ql``. `Quick queries `__, run in `QL for Eclipse `__, are no exception: the quick query window maintains a temporary query file in the background. - Parts of queries can be lifted into `library files `__ with the extension ``qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. + Parts of queries can be lifted into `library files `__ with the extension ``.qll``. Definitions within such libraries can be brought into scope using ``import`` statements, and similarly QLL files can import each other’s definitions using “import” statements. Logic can be encapsulated as user-defined `predicates `__ and `classes `__, and organized into `modules `__. Each QLL file implicitly defines a module, but QL and QLL files can also contain explicit module definitions, as we will see later. diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 3c062089428c..156cb0a4a68f 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -64,7 +64,7 @@ Working with functions Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by class Call and its subclasses: +Calls to functions are modeled by class ``Call`` and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function @@ -103,7 +103,7 @@ Working with macros #define square(x) x*x y = square(y0), z = square(z0) -is represented in the CodeQL database database as: +is represented in the CodeQL database as: - A Macro entity representing the text of the *head* and *body* of the macro - Assignment nodes, representing the two assignments after preprocessing @@ -117,4 +117,4 @@ Useful predicates on ``Element``: ``isInMacroExpansion()``, ``isAffectedByMacro( .. note:: - The CodeQL database also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. \ No newline at end of file + The CodeQL database also contains information about macro definitions, which are represented by class ``Macro``. These macro definitions are related to the AST nodes resulting from their uses by the class ``MacroAccess``. diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index f7afe713c4ae..46106204ed40 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -158,7 +158,7 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes in continued +Classes continued ======================= .. container:: column-left diff --git a/docs/language/ql-training/slide-snippets/intro-ql-general.rst b/docs/language/ql-training/slide-snippets/intro-ql-general.rst index d559c5bbeb7d..ae0c0cdabb58 100644 --- a/docs/language/ql-training/slide-snippets/intro-ql-general.rst +++ b/docs/language/ql-training/slide-snippets/intro-ql-general.rst @@ -121,7 +121,7 @@ QL is: - a **logic** language based on first-order logic - a **declarative** language without side effects - an **object-oriented** language -- a **query** language working on a read-only CodeQL database database +- a **query** language working on a read-only CodeQL database - equipped with rich standard libraries **for program analysis** .. note:: From 8d02a740dda1b8ed961249b4e40d7e3dfd0c7409 Mon Sep 17 00:00:00 2001 From: james Date: Tue, 5 Nov 2019 20:03:47 +0000 Subject: [PATCH 0214/2538] docs: address remaining comments --- docs/language/ql-training/conf.py | 8 ++++---- .../ql-training/slide-snippets/local-data-flow.rst | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/language/ql-training/conf.py b/docs/language/ql-training/conf.py index 8f8a13569b51..117f515a54fa 100644 --- a/docs/language/ql-training/conf.py +++ b/docs/language/ql-training/conf.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- # -# QL training slides build configuration file +# CodeQL training slides build configuration file # # This file is execfile()d with the current directory set to its # containing dir. @@ -59,7 +59,7 @@ def setup(sphinx): master_doc = 'index' # General information about the project. -project = u'QL training and variant analysis examples' +project = u'CodeQL training and variant analysis examples' # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, @@ -77,10 +77,10 @@ def setup(sphinx): # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -html_title = 'QL training and variant analysis examples' +html_title = 'CodeQL training and variant analysis examples' # Output file base name for HTML help builder. -htmlhelp_basename = 'QL training' +htmlhelp_basename = 'CodeQL training' # The Semmle version info for the current release you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index 068dfc9170ac..85b851a9ce05 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -70,7 +70,7 @@ Local vs global data flow For further information, see: - - `Introduction to data flow analysis in QL `__ + - `Introduction to data flow analysis in CodeQL `__ .. rst-class:: background2 From 0df3d2ce602a76b5dd8b67e9016631c7148042ea Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 5 Nov 2019 13:00:55 -0800 Subject: [PATCH 0215/2538] [zlaski/pointer-overflow-check] Improve test case. --- .../Memory Management/PointerOverflowCheck/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp index 24f16198e7b7..97912bbb475c 100644 --- a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/PointerOverflowCheck/test.cpp @@ -9,7 +9,7 @@ bool check_pointer_overflow(P *ptr, P *ptr_end) { // x86-64 gcc 9.2 -O2: not deleted // x86-64 clang 9.0.0 -O2: not deleted // x64 msvc v19.22 /O2: not deleted - return ptr + 4 >= ptr_end; // GOOD + return ptr_end - ptr > 4; // GOOD } struct Q { @@ -22,6 +22,6 @@ struct Q { void foo(int untrusted_int) { Q q; if (q.begin() + untrusted_int > q.end() || // GOOD - q.begin() + untrusted_int < q.begin()) // BAD + q.begin() + untrusted_int < q.begin()) // BAD [NOT DETECTED] throw q; } From 1f82ea77502fb98dd43a3626836c6600d32b9f2c Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Tue, 5 Nov 2019 18:25:41 -0800 Subject: [PATCH 0216/2538] [zlaski/pointer-overflow-check] Refine query to exclude macros (other than 'assert'). --- .../PointerOverflowCheck-good.cpp | 2 +- .../PointerOverflowCheck.qhelp | 15 +++++++-------- .../Memory Management/PointerOverflowCheck.ql | 17 ++++++++++++++--- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp index 0d10ea1fb19e..14e0d07a6a94 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck-good.cpp @@ -1,3 +1,3 @@ bool check_pointer_overflow(P *ptr, P *ptr_end) { - return ptr + 4 >= ptr_end; // GOOD + return ptr_end - ptr >= 4; // GOOD } diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp index 6d251e3e2b12..5c93c70596bd 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.qhelp @@ -4,7 +4,7 @@

    -When checking for out-of-range pointer values, one might write tests like +When checking for out-of-range pointer values, we might write tests like p + a < p and check if the value "wraps around". Such a test is wrong in that it relies on the overflow of p + a, which has undefined behavior. In fact, many optimizing compilers will remove @@ -18,13 +18,12 @@ the operating system) or nonexistent.

    When checking for an out-of-range pointer, compare the pointer -value p against a known value p_max representing -the highest allowable memory address. Ideally, p_max should -point just past the end of a data structure, such as an array or a vector. -For lower-level work, it should point at the highest address in the program -heap. It is also important that p + a points at a valid object -and that a is small enough so that the expression p + a -does not itself overflow. +value p against a known pointer value p_max representing +the highest allowable memory address. The p_max pointer should +point inside or just past the end of a defined memory region, such that +p + a <= p_max. Since we do not wish to evaluate p + a +(which may result in undefined behavior), we rewrite the inequality as +p_max - p > a.

    diff --git a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql index c8874bb214ae..f7c0ebf7a723 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/PointerOverflowCheck.ql @@ -3,7 +3,7 @@ * @description Testing for out-of-range pointers by adding a value to a pointer * to see if it "wraps around" is dangerous because it relies * on undefined behavior and may lead to attempted use of - * nonexistent or inaccessible memory locations + * nonexistent or inaccessible memory locations. * @kind problem * @problem.severity warning * @precision high @@ -14,12 +14,23 @@ import cpp private import semmle.code.cpp.valuenumbering.GlobalValueNumbering -private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +class AssertMacro extends Macro { + AssertMacro() { + getName() = "assert" or + getName() = "_ASSERT" or + getName() = "_ASSERTE" or + getName() = "_ASSERT_EXPR" + } +} from RelationalOperation ro, PointerAddExpr add, Expr expr1, Expr expr2 where ro.getAnOperand() = add and add.getAnOperand() = expr1 and ro.getAnOperand() = expr2 and - globalValueNumber(expr1) = globalValueNumber(expr2) + globalValueNumber(expr1) = globalValueNumber(expr2) and + not exists(MacroInvocation mi | + mi.getAnAffectedElement() = add and not mi.getMacro() instanceof AssertMacro + ) select ro, "Pointer out-of-range check relying on pointer overflow is undefined." From fca7d9a391ea21206c6ec533e8fd66ac780c0e31 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 6 Nov 2019 07:42:34 +0100 Subject: [PATCH 0217/2538] C#: Cache IRType like for C++ --- csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll | 1 + csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll | 2 ++ 2 files changed, 3 insertions(+) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 0abfa14023d8..5534ed20914d 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -4,6 +4,7 @@ private import internal.IRTypeInternal +cached private newtype TIRType = TIRVoidType() or TIRUnknownType() or diff --git a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll index ac400b210a50..36b1285f9e01 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/internal/CSharpType.qll @@ -144,6 +144,7 @@ private IRType getIRTypeForPRValue(Type type) { string getOpaqueTagIdentityString(Type tag) { result = tag.getQualifiedName() } +cached private newtype TCSharpType = TPRValueType(Type type) { exists(getIRTypeForPRValue(type)) } or TGLValueAddressType(Type type) { any() } or @@ -163,6 +164,7 @@ class CSharpType extends TCSharpType { * Gets the `IRType` that represents this `CSharpType`. Many different `CSharpType`s can map to a * single `IRType`. */ + cached abstract IRType getIRType(); /** From 21d4e5f18624397b811c9fba594924de5be640f4 Mon Sep 17 00:00:00 2001 From: Esben Sparre Andreasen Date: Wed, 6 Nov 2019 10:16:43 +0100 Subject: [PATCH 0218/2538] Doc: Add missing `t` in `support`. --- change-notes/1.23/analysis-javascript.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 812e1e677487..49f527af4242 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -2,7 +2,7 @@ ## General improvements -* Suppor for `globalThis` has been added. +* Support for `globalThis` has been added. * Support for the following frameworks and libraries has been improved: - [firebase](https://www.npmjs.com/package/firebase) From 7a7a8b2b091fad67b88fa138bdad41698a295071 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 25 Oct 2019 11:11:26 +0100 Subject: [PATCH 0219/2538] JS: More steps in getImmediatePredecessor --- .../semmle/javascript/dataflow/DataFlow.qll | 73 +++++++++++-------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 8798df6cc37c..7c77df24e09a 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -188,11 +188,7 @@ module DataFlow { lvalueFlowStep(result, this) and not lvalueDefaultFlowStep(_, this) or - // Use of variable -> definition of variable - exists(SsaVariable var | - this = valueNode(var.getAUse()) and - result = TSsaDefNode(var) - ) + immediateFlowStep(result, this) or // Refinement of variable -> original definition of variable exists(SsaRefinementNode refinement | @@ -1299,6 +1295,44 @@ module DataFlow { ) } + /** + * Flow steps shared between `getImmediatePredecessor` and `localFlowStep`. + * + * Inlining is forced because the two relations are indexed differently. + */ + pragma[inline] + private predicate immediateFlowStep(Node pred, Node succ) { + exists(SsaVariable v | + pred = TSsaDefNode(v.getDefinition()) and + succ = valueNode(v.getAUse()) + ) + or + exists(Expr predExpr, Expr succExpr | + pred = valueNode(predExpr) and succ = valueNode(succExpr) + | + predExpr = succExpr.(ParExpr).getExpression() + or + predExpr = succExpr.(SeqExpr).getLastOperand() + or + predExpr = succExpr.(AssignExpr).getRhs() + or + predExpr = succExpr.(TypeAssertion).getExpression() + or + predExpr = succExpr.(NonNullAssertion).getExpression() + or + predExpr = succExpr.(ExpressionWithTypeArguments).getExpression() + ) + or + // flow from 'this' parameter into 'this' expressions + exists(ThisExpr thiz | + pred = TThisNode(thiz.getBindingContainer()) and + succ = valueNode(thiz) + ) + or + // `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform + pred = TReflectiveCallNode(succ.asExpr(), _) + } + /** * Holds if data can flow from `pred` to `succ` in one local step. */ @@ -1309,6 +1343,8 @@ module DataFlow { or lvalueDefaultFlowStep(pred, succ) or + immediateFlowStep(pred, succ) + or // Flow through implicit SSA nodes exists(SsaImplicitDefinition ssa | succ = TSsaDefNode(ssa) | // from any explicit definition or implicit init of a captured variable into @@ -1326,45 +1362,18 @@ module DataFlow { pred = TSsaDefNode(ssa.(SsaPseudoDefinition).getAnInput().getDefinition()) ) or - // flow out of local variables - exists(SsaVariable v | - pred = TSsaDefNode(v.getDefinition()) and - succ = valueNode(v.getAUse()) - ) - or exists(Expr predExpr, Expr succExpr | pred = valueNode(predExpr) and succ = valueNode(succExpr) | - predExpr = succExpr.(ParExpr).getExpression() - or - predExpr = succExpr.(SeqExpr).getLastOperand() - or predExpr = succExpr.(LogicalBinaryExpr).getAnOperand() or - predExpr = succExpr.(AssignExpr).getRhs() - or predExpr = succExpr.(ConditionalExpr).getABranch() or - predExpr = succExpr.(TypeAssertion).getExpression() - or - predExpr = succExpr.(NonNullAssertion).getExpression() - or - predExpr = succExpr.(ExpressionWithTypeArguments).getExpression() - or exists(Function f | predExpr = f.getAReturnedExpr() and localCall(succExpr, f) ) ) - or - // flow from 'this' parameter into 'this' expressions - exists(ThisExpr thiz | - pred = TThisNode(thiz.getBindingContainer()) and - succ = valueNode(thiz) - ) - or - // `f.call(...)` and `f.apply(...)` evaluate to the result of the reflective call they perform - pred = TReflectiveCallNode(succ.asExpr(), _) } /** From bc35f24f31e8d6772e16eb02adb74a3ad38aaaec Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 25 Oct 2019 11:11:42 +0100 Subject: [PATCH 0220/2538] JS: Generalize access paths to arbitrary root nodes --- .../semmle/javascript/GlobalAccessPaths.qll | 178 ++++++++++++++---- .../javascript/dataflow/TypeTracking.qll | 20 ++ .../dataflow/internal/CallGraphs.qll | 6 +- .../CallGraphs/AnnotatedTest/access-path.js | 39 ++++ 4 files changed, 198 insertions(+), 45 deletions(-) create mode 100644 javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 9e089fc9cf08..99e0d168298d 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -5,6 +5,24 @@ import javascript module GlobalAccessPath { + /** + * A source node that can be the root of an access path. + */ + private class Root extends DataFlow::SourceNode { + Root() { + not this.accessesGlobal(_) and + not this instanceof DataFlow::PropRead and + not this instanceof PropertyProjection and + not this instanceof Closure::ClosureNamespaceAccess and + not this = DataFlow::parameterNode(any(ImmediatelyInvokedFunctionExpr iife).getAParameter()) + } + + /** Holds if this represents the root of the global access path. */ + predicate isGlobal() { + this = DataFlow::globalAccessPathRootPseudoNode() + } + } + /** * A local variable with exactly one definition, not counting implicit initialization. */ @@ -21,52 +39,56 @@ module GlobalAccessPath { } /** - * Gets the global access path referred to by `node`. + * Gets the access path relative to `root` referred to by `node`. * * This holds for direct references as well as for aliases * established through local data flow. * * Examples: * ``` - * function f() { - * let v = foo.bar; // reference to 'foo.bar' - * v.baz; // reference to 'foo.bar.baz' + * function f(x) { + * let a = x.f.g; // access path relative to 'x' is '.f.g' + * let b = a.h; // access path relative to 'x' is '.f.g.h' * } - * - * (function(ns) { - * ns.x; // reference to 'NS.x' - * })(NS = NS || {}); * ``` */ cached - string fromReference(DataFlow::Node node) { - result = fromReference(node.getImmediatePredecessor()) + string fromReference(DataFlow::Node node, Root root) { + root = node and + not root.isGlobal() and + result = "" + or + result = fromReference(node.getImmediatePredecessor(), root) or exists(EffectivelyConstantVariable var | var.isCaptured() and node.asExpr() = var.getAnAccess() and - result = fromReference(var.getValue()) + result = fromReference(var.getValue(), root) ) or node.accessesGlobal(result) and - result != "undefined" + result != "undefined" and + root.isGlobal() or not node.accessesGlobal(_) and exists(DataFlow::PropRead prop | node = prop | - result = fromReference(prop.getBase()) + "." + prop.getPropertyName() + result = fromReference(prop.getBase(), root) + "." + prop.getPropertyName() ) or - exists(Closure::ClosureNamespaceAccess acc | node = acc | result = acc.getClosureNamespace()) + exists(Closure::ClosureNamespaceAccess acc | node = acc | + result = acc.getClosureNamespace() and + root.isGlobal() + ) or exists(PropertyProjection proj | node = proj | proj.isSingletonProjection() and - result = fromReference(proj.getObject()) + "." + proj.getASelector() + result = fromReference(proj.getObject(), root) + "." + proj.getASelector() ) or // Treat 'e || {}' as having the same name as 'e' exists(LogOrExpr e | node.asExpr() = e | e.getRightOperand().(ObjectExpr).getNumProperty() = 0 and - result = fromReference(e.getLeftOperand().flow()) + result = fromReference(e.getLeftOperand().flow(), root) ) or // Treat 'e && e.f' as having the same name as 'e.f' @@ -84,10 +106,33 @@ module GlobalAccessPath { rhs.getBase().(PropAccess).getQualifiedName() = name ) ) and - result = fromReference(rhs.flow()) + result = fromReference(rhs.flow(), root) ) } + /** + * Gets the global access path referred to by `node`. + * + * This holds for direct references as well as for aliases + * established through local data flow. + * + * Examples: + * ``` + * function f() { + * let v = foo.bar; // reference to 'foo.bar' + * v.baz; // reference to 'foo.bar.baz' + * } + * + * (function(ns) { + * ns.x; // reference to 'NS.x' + * })(NS = NS || {}); + * ``` + */ + cached + string fromReference(DataFlow::Node node) { + result = fromReference(node, DataFlow::globalAccessPathRootPseudoNode()) + } + /** * Holds if `rhs` is the right-hand side of a self-assignment. * @@ -96,7 +141,9 @@ module GlobalAccessPath { * foo = foo || {}; * ``` */ - private predicate isSelfAssignment(DataFlow::Node rhs) { fromRhs(rhs) = fromReference(rhs) } + private predicate isSelfAssignment(DataFlow::Node rhs) { + fromRhs(rhs, DataFlow::globalAccessPathRootPseudoNode()) = fromReference(rhs, DataFlow::globalAccessPathRootPseudoNode()) + } /** * Holds if there is an assignment to `accessPath` in `file`, not counting @@ -104,7 +151,7 @@ module GlobalAccessPath { */ private predicate isAssignedInFile(string accessPath, File file) { exists(DataFlow::Node rhs | - fromRhs(rhs) = accessPath and + fromRhs(rhs, DataFlow::globalAccessPathRootPseudoNode()) = accessPath and not isSelfAssignment(rhs) and // Note: Avoid unneeded materialization of DataFlow::Node.getFile() rhs.getAstNode().getFile() = file @@ -112,7 +159,7 @@ module GlobalAccessPath { } /** - * Holds if `accessPath` is only assigned to from one file, not counting + * Holds if the global `accessPath` is only assigned to from one file, not counting * self-assignments. */ predicate isAssignedInUniqueFile(string accessPath) { @@ -120,66 +167,117 @@ module GlobalAccessPath { } /** - * Gets the global access path `node` is being assigned to, if any. + * Gets the access path relative to `root`, which `node` is being assigned to, if any. * * Only holds for the immediate right-hand side of an assignment or property, not * for nodes that transitively flow there. * - * For example, the class nodes below all map to `foo.bar`: + * For example, the class nodes below all map to `.foo.bar` relative to `x`: * ``` - * foo.bar = class {}; - * - * foo = { bar: class {} }; - * - * (function(f) { - * f.bar = class {} - * })(foo = foo || {}); + * function f(x) { + * x.foo.bar = class {}; + * x.foo = { bar: class() }; + * let alias = x; + * alias.foo.bar = class {}; + * } * ``` */ cached - string fromRhs(DataFlow::Node node) { + string fromRhs(DataFlow::Node node, Root root) { exists(DataFlow::SourceNode base, string baseName, string name | node = base.getAPropertyWrite(name).getRhs() and result = baseName + "." + name | - baseName = fromReference(base) + baseName = fromReference(base, root) or - baseName = fromRhs(base) + baseName = fromRhs(base, root) ) or exists(GlobalVariable var | node = var.getAnAssignedExpr().flow() and - result = var.getName() + result = var.getName() and + root.isGlobal() ) or exists(FunctionDeclStmt fun | node = DataFlow::valueNode(fun) and - result = fun.getId().(GlobalVarDecl).getName() + result = fun.getId().(GlobalVarDecl).getName() and + root.isGlobal() ) or exists(ClassDeclStmt cls | node = DataFlow::valueNode(cls) and - result = cls.getIdentifier().(GlobalVarDecl).getName() + result = cls.getIdentifier().(GlobalVarDecl).getName() and + root.isGlobal() ) or exists(EnumDeclaration decl | node = DataFlow::valueNode(decl) and - result = decl.getIdentifier().(GlobalVarDecl).getName() + result = decl.getIdentifier().(GlobalVarDecl).getName() and + root.isGlobal() ) or exists(NamespaceDeclaration decl | node = DataFlow::valueNode(decl) and - result = decl.getId().(GlobalVarDecl).getName() + result = decl.getId().(GlobalVarDecl).getName() and + root.isGlobal() ) } + /** + * Gets the global access path `node` is being assigned to, if any. + * + * Only holds for the immediate right-hand side of an assignment or property, not + * for nodes that transitively flow there. + * + * For example, the class nodes below all map to `foo.bar`: + * ``` + * foo.bar = class {}; + * + * foo = { bar: class {} }; + * + * (function(f) { + * f.bar = class {} + * })(foo = foo || {}); + * ``` + */ + cached + string fromRhs(DataFlow::Node node) { + result = fromRhs(node, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Gets the access path relative to `root` referenced by or assigned to `node`. + */ + string getAccessPath(DataFlow::Node node, Root root) { + result = fromReference(node, root) + or + not exists(fromReference(node, root)) and + result = fromRhs(node, root) + } + /** * Gets the global access path referenced by or assigned to `node`. */ string getAccessPath(DataFlow::Node node) { - result = fromReference(node) + result = getAccessPath(node, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Holds if there is a step from `pred` to `succ` through an assignment to an access path. + */ + pragma[inline] + predicate step(DataFlow::Node pred, DataFlow::Node succ) { + exists(string name, Root root | + name = fromRhs(pred, root) and + name = fromReference(succ, root) and + not root.isGlobal() + ) or - not exists(fromReference(node)) and - result = fromRhs(node) + exists(string name | + name = fromRhs(pred) and + name = fromReference(succ) and + isAssignedInUniqueFile(name) + ) } } diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index ef639d99ad4e..62e53962c3f3 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -14,6 +14,9 @@ private class PropertyName extends string { this = any(DataFlow::PropRef pr).getPropertyName() or GlobalAccessPath::isAssignedInUniqueFile(this) + or + this = GlobalAccessPath::fromRhs(_, _) and + this != "" } } @@ -95,6 +98,7 @@ module StepSummary { any(AdditionalTypeTrackingStep st).step(pred, succ) and summary = LevelStep() or + // Store to global access path exists(string name | name = GlobalAccessPath::fromRhs(pred) and GlobalAccessPath::isAssignedInUniqueFile(name) and @@ -102,6 +106,7 @@ module StepSummary { summary = StoreStep(name) ) or + // Load from global access path exists(string name | name = GlobalAccessPath::fromReference(succ) and GlobalAccessPath::isAssignedInUniqueFile(name) and @@ -109,6 +114,21 @@ module StepSummary { summary = LoadStep(name) ) or + // Store to non-global access path + exists(string name | + name = GlobalAccessPath::fromRhs(pred, succ) and + succ != DataFlow::globalAccessPathRootPseudoNode() and + summary = StoreStep(name) + ) + or + // Load from non-global access path + exists(string name | + name = GlobalAccessPath::fromReference(succ, pred) and + pred != DataFlow::globalAccessPathRootPseudoNode() and + summary = LoadStep(name) and + name != "" + ) + or // Summarize calls with flow directly from a parameter to a return. exists(DataFlow::ParameterNode param, DataFlow::FunctionNode fun | ( diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll index a5e140734a4f..1e554b170f18 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -43,11 +43,7 @@ module CallGraph { or imprecision = 0 and t.start() and - exists(string name | - GlobalAccessPath::isAssignedInUniqueFile(name) and - GlobalAccessPath::fromRhs(function) = name and - GlobalAccessPath::fromReference(result) = name - ) + GlobalAccessPath::step(function, result) or imprecision = 0 and exists(DataFlow::ClassNode cls | diff --git a/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js new file mode 100644 index 000000000000..f320d3ae8f49 --- /dev/null +++ b/javascript/ql/test/library-tests/CallGraphs/AnnotatedTest/access-path.js @@ -0,0 +1,39 @@ +function foo() { + let self = this; + + /** name:direct */ + self.foo.bar.direct = function() {}; + + /** calls:direct */ + self.foo.bar.direct(); + + self.foo.bar = { + /** name:baz */ + baz() {}, + bong() { + /** calls:baz */ + self.foo.bar.baz(); + } + } + + /** calls:baz */ + self.foo.bar.baz(); + + self.foo.bar.Class = class { + /** name:m */ + m() {} + } + + self.foo.bar.instance = new self.foo.bar.Class(); + + /** calls:m */ + self.foo.bar.instance.m(); + + let unknownObject = unknownCall(); + + /** name:direct2 */ + unknownObject.bar.baz.direct = function() {}; + + /** calls:direct2 */ + unknownObject.bar.baz.direct(); +} From e90516d4d8baebff5228d6190f58306f47407175 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 24 Oct 2019 09:51:47 +0100 Subject: [PATCH 0221/2538] JS: Dont use getALocalSource in fromRhs --- .../ql/src/semmle/javascript/GlobalAccessPaths.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 99e0d168298d..3e797e7914c1 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -184,13 +184,13 @@ module GlobalAccessPath { */ cached string fromRhs(DataFlow::Node node, Root root) { - exists(DataFlow::SourceNode base, string baseName, string name | - node = base.getAPropertyWrite(name).getRhs() and - result = baseName + "." + name + exists(DataFlow::PropWrite write, string baseName | + node = write.getRhs() and + result = baseName + "." + write.getPropertyName() | - baseName = fromReference(base, root) + baseName = fromReference(write.getBase(), root) or - baseName = fromRhs(base, root) + baseName = fromRhs(write.getBase(), root) ) or exists(GlobalVariable var | From c365833731965757e9123cb87d446c5a92bcdaa0 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 25 Oct 2019 11:47:50 +0100 Subject: [PATCH 0222/2538] JS: Refactor the public access path API --- .../ql/src/semmle/javascript/Closure.qll | 4 +- .../semmle/javascript/GlobalAccessPaths.qll | 169 +++++++++++++----- javascript/ql/src/semmle/javascript/JSDoc.qll | 2 +- .../src/semmle/javascript/dataflow/Nodes.qll | 10 +- .../javascript/dataflow/TypeTracking.qll | 19 +- .../dataflow/internal/CallGraphs.qll | 2 +- 6 files changed, 136 insertions(+), 70 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/Closure.qll b/javascript/ql/src/semmle/javascript/Closure.qll index 066f68ca5fae..83b8049d48fa 100644 --- a/javascript/ql/src/semmle/javascript/Closure.qll +++ b/javascript/ql/src/semmle/javascript/Closure.qll @@ -230,7 +230,7 @@ module Closure { * Gets the closure namespace path addressed by the given data flow node, if any. */ string getClosureNamespaceFromSourceNode(DataFlow::SourceNode node) { - result = GlobalAccessPath::getAccessPath(node) and + node = AccessPath::getAReferenceOrAssignmentTo(result) and hasClosureNamespacePrefix(result) } @@ -238,7 +238,7 @@ module Closure { * Gets the closure namespace path written to by the given property write, if any. */ string getWrittenClosureNamespace(DataFlow::PropWrite node) { - result = GlobalAccessPath::fromRhs(node.getRhs()) and + node.getRhs() = AccessPath::getAnAssignmentTo(result) and hasClosureNamespacePrefix(result) } diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 3e797e7914c1..8833e3a91799 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -4,11 +4,41 @@ import javascript +deprecated module GlobalAccessPath { + /** + * DEPRECATED. Instead use `AccessPath::getAReferenceTo` with the result and parameter reversed. + */ + pragma[inline] + string fromReference(DataFlow::Node node) { + node = AccessPath::getAReferenceTo(result) + } + + /** + * DEPRECATED. Instead use `AccessPath::getAnAssignmentTo` with the result and parameter reversed. + */ + pragma[inline] + string fromRhs(DataFlow::Node node) { + node = AccessPath::getAnAssignmentTo(result) + } + + /** + * DEPRECATED. Use `AccessPath::getAReferenceOrAssignmentTo`. + */ + pragma[inline] + string getAccessPath(DataFlow::Node node) { + result = fromReference(node) + or + not exists(fromReference(node)) and + result = fromRhs(node) + } +} + +module AccessPath { /** * A source node that can be the root of an access path. */ - private class Root extends DataFlow::SourceNode { + class Root extends DataFlow::SourceNode { Root() { not this.accessesGlobal(_) and not this instanceof DataFlow::PropRead and @@ -53,7 +83,7 @@ module GlobalAccessPath { * ``` */ cached - string fromReference(DataFlow::Node node, Root root) { + private string fromReference(DataFlow::Node node, Root root) { root = node and not root.isGlobal() and result = "" @@ -110,29 +140,6 @@ module GlobalAccessPath { ) } - /** - * Gets the global access path referred to by `node`. - * - * This holds for direct references as well as for aliases - * established through local data flow. - * - * Examples: - * ``` - * function f() { - * let v = foo.bar; // reference to 'foo.bar' - * v.baz; // reference to 'foo.bar.baz' - * } - * - * (function(ns) { - * ns.x; // reference to 'NS.x' - * })(NS = NS || {}); - * ``` - */ - cached - string fromReference(DataFlow::Node node) { - result = fromReference(node, DataFlow::globalAccessPathRootPseudoNode()) - } - /** * Holds if `rhs` is the right-hand side of a self-assignment. * @@ -183,7 +190,7 @@ module GlobalAccessPath { * ``` */ cached - string fromRhs(DataFlow::Node node, Root root) { + private string fromRhs(DataFlow::Node node, Root root) { exists(DataFlow::PropWrite write, string baseName | node = write.getRhs() and result = baseName + "." + write.getPropertyName() @@ -225,42 +232,109 @@ module GlobalAccessPath { } /** - * Gets the global access path `node` is being assigned to, if any. + * Gets a node that refers to the given access path relative to the given `root` node, + * or `root` itself if the access path is empty. * - * Only holds for the immediate right-hand side of an assignment or property, not - * for nodes that transitively flow there. + * This works for direct references as well as for aliases established through local data flow. + * + * Note that non-empty access paths contain an initial `.`, such as in `.foo.bar`. * - * For example, the class nodes below all map to `foo.bar`: + * For example: * ``` - * foo.bar = class {}; + * function f(x) { + * let a = x.f.g; // reference to (x, ".f.g") + * let b = a.h; // reference to (x, ".f.g.h") + * } + * ``` + */ + DataFlow::Node getAReferenceTo(Root root, string path) { + path = fromReference(result, root) and + not root.isGlobal() + } + + /** + * Gets a node that refers to the given global access path. * - * foo = { bar: class {} }; + * This works for direct references as well as for aliases established through local data flow. + * + * Examples: + * ``` + * function f() { + * let v = foo.bar; // reference to 'foo.bar' + * v.baz; // reference to 'foo.bar.baz' + * } + * + * (function(ns) { + * ns.x; // reference to 'NS.x' + * })(NS = NS || {}); + * ``` + */ + DataFlow::Node getAReferenceTo(string path) { + path = fromReference(result, DataFlow::globalAccessPathRootPseudoNode()) + } + + /** + * Gets a node that is assigned to the given access path relative to the given `root` node. + * + * Only gets the immediate right-hand side of an assignment or property, not + * nodes that transitively flow there. + * + * Note that access paths contain an initial `.`, such as in `.foo.bar`. * + * For example, the class nodes below are all assignments to `(x, ".foo.bar")`. + * ``` + * function f(x) { + * x.foo.bar = class {}; + * x.foo = { bar: class() }; + * let alias = x; + * alias.foo.bar = class {}; + * } + * ``` + */ + DataFlow::Node getAnAssignmentTo(Root root, string path) { + path = fromRhs(result, root) and + not root.isGlobal() + } + + /** + * Gets a node that is assigned to the given global access path. + * + * Only gets the immediate right-hand side of an assignment or property or a global declaration, + * not nodes that transitively flow there. + * + * For example, the class nodes below are all assignmetns to `foo.bar`: + * ``` + * foo.bar = class {}; + * foo = { bar: class {} }; * (function(f) { * f.bar = class {} * })(foo = foo || {}); * ``` */ - cached - string fromRhs(DataFlow::Node node) { - result = fromRhs(node, DataFlow::globalAccessPathRootPseudoNode()) + DataFlow::Node getAnAssignmentTo(string path) { + path = fromRhs(result, DataFlow::globalAccessPathRootPseudoNode()) } /** - * Gets the access path relative to `root` referenced by or assigned to `node`. + * Gets a node that refers to or is assigned to the given global access path. + * + * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ - string getAccessPath(DataFlow::Node node, Root root) { - result = fromReference(node, root) + DataFlow::Node getAReferenceOrAssignmentTo(string path) { + result = getAReferenceTo(path) or - not exists(fromReference(node, root)) and - result = fromRhs(node, root) + result = getAnAssignmentTo(path) } /** - * Gets the global access path referenced by or assigned to `node`. + * Gets a node that refers to or is assigned to the given access path. + * + * See `getAReferenceTo` and `getAnAssignmentTo` for more details. */ - string getAccessPath(DataFlow::Node node) { - result = getAccessPath(node, DataFlow::globalAccessPathRootPseudoNode()) + DataFlow::Node getAReferenceOrAssignmentTo(Root root, string path) { + result = getAReferenceTo(root, path) + or + result = getAnAssignmentTo(root, path) } /** @@ -269,14 +343,13 @@ module GlobalAccessPath { pragma[inline] predicate step(DataFlow::Node pred, DataFlow::Node succ) { exists(string name, Root root | - name = fromRhs(pred, root) and - name = fromReference(succ, root) and - not root.isGlobal() + pred = getAnAssignmentTo(root, name) and + succ = getAReferenceTo(root, name) ) or exists(string name | - name = fromRhs(pred) and - name = fromReference(succ) and + pred = getAnAssignmentTo(name) and + succ = getAReferenceTo(name) and isAssignedInUniqueFile(name) ) } diff --git a/javascript/ql/src/semmle/javascript/JSDoc.qll b/javascript/ql/src/semmle/javascript/JSDoc.qll index 806a9477ba61..c080061bc7c9 100644 --- a/javascript/ql/src/semmle/javascript/JSDoc.qll +++ b/javascript/ql/src/semmle/javascript/JSDoc.qll @@ -582,7 +582,7 @@ module JSDoc { * within this container. */ string resolveAlias(string alias) { - result = GlobalAccessPath::getAccessPath(getNodeFromAlias(alias)) + getNodeFromAlias(alias) = AccessPath::getAReferenceOrAssignmentTo(result) } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index a44f2909ce0f..a1e15538ad26 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -771,11 +771,7 @@ class ClassNode extends DataFlow::SourceNode { */ pragma[noinline] predicate hasQualifiedName(string name) { - exists(DataFlow::Node rhs | - getAClassReference().flowsTo(rhs) and - name = GlobalAccessPath::fromRhs(rhs) and - GlobalAccessPath::isAssignedInUniqueFile(name) - ) + getAClassReference().flowsTo(AccessPath::getAnAssignmentTo(name)) } } @@ -883,7 +879,7 @@ module ClassNode { } private DataFlow::PropRef getAPrototypeReferenceInFile(string name, File f) { - GlobalAccessPath::getAccessPath(result.getBase()) = name and + result.getBase() = AccessPath::getAReferenceOrAssignmentTo(name) and result.getPropertyName() = "prototype" and result.getFile() = f } @@ -904,7 +900,7 @@ module ClassNode { ) or exists(string name | - name = GlobalAccessPath::fromRhs(this) and + this = AccessPath::getAnAssignmentTo(name) and exists(getAPrototypeReferenceInFile(name, getFile())) ) ) diff --git a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll index 62e53962c3f3..ecbb31877286 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TypeTracking.qll @@ -13,10 +13,9 @@ private class PropertyName extends string { PropertyName() { this = any(DataFlow::PropRef pr).getPropertyName() or - GlobalAccessPath::isAssignedInUniqueFile(this) + AccessPath::isAssignedInUniqueFile(this) or - this = GlobalAccessPath::fromRhs(_, _) and - this != "" + exists(AccessPath::getAnAssignmentTo(_, this)) } } @@ -100,31 +99,29 @@ module StepSummary { or // Store to global access path exists(string name | - name = GlobalAccessPath::fromRhs(pred) and - GlobalAccessPath::isAssignedInUniqueFile(name) and + pred = AccessPath::getAnAssignmentTo(name) and + AccessPath::isAssignedInUniqueFile(name) and succ = DataFlow::globalAccessPathRootPseudoNode() and summary = StoreStep(name) ) or // Load from global access path exists(string name | - name = GlobalAccessPath::fromReference(succ) and - GlobalAccessPath::isAssignedInUniqueFile(name) and + succ = AccessPath::getAReferenceTo(name) and + AccessPath::isAssignedInUniqueFile(name) and pred = DataFlow::globalAccessPathRootPseudoNode() and summary = LoadStep(name) ) or // Store to non-global access path exists(string name | - name = GlobalAccessPath::fromRhs(pred, succ) and - succ != DataFlow::globalAccessPathRootPseudoNode() and + pred = AccessPath::getAnAssignmentTo(succ, name) and summary = StoreStep(name) ) or // Load from non-global access path exists(string name | - name = GlobalAccessPath::fromReference(succ, pred) and - pred != DataFlow::globalAccessPathRootPseudoNode() and + succ = AccessPath::getAReferenceTo(pred, name) and summary = LoadStep(name) and name != "" ) diff --git a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll index 1e554b170f18..d58a83fa0bd2 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/internal/CallGraphs.qll @@ -43,7 +43,7 @@ module CallGraph { or imprecision = 0 and t.start() and - GlobalAccessPath::step(function, result) + AccessPath::step(function, result) or imprecision = 0 and exists(DataFlow::ClassNode cls | From b373901e11461d598edb6101dadaa9544ce7e0c8 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 28 Oct 2019 09:36:27 +0000 Subject: [PATCH 0223/2538] JS: Avoid leading dot in access paths --- .../semmle/javascript/GlobalAccessPaths.qll | 34 ++++++++++++------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 8833e3a91799..2b7da2fe7aea 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -68,6 +68,18 @@ module AccessPath { DataFlow::Node getValue() { result = getSsaDefinition().getRhsNode() } } + /** + * Appends a single property name onto the access path `base`, where + * the empty string represents the empty access path. + */ + bindingset[base, prop] + private string join(string base, string prop) { + base = "" and result = prop + or + base != "" and + result = base + "." + prop + } + /** * Gets the access path relative to `root` referred to by `node`. * @@ -77,8 +89,8 @@ module AccessPath { * Examples: * ``` * function f(x) { - * let a = x.f.g; // access path relative to 'x' is '.f.g' - * let b = a.h; // access path relative to 'x' is '.f.g.h' + * let a = x.f.g; // access path relative to 'x' is 'f.g' + * let b = a.h; // access path relative to 'x' is 'f.g.h' * } * ``` */ @@ -102,7 +114,7 @@ module AccessPath { or not node.accessesGlobal(_) and exists(DataFlow::PropRead prop | node = prop | - result = fromReference(prop.getBase(), root) + "." + prop.getPropertyName() + result = join(fromReference(prop.getBase(), root), prop.getPropertyName()) ) or exists(Closure::ClosureNamespaceAccess acc | node = acc | @@ -112,7 +124,7 @@ module AccessPath { or exists(PropertyProjection proj | node = proj | proj.isSingletonProjection() and - result = fromReference(proj.getObject(), root) + "." + proj.getASelector() + result = join(fromReference(proj.getObject(), root), proj.getASelector().getStringValue()) ) or // Treat 'e || {}' as having the same name as 'e' @@ -179,7 +191,7 @@ module AccessPath { * Only holds for the immediate right-hand side of an assignment or property, not * for nodes that transitively flow there. * - * For example, the class nodes below all map to `.foo.bar` relative to `x`: + * For example, the class nodes below all map to `foo.bar` relative to `x`: * ``` * function f(x) { * x.foo.bar = class {}; @@ -193,7 +205,7 @@ module AccessPath { private string fromRhs(DataFlow::Node node, Root root) { exists(DataFlow::PropWrite write, string baseName | node = write.getRhs() and - result = baseName + "." + write.getPropertyName() + result = join(baseName, write.getPropertyName()) | baseName = fromReference(write.getBase(), root) or @@ -237,13 +249,11 @@ module AccessPath { * * This works for direct references as well as for aliases established through local data flow. * - * Note that non-empty access paths contain an initial `.`, such as in `.foo.bar`. - * * For example: * ``` * function f(x) { - * let a = x.f.g; // reference to (x, ".f.g") - * let b = a.h; // reference to (x, ".f.g.h") + * let a = x.f.g; // reference to (x, "f.g") + * let b = a.h; // reference to (x, "f.g.h") * } * ``` */ @@ -279,9 +289,7 @@ module AccessPath { * Only gets the immediate right-hand side of an assignment or property, not * nodes that transitively flow there. * - * Note that access paths contain an initial `.`, such as in `.foo.bar`. - * - * For example, the class nodes below are all assignments to `(x, ".foo.bar")`. + * For example, the class nodes below are all assignments to `(x, "foo.bar")`. * ``` * function f(x) { * x.foo.bar = class {}; From 7e80823cb62179e2bd21950131f6a864ba2feaa4 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 30 Oct 2019 10:40:09 +0000 Subject: [PATCH 0224/2538] JS: Fix deprecated API usage --- javascript/ql/src/semmle/javascript/dataflow/Nodes.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll index a1e15538ad26..d06056a4696e 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/Nodes.qll @@ -965,7 +965,7 @@ module ClassNode { ) or exists(string name | - GlobalAccessPath::fromRhs(this) = name and + this = AccessPath::getAnAssignmentTo(name) and result = getAPrototypeReferenceInFile(name, getFile()) ) or From 3ec95881b497c8738703e85f847267d148c39585 Mon Sep 17 00:00:00 2001 From: Asger F <42069257+asger-semmle@users.noreply.github.com> Date: Wed, 30 Oct 2019 11:16:35 +0000 Subject: [PATCH 0225/2538] Update javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll Co-Authored-By: Max Schaefer <54907921+max-schaefer@users.noreply.github.com> --- javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll index 2b7da2fe7aea..b19a19482d16 100644 --- a/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll +++ b/javascript/ql/src/semmle/javascript/GlobalAccessPaths.qll @@ -165,7 +165,7 @@ module AccessPath { } /** - * Holds if there is an assignment to `accessPath` in `file`, not counting + * Holds if there is an assignment to the global `accessPath` in `file`, not counting * self-assignments. */ private predicate isAssignedInFile(string accessPath, File file) { From 81723ab92a8d3bdda994a3020ed948e95a5c7f63 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 6 Nov 2019 11:57:34 +0000 Subject: [PATCH 0226/2538] JS: Update GlobalAccessPaths test --- .../GlobalAccessPaths/GlobalAccessPaths.expected | 6 ++++-- .../GlobalAccessPaths/GlobalAccessPaths.ql | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected index a54916e01429..414252881a2f 100644 --- a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected +++ b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.expected @@ -1,4 +1,4 @@ -test_fromReference +test_getAReferenceTo | other_ns.js:2:11:2:12 | ns | NS | | other_ns.js:3:3:3:4 | ns | NS | | other_ns.js:3:3:3:8 | ns.foo | NS.foo | @@ -39,6 +39,7 @@ test_fromReference | test.js:12:19:12:25 | foo.bar | foo.bar | | test.js:13:7:13:15 | something | something | | test.js:14:5:14:23 | notUnique | bar.baz | +| test.js:14:5:14:23 | notUnique = bar.baz | bar.baz | | test.js:14:17:14:19 | bar | bar | | test.js:14:17:14:23 | bar.baz | bar.baz | | test.js:22:11:22:12 | ns | NS | @@ -54,10 +55,11 @@ test_fromReference | test.js:33:9:33:16 | bar = {} | foo.bar | | test.js:33:22:33:24 | foo | foo | | test.js:39:3:39:20 | lazyInit | foo.bar | +| test.js:39:3:39:20 | lazyInit = foo.bar | foo.bar | | test.js:39:14:39:16 | foo | foo | | test.js:39:14:39:20 | foo.bar | foo.bar | | test.js:40:3:40:10 | lazyInit | foo.bar | -test_fromRhs +test_getAnAssignmentTo | other_ns.js:4:9:4:16 | NS \|\| {} | NS | | other_ns.js:6:12:6:13 | {} | Conflict | | test.js:1:1:20:1 | functio ... ss {}\\n} | f | diff --git a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql index 4a233f3947b8..8412511df8d4 100644 --- a/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql +++ b/javascript/ql/test/library-tests/GlobalAccessPaths/GlobalAccessPaths.ql @@ -1,9 +1,11 @@ import javascript -query string test_fromReference(DataFlow::Node node) { - result = GlobalAccessPath::fromReference(node) +query string test_getAReferenceTo(DataFlow::Node node) { + node = AccessPath::getAReferenceTo(result) } -query string test_fromRhs(DataFlow::Node node) { result = GlobalAccessPath::fromRhs(node) } +query string test_getAnAssignmentTo(DataFlow::Node node) { + node = AccessPath::getAnAssignmentTo(result) +} -query string test_assignedUnique() { GlobalAccessPath::isAssignedInUniqueFile(result) } +query string test_assignedUnique() { AccessPath::isAssignedInUniqueFile(result) } From dc923ef694ca8cec80f8b25c7285ee13c6231753 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 6 Nov 2019 13:28:46 +0100 Subject: [PATCH 0227/2538] remove change note Co-Authored-By: Esben Sparre Andreasen --- change-notes/1.23/analysis-javascript.md | 1 - 1 file changed, 1 deletion(-) diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 8b89369fcff7..bb1357589043 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -11,7 +11,6 @@ - [rate-limiter-flexible](https://www.npmjs.com/package/rate-limiter-flexible) * The call graph has been improved to resolve method calls in more cases. This may produce more security alerts. -* Promises derived from a Deferred object are now recognized. * TypeScript 3.6 and 3.7 features are now supported. From 19554ff6e7a8584e63b76bbde90ff88379e26781 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 6 Nov 2019 13:37:54 +0100 Subject: [PATCH 0228/2538] change "e.g." to "for example" in qldoc --- javascript/ql/src/Statements/UseOfReturnlessFunction.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 48af33b8e436..123515a7cbd3 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -160,7 +160,7 @@ predicate voidArrayCallback(DataFlow::CallNode call, Function func) { module Deferred { /** * An instance of a `Deferred` class. - * E.g. the result from `new Deferred()` or `new $.Deferred()`. + * For example the result from `new Deferred()` or `new $.Deferred()`. */ class DeferredInstance extends DataFlow::NewNode { // Describes both `new Deferred()`, `new $.Deferred` and other variants. From 24615f2bdbb73398e129cc28fa8a95326c5e53c8 Mon Sep 17 00:00:00 2001 From: james Date: Wed, 6 Nov 2019 12:37:20 +0000 Subject: [PATCH 0229/2538] docs: further review comments --- docs/language/ql-training/cpp/control-flow-cpp.rst | 2 +- docs/language/ql-training/cpp/intro-ql-cpp.rst | 12 ++++++------ .../ql-training/cpp/program-representation-cpp.rst | 10 +++++----- docs/language/ql-training/java/intro-ql-java.rst | 10 +++++----- .../ql-training/java/program-representation-java.rst | 12 ++++++------ .../ql-training/java/query-injection-java.rst | 6 +++--- .../ql-training/slide-snippets/local-data-flow.rst | 2 +- 7 files changed, 27 insertions(+), 27 deletions(-) diff --git a/docs/language/ql-training/cpp/control-flow-cpp.rst b/docs/language/ql-training/cpp/control-flow-cpp.rst index 3fddc3f80728..f72633b714f2 100644 --- a/docs/language/ql-training/cpp/control-flow-cpp.rst +++ b/docs/language/ql-training/cpp/control-flow-cpp.rst @@ -89,7 +89,7 @@ Control flow graphs Modeling control flow ===================== -The control flow is modeled with a QL class, ``ControlFlowNode``. Examples of control flow nodes include statements and expressions. +The control flow is modeled with a CodeQL class, ``ControlFlowNode``. Examples of control flow nodes include statements and expressions. - ``ControlFlowNode`` provides API for traversing the control flow graph: diff --git a/docs/language/ql-training/cpp/intro-ql-cpp.rst b/docs/language/ql-training/cpp/intro-ql-cpp.rst index 9cfb1d3b442c..4e2cd4ca0b44 100644 --- a/docs/language/ql-training/cpp/intro-ql-cpp.rst +++ b/docs/language/ql-training/cpp/intro-ql-cpp.rst @@ -70,7 +70,7 @@ A simple CodeQL query A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `CodeQL for C/C++ standard library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL library for C/C++ `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ifStmt has the type IfStmt, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -135,10 +135,10 @@ A predicate allows you to pull out and name parts of a query. You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes -======= +Classes in QL +============= -A class allows you to name a set of values and define (member) predicates on them. +A QL class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -158,8 +158,8 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes continued -================= +Classes in QL continued +======================= .. container:: column-left diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 156cb0a4a68f..8f7a4d43de98 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -21,16 +21,16 @@ Agenda .. resume slides -AST classes -=========== +AST CodeQL classes +================== -Important AST classes include: +Important AST CodeQL classes include: - ``Expr``: expressions such as assignments, variable references, function calls, ... - ``Stmt``: statements such as conditionals, loops, try statements, ... - ``DeclarationEntry``: places where functions, variables or types are declared and/or defined -These three (and all other AST classes) are subclasses of ``Element``. +These three (and all other AST CodeQL classes) are subclasses of ``Element``. Symbol table ============ @@ -64,7 +64,7 @@ Working with functions Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by class ``Call`` and its subclasses: +Calls to functions are modeled by CodeQL class ``Call`` and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function diff --git a/docs/language/ql-training/java/intro-ql-java.rst b/docs/language/ql-training/java/intro-ql-java.rst index 46106204ed40..1666d9caca8c 100644 --- a/docs/language/ql-training/java/intro-ql-java.rst +++ b/docs/language/ql-training/java/intro-ql-java.rst @@ -70,7 +70,7 @@ A simple CodeQL query A `query `__ consists of a “select” clause that indicates what results should be returned. Typically it will also provide a “from” clause to declare some variables, and a “where” clause to state conditions over those variables. For more information on the structure of query files (including links to useful topics in the `QL language handbook `__), see `Introduction to query files `__. - In our example here, the first line of the query imports the `CodeQL for Java library `__, which defines concepts like ``IfStmt`` and ``Block``. + In our example here, the first line of the query imports the `CodeQL library for Java `__, which defines concepts like ``IfStmt`` and ``Block``. The query proper starts by declaring two variables–ifStmt and block. These variables represent sets of values in the database, according to the type of each of the variables. For example, ``ifStmt`` has the type ``IfStmt``, which means it represents the set of all if statements in the program. If we simply selected these two variables:: @@ -135,10 +135,10 @@ A predicate allows you to pull out and name parts of a query. You can imagine a predicate to be a self-contained from-where-select statement, that produces an intermediate relation, or table. In this case, the ``isEmpty`` predicate will be the set of all blocks which are empty. -Classes -======= +Classes in QL +============= -A class allows you to name a set of values and define (member) predicates on them. +A QL class allows you to name a set of values and define (member) predicates on them. A class has at least one supertype and optionally a **characteristic predicate**; it contains the values that belong to *all* supertypes *and* satisfy the characteristic predicate, if provided. @@ -158,7 +158,7 @@ Member predicates are inherited and can be overridden. In the example, declaring a variable “EmptyBlock e” will allow it to range over only those blocks that have zero statements. -Classes continued +Classes in QL continued ======================= .. container:: column-left diff --git a/docs/language/ql-training/java/program-representation-java.rst b/docs/language/ql-training/java/program-representation-java.rst index ba9b1a9d80dd..a66a81d60830 100644 --- a/docs/language/ql-training/java/program-representation-java.rst +++ b/docs/language/ql-training/java/program-representation-java.rst @@ -12,7 +12,7 @@ Agenda - Abstract syntax trees - Database representation - Program elements -- AST classes +- AST CodeQL classes .. insert abstract-syntax-tree.rst @@ -23,7 +23,7 @@ Agenda Program elements ================ -- The QL class ``Element`` represents program elements with a name. +- The CodeQL class ``Element`` represents program elements with a name. - This includes: packages (``Package``), compilation units (``CompilationUnit``), types (``Type``), methods (``Method``), constructors (``Constructor``), and variables (``Variable``). - It is often convenient to refer to an element that might either be a method or a constructor; the class ``Callable``, which is a common superclass of ``Method`` and ``Constructor``, can be used for this purpose. @@ -31,7 +31,7 @@ Program elements AST === -There are two primary AST classes, used within ``Callables``: +There are two primary AST CodeQL classes, used within ``Callables``: - ``Expr``: expressions such as assignments, variable references, function calls, ... - ``Stmt``: statements such as conditionals, loops, try statements, ... @@ -47,7 +47,7 @@ Types The database also includes information about the types used in a program: -- ``PrimitiveType`` represents a `primitive type `__, that is, one of ``boolean``, ``byte``, ``char``, ``double``, ``float``, ``int``, ``long``, ``short``. QL also classifies ``void`` and ```` (the type of the ``null`` literal) as primitive types. +- ``PrimitiveType`` represents a `primitive type `__, that is, one of ``boolean``, ``byte``, ``char``, ``double``, ``float``, ``int``, ``long``, ``short``. CodeQL also classifies ``void`` and ```` (the type of the ``null`` literal) as primitive types. - ``RefType`` represents a reference type; it has several subclasses: - ``Class`` represents a Java class. @@ -74,9 +74,9 @@ Working with variables Working with callables ====================== -Callables are represented by the ``Callable`` QL class. +Callables are represented by the ``Callable`` CodeQL class. -Calls to callables are modeled by the QL class ``Call`` and its subclasses: +Calls to callables are modeled by the CodeQL class ``Call`` and its subclasses: - ``Call.getCallee()`` gets the declared target of the call - ``Call.getAReference()`` gets a call to this function diff --git a/docs/language/ql-training/java/query-injection-java.rst b/docs/language/ql-training/java/query-injection-java.rst index a5b46eabda5c..799c99e52095 100644 --- a/docs/language/ql-training/java/query-injection-java.rst +++ b/docs/language/ql-training/java/query-injection-java.rst @@ -77,14 +77,14 @@ Let’s start by looking for calls to methods with names of the form ``sparql*Qu .. note:: - - When performing `variant analysis `__, it is usually helpful to write a simple query that finds the simple syntactic pattern, before trying to go on to describe the cases where it goes wrong. - - In this case, we start by looking for all the method calls which appear to run, before trying to refine the query to find cases which are vulnerable to query injection. + - When performing `variant analysis `__, it is usually helpful to write a simple query that finds the simple syntactic pattern, before trying to go on to describe the cases where it goes wrong. + - In this case, we start by looking for all the method calls that appear to run, before trying to refine the query to find cases which are vulnerable to query injection. - The ``select`` clause defines what this query is looking for: - a ``MethodAccess``: the call to a SPARQL query method - a ``Method``: the SPARQL query method. - - The ``where`` part of the query ties these variables together using `predicates `__ defined in the `standard CodeQL for Java library `__. + - The ``where`` part of the query ties these variables together using `predicates `__ defined in the `standard CodeQL library for Java `__. CodeQL query: find string concatenation ======================================= diff --git a/docs/language/ql-training/slide-snippets/local-data-flow.rst b/docs/language/ql-training/slide-snippets/local-data-flow.rst index 85b851a9ce05..ed681b0398ae 100644 --- a/docs/language/ql-training/slide-snippets/local-data-flow.rst +++ b/docs/language/ql-training/slide-snippets/local-data-flow.rst @@ -70,7 +70,7 @@ Local vs global data flow For further information, see: - - `Introduction to data flow analysis in CodeQL `__ + - `Introduction to data flow analysis with CodeQL `__ .. rst-class:: background2 From a4bf361f6440b7acf870ae9e1509448aa0337e0a Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 15:37:54 +0000 Subject: [PATCH 0230/2538] JavaScript: Remove remaining `--experimental` extractor options. --- .../ql/test/library-tests/CFG/CFG.expected | 8 +- .../ql/test/library-tests/CFG/classes.js | 2 - .../ql/test/library-tests/CFG/fields.js | 2 - .../ql/test/library-tests/CFG/mixedMembers.js | 2 - .../ql/test/library-tests/CFG/staticFields.js | 3 - .../ql/test/library-tests/Classes/fields.js | 2 - .../Comprehensions/comprehensions.js | 2 - .../ql/test/library-tests/DataFlow/tst.js | 2 - .../ql/test/library-tests/Decorators/tst.js | 2 - .../ql/test/library-tests/DefUse/es2015.js | 2 - .../test/library-tests/Expr/legacyletexpr.js | 2 - .../test/library-tests/Expr/mozextensions.js | 2 - .../ql/test/library-tests/Expr/tests.expected | 84 +++++++++---------- .../library-tests/Flow/namespace-reexport.js | 2 - .../library-tests/Flow/reexport-mixins.js | 2 - .../library-tests/Flow/reexport/lib/index.js | 2 - .../library-tests/Functions/exprclosures.js | 2 - .../ql/test/library-tests/LocalObjects/tst.js | 2 - javascript/ql/test/library-tests/Modules/b.js | 2 - .../ql/test/library-tests/Modules/m/c.js | 2 - .../test/library-tests/Modules/tests.expected | 6 +- .../OptionalChaining/short-circuiting.js | 1 - .../library-tests/OptionalChaining/tst.js | 2 - .../ql/test/library-tests/ThisExpr/tst.js | 1 - .../TypeInference/NullishCoalescing/tst.js | 1 - .../TypeInference/OptionalChaining/tst.js | 1 - .../frameworks/ReactJS/statePropertyReads.js | 2 - .../frameworks/ReactJS/statePropertyWrites.js | 2 - .../ql/test/library-tests/stmts/foreach.js | 2 - .../test/library-tests/stmts/guardedCatch.js | 2 - .../ql/test/library-tests/stmts/jscript.js | 2 - .../test/library-tests/stmts/legacyletstmt.js | 2 - .../variables/getDeclaringContainer.expected | 4 +- .../library-tests/variables/legacyletstmt.js | 2 - .../Declarations/DeadStoreOfLocal/fields.js | 2 - .../Declarations/UnusedVariable/funbind.js | 2 - .../Declarations/UnusedVariable/restprops.js | 2 - .../HeterogeneousComparison/tst.js | 2 - .../ImplicitOperandConversion/tst.js | 1 - .../Expressions/ShiftOutOfRange/tst.js | 2 - .../SuspiciousInvocation/fields.js | 2 - .../SuspiciousInvocation/optional-chaining.js | 1 - .../SuspiciousPropAccess/optional-chaining.js | 1 - .../yield_in_non_generator.js | 2 - .../UnboundEventHandlerReceiver/tst.js | 2 - .../ExpressionClosures/foreach.js | 2 - .../ExpressionClosures/jscript.js | 2 - .../ExpressionClosures/letExpr.js | 2 - .../ExpressionClosures/letStmt.js | 2 - .../postfixComprehension.js | 2 - .../ExpressionClosures/tst.js | 2 - .../ForInComprehensionBlocks/tst.js | 2 - .../SemicolonInsertion/jscript.js | 2 - .../YieldInNonGenerator/tst.js | 3 - .../React/DirectStateMutation/valid9.js | 2 - .../issue7506.js | 2 - .../undefined.js | 2 - .../UnusedOrUndefinedStateProperty/unused.js | 2 - .../UselessConditional/UselessConditional.js | 2 - 59 files changed, 51 insertions(+), 156 deletions(-) diff --git a/javascript/ql/test/library-tests/CFG/CFG.expected b/javascript/ql/test/library-tests/CFG/CFG.expected index 7904099cb441..a41f1c4999ac 100644 --- a/javascript/ql/test/library-tests/CFG/CFG.expected +++ b/javascript/ql/test/library-tests/CFG/CFG.expected @@ -546,7 +546,7 @@ | classes | 39 | static x = 5; | 39 | t = cla ... () {} } | | classes | 39 | t | 39 | A | | classes | 39 | t = cla ... () {} } | 39 | t | -| classes | 39 | t = cla ... () {} } | 42 | exit node of | +| classes | 39 | t = cla ... () {} } | 40 | exit node of | | classes | 39 | x | 39 | 5 | | classes | 39 | {} | 39 | exit node of () {} | | decorated_parameter | 1 | C | 2 | foo | @@ -625,7 +625,7 @@ | fields | 8 | {} | 8 | exit node of () {} | | fields | 11 | A | 12 | constructor | | fields | 11 | B | 11 | A | -| fields | 11 | class B ... \\n z;\\n} | 21 | exit node of | +| fields | 11 | class B ... \\n z;\\n} | 19 | exit node of | | fields | 12 | constru ... er;\\n } | 11 | class B ... \\n z;\\n} | | fields | 12 | constructor | 12 | function in constru ... er;\\n } | | fields | 12 | entry node of () {\\n ... er;\\n } | 12 | {\\n b ... er;\\n } | @@ -680,7 +680,7 @@ | globals | 19 | h | 20 | {\\n} | | globals | 20 | {\\n} | 21 | exit node of function\\n h()\\n{\\n} | | mixedMembers | 1 | Mixed | 3 | constructor | -| mixedMembers | 1 | class M ... z) {}\\n} | 7 | exit node of | +| mixedMembers | 1 | class M ... z) {}\\n} | 6 | exit node of | | mixedMembers | 1 | entry node of | 1 | Mixed | | mixedMembers | 2 | 3 | 2 | x = 3 | | mixedMembers | 2 | x | 2 | 3 | @@ -746,7 +746,7 @@ | staticFields | 2 | C | 2 | new C() | | staticFields | 2 | instance | 2 | C | | staticFields | 2 | new C() | 2 | static ... ew C(); | -| staticFields | 2 | static ... ew C(); | 7 | exit node of | +| staticFields | 2 | static ... ew C(); | 4 | exit node of | | staticFieldsTS | 1 | C | 1 | constructor | | staticFieldsTS | 1 | class C ... C();\\n} | 2 | instance | | staticFieldsTS | 1 | constructor | 1 | function in constructor() {} | diff --git a/javascript/ql/test/library-tests/CFG/classes.js b/javascript/ql/test/library-tests/CFG/classes.js index cf4bedc2a3b2..fa35da77f32f 100644 --- a/javascript/ql/test/library-tests/CFG/classes.js +++ b/javascript/ql/test/library-tests/CFG/classes.js @@ -37,5 +37,3 @@ t = class extends A { f() {} } t = class extends A { x = 5; f() {} } t = class extends A { static x = 5; f() {} } t = class extends A { static x = 5; f() {} constructor() {} } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/fields.js b/javascript/ql/test/library-tests/CFG/fields.js index ef4b105c9ff6..e93c13eaa182 100644 --- a/javascript/ql/test/library-tests/CFG/fields.js +++ b/javascript/ql/test/library-tests/CFG/fields.js @@ -16,5 +16,3 @@ class B extends A { } z; } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/CFG/mixedMembers.js b/javascript/ql/test/library-tests/CFG/mixedMembers.js index 33de7b7ff4a0..8ff3721d61c9 100644 --- a/javascript/ql/test/library-tests/CFG/mixedMembers.js +++ b/javascript/ql/test/library-tests/CFG/mixedMembers.js @@ -3,5 +3,3 @@ class Mixed { constructor(y) {} method(z) {} } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/CFG/staticFields.js b/javascript/ql/test/library-tests/CFG/staticFields.js index 5d8fc7605a25..fa3070ab19fa 100644 --- a/javascript/ql/test/library-tests/CFG/staticFields.js +++ b/javascript/ql/test/library-tests/CFG/staticFields.js @@ -1,6 +1,3 @@ class C { static instance = new C(); } - -// semmle-extractor-options: --experimental - diff --git a/javascript/ql/test/library-tests/Classes/fields.js b/javascript/ql/test/library-tests/Classes/fields.js index 63b701e48acc..f71520fc1f8a 100644 --- a/javascript/ql/test/library-tests/Classes/fields.js +++ b/javascript/ql/test/library-tests/Classes/fields.js @@ -2,5 +2,3 @@ class C { x; y = 42 } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/Comprehensions/comprehensions.js b/javascript/ql/test/library-tests/Comprehensions/comprehensions.js index 5194bcc9ddd1..32b649bfdaec 100644 --- a/javascript/ql/test/library-tests/Comprehensions/comprehensions.js +++ b/javascript/ql/test/library-tests/Comprehensions/comprehensions.js @@ -8,5 +8,3 @@ year; year; (for (i of numbers) for (j of letters) i+j); (for (i of numbers) for (j of letters) if (i | | functions.js:7:7:7:16 | in_f_again | functions.js:1:1:10:7 | | | functions.js:10:1:10:6 | global | functions.js:1:1:10:7 | | -| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:3:42 | | -| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:20:1:20 | x | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:23:1:23 | x | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:25:1:25 | 1 | mozextensions.js:1:1:3:42 | | +| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:2:0 | | +| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:20:1:20 | x | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:23:1:23 | x | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:25:1:25 | 1 | mozextensions.js:1:1:2:0 | | | nullSensitiveContexts.js:7:1:7:3 | foo | nullSensitiveContexts.js:1:1:61:0 | | | nullSensitiveContexts.js:7:1:7:8 | foo[bar] | nullSensitiveContexts.js:1:1:61:0 | | | nullSensitiveContexts.js:7:5:7:7 | bar | nullSensitiveContexts.js:1:1:61:0 | | @@ -1922,25 +1922,25 @@ test_getContainer | functions.js:7:4:7:4 | x | functions.js:1:1:9:1 | functio ... \\t\\t});\\n} | | functions.js:7:7:7:16 | in_f_again | functions.js:1:1:9:1 | functio ... \\t\\t});\\n} | | functions.js:10:1:10:6 | global | functions.js:1:1:10:7 | | -| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:3:42 | | -| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:3:42 | | -| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:3:42 | | -| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:3:42 | | +| legacyletexpr.js:1:1:1:7 | console | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:11 | console.log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:1:1:39 | console ... x + y) | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:9:1:11 | log | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:13:1:38 | let (x ... ) x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:18 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:18:1:23 | x = 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:22:1:23 | 23 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:26 | y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:26:1:31 | y = 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:30:1:31 | 19 | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:34 | x | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:34:1:38 | x + y | legacyletexpr.js:1:1:2:0 | | +| legacyletexpr.js:1:38:1:38 | y | legacyletexpr.js:1:1:2:0 | | +| mozextensions.js:1:1:1:5 | array | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:9 | array.map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:1:1:26 | array.m ... x) x+1) | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:7:1:9 | map | mozextensions.js:1:1:2:0 | | +| mozextensions.js:1:11:1:25 | function(x) x+1 | mozextensions.js:1:1:2:0 | | | mozextensions.js:1:20:1:20 | x | mozextensions.js:1:11:1:25 | function(x) x+1 | | mozextensions.js:1:23:1:23 | x | mozextensions.js:1:11:1:25 | function(x) x+1 | | mozextensions.js:1:23:1:25 | x+1 | mozextensions.js:1:11:1:25 | function(x) x+1 | diff --git a/javascript/ql/test/library-tests/Flow/namespace-reexport.js b/javascript/ql/test/library-tests/Flow/namespace-reexport.js index 0a1e70c5abe9..021a140061ab 100644 --- a/javascript/ql/test/library-tests/Flow/namespace-reexport.js +++ b/javascript/ql/test/library-tests/Flow/namespace-reexport.js @@ -1,3 +1 @@ export * as h from './h'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport-mixins.js b/javascript/ql/test/library-tests/Flow/reexport-mixins.js index f38cd783b9b2..ff303ad3432b 100644 --- a/javascript/ql/test/library-tests/Flow/reexport-mixins.js +++ b/javascript/ql/test/library-tests/Flow/reexport-mixins.js @@ -1,3 +1 @@ export default from './mixins'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport/lib/index.js b/javascript/ql/test/library-tests/Flow/reexport/lib/index.js index 5ffc9d62bc4a..e20cf1a083e8 100644 --- a/javascript/ql/test/library-tests/Flow/reexport/lib/index.js +++ b/javascript/ql/test/library-tests/Flow/reexport/lib/index.js @@ -1,3 +1 @@ export data from './src/utils/util' - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Functions/exprclosures.js b/javascript/ql/test/library-tests/Functions/exprclosures.js index 66e0f855744b..dd6a10086bd1 100644 --- a/javascript/ql/test/library-tests/Functions/exprclosures.js +++ b/javascript/ql/test/library-tests/Functions/exprclosures.js @@ -1,3 +1 @@ a.map(function(x) x+1); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/library-tests/LocalObjects/tst.js b/javascript/ql/test/library-tests/LocalObjects/tst.js index dee138c0f270..a02a29776c00 100644 --- a/javascript/ql/test/library-tests/LocalObjects/tst.js +++ b/javascript/ql/test/library-tests/LocalObjects/tst.js @@ -89,5 +89,3 @@ let bound = {}; bound::unknown(); }); - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/b.js b/javascript/ql/test/library-tests/Modules/b.js index 4b58c09c31b3..835bd1abbf6a 100644 --- a/javascript/ql/test/library-tests/Modules/b.js +++ b/javascript/ql/test/library-tests/Modules/b.js @@ -5,5 +5,3 @@ f(); export { f as g }; export f2 from './a'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/m/c.js b/javascript/ql/test/library-tests/Modules/m/c.js index 6c3645f382d6..8192ccc9b45d 100644 --- a/javascript/ql/test/library-tests/Modules/m/c.js +++ b/javascript/ql/test/library-tests/Modules/m/c.js @@ -3,5 +3,3 @@ import * as b from '../b'; b.g(); export { g as h } from '../b'; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/tests.expected b/javascript/ql/test/library-tests/Modules/tests.expected index 8cdd45f90667..39d24b097009 100644 --- a/javascript/ql/test/library-tests/Modules/tests.expected +++ b/javascript/ql/test/library-tests/Modules/tests.expected @@ -104,15 +104,15 @@ test_Module_exports | a.js:1:1:5:32 | | default | a.js:1:1:3:1 | export ... n 23;\\n} | | a.js:1:1:5:32 | | x | a.js:5:1:5:32 | export ... } = o; | | a.js:1:1:5:32 | | y | a.js:5:1:5:32 | export ... } = o; | -| b.js:1:1:10:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | -| b.js:1:1:10:0 | | g | b.js:5:1:5:18 | export { f as g }; | +| b.js:1:1:8:0 | | f2 | b.js:7:1:7:21 | export ... './a'; | +| b.js:1:1:8:0 | | g | b.js:5:1:5:18 | export { f as g }; | | e.js:1:1:4:0 | | g | e.js:3:1:3:35 | export ... './a'; | | e.js:1:1:4:0 | | x | e.js:2:1:2:16 | export { x, y }; | | e.js:1:1:4:0 | | y | e.js:2:1:2:16 | export { x, y }; | | es2015_require.js:1:1:3:25 | | default | es2015_require.js:3:1:3:25 | export ... ss C {} | | export-in-mjs.mjs:1:1:1:34 | | exported_from_mjs | export-in-mjs.mjs:1:1:1:34 | export ... s = 42; | | f.ts:1:1:6:0 | | foo | f.ts:5:1:5:24 | export ... oo() {} | -| m/c.js:1:1:8:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | +| m/c.js:1:1:6:0 | | h | m/c.js:5:1:5:30 | export ... '../b'; | | tst.html:4:23:8:0 | | y | tst.html:7:3:7:22 | export const y = 42; | test_ExportDefaultDeclarations | a.js:1:1:3:1 | export ... n 23;\\n} | diff --git a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js index 97576676994f..7367e64dd4c8 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js +++ b/javascript/ql/test/library-tests/OptionalChaining/short-circuiting.js @@ -13,4 +13,3 @@ DUMP(o3); DUMP(o4); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/OptionalChaining/tst.js b/javascript/ql/test/library-tests/OptionalChaining/tst.js index b0ee74357220..39389024d6d0 100644 --- a/javascript/ql/test/library-tests/OptionalChaining/tst.js +++ b/javascript/ql/test/library-tests/OptionalChaining/tst.js @@ -13,5 +13,3 @@ a?.m().b; a.m?.().b; a.m()?.b; a?.m?.()?.b; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/ThisExpr/tst.js b/javascript/ql/test/library-tests/ThisExpr/tst.js index 418021624e73..316e3feb1dee 100644 --- a/javascript/ql/test/library-tests/ThisExpr/tst.js +++ b/javascript/ql/test/library-tests/ThisExpr/tst.js @@ -146,4 +146,3 @@ class C_lodash { } } -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js index 6c3458781a1f..28d7e45c44e6 100644 --- a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js +++ b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/tst.js @@ -21,4 +21,3 @@ v7 = x ?? {}; }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js index 4890c8335ccc..42747617b6bc 100644 --- a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js +++ b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/tst.js @@ -22,4 +22,3 @@ var v11 = h(); var v12 = h?.(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js index df115aac5b8b..697bc35c1505 100644 --- a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyReads.js @@ -11,5 +11,3 @@ class Reads extends React.Component { prevState.p4; } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js index 4f15d9a1b31a..692400c7381a 100644 --- a/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/statePropertyWrites.js @@ -43,5 +43,3 @@ React.createClass({ }; } }); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/stmts/foreach.js b/javascript/ql/test/library-tests/stmts/foreach.js index ee6fd60e59be..1df300534371 100644 --- a/javascript/ql/test/library-tests/stmts/foreach.js +++ b/javascript/ql/test/library-tests/stmts/foreach.js @@ -6,5 +6,3 @@ for each (var item in obj) { } console.log(sum); // logs "26", which is 5+13+8 - -//semmle-extractor-options: --experimental --extract-program-text diff --git a/javascript/ql/test/library-tests/stmts/guardedCatch.js b/javascript/ql/test/library-tests/stmts/guardedCatch.js index 2c9a24cdb073..0c7b4c2b890b 100644 --- a/javascript/ql/test/library-tests/stmts/guardedCatch.js +++ b/javascript/ql/test/library-tests/stmts/guardedCatch.js @@ -7,5 +7,3 @@ function f(g) { console.log("something else!"); } } - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/jscript.js b/javascript/ql/test/library-tests/stmts/jscript.js index 6e281fcec08e..0f6a81c8fb36 100644 --- a/javascript/ql/test/library-tests/stmts/jscript.js +++ b/javascript/ql/test/library-tests/stmts/jscript.js @@ -1,5 +1,3 @@ function window::onload() {} window.onload = function onload() {} - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/legacyletstmt.js b/javascript/ql/test/library-tests/stmts/legacyletstmt.js index e88411c12c10..89b5e7505e9c 100644 --- a/javascript/ql/test/library-tests/stmts/legacyletstmt.js +++ b/javascript/ql/test/library-tests/stmts/legacyletstmt.js @@ -1,5 +1,3 @@ let (x = 23, y = 19) { console.log(x + y); } - -//semmle-extractor-options: --experimental --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected index 158f001459cf..bf97e07b559e 100644 --- a/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected +++ b/javascript/ql/test/library-tests/variables/getDeclaringContainer.expected @@ -24,7 +24,7 @@ | x | defaultargs.js:3:3:3:25 | functio ... = x) {} | | x | defaultargs.js:4:3:4:51 | functio ... [0]) {} | | x | for.js:1:2:5:1 | functio ... x;\\n} | -| x | legacyletstmt.js:1:1:9:42 | | +| x | legacyletstmt.js:1:1:8:0 | | | x | let.js:1:1:22:0 | | | x | let.js:1:1:22:0 | | | x | let.js:1:1:22:0 | | @@ -36,7 +36,7 @@ | x | variables.js:13:1:23:1 | functio ... z;\\n\\t}\\n} | | y | defaultargs.js:3:3:3:25 | functio ... = x) {} | | y | defaultargs.js:4:3:4:51 | functio ... [0]) {} | -| y | legacyletstmt.js:1:1:9:42 | | +| y | legacyletstmt.js:1:1:8:0 | | | y | let.js:1:1:22:0 | | | y | let.js:14:1:21:1 | functio ... }\\n} | | y | typeoftype.ts:3:3:5:3 | functio ... e x\\n } | diff --git a/javascript/ql/test/library-tests/variables/legacyletstmt.js b/javascript/ql/test/library-tests/variables/legacyletstmt.js index 07531d1cc9cb..69beaac8a096 100644 --- a/javascript/ql/test/library-tests/variables/legacyletstmt.js +++ b/javascript/ql/test/library-tests/variables/legacyletstmt.js @@ -5,5 +5,3 @@ let (x = 23, y = 19) { } console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js index 6b5cc4cc2d86..22e649c68c67 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/fields.js @@ -3,5 +3,3 @@ var x = 42; class C { myX = x } - -// semmle-extractor-options: --experimental --source-type module diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js index b3210a087758..ce0a9ddfd0fd 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/funbind.js @@ -2,5 +2,3 @@ function test(bar, e) { let foo = bar; e.target::foo::baz(); } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js b/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js index d4e6de4b3ba0..3f0516d22666 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/restprops.js @@ -2,5 +2,3 @@ function f(o) { let { x, ...ys } = o; return ys; } - -// semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js index 46199104674c..f500d4cdafce 100644 --- a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js +++ b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/tst.js @@ -232,5 +232,3 @@ function l() { function f(...x) { x === 42 }; - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js index e1ef6f1cdfd6..a454ed9bde30 100644 --- a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js +++ b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/tst.js @@ -107,4 +107,3 @@ function l() { g(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js index 356d0cf57ee6..a8cedd993b2a 100644 --- a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js +++ b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/tst.js @@ -1,4 +1,2 @@ var n = 1<<40; // NOT OK var n2 = BigInt(1) << 40n; // OK - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js index 23651d79e6cc..01a0c35bc5b7 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/fields.js @@ -3,5 +3,3 @@ class A { } class B {} - -// semmle-extractor-options: --experimental --source-type module diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js index 2df3535216ab..9be73a4dde52 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/optional-chaining.js @@ -7,4 +7,3 @@ b(); b?.(); }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js index 9f6625072271..fa6003ad7959 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/optional-chaining.js @@ -7,4 +7,3 @@ b.p; b?.p; }); -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js index ae0bcba2a237..c0cd2619e81c 100644 --- a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/yield_in_non_generator.js @@ -4,5 +4,3 @@ function outer() { } inner().next() } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js index 6733344c3ba0..6657556b072d 100644 --- a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js +++ b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/tst.js @@ -172,5 +172,3 @@ class Component4 extends React.Component { this.setState({ }); } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js index 0095642669c6..1df300534371 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/foreach.js @@ -6,5 +6,3 @@ for each (var item in obj) { } console.log(sum); // logs "26", which is 5+13+8 - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js index 373939cae64b..0f6a81c8fb36 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/jscript.js @@ -1,5 +1,3 @@ function window::onload() {} window.onload = function onload() {} - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js index 51e8fd38fda3..a5c7a09b6be5 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letExpr.js @@ -3,5 +3,3 @@ var x = 42, y = 19; console.log(let (x = 23, y = 19) x + y); console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js index 07531d1cc9cb..69beaac8a096 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/letStmt.js @@ -5,5 +5,3 @@ let (x = 23, y = 19) { } console.log(x - y); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js index bb08a86ceec7..3cca1b5c615f 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/postfixComprehension.js @@ -2,5 +2,3 @@ var numbers = [1, 2, 3, 4, 5]; var squares = [i*i for (i of numbers)]; var specialKeyCodes = [for (keyCodeName of Object.keys(SPECIAL_CODES_MAP)) SPECIAL_CODES_MAP[keyCodeName]]; - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js index dbfeda687e0f..202ea2a262a6 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/tst.js @@ -6,5 +6,3 @@ // OK [1, 2, 3].map((x) => x * x); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js index 301356339744..08542e2be521 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/tst.js @@ -1,4 +1,2 @@ var a = [23,,42]; var desc = [for(i in a) i + " = a[" + i + "]"]; - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js index 66a296a0ae86..5e9b07cf6757 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/jscript.js @@ -23,5 +23,3 @@ foo(); foo(); foo(); foo(); - -//semmle-extractor-options: --experimental \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js index 5081e9991d16..a68f3ad35f9b 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/tst.js @@ -4,6 +4,3 @@ function idMaker(){ // NOT OK yield index++; } - -//semmle-extractor-options: --experimental - diff --git a/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js b/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js index f1adc83643f7..0d4d465638dd 100644 --- a/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js +++ b/javascript/ql/test/query-tests/React/DirectStateMutation/valid9.js @@ -11,5 +11,3 @@ React.createClass({ }; } }); - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js index 7d5a881389c5..f5acdc8d99ab 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/issue7506.js @@ -19,5 +19,3 @@ class C2 extends React.Component { const { p1: p2 } = state } } - -// semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js index dda64bc62e81..6db5702e2fcf 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/undefined.js @@ -166,5 +166,3 @@ class C11 extends React.Component { this.state.writeIn_getDerivedStateFromProps; // OK } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js index e1972ddec1f9..d71aa7136da9 100644 --- a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/unused.js @@ -72,5 +72,3 @@ class C6 extends React.Component { } } - -//semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js b/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js index 8731ac0cfacd..a3e429ed0b54 100644 --- a/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js +++ b/javascript/ql/test/query-tests/Statements/UselessConditional/UselessConditional.js @@ -176,5 +176,3 @@ async function awaitFlow(){ if (v) { // OK } }); - -// semmle-extractor-options: --experimental From 2e7bd4db6f163b3d19eda68fab2b460dc8f43196 Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Wed, 6 Nov 2019 12:59:45 +0000 Subject: [PATCH 0231/2538] Update docs/language/ql-training/cpp/program-representation-cpp.rst Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/ql-training/cpp/program-representation-cpp.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/ql-training/cpp/program-representation-cpp.rst b/docs/language/ql-training/cpp/program-representation-cpp.rst index 8f7a4d43de98..7048251aa022 100644 --- a/docs/language/ql-training/cpp/program-representation-cpp.rst +++ b/docs/language/ql-training/cpp/program-representation-cpp.rst @@ -64,7 +64,7 @@ Working with functions Functions are represented by the Function class. Each declaration or definition of a function is represented by a ``FunctionDeclarationEntry``. -Calls to functions are modeled by CodeQL class ``Call`` and its subclasses: +Calls to functions are modeled by the CodeQL class ``Call`` and its subclasses: - ``Call.getTarget()`` gets the declared target of the call; undefined for calls through function pointers - ``Function.getACallToThisFunction()`` gets a call to this function From 79f107946068940e7050b1ed3bc52abf54c48ac8 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 13:01:23 +0000 Subject: [PATCH 0232/2538] JavaScript: Add `options` files with `--experimental` extractor options. --- javascript/ql/test/library-tests/CFG/options | 1 + javascript/ql/test/library-tests/Classes/options | 1 + javascript/ql/test/library-tests/Comprehensions/options | 1 + javascript/ql/test/library-tests/DataFlow/options | 1 + javascript/ql/test/library-tests/Decorators/options | 1 + javascript/ql/test/library-tests/DefUse/options | 1 + javascript/ql/test/library-tests/Expr/options | 1 + javascript/ql/test/library-tests/Flow/options | 1 + javascript/ql/test/library-tests/Flow/reexport/lib/options | 1 + javascript/ql/test/library-tests/Functions/options | 1 + javascript/ql/test/library-tests/LocalObjects/options | 1 + javascript/ql/test/library-tests/Modules/m/options | 1 + javascript/ql/test/library-tests/Modules/options | 1 + javascript/ql/test/library-tests/OptionalChaining/options | 1 + javascript/ql/test/library-tests/ThisExpr/options | 1 + .../test/library-tests/TypeInference/NullishCoalescing/options | 1 + .../ql/test/library-tests/TypeInference/OptionalChaining/options | 1 + javascript/ql/test/library-tests/frameworks/ReactJS/options | 1 + javascript/ql/test/library-tests/stmts/options | 1 + javascript/ql/test/library-tests/variables/options | 1 + .../ql/test/query-tests/Declarations/DeadStoreOfLocal/options | 1 + .../ql/test/query-tests/Declarations/UnusedVariable/options | 1 + .../test/query-tests/Expressions/HeterogeneousComparison/options | 1 + .../query-tests/Expressions/ImplicitOperandConversion/options | 1 + .../ql/test/query-tests/Expressions/ShiftOutOfRange/options | 1 + .../ql/test/query-tests/Expressions/SuspiciousInvocation/options | 1 + .../ql/test/query-tests/Expressions/SuspiciousPropAccess/options | 1 + .../query-tests/Expressions/UnboundEventHandlerReceiver/options | 1 + .../test/query-tests/LanguageFeatures/ExpressionClosures/options | 1 + .../LanguageFeatures/ForInComprehensionBlocks/options | 1 + .../test/query-tests/LanguageFeatures/SemicolonInsertion/options | 1 + .../query-tests/LanguageFeatures/YieldInNonGenerator/options | 1 + javascript/ql/test/query-tests/React/DirectStateMutation/options | 1 + .../query-tests/React/UnusedOrUndefinedStateProperty/options | 1 + .../ql/test/query-tests/Statements/UselessConditional/options | 1 + 35 files changed, 35 insertions(+) create mode 100644 javascript/ql/test/library-tests/CFG/options create mode 100644 javascript/ql/test/library-tests/Classes/options create mode 100644 javascript/ql/test/library-tests/Comprehensions/options create mode 100644 javascript/ql/test/library-tests/DataFlow/options create mode 100644 javascript/ql/test/library-tests/Decorators/options create mode 100644 javascript/ql/test/library-tests/DefUse/options create mode 100644 javascript/ql/test/library-tests/Expr/options create mode 100644 javascript/ql/test/library-tests/Flow/options create mode 100644 javascript/ql/test/library-tests/Flow/reexport/lib/options create mode 100644 javascript/ql/test/library-tests/Functions/options create mode 100644 javascript/ql/test/library-tests/LocalObjects/options create mode 100644 javascript/ql/test/library-tests/Modules/m/options create mode 100644 javascript/ql/test/library-tests/Modules/options create mode 100644 javascript/ql/test/library-tests/OptionalChaining/options create mode 100644 javascript/ql/test/library-tests/ThisExpr/options create mode 100644 javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options create mode 100644 javascript/ql/test/library-tests/TypeInference/OptionalChaining/options create mode 100644 javascript/ql/test/library-tests/frameworks/ReactJS/options create mode 100644 javascript/ql/test/library-tests/stmts/options create mode 100644 javascript/ql/test/library-tests/variables/options create mode 100644 javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options create mode 100644 javascript/ql/test/query-tests/Declarations/UnusedVariable/options create mode 100644 javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options create mode 100644 javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options create mode 100644 javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options create mode 100644 javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options create mode 100644 javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options create mode 100644 javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options create mode 100644 javascript/ql/test/query-tests/React/DirectStateMutation/options create mode 100644 javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options create mode 100644 javascript/ql/test/query-tests/Statements/UselessConditional/options diff --git a/javascript/ql/test/library-tests/CFG/options b/javascript/ql/test/library-tests/CFG/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/CFG/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Classes/options b/javascript/ql/test/library-tests/Classes/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Classes/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Comprehensions/options b/javascript/ql/test/library-tests/Comprehensions/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Comprehensions/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/DataFlow/options b/javascript/ql/test/library-tests/DataFlow/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/DataFlow/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Decorators/options b/javascript/ql/test/library-tests/Decorators/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Decorators/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/DefUse/options b/javascript/ql/test/library-tests/DefUse/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/DefUse/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Expr/options b/javascript/ql/test/library-tests/Expr/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Expr/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/options b/javascript/ql/test/library-tests/Flow/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Flow/reexport/lib/options b/javascript/ql/test/library-tests/Flow/reexport/lib/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Flow/reexport/lib/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Functions/options b/javascript/ql/test/library-tests/Functions/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Functions/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/LocalObjects/options b/javascript/ql/test/library-tests/LocalObjects/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/LocalObjects/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/m/options b/javascript/ql/test/library-tests/Modules/m/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Modules/m/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/Modules/options b/javascript/ql/test/library-tests/Modules/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/Modules/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/OptionalChaining/options b/javascript/ql/test/library-tests/OptionalChaining/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/OptionalChaining/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/ThisExpr/options b/javascript/ql/test/library-tests/ThisExpr/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/ThisExpr/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/TypeInference/NullishCoalescing/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/TypeInference/OptionalChaining/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/frameworks/ReactJS/options b/javascript/ql/test/library-tests/frameworks/ReactJS/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/ReactJS/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/stmts/options b/javascript/ql/test/library-tests/stmts/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/stmts/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/library-tests/variables/options b/javascript/ql/test/library-tests/variables/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/library-tests/variables/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfLocal/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Declarations/UnusedVariable/options b/javascript/ql/test/query-tests/Declarations/UnusedVariable/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UnusedVariable/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/HeterogeneousComparison/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/ImplicitOperandConversion/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/ShiftOutOfRange/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousInvocation/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/SuspiciousPropAccess/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Expressions/UnboundEventHandlerReceiver/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/ExpressionClosures/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/ForInComprehensionBlocks/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/YieldInNonGenerator/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/DirectStateMutation/options b/javascript/ql/test/query-tests/React/DirectStateMutation/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/React/DirectStateMutation/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/React/UnusedOrUndefinedStateProperty/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental diff --git a/javascript/ql/test/query-tests/Statements/UselessConditional/options b/javascript/ql/test/query-tests/Statements/UselessConditional/options new file mode 100644 index 000000000000..ae107b46f9ea --- /dev/null +++ b/javascript/ql/test/query-tests/Statements/UselessConditional/options @@ -0,0 +1 @@ +semmle-extractor-options: --experimental From 1fa8c43a8c4ca2cd8905318634c03e42e7e179f3 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:00:51 +0000 Subject: [PATCH 0233/2538] JavaScript: Remove a redundant extractor option. --- javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js index abf7cc4034f4..8eb1794ae7b2 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/l.js @@ -3,5 +3,3 @@ class C { } module.exports = C; - -// semmle-extractor-options: --abort-on-parse-errors \ No newline at end of file From 48483724358022cf3df1494bfb316d5a04ddac7d Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:09:17 +0000 Subject: [PATCH 0234/2538] JavaScript: Replace `--externs` extractor flag with `/** @externs */` comment. --- javascript/ql/test/library-tests/Externs/Point.js | 2 +- .../test/query-tests/Declarations/ArgumentsRedefined/externs.js | 2 +- .../test/query-tests/Declarations/DeadStoreOfGlobal/externs.js | 2 +- .../query-tests/Declarations/DeadStoreOfProperty/externs.js | 2 +- .../test/query-tests/Declarations/RedeclaredVariable/externs.js | 2 +- .../test/query-tests/Declarations/TooManyParameters/externs.js | 2 +- .../ql/test/query-tests/Declarations/UnusedParameter/externs.js | 2 +- .../ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js | 2 +- .../ql/test/query-tests/Expressions/SelfAssignment/externs.js | 2 +- javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js | 2 +- .../query-tests/LanguageFeatures/InconsistentNew/externs.js | 2 +- .../SemicolonInsertion/SemicolonInsertion.expected | 2 +- .../query-tests/LanguageFeatures/SpuriousArguments/externs.js | 2 +- .../query-tests/NodeJS/DubiousImport/DubiousImport.expected | 2 +- javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js | 2 +- .../ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js | 2 +- javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js | 2 +- 17 files changed, 17 insertions(+), 17 deletions(-) diff --git a/javascript/ql/test/library-tests/Externs/Point.js b/javascript/ql/test/library-tests/Externs/Point.js index a811a4820096..ea4c950e7d20 100644 --- a/javascript/ql/test/library-tests/Externs/Point.js +++ b/javascript/ql/test/library-tests/Externs/Point.js @@ -17,4 +17,4 @@ Point.prototype['final']; /** @type {!Point} */ var aPoint; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js b/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js index f91c316b0ed5..7824a7ffe020 100644 --- a/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js +++ b/javascript/ql/test/query-tests/Declarations/ArgumentsRedefined/externs.js @@ -1,3 +1,3 @@ var arguments; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js index d3594220a05f..6e79be49a811 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfGlobal/externs.js @@ -38,4 +38,4 @@ function Worker(opt_arg0) {} */ Worker.prototype.onmessage = function() {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js index a32e349e56de..11caae4e1b1a 100644 --- a/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js +++ b/javascript/ql/test/query-tests/Declarations/DeadStoreOfProperty/externs.js @@ -40,4 +40,4 @@ function Element() {} */ Element.prototype.clientTop; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js index 19dd15789e9f..0a9eab069964 100644 --- a/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js +++ b/javascript/ql/test/query-tests/Declarations/RedeclaredVariable/externs.js @@ -2,4 +2,4 @@ var f = function() {}; var f = function(x) {}; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js b/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js index a3c8c8999c00..4327b4885f59 100644 --- a/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js +++ b/javascript/ql/test/query-tests/Declarations/TooManyParameters/externs.js @@ -1,4 +1,4 @@ // OK: overly long parameter lists in external APIs aren't the fault of the externs definitions function f(a, b, c, d, e, f, g, h) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js b/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js index ec8e5c4f6dbf..9153844b527c 100644 --- a/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js +++ b/javascript/ql/test/query-tests/Declarations/UnusedParameter/externs.js @@ -1,3 +1,3 @@ function String(str) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js b/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js index d3fff8862596..98a1d68e5203 100644 --- a/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js +++ b/javascript/ql/test/query-tests/Expressions/ExprHasNoEffect/externs.js @@ -53,4 +53,4 @@ function Error() {} */ function SyntaxError() {} -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js b/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js index 70685e250c1d..58b2c99e8923 100644 --- a/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js +++ b/javascript/ql/test/query-tests/Expressions/SelfAssignment/externs.js @@ -36,4 +36,4 @@ function Element() {} Element.prototype.innerHTML; -// semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js b/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js index f27d6054e270..433db5a26f48 100644 --- a/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js +++ b/javascript/ql/test/query-tests/JSDoc/BadParamTag/externs.js @@ -3,4 +3,4 @@ */ function f(x) {} -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js b/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js index c81b555e5aae..0ffbf63dd3f3 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/InconsistentNew/externs.js @@ -7,4 +7,4 @@ String.prototype.toString = function() {}; function Array() {} Array.prototype.toString = function() {}; -//semmle-extractor-options: --externs \ No newline at end of file +/** @externs */ \ No newline at end of file diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected index 81808eb76ba4..bab6488e83b8 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected +++ b/javascript/ql/test/query-tests/LanguageFeatures/SemicolonInsertion/SemicolonInsertion.expected @@ -1,4 +1,4 @@ | export.js:5:8:5:17 | var x = 42 | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | export.js:1:1:29:0 | | the enclosing script | -| jscript.js:3:1:3:36 | window. ... ad() {} | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | jscript.js:1:1:27:42 | | the enclosing script | +| jscript.js:3:1:3:36 | window. ... ad() {} | Avoid automated semicolon insertion (95% of all statements in $@ have an explicit semicolon). | jscript.js:1:1:26:0 | | the enclosing script | | tst.js:5:1:5:3 | var a = ... : 2\\n } | Avoid automated semicolon insertion (91% of all statements in $@ have an explicit semicolon). | tst.js:1:1:42:1 | functio ... oo();\\n} | the enclosing function | | tst.js:7:3:7:10 | return 1 | Avoid automated semicolon insertion (91% of all statements in $@ have an explicit semicolon). | tst.js:1:1:42:1 | functio ... oo();\\n} | the enclosing function | diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js b/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js index cf8665ea531c..c8a88126efbf 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SpuriousArguments/externs.js @@ -39,4 +39,4 @@ function Number() {} Number.parseFloat = function(num) {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected b/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected index e28c1641af82..88425eed7286 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/DubiousImport.expected @@ -1,5 +1,5 @@ | a.js:1:11:1:28 | require('./b').foo | Module $@ does not export symbol foo. | b.js:1:1:5:21 | | b | | main.js:5:1:5:5 | b.foo | Module $@ does not export symbol foo. | b.js:1:1:5:21 | | b | | main.js:15:1:15:9 | fs.renmae | Module $@ does not export symbol renmae. | fs.js:1:1:15:0 | | fs | -| main.js:23:1:23:5 | l.bar | Module $@ does not export symbol bar. | l.js:1:1:7:52 | | l | +| main.js:23:1:23:5 | l.bar | Module $@ does not export symbol bar. | l.js:1:1:6:0 | | l | | multi_import.js:16:3:16:10 | mod2.bar | Module $@ does not export symbol bar. | b.js:1:1:5:21 | | b | diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js index f1cb91159f05..bd8e36c10e35 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/externs.js @@ -615,4 +615,4 @@ Array.some = function(arr, callback, opt_context) {}; */ Array.isArray = function(arr) {}; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js index e4c633ecf31f..fefe8f6b2e78 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs-monkeypatch.js @@ -2,4 +2,4 @@ var fs = require('fs'); fs.move = fs.rename; -//semmle-extractor-options: --externs +/** @externs */ diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js index 9fc7f5f13437..7b5e87d891a3 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/fs.js @@ -11,4 +11,4 @@ fs.rename; module.exports = fs; -//semmle-extractor-options: --externs +/** @externs */ From 8fdf6298b980e7426e026fbdd6365a2478e94026 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:14:07 +0000 Subject: [PATCH 0235/2538] JavaScript: Remove `--platform node` extractor options. --- javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js | 3 +-- .../ql/test/query-tests/NodeJS/UnusedDependency/src/other.js | 2 -- .../ql/test/query-tests/Security/CWE-089/untyped/tst4.js | 2 -- .../test/query-tests/Statements/ReturnOutsideFunction/node.js | 3 +-- .../test/tutorials/Introducing the JavaScript libraries/m.js | 4 ++-- 5 files changed, 4 insertions(+), 10 deletions(-) diff --git a/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js b/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js index 3d097fb8edea..c475ea2262fc 100644 --- a/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js +++ b/javascript/ql/test/query-tests/NodeJS/DubiousImport/f.js @@ -4,5 +4,4 @@ module.exports = me; }(module)); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); // ensure this is treated as Node.js code diff --git a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js index 20c9961d6266..3b29030a26f2 100644 --- a/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js +++ b/javascript/ql/test/query-tests/NodeJS/UnusedDependency/src/other.js @@ -1,4 +1,2 @@ import hipsterness from 'react'; import curry from 'lodash/function/curry'; - -//semmle-extractor-options: --platform node diff --git a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js index 7df5c6b4f3fc..73cddfb3a6ae 100644 --- a/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js +++ b/javascript/ql/test/query-tests/Security/CWE-089/untyped/tst4.js @@ -7,5 +7,3 @@ angular.module('myApp', ['ngRoute']) .controller('FindPost', function($routeParams) { db.get('SELECT * FROM Post WHERE id = "' + $routeParams.id + '"'); }); - -// semmle-extractor-options: --platform node diff --git a/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js b/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js index 3397ebd38a4e..572dbe250355 100644 --- a/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js +++ b/javascript/ql/test/query-tests/Statements/ReturnOutsideFunction/node.js @@ -1,5 +1,4 @@ // not a syntax error, but still NOT OK return 42; -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("path") // ensure this is treated as Node.js code diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js index c53a0a153271..a54fda636cca 100644 --- a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/m.js @@ -1,2 +1,2 @@ -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process") +; From 5681565d4addcc24fefabfd19737f4e686c887e0 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:20:23 +0000 Subject: [PATCH 0236/2538] JavaScript: Move `--html elements` extractor options into `options` file. --- .../ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html | 1 - .../ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html | 1 - .../ql/test/query-tests/DOM/HTML/ConflictingAttributes.html | 1 - .../ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html | 1 - javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html | 1 - .../ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html | 1 - .../ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html | 1 - .../ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html | 1 - javascript/ql/test/query-tests/DOM/HTML/options | 1 + 9 files changed, 1 insertion(+), 8 deletions(-) create mode 100644 javascript/ql/test/query-tests/DOM/HTML/options diff --git a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html index 3277461d787c..98a490ec408a 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html +++ b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttribute.html @@ -4,5 +4,4 @@
  • First element
  • Second element -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html index 7800cfcd0486..bb5969c1f79e 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/AmbiguousIdAttributeGood.html @@ -10,5 +10,4 @@
  • duplicate-class
  • duplicate-class
  • -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html index 370337bc7af2..92af95c3e3c1 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html +++ b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributes.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html index 9b6a94b0e2df..dfe1141a21bf 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/ConflictingAttributesGood.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html index eedc176211bf..a78e3314283d 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html +++ b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributes.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html index 9b6a94b0e2df..dfe1141a21bf 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/DuplicateAttributesGood.html @@ -1,2 +1 @@ Semmle -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html index 666592a77162..9da8fcde5022 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html +++ b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttribute.html @@ -1,2 +1 @@
    An important heading
    -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html index 9a7815efb644..1dfea0491fe9 100644 --- a/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html +++ b/javascript/ql/test/query-tests/DOM/HTML/MalformedIdAttributeGood.html @@ -1,2 +1 @@
    An important heading
    -semmle-extractor-options: --html elements diff --git a/javascript/ql/test/query-tests/DOM/HTML/options b/javascript/ql/test/query-tests/DOM/HTML/options new file mode 100644 index 000000000000..49be7a9261ee --- /dev/null +++ b/javascript/ql/test/query-tests/DOM/HTML/options @@ -0,0 +1 @@ +semmle-extractor-options: --html elements From 6b817203fdcc89c58022d856d07198d8579d244a Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:24:52 +0000 Subject: [PATCH 0237/2538] JavaScript: Move `--tolerate-parse-errors` extractor options into `options` file. --- javascript/ql/test/library-tests/Errors/options | 1 + javascript/ql/test/library-tests/Errors/setters.js | 2 -- javascript/ql/test/library-tests/Errors/tst.js | 2 -- javascript/ql/test/library-tests/JSON/JSONError.expected | 1 - javascript/ql/test/library-tests/JSON/invalid.json | 1 - javascript/ql/test/library-tests/JSON/options | 1 + .../ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts | 2 -- .../ql/test/library-tests/TypeScript/SyntaxErrors/options | 1 + javascript/ql/test/library-tests/YAML/YAMLError.expected | 2 +- javascript/ql/test/library-tests/YAML/err.yaml | 1 - javascript/ql/test/library-tests/YAML/options | 1 + javascript/ql/test/library-tests/frameworks/Express/options | 1 + .../ql/test/query-tests/AngularJS/DuplicateDependency/options | 1 + .../test/query-tests/Declarations/UniqueParameterNames/options | 1 + .../test/query-tests/Declarations/UniqueParameterNames/tst.js | 2 -- .../ql/test/query-tests/LanguageFeatures/SyntaxError/options | 1 + .../ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js | 2 -- javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js | 2 -- javascript/ql/test/query-tests/filters/ClassifyFiles/options | 1 + .../test/query-tests/filters/ClassifyFiles/some-template.html | 1 - javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js | 1 - javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html | 1 - javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html | 1 - .../test/tutorials/Introducing the JavaScript libraries/options | 1 + 24 files changed, 11 insertions(+), 20 deletions(-) create mode 100644 javascript/ql/test/library-tests/Errors/options create mode 100644 javascript/ql/test/library-tests/JSON/options create mode 100644 javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options create mode 100644 javascript/ql/test/library-tests/YAML/options create mode 100644 javascript/ql/test/library-tests/frameworks/Express/options create mode 100644 javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options create mode 100644 javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options create mode 100644 javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/options create mode 100644 javascript/ql/test/tutorials/Introducing the JavaScript libraries/options diff --git a/javascript/ql/test/library-tests/Errors/options b/javascript/ql/test/library-tests/Errors/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/library-tests/Errors/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Errors/setters.js b/javascript/ql/test/library-tests/Errors/setters.js index 50865e9f0c9b..a8d40c45d2fd 100644 --- a/javascript/ql/test/library-tests/Errors/setters.js +++ b/javascript/ql/test/library-tests/Errors/setters.js @@ -8,5 +8,3 @@ var o = { set y(...ys) {}, set z(z, ...zs) {} }; - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/Errors/tst.js b/javascript/ql/test/library-tests/Errors/tst.js index baf2fbf47110..f0931ee0e495 100644 --- a/javascript/ql/test/library-tests/Errors/tst.js +++ b/javascript/ql/test/library-tests/Errors/tst.js @@ -1,4 +1,2 @@ while } - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/JSON/JSONError.expected b/javascript/ql/test/library-tests/JSON/JSONError.expected index 37d5aabfd087..e63d38624911 100644 --- a/javascript/ql/test/library-tests/JSON/JSONError.expected +++ b/javascript/ql/test/library-tests/JSON/JSONError.expected @@ -1,2 +1 @@ | invalid.json:3:1:3:1 | Error: Comments are not legal in JSON. | -| invalid.json:4:1:4:1 | Error: Comments are not legal in JSON. | diff --git a/javascript/ql/test/library-tests/JSON/invalid.json b/javascript/ql/test/library-tests/JSON/invalid.json index 54c870bb9072..03f76948f638 100644 --- a/javascript/ql/test/library-tests/JSON/invalid.json +++ b/javascript/ql/test/library-tests/JSON/invalid.json @@ -1,4 +1,3 @@ "hi" // JSON doesn't have comments -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/JSON/options b/javascript/ql/test/library-tests/JSON/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/library-tests/JSON/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts index 6bba445dce42..55716a17a65e 100644 --- a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts +++ b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/jsdocTypes.ts @@ -23,5 +23,3 @@ var nns: Array; var dns: Array; var anys: Array<*>; var vars: Array<...number>; - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/SyntaxErrors/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/YAML/YAMLError.expected b/javascript/ql/test/library-tests/YAML/YAMLError.expected index 2045e49be51f..386d8874ef21 100644 --- a/javascript/ql/test/library-tests/YAML/YAMLError.expected +++ b/javascript/ql/test/library-tests/YAML/YAMLError.expected @@ -1 +1 @@ -| err.yaml:4:1:4:1 | found unexpected end of stream | +| err.yaml:3:1:3:1 | found unexpected end of stream | diff --git a/javascript/ql/test/library-tests/YAML/err.yaml b/javascript/ql/test/library-tests/YAML/err.yaml index f6d3951be962..96d2d75ddc0e 100644 --- a/javascript/ql/test/library-tests/YAML/err.yaml +++ b/javascript/ql/test/library-tests/YAML/err.yaml @@ -1,3 +1,2 @@ "unterminated string -# semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/YAML/options b/javascript/ql/test/library-tests/YAML/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/library-tests/YAML/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/library-tests/frameworks/Express/options b/javascript/ql/test/library-tests/frameworks/Express/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/Express/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options b/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/query-tests/AngularJS/DuplicateDependency/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js index 2d543e5bf1b4..470b14e8300d 100644 --- a/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js +++ b/javascript/ql/test/query-tests/Declarations/UniqueParameterNames/tst.js @@ -12,5 +12,3 @@ this.addPropertyListener(prop.name, function(_, _, _, a) { function f(x, y, x) { 'use strict'; } - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js index 2da4e693aeb8..e7aaa89f128a 100644 --- a/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js +++ b/javascript/ql/test/query-tests/LanguageFeatures/SyntaxError/tst.js @@ -1,4 +1,2 @@ function findBox() { return $("box.important - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js index ba9b39b4f729..5d56c9b782e0 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/nonbmp.js @@ -1,3 +1 @@ 😼😼 - -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/options b/javascript/ql/test/query-tests/filters/ClassifyFiles/options new file mode 100644 index 000000000000..13f987b19caf --- /dev/null +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html index 734e6cf7da8c..671a0c7b51b0 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/some-template.html @@ -1,4 +1,3 @@ -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js index 1a42f3cf925f..cda213805250 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/templ.js @@ -3,4 +3,3 @@ common.autofocus('#id_password'); {% else %} common.autofocus('#id_username'); {% endif %} -// semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html index c21d85208f52..e3bdc7444255 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl.html @@ -5,4 +5,3 @@ common.autofocus('#id_username'); {% endif %} -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html index 8e96a8b41f4d..700fe9c08d2d 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/tmpl2.html @@ -5,4 +5,3 @@ {{/config}} } -semmle-extractor-options: --tolerate-parse-errors diff --git a/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options new file mode 100644 index 000000000000..a1b2b21840fa --- /dev/null +++ b/javascript/ql/test/tutorials/Introducing the JavaScript libraries/options @@ -0,0 +1 @@ +semmle-extractor-options: --tolerate-parse-errors \ No newline at end of file From 3ad5af7ceff7a942277bb5ef0a42b09cdf21c1a2 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 5 Nov 2019 16:44:57 +0000 Subject: [PATCH 0238/2538] JavaScript: Move `--extract-program-text` extractor options into `options` files. --- .../test/library-tests/Lines/Lines.expected | 10 ++-- .../ql/test/library-tests/Lines/options | 1 + .../ql/test/library-tests/Lines/tst1.js | 4 +- .../ql/test/library-tests/Lines/tst2.js | 2 +- .../ql/test/library-tests/Lines/tst3.js | 4 +- .../TypeScript/Modifiers/options | 1 + .../library-tests/TypeScript/Modifiers/tst.ts | 2 - .../test/library-tests/stmts/conditionals.js | 2 +- .../ql/test/library-tests/stmts/es2015.js | 2 +- .../ql/test/library-tests/stmts/functions.js | 2 +- .../ql/test/library-tests/stmts/loops.js | 2 +- .../ql/test/library-tests/stmts/options | 2 +- .../ql/test/library-tests/stmts/others.js | 2 +- .../test/library-tests/stmts/tests.expected | 51 +++++++++---------- javascript/ql/test/library-tests/stmts/try.js | 2 +- 15 files changed, 43 insertions(+), 46 deletions(-) create mode 100644 javascript/ql/test/library-tests/Lines/options create mode 100644 javascript/ql/test/library-tests/TypeScript/Modifiers/options diff --git a/javascript/ql/test/library-tests/Lines/Lines.expected b/javascript/ql/test/library-tests/Lines/Lines.expected index 552c1b8ff0e1..e3c7973c9b81 100644 --- a/javascript/ql/test/library-tests/Lines/Lines.expected +++ b/javascript/ql/test/library-tests/Lines/Lines.expected @@ -1,4 +1,4 @@ -| tst1.js:1:1:1:55 | abc // semmle-extractor-options: --extract-program-text | abc // semmle-extractor-options: --extract-program-text | \n | +| tst1.js:1:1:1:3 | abc | abc | \n | | tst1.js:2:1:2:3 | def | def | \r | | tst1.js:3:1:3:3 | ghi | ghi | \r\n | | tst1.js:4:1:4:3 | jkl | jkl | \n | @@ -6,13 +6,13 @@ | tst1.js:6:1:6:3 | mno | mno | \u2028 | | tst1.js:7:1:7:0 | | | \n | | tst1.js:8:1:8:3 | pqr | pqr | \u2029 | -| tst1.js:9:1:9:3 | stu | stu | | -| tst2.js:1:1:1:63 | first_line // semmle-extractor-options: --extract-program-text | first_line // semmle-extractor-options: --extract-program-text | \n | -| tst3.js:1:1:1:56 | 42; // semmle-extractor-options: --extract-program-text | 42; // semmle-extractor-options: --extract-program-text | \n | +| tst1.js:9:1:9:3 | stu | stu | \n | +| tst2.js:1:1:1:10 | first_line | first_line | \n | +| tst3.js:1:1:1:3 | 42; | 42; | \n | | tst3.js:2:1:2:4 | \t42; | \t42; | \n | | tst3.js:3:1:3:5 | \t\t42; | \t\t42; | \n | | tst3.js:4:1:4:6 | \t\t\t42; | \t\t\t42; | \n | | tst3.js:5:1:5:6 | \t\t 42; | \t\t 42; | \n | | tst3.js:6:1:6:6 | \t \t42; | \t \t42; | \n | | tst3.js:7:1:7:7 | 42; | 42; | \n | -| tst3.js:8:1:8:5 | 42; | 42; | | +| tst3.js:8:1:8:5 | 42; | 42; | \n | diff --git a/javascript/ql/test/library-tests/Lines/options b/javascript/ql/test/library-tests/Lines/options new file mode 100644 index 000000000000..d51f2d49be28 --- /dev/null +++ b/javascript/ql/test/library-tests/Lines/options @@ -0,0 +1 @@ +semmle-extractor-options: --extract-program-text diff --git a/javascript/ql/test/library-tests/Lines/tst1.js b/javascript/ql/test/library-tests/Lines/tst1.js index f10f44a74409..d5fa50c5f3a5 100644 --- a/javascript/ql/test/library-tests/Lines/tst1.js +++ b/javascript/ql/test/library-tests/Lines/tst1.js @@ -1,5 +1,5 @@ -abc // semmle-extractor-options: --extract-program-text +abc def ghi jkl mno
 -pqr
stu \ No newline at end of file +pqr
stu diff --git a/javascript/ql/test/library-tests/Lines/tst2.js b/javascript/ql/test/library-tests/Lines/tst2.js index d3c776091455..c380edd400cb 100644 --- a/javascript/ql/test/library-tests/Lines/tst2.js +++ b/javascript/ql/test/library-tests/Lines/tst2.js @@ -1 +1 @@ -first_line // semmle-extractor-options: --extract-program-text +first_line diff --git a/javascript/ql/test/library-tests/Lines/tst3.js b/javascript/ql/test/library-tests/Lines/tst3.js index ad0059d91eab..8c8468ffab22 100644 --- a/javascript/ql/test/library-tests/Lines/tst3.js +++ b/javascript/ql/test/library-tests/Lines/tst3.js @@ -1,8 +1,8 @@ -42; // semmle-extractor-options: --extract-program-text +42; 42; 42; 42; 42; 42; 42; - 42; \ No newline at end of file + 42; diff --git a/javascript/ql/test/library-tests/TypeScript/Modifiers/options b/javascript/ql/test/library-tests/TypeScript/Modifiers/options new file mode 100644 index 000000000000..d51f2d49be28 --- /dev/null +++ b/javascript/ql/test/library-tests/TypeScript/Modifiers/options @@ -0,0 +1 @@ +semmle-extractor-options: --extract-program-text diff --git a/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts b/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts index a56c724cf57e..615a36ae6e5a 100644 --- a/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts +++ b/javascript/ql/test/library-tests/TypeScript/Modifiers/tst.ts @@ -113,5 +113,3 @@ interface InterfaceFields { z?: number; readonly w?: number; } - -// semmle-extractor-options: --extract-program-text \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/conditionals.js b/javascript/ql/test/library-tests/stmts/conditionals.js index 12562b2881f4..e21a4299f87a 100644 --- a/javascript/ql/test/library-tests/stmts/conditionals.js +++ b/javascript/ql/test/library-tests/stmts/conditionals.js @@ -1,4 +1,4 @@ -if (true) // semmle-extractor-options: --extract-program-text +if (true) ; if (b) ; diff --git a/javascript/ql/test/library-tests/stmts/es2015.js b/javascript/ql/test/library-tests/stmts/es2015.js index 6264c54a04fe..09a501be36b6 100644 --- a/javascript/ql/test/library-tests/stmts/es2015.js +++ b/javascript/ql/test/library-tests/stmts/es2015.js @@ -1,2 +1,2 @@ -for (var x of [1, 2, 3]) // semmle-extractor-options: --extract-program-text +for (var x of [1, 2, 3]) console.log(x); diff --git a/javascript/ql/test/library-tests/stmts/functions.js b/javascript/ql/test/library-tests/stmts/functions.js index f1ac615a0403..20ecacefad57 100644 --- a/javascript/ql/test/library-tests/stmts/functions.js +++ b/javascript/ql/test/library-tests/stmts/functions.js @@ -1,4 +1,4 @@ -function g(x, y) { // semmle-extractor-options: --extract-program-text +function g(x, y) { return x+y; } diff --git a/javascript/ql/test/library-tests/stmts/loops.js b/javascript/ql/test/library-tests/stmts/loops.js index e2a63b3e3f99..6d424254d74c 100644 --- a/javascript/ql/test/library-tests/stmts/loops.js +++ b/javascript/ql/test/library-tests/stmts/loops.js @@ -1,4 +1,4 @@ -while(true) // semmle-extractor-options: --extract-program-text +while(true) ; outer: for(a; b; c) { for(;;) diff --git a/javascript/ql/test/library-tests/stmts/options b/javascript/ql/test/library-tests/stmts/options index ae107b46f9ea..7b186f72cc57 100644 --- a/javascript/ql/test/library-tests/stmts/options +++ b/javascript/ql/test/library-tests/stmts/options @@ -1 +1 @@ -semmle-extractor-options: --experimental +semmle-extractor-options: --experimental --extract-program-text diff --git a/javascript/ql/test/library-tests/stmts/others.js b/javascript/ql/test/library-tests/stmts/others.js index 58d6c5c1709d..3b2a62a47bfe 100644 --- a/javascript/ql/test/library-tests/stmts/others.js +++ b/javascript/ql/test/library-tests/stmts/others.js @@ -1,4 +1,4 @@ -with(a) { // semmle-extractor-options: --extract-program-text +with(a) { } debugger; var x = 23, y; \ No newline at end of file diff --git a/javascript/ql/test/library-tests/stmts/tests.expected b/javascript/ql/test/library-tests/stmts/tests.expected index c4632fbc065c..75d6f0a24b45 100644 --- a/javascript/ql/test/library-tests/stmts/tests.expected +++ b/javascript/ql/test/library-tests/stmts/tests.expected @@ -4,14 +4,11 @@ test_LetStmt test_LineTerminators | conditionals.js:12:1:12:1 | } | | functions.js:9:1:9:1 | } | -| guardedCatch.js:11:1:11:65 | //semmle-extractor-options: --experimental --extract-program-text | -| jscript.js:5:1:5:65 | //semmle-extractor-options: --experimental --extract-program-text | -| legacyletstmt.js:5:1:5:65 | //semmle-extractor-options: --experimental --extract-program-text | | loops.js:22:1:22:18 | for (x = 0 in xs); | | others.js:4:1:4:14 | var x = 23, y; | | try.js:5:1:5:29 | try {} catch(x) {} finally {} | test_EnclosingStmt -| conditionals.js:1:5:1:8 | true | conditionals.js:1:1:2:5 | if (tru ... t\\n ; | +| conditionals.js:1:5:1:8 | true | conditionals.js:1:1:2:5 | if (true)\\n ; | | conditionals.js:3:5:3:5 | b | conditionals.js:3:1:6:5 | if (b)\\n ... e\\n ; | | conditionals.js:7:9:7:9 | b | conditionals.js:7:1:12:1 | switch ... ault:\\n} | | conditionals.js:8:6:8:7 | 23 | conditionals.js:8:1:8:8 | case 23: | @@ -96,7 +93,7 @@ test_EnclosingStmt | legacyletstmt.js:2:15:2:15 | x | legacyletstmt.js:2:3:2:21 | console.log(x + y); | | legacyletstmt.js:2:15:2:19 | x + y | legacyletstmt.js:2:3:2:21 | console.log(x + y); | | legacyletstmt.js:2:19:2:19 | y | legacyletstmt.js:2:3:2:21 | console.log(x + y); | -| loops.js:1:7:1:10 | true | loops.js:1:1:2:5 | while(t ... t\\n ; | +| loops.js:1:7:1:10 | true | loops.js:1:1:2:5 | while(true)\\n ; | | loops.js:3:1:3:5 | outer | loops.js:3:1:11:1 | outer: ... inue;\\n} | | loops.js:3:12:3:12 | a | loops.js:3:8:11:1 | for(a; ... inue;\\n} | | loops.js:3:15:3:15 | b | loops.js:3:8:11:1 | for(a; ... inue;\\n} | @@ -129,7 +126,7 @@ test_EnclosingStmt | loops.js:22:6:22:6 | x | loops.js:22:1:22:18 | for (x = 0 in xs); | | loops.js:22:10:22:10 | 0 | loops.js:22:1:22:18 | for (x = 0 in xs); | | loops.js:22:15:22:16 | xs | loops.js:22:1:22:18 | for (x = 0 in xs); | -| others.js:1:6:1:6 | a | others.js:1:1:2:1 | with(a) ... -text\\n} | +| others.js:1:6:1:6 | a | others.js:1:1:2:1 | with(a) {\\n} | | others.js:4:5:4:5 | x | others.js:4:1:4:14 | var x = 23, y; | | others.js:4:5:4:10 | x = 23 | others.js:4:1:4:14 | var x = 23, y; | | others.js:4:9:4:10 | 23 | others.js:4:1:4:14 | var x = 23, y; | @@ -140,7 +137,7 @@ test_EnclosingStmt | try.js:5:14:5:14 | x | try.js:5:8:5:18 | catch(x) {} | test_NumCatchClauses | guardedCatch.js:2:2:8:2 | try {\\n\\t ... !");\\n\\t} | 2 | -| try.js:1:1:3:16 | try { / ... ) { ; } | 1 | +| try.js:1:1:3:16 | try {\\n ... ) { ; } | 1 | | try.js:4:1:4:20 | try {} finally { ; } | 0 | | try.js:5:1:5:29 | try {} ... ally {} | 1 | test_DoubleColonMethods @@ -151,7 +148,7 @@ test_SemicolonInsertion test_getGuard | guardedCatch.js:4:4:6:2 | catch ( ... !");\\n\\t} | guardedCatch.js:4:16:4:33 | e instanceof Error | test_Containers -| conditionals.js:1:1:2:5 | if (tru ... t\\n ; | conditionals.js:1:1:12:1 | | +| conditionals.js:1:1:2:5 | if (true)\\n ; | conditionals.js:1:1:12:1 | | | conditionals.js:2:5:2:5 | ; | conditionals.js:1:1:12:1 | | | conditionals.js:3:1:6:5 | if (b)\\n ... e\\n ; | conditionals.js:1:1:12:1 | | | conditionals.js:4:5:4:5 | ; | conditionals.js:1:1:12:1 | | @@ -164,22 +161,22 @@ test_Containers | es2015.js:1:1:2:16 | for (va ... log(x); | es2015.js:1:1:3:0 | | | es2015.js:1:6:1:10 | var x | es2015.js:1:1:3:0 | | | es2015.js:2:2:2:16 | console.log(x); | es2015.js:1:1:3:0 | | -| foreach.js:1:1:1:12 | var sum = 0; | foreach.js:1:1:11:0 | | -| foreach.js:2:1:2:42 | var obj ... p3: 8}; | foreach.js:1:1:11:0 | | -| foreach.js:4:1:6:1 | for eac ... item;\\n} | foreach.js:1:1:11:0 | | -| foreach.js:4:11:4:18 | var item | foreach.js:1:1:11:0 | | -| foreach.js:4:28:6:1 | {\\n sum += item;\\n} | foreach.js:1:1:11:0 | | -| foreach.js:5:3:5:14 | sum += item; | foreach.js:1:1:11:0 | | -| foreach.js:8:1:8:17 | console.log(sum); | foreach.js:1:1:11:0 | | +| foreach.js:1:1:1:12 | var sum = 0; | foreach.js:1:1:9:0 | | +| foreach.js:2:1:2:42 | var obj ... p3: 8}; | foreach.js:1:1:9:0 | | +| foreach.js:4:1:6:1 | for eac ... item;\\n} | foreach.js:1:1:9:0 | | +| foreach.js:4:11:4:18 | var item | foreach.js:1:1:9:0 | | +| foreach.js:4:28:6:1 | {\\n sum += item;\\n} | foreach.js:1:1:9:0 | | +| foreach.js:5:3:5:14 | sum += item; | foreach.js:1:1:9:0 | | +| foreach.js:8:1:8:17 | console.log(sum); | foreach.js:1:1:9:0 | | | functions.js:1:1:3:1 | functio ... x+y;\\n} | functions.js:1:1:9:1 | | -| functions.js:1:18:3:1 | { // se ... x+y;\\n} | functions.js:1:1:3:1 | functio ... x+y;\\n} | +| functions.js:1:18:3:1 | {\\n return x+y;\\n} | functions.js:1:1:3:1 | functio ... x+y;\\n} | | functions.js:2:5:2:15 | return x+y; | functions.js:1:1:3:1 | functio ... x+y;\\n} | | functions.js:5:1:5:15 | function h() {} | functions.js:1:1:9:1 | | | functions.js:5:14:5:15 | {} | functions.js:5:1:5:15 | function h() {} | | functions.js:7:1:9:1 | k = fun ... turn;\\n} | functions.js:1:1:9:1 | | | functions.js:7:16:9:1 | {\\n return;\\n} | functions.js:7:5:9:1 | functio ... turn;\\n} | | functions.js:8:5:8:11 | return; | functions.js:7:5:9:1 | functio ... turn;\\n} | -| guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | guardedCatch.js:1:1:11:65 | | +| guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | guardedCatch.js:1:1:10:0 | | | guardedCatch.js:1:15:9:1 | {\\n\\ttry ... );\\n\\t}\\n} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:2:2:8:2 | try {\\n\\t ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:2:6:4:2 | {\\n\\t\\tg();\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | @@ -190,14 +187,14 @@ test_Containers | guardedCatch.js:6:4:8:2 | catch ( ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:6:14:8:2 | {\\n\\t\\tcon ... !");\\n\\t} | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | | guardedCatch.js:7:3:7:33 | console ... lse!"); | guardedCatch.js:1:1:9:1 | functio ... );\\n\\t}\\n} | -| jscript.js:1:1:1:28 | functio ... ad() {} | jscript.js:1:1:5:65 | | +| jscript.js:1:1:1:28 | functio ... ad() {} | jscript.js:1:1:4:0 | | | jscript.js:1:27:1:28 | {} | jscript.js:1:1:1:28 | functio ... ad() {} | -| jscript.js:3:1:3:36 | window. ... ad() {} | jscript.js:1:1:5:65 | | +| jscript.js:3:1:3:36 | window. ... ad() {} | jscript.js:1:1:4:0 | | | jscript.js:3:35:3:36 | {} | jscript.js:3:17:3:36 | function onload() {} | -| legacyletstmt.js:1:1:3:1 | let (x ... + y);\\n} | legacyletstmt.js:1:1:5:65 | | -| legacyletstmt.js:1:22:3:1 | {\\n con ... + y);\\n} | legacyletstmt.js:1:1:5:65 | | -| legacyletstmt.js:2:3:2:21 | console.log(x + y); | legacyletstmt.js:1:1:5:65 | | -| loops.js:1:1:2:5 | while(t ... t\\n ; | loops.js:1:1:22:18 | | +| legacyletstmt.js:1:1:3:1 | let (x ... + y);\\n} | legacyletstmt.js:1:1:4:0 | | +| legacyletstmt.js:1:22:3:1 | {\\n con ... + y);\\n} | legacyletstmt.js:1:1:4:0 | | +| legacyletstmt.js:2:3:2:21 | console.log(x + y); | legacyletstmt.js:1:1:4:0 | | +| loops.js:1:1:2:5 | while(true)\\n ; | loops.js:1:1:22:18 | | | loops.js:2:5:2:5 | ; | loops.js:1:1:22:18 | | | loops.js:3:1:11:1 | outer: ... inue;\\n} | loops.js:1:1:22:18 | | | loops.js:3:8:11:1 | for(a; ... inue;\\n} | loops.js:1:1:22:18 | | @@ -223,12 +220,12 @@ test_Containers | loops.js:21:16:21:16 | ; | loops.js:1:1:22:18 | | | loops.js:22:1:22:18 | for (x = 0 in xs); | loops.js:1:1:22:18 | | | loops.js:22:18:22:18 | ; | loops.js:1:1:22:18 | | -| others.js:1:1:2:1 | with(a) ... -text\\n} | others.js:1:1:4:14 | | -| others.js:1:9:2:1 | { // se ... -text\\n} | others.js:1:1:4:14 | | +| others.js:1:1:2:1 | with(a) {\\n} | others.js:1:1:4:14 | | +| others.js:1:9:2:1 | {\\n} | others.js:1:1:4:14 | | | others.js:3:1:3:9 | debugger; | others.js:1:1:4:14 | | | others.js:4:1:4:14 | var x = 23, y; | others.js:1:1:4:14 | | -| try.js:1:1:3:16 | try { / ... ) { ; } | try.js:1:1:5:29 | | -| try.js:1:5:3:1 | { // se ... "!";\\n} | try.js:1:1:5:29 | | +| try.js:1:1:3:16 | try {\\n ... ) { ; } | try.js:1:1:5:29 | | +| try.js:1:5:3:1 | {\\n throw "!";\\n} | try.js:1:1:5:29 | | | try.js:2:5:2:14 | throw "!"; | try.js:1:1:5:29 | | | try.js:3:3:3:16 | catch(x) { ; } | try.js:1:1:5:29 | | | try.js:3:12:3:16 | { ; } | try.js:1:1:5:29 | | diff --git a/javascript/ql/test/library-tests/stmts/try.js b/javascript/ql/test/library-tests/stmts/try.js index 2d82952fbd38..0151114bf840 100644 --- a/javascript/ql/test/library-tests/stmts/try.js +++ b/javascript/ql/test/library-tests/stmts/try.js @@ -1,4 +1,4 @@ -try { // semmle-extractor-options: --extract-program-text +try { throw "!"; } catch(x) { ; } try {} finally { ; } From 725059deea8abccc6a38531fed27e7db47d7a2a7 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 12:08:33 +0000 Subject: [PATCH 0239/2538] JavaScript: Remove `--source-type module` extractor options. --- .../library-tests/DataFlow/flowStep.expected | 8 ++++---- javascript/ql/test/library-tests/DataFlow/tst.ts | 4 +--- .../library-tests/Flow/AbstractValues.expected | 16 ++++++++-------- javascript/ql/test/library-tests/Flow/tst.ts | 4 +--- .../InterProceduralFlow/callback.js | 2 +- .../InterProceduralFlow/properties2.js | 2 +- .../library-tests/NPM/ImportedModule.expected | 10 +++++----- .../ql/test/library-tests/NPM/Modules.expected | 6 +++--- .../NPM/NPMPackage_getMainModule.expected | 4 ++-- .../ql/test/library-tests/NPM/src/index.js | 3 +-- .../ql/test/library-tests/NPM/src/lib/tst.js | 3 +-- .../src/node_modules/third-party-module/fancy.js | 3 +-- .../NodeJS/Module_getAnImport.expected | 1 + .../NodeJS/Module_getAnImportedModule.expected | 2 +- .../test/library-tests/NodeJS/Modules.expected | 2 +- .../test/library-tests/NodeJS/Require.expected | 1 + .../library-tests/NodeJS/RequireImport.expected | 2 +- javascript/ql/test/library-tests/NodeJS/e.js | 3 +-- 18 files changed, 35 insertions(+), 41 deletions(-) diff --git a/javascript/ql/test/library-tests/DataFlow/flowStep.expected b/javascript/ql/test/library-tests/DataFlow/flowStep.expected index a6446732fbe6..ad843094a5e5 100644 --- a/javascript/ql/test/library-tests/DataFlow/flowStep.expected +++ b/javascript/ql/test/library-tests/DataFlow/flowStep.expected @@ -142,11 +142,11 @@ | tst.js:111:29:111:31 | o2c | tst.js:111:6:111:38 | v2c | | tst.js:111:36:111:38 | o2d | tst.js:111:6:111:32 | [v2a, v ... = o2c] | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | -| tst.ts:1:1:1:1 | A | tst.ts:1:11:1:11 | A | +| tst.ts:1:1:1:1 | A | tst.ts:1:18:1:18 | A | | tst.ts:1:1:1:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:1:5:1 | A | tst.ts:7:1:7:0 | A | -| tst.ts:1:1:5:1 | A | tst.ts:11:11:11:11 | A | -| tst.ts:1:1:5:1 | namespa ... lysed\\n} | tst.ts:1:1:5:1 | A | +| tst.ts:1:8:5:1 | A | tst.ts:7:1:7:0 | A | +| tst.ts:1:8:5:1 | A | tst.ts:11:11:11:11 | A | +| tst.ts:1:8:5:1 | namespa ... lysed\\n} | tst.ts:1:8:5:1 | A | | tst.ts:2:14:2:19 | x | tst.ts:4:3:4:3 | x | | tst.ts:2:18:2:19 | 42 | tst.ts:2:14:2:19 | x | | tst.ts:7:1:7:0 | A | tst.ts:8:3:8:3 | A | diff --git a/javascript/ql/test/library-tests/DataFlow/tst.ts b/javascript/ql/test/library-tests/DataFlow/tst.ts index dca2ee632b7e..29c85cba9337 100644 --- a/javascript/ql/test/library-tests/DataFlow/tst.ts +++ b/javascript/ql/test/library-tests/DataFlow/tst.ts @@ -1,4 +1,4 @@ -namespace A { +export namespace A { export let x = 42; setX(); x; // global namespace exports are incompletely analysed @@ -11,5 +11,3 @@ function setX() { var nd2 = A.x as number; // flow through type assertions class StringList extends List {} // flow through expressions with type arguments - -// semmle-extractor-options: --source-type module diff --git a/javascript/ql/test/library-tests/Flow/AbstractValues.expected b/javascript/ql/test/library-tests/Flow/AbstractValues.expected index 42117cac98a7..531faf562bdd 100644 --- a/javascript/ql/test/library-tests/Flow/AbstractValues.expected +++ b/javascript/ql/test/library-tests/Flow/AbstractValues.expected @@ -194,8 +194,8 @@ | n.js:2:1:2:15 | function g | | n.js:2:1:2:15 | instance of function g | | n.js:3:16:3:23 | object literal | -| namespace-reexport.js:1:1:4:0 | exports object of module namespace-reexport | -| namespace-reexport.js:1:1:4:0 | module object of module namespace-reexport | +| namespace-reexport.js:1:1:2:0 | exports object of module namespace-reexport | +| namespace-reexport.js:1:1:2:0 | module object of module namespace-reexport | | nestedImport.js:1:1:13:0 | exports object of module nestedImport | | nestedImport.js:1:1:13:0 | module object of module nestedImport | | nestedImport.js:9:1:12:1 | function tst | @@ -235,14 +235,14 @@ | objlit.js:43:12:45:3 | object literal | | reexport-d.js:1:1:2:0 | exports object of module reexport-d | | reexport-d.js:1:1:2:0 | module object of module reexport-d | -| reexport-mixins.js:1:1:4:0 | exports object of module reexport-mixins | -| reexport-mixins.js:1:1:4:0 | module object of module reexport-mixins | +| reexport-mixins.js:1:1:2:0 | exports object of module reexport-mixins | +| reexport-mixins.js:1:1:2:0 | module object of module reexport-mixins | | reexport-unknown.js:1:1:2:0 | exports object of module reexport-unknown | | reexport-unknown.js:1:1:2:0 | module object of module reexport-unknown | | reexport/client/src/index.js:1:1:3:0 | exports object of module index | | reexport/client/src/index.js:1:1:3:0 | module object of module index | -| reexport/lib/index.js:1:1:4:0 | exports object of module index | -| reexport/lib/index.js:1:1:4:0 | module object of module index | +| reexport/lib/index.js:1:1:2:0 | exports object of module index | +| reexport/lib/index.js:1:1:2:0 | module object of module index | | reexport/lib/src/utils/util.js:1:1:3:0 | exports object of module util | | reexport/lib/src/utils/util.js:1:1:3:0 | module object of module util | | refinements.js:1:1:8:1 | function f1 | @@ -341,8 +341,8 @@ | tst.js:174:1:183:1 | function awaitFlow | | tst.mjs:1:1:4:0 | exports object of module tst | | tst.mjs:1:1:4:0 | module object of module tst | -| tst.ts:1:1:15:0 | exports object of module tst | -| tst.ts:1:1:15:0 | module object of module tst | +| tst.ts:1:1:13:0 | exports object of module tst | +| tst.ts:1:1:13:0 | module object of module tst | | tst.ts:8:1:10:1 | function setX | | tst.ts:8:1:10:1 | instance of function setX | | with.js:1:1:17:1 | function f | diff --git a/javascript/ql/test/library-tests/Flow/tst.ts b/javascript/ql/test/library-tests/Flow/tst.ts index 615efbb7103c..63e329f75c01 100644 --- a/javascript/ql/test/library-tests/Flow/tst.ts +++ b/javascript/ql/test/library-tests/Flow/tst.ts @@ -1,4 +1,4 @@ -namespace A { +export namespace A { export let x = 42; setX(); let x2 = x; @@ -10,5 +10,3 @@ function setX() { } let a = A; - -// semmle-extractor-options: --source-type module diff --git a/javascript/ql/test/library-tests/InterProceduralFlow/callback.js b/javascript/ql/test/library-tests/InterProceduralFlow/callback.js index 8ba9bd12fee4..1e4d7aed2e88 100644 --- a/javascript/ql/test/library-tests/InterProceduralFlow/callback.js +++ b/javascript/ql/test/library-tests/InterProceduralFlow/callback.js @@ -28,4 +28,4 @@ let source3 = "source3"; call2(source3, store); call2(source3, confounder); -// semmle-extractor-options: --source-type module +export default 0; diff --git a/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js b/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js index 849516d57bba..9f1b0c9ba070 100644 --- a/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js +++ b/javascript/ql/test/library-tests/InterProceduralFlow/properties2.js @@ -42,4 +42,4 @@ var o5 = {}; setP(o5, "not a source"); var sink10 = getP(o5); -// semmle-extractor-options: --source-type module +export default 0; diff --git a/javascript/ql/test/library-tests/NPM/ImportedModule.expected b/javascript/ql/test/library-tests/NPM/ImportedModule.expected index 2a89dfeb3945..ce2a65d591f2 100644 --- a/javascript/ql/test/library-tests/NPM/ImportedModule.expected +++ b/javascript/ql/test/library-tests/NPM/ImportedModule.expected @@ -1,6 +1,6 @@ -| src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:5:0 | | -| src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| src/lib/tst2.js:1:1:1:13 | require("..") | src/index.js:1:1:4:0 | | +| src/node_modules/nested/tst3.js:1:1:1:29 | require ... odule') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | | src/node_modules/nested/tst3.js:2:1:2:12 | require('a') | src/node_modules/nested/node_modules/a/index.js:1:1:1:25 | | -| src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | -| src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:5:0 | | -| src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| src/node_modules/tst2.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | +| src/tst2.js:1:1:1:12 | require(".") | src/index.js:1:1:4:0 | | +| src/tst.js:1:1:1:38 | require ... cy.js') | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/Modules.expected b/javascript/ql/test/library-tests/NPM/Modules.expected index 4d0dde9c33e9..e7fa54d6f9aa 100644 --- a/javascript/ql/test/library-tests/NPM/Modules.expected +++ b/javascript/ql/test/library-tests/NPM/Modules.expected @@ -1,9 +1,9 @@ | b | src/node_modules/b/lib/index.js:1:1:2:0 | | | b | src/node_modules/b/lib/index.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | -| test-package | src/index.js:1:1:5:0 | | +| test-package | src/index.js:1:1:4:0 | | | test-package | src/lib/tst2.js:1:1:1:14 | | -| test-package | src/lib/tst.js:1:1:5:0 | | +| test-package | src/lib/tst.js:1:1:4:0 | | | test-package | src/tst2.js:1:1:1:13 | | | test-package | src/tst.js:1:1:2:38 | | -| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected index 67fd1880bf08..a8b7753abaec 100644 --- a/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected +++ b/javascript/ql/test/library-tests/NPM/NPMPackage_getMainModule.expected @@ -1,4 +1,4 @@ | b | src/node_modules/b/lib/index.ts:1:1:2:0 | | | c | src/node_modules/c/src/index.js:1:1:2:0 | | -| test-package | src/index.js:1:1:5:0 | | -| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:5:0 | | +| test-package | src/index.js:1:1:4:0 | | +| third-party-module | src/node_modules/third-party-module/fancy.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NPM/src/index.js b/javascript/ql/test/library-tests/NPM/src/index.js index b875bfd3a103..e99778b633fb 100644 --- a/javascript/ql/test/library-tests/NPM/src/index.js +++ b/javascript/ql/test/library-tests/NPM/src/index.js @@ -1,4 +1,3 @@ alert("Hello"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NPM/src/lib/tst.js b/javascript/ql/test/library-tests/NPM/src/lib/tst.js index 840fb76057be..d8fc422959c3 100644 --- a/javascript/ql/test/library-tests/NPM/src/lib/tst.js +++ b/javascript/ql/test/library-tests/NPM/src/lib/tst.js @@ -1,4 +1,3 @@ alert("world"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js b/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js index f53610fe05c9..7dfe5aea1d2d 100644 --- a/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js +++ b/javascript/ql/test/library-tests/NPM/src/node_modules/third-party-module/fancy.js @@ -1,4 +1,3 @@ ('alert' in this ? alert : console.log)("Hello"); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected index 9f2e4dba88ed..d1cc25761419 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImport.expected @@ -9,6 +9,7 @@ | b.js:1:1:8:0 | | b.js:1:1:1:18 | require('./sub/c') | | d.js:1:1:7:15 | | d.js:1:1:1:38 | require ... s/ini') | | d.js:1:1:7:15 | | d.js:7:1:7:14 | require('foo') | +| e.js:1:1:6:0 | | e.js:5:1:5:18 | require("process") | | index.js:1:1:3:0 | | index.js:1:12:1:26 | require('path') | | index.js:1:1:3:0 | | index.js:2:1:2:41 | require ... b.js")) | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:1:12:1:36 | require ... on-me') | diff --git a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected index c038d8f90315..0fa0e65f3594 100644 --- a/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected +++ b/javascript/ql/test/library-tests/NodeJS/Module_getAnImportedModule.expected @@ -1,6 +1,6 @@ | a.js:1:1:14:0 | | b.js:1:1:8:0 | | | a.js:1:1:14:0 | | d.js:1:1:7:15 | | -| a.js:1:1:14:0 | | e.js:1:1:7:0 | | +| a.js:1:1:14:0 | | e.js:1:1:6:0 | | | a.js:1:1:14:0 | | index.js:1:1:3:0 | | | a.js:1:1:14:0 | | sub/c.js:1:1:4:0 | | | b.js:1:1:8:0 | | sub/c.js:1:1:4:0 | | diff --git a/javascript/ql/test/library-tests/NodeJS/Modules.expected b/javascript/ql/test/library-tests/NodeJS/Modules.expected index 05306ec82c52..1ef82d0328ea 100644 --- a/javascript/ql/test/library-tests/NodeJS/Modules.expected +++ b/javascript/ql/test/library-tests/NodeJS/Modules.expected @@ -1,7 +1,7 @@ | a.js:1:1:14:0 | | a.js:0:0:0:0 | a.js | a.js | a | | b.js:1:1:8:0 | | b.js:0:0:0:0 | b.js | b.js | b | | d.js:1:1:7:15 | | d.js:0:0:0:0 | d.js | d.js | d | -| e.js:1:1:7:0 | | e.js:0:0:0:0 | e.js | e.js | e | +| e.js:1:1:6:0 | | e.js:0:0:0:0 | e.js | e.js | e | | index.js:1:1:3:0 | | index.js:0:0:0:0 | index.js | index.js | index | | mjs-files/require-from-js.js:1:1:4:0 | | mjs-files/require-from-js.js:0:0:0:0 | mjs-files/require-from-js.js | mjs-files/require-from-js.js | require-from-js | | sub/c.js:1:1:4:0 | | sub/c.js:0:0:0:0 | sub/c.js | sub/c.js | c | diff --git a/javascript/ql/test/library-tests/NodeJS/Require.expected b/javascript/ql/test/library-tests/NodeJS/Require.expected index 491c80a9a875..7e9a50685ab3 100644 --- a/javascript/ql/test/library-tests/NodeJS/Require.expected +++ b/javascript/ql/test/library-tests/NodeJS/Require.expected @@ -9,6 +9,7 @@ | b.js:1:1:1:18 | require('./sub/c') | | d.js:1:1:1:38 | require ... s/ini') | | d.js:7:1:7:14 | require('foo') | +| e.js:5:1:5:18 | require("process") | | f.js:2:1:2:7 | r("fs") | | index.js:1:12:1:26 | require('path') | | index.js:2:1:2:41 | require ... b.js")) | diff --git a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected index a7ec65d67a2e..e01527d2784f 100644 --- a/javascript/ql/test/library-tests/NodeJS/RequireImport.expected +++ b/javascript/ql/test/library-tests/NodeJS/RequireImport.expected @@ -3,7 +3,7 @@ | a.js:4:6:4:29 | require ... /d.js') | ./sub/../d.js | d.js:1:1:7:15 | | | a.js:7:1:7:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | a.js:10:1:10:18 | require(__dirname) | | index.js:1:1:3:0 | | -| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:7:0 | | +| a.js:11:1:11:25 | require ... + '/e') | /e | e.js:1:1:6:0 | | | a.js:12:1:12:28 | require ... + 'c') | ./sub/c | sub/c.js:1:1:4:0 | | | b.js:1:1:1:18 | require('./sub/c') | ./sub/c | sub/c.js:1:1:4:0 | | | d.js:7:1:7:14 | require('foo') | foo | sub/f.js:1:1:4:17 | | diff --git a/javascript/ql/test/library-tests/NodeJS/e.js b/javascript/ql/test/library-tests/NodeJS/e.js index 0a3f338f7d07..22254c563267 100644 --- a/javascript/ql/test/library-tests/NodeJS/e.js +++ b/javascript/ql/test/library-tests/NodeJS/e.js @@ -2,5 +2,4 @@ require('./a.js'); })(); -// semmle-extractor-options: --platform -// semmle-extractor-options: node +require("process"); From 49008c9ff5923efbe3f29ccf66901eec67c40aa7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 5 Nov 2019 14:20:10 +0100 Subject: [PATCH 0240/2538] C++: IR data flow local virtual dispatch This is just good enough to cause no performance regressions and pass the virtual-dispatch tests we have for `security.TaintTracking`. In particular, it fixes the tests for `UncontrolledProcessOperation.ql` when enabling `DefaultTaintTracking.qll`. --- .../ir/dataflow/internal/DataFlowDispatch.qll | 53 +++++++++++++++++++ .../dataflow/dataflow-tests/dispatch.cpp | 46 ++++++++++++++++ .../dataflow/dataflow-tests/test.expected | 6 +++ .../dataflow-tests/test_diff.expected | 2 + .../dataflow/dataflow-tests/test_ir.expected | 8 +++ 5 files changed, 115 insertions(+) create mode 100644 cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll index d0325a28d3e9..9572639de595 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowDispatch.qll @@ -1,5 +1,6 @@ private import cpp private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.DataFlow Function viableImpl(CallInstruction call) { result = viableCallable(call) } @@ -20,6 +21,58 @@ Function viableCallable(CallInstruction call) { functionSignatureWithBody(qualifiedName, nparams, result) and strictcount(Function other | functionSignatureWithBody(qualifiedName, nparams, other)) = 1 ) + or + // Rudimentary virtual dispatch support. It's essentially local data flow + // where the source is a derived-to-base conversion and the target is the + // qualifier of a call. + exists(Class derived, DataFlow::Node thisArgument | + nodeMayHaveClass(derived, thisArgument) and + overrideMayAffectCall(derived, thisArgument, _, result, call) + ) +} + +/** + * Holds if `call` is a virtual function call with qualifier `thisArgument` in + * `enclosingFunction`, whose static target is overridden by + * `overridingFunction` in `overridingClass`. + */ +pragma[noinline] +private predicate overrideMayAffectCall( + Class overridingClass, DataFlow::Node thisArgument, Function enclosingFunction, + MemberFunction overridingFunction, CallInstruction call +) { + call.getEnclosingFunction() = enclosingFunction and + overridingFunction.getAnOverriddenFunction+() = call.getStaticCallTarget() and + overridingFunction.getDeclaringType() = overridingClass and + thisArgument = DataFlow::instructionNode(call.getThisArgument()) +} + +/** + * Holds if `node` may have dynamic class `derived`, where `derived` is a class + * that may affect virtual dispatch within the enclosing function. + * + * For the sake of performance, this recursion is written out manually to make + * it a relation on `Class x Node` rather than `Node x Node` or `MemberFunction + * x Node`, both of which would be larger. It's a forward search since there + * should usually be fewer classes than calls. + * + * If a value is cast several classes up in the hierarchy, that will be modeled + * as a chain of `ConvertToBaseInstruction`s and will cause the search to start + * from each of them and pass through subsequent ones. There might be + * performance to gain by stopping before a second upcast and reconstructing + * the full chain in a "big-step" recursion after this one. + */ +private predicate nodeMayHaveClass(Class derived, DataFlow::Node node) { + exists(ConvertToBaseInstruction toBase | + derived = toBase.getDerivedClass() and + overrideMayAffectCall(derived, _, toBase.getEnclosingFunction(), _, _) and + node.asInstruction() = toBase + ) + or + exists(DataFlow::Node prev | + nodeMayHaveClass(derived, prev) and + DataFlow::localFlowStep(prev, node) + ) } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp new file mode 100644 index 000000000000..f37eb4e9cbe6 --- /dev/null +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp @@ -0,0 +1,46 @@ +int source(); +void sink(int); + +// This class has the opposite behavior of what the member function names suggest. +struct Top { + virtual int isSource1() { return 0; } + virtual int isSource2() { return 0; } + virtual void isSink(int x) { } + virtual int notSource1() { return source(); } + virtual int notSource2() { return source(); } + virtual void notSink(int x) { sink(x); } +}; + +// This class has the correct behavior for just the functions ending in 2. +struct Middle : Top { + int isSource2() override { return source(); } + int notSource2() override { return 0; } +}; + +// This class has all the behavior suggested by the function names. +struct Bottom : Middle { + int isSource1() override { return source(); } + void isSink(int x) override { sink(x); } + int notSource1() override { return 0; } + void notSink(int x) override { } +}; + +void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { + Top *topPtr = bottomPtr, &topRef = bottomRef; + + sink(topPtr->isSource1()); // flow [NOT DETECTED] + sink(topPtr->isSource2()); // flow [NOT DETECTED by AST] + topPtr->isSink(source()); // flow [NOT DETECTED] + + sink(topPtr->notSource1()); // no flow [FALSE POSITIVE] + sink(topPtr->notSource2()); // no flow [FALSE POSITIVE] + topPtr->notSink(source()); // no flow [FALSE POSITIVE] + + sink(topRef.isSource1()); // flow [NOT DETECTED] + sink(topRef.isSource2()); // flow [NOT DETECTED by AST] + topRef.isSink(source()); // flow [NOT DETECTED] + + sink(topRef.notSource1()); // no flow [FALSE POSITIVE] + sink(topRef.notSource2()); // no flow [FALSE POSITIVE] + topRef.notSink(source()); // no flow [FALSE POSITIVE] +} diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected index 6527db4b77e8..24fa6fdb5bd9 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.expected @@ -15,6 +15,12 @@ | clang.cpp:30:27:30:34 | call to getFirst | clang.cpp:28:27:28:32 | call to source | | clang.cpp:37:10:37:11 | m2 | clang.cpp:34:32:34:37 | call to source | | clang.cpp:45:17:45:18 | m2 | clang.cpp:43:35:43:40 | call to source | +| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:37:19:37:24 | call to source | +| dispatch.cpp:11:38:11:38 | x | dispatch.cpp:45:18:45:23 | call to source | +| dispatch.cpp:35:16:35:25 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source | +| dispatch.cpp:36:16:36:25 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source | +| dispatch.cpp:43:15:43:24 | call to notSource1 | dispatch.cpp:9:37:9:42 | call to source | +| dispatch.cpp:44:15:44:24 | call to notSource2 | dispatch.cpp:10:37:10:42 | call to source | | lambdas.cpp:14:3:14:6 | t | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:18:8:18:8 | call to operator() | lambdas.cpp:8:10:8:15 | call to source | | lambdas.cpp:21:3:21:6 | t | lambdas.cpp:8:10:8:15 | call to source | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 7d0d4e7d72e0..8e914d533374 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -5,6 +5,8 @@ | clang.cpp:28:27:28:32 | clang.cpp:29:27:29:28 | AST only | | clang.cpp:28:27:28:32 | clang.cpp:30:27:30:34 | AST only | | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | +| dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | +| dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 9b67a013a58a..8d21837510e3 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -12,6 +12,14 @@ | clang.cpp:37:10:37:11 | Load: m2 | clang.cpp:34:32:34:37 | Call: call to source | | clang.cpp:41:18:41:19 | Load: m2 | clang.cpp:39:42:39:47 | Call: call to source | | clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | +| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:37:19:37:24 | Call: call to source | +| dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:45:18:45:23 | Call: call to source | +| dispatch.cpp:32:16:32:24 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | +| dispatch.cpp:35:16:35:25 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | +| dispatch.cpp:36:16:36:25 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | +| dispatch.cpp:40:15:40:23 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | +| dispatch.cpp:43:15:43:24 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | +| dispatch.cpp:44:15:44:24 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | | test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | | test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source | | test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source | From ec9ef334864e59dc9e95fda9ab8267b99e7f29dd Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 6 Nov 2019 13:59:52 +0100 Subject: [PATCH 0241/2538] C++: IR data flow through inheritance conversions This makes IR data flow behave more like AST data flow, and it makes IR virtual dispatch work without further changes. --- .../semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll | 3 ++- .../library-tests/dataflow/dataflow-tests/dispatch.cpp | 8 ++++---- .../dataflow/dataflow-tests/test_diff.expected | 4 ++++ .../dataflow/dataflow-tests/test_ir.expected | 4 ++++ 4 files changed, 14 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll index cd989c947103..4e84424fcb7a 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll @@ -205,7 +205,8 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction iTo.(CopyInstruction).getSourceValue() = iFrom or iTo.(PhiInstruction).getAnOperand().getDef() = iFrom or // Treat all conversions as flow, even conversions between different numeric types. - iTo.(ConvertInstruction).getUnary() = iFrom + iTo.(ConvertInstruction).getUnary() = iFrom or + iTo.(InheritanceConversionInstruction).getUnary() = iFrom } /** diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp index f37eb4e9cbe6..5e4f2f97f465 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/dispatch.cpp @@ -28,17 +28,17 @@ struct Bottom : Middle { void VirtualDispatch(Bottom *bottomPtr, Bottom &bottomRef) { Top *topPtr = bottomPtr, &topRef = bottomRef; - sink(topPtr->isSource1()); // flow [NOT DETECTED] + sink(topPtr->isSource1()); // flow [NOT DETECTED by AST] sink(topPtr->isSource2()); // flow [NOT DETECTED by AST] - topPtr->isSink(source()); // flow [NOT DETECTED] + topPtr->isSink(source()); // flow [NOT DETECTED by AST] sink(topPtr->notSource1()); // no flow [FALSE POSITIVE] sink(topPtr->notSource2()); // no flow [FALSE POSITIVE] topPtr->notSink(source()); // no flow [FALSE POSITIVE] - sink(topRef.isSource1()); // flow [NOT DETECTED] + sink(topRef.isSource1()); // flow [NOT DETECTED by AST] sink(topRef.isSource2()); // flow [NOT DETECTED by AST] - topRef.isSink(source()); // flow [NOT DETECTED] + topRef.isSink(source()); // flow [NOT DETECTED by AST] sink(topRef.notSource1()); // no flow [FALSE POSITIVE] sink(topRef.notSource2()); // no flow [FALSE POSITIVE] diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected index 8e914d533374..9b8be3abd1e9 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_diff.expected @@ -7,6 +7,10 @@ | clang.cpp:39:42:39:47 | clang.cpp:41:18:41:19 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:32:16:32:24 | IR only | | dispatch.cpp:16:37:16:42 | dispatch.cpp:40:15:40:23 | IR only | +| dispatch.cpp:22:37:22:42 | dispatch.cpp:31:16:31:24 | IR only | +| dispatch.cpp:22:37:22:42 | dispatch.cpp:39:15:39:23 | IR only | +| dispatch.cpp:33:18:33:23 | dispatch.cpp:23:38:23:38 | IR only | +| dispatch.cpp:41:17:41:22 | dispatch.cpp:23:38:23:38 | IR only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:14:3:14:6 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:18:8:18:8 | AST only | | lambdas.cpp:8:10:8:15 | lambdas.cpp:21:3:21:6 | AST only | diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected index 8d21837510e3..651e580a105f 100644 --- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected +++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test_ir.expected @@ -14,9 +14,13 @@ | clang.cpp:45:17:45:18 | Load: m2 | clang.cpp:43:35:43:40 | Call: call to source | | dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:37:19:37:24 | Call: call to source | | dispatch.cpp:11:38:11:38 | Load: x | dispatch.cpp:45:18:45:23 | Call: call to source | +| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:33:18:33:23 | Call: call to source | +| dispatch.cpp:23:38:23:38 | Load: x | dispatch.cpp:41:17:41:22 | Call: call to source | +| dispatch.cpp:31:16:31:24 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source | | dispatch.cpp:32:16:32:24 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | | dispatch.cpp:35:16:35:25 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | | dispatch.cpp:36:16:36:25 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | +| dispatch.cpp:39:15:39:23 | Call: call to isSource1 | dispatch.cpp:22:37:22:42 | Call: call to source | | dispatch.cpp:40:15:40:23 | Call: call to isSource2 | dispatch.cpp:16:37:16:42 | Call: call to source | | dispatch.cpp:43:15:43:24 | Call: call to notSource1 | dispatch.cpp:9:37:9:42 | Call: call to source | | dispatch.cpp:44:15:44:24 | Call: call to notSource2 | dispatch.cpp:10:37:10:42 | Call: call to source | From aa841c306dd0a2ca2e732a29df4883ace4bba4ad Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Tue, 5 Nov 2019 14:48:31 +0100 Subject: [PATCH 0242/2538] C++: Use virtual dispatch in DefaultTaintTracking This bit is only used by the compatibility code that sends flow into parameters of functions without body. --- .../semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll index 0753dfd266e3..e0135e0ad2f0 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/dataflow/DefaultTaintTracking.qll @@ -2,6 +2,7 @@ import cpp import semmle.code.cpp.security.Security private import semmle.code.cpp.ir.dataflow.DataFlow private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.dataflow.internal.DataFlowDispatch as Dispatch /** * A predictable instruction is one where an external user can predict @@ -145,7 +146,8 @@ GlobalOrNamespaceVariable globalVarFromId(string id) { } Function resolveCall(Call call) { - // TODO: improve virtual dispatch. This will help in the test for - // `UncontrolledProcessOperation.ql`. - result = call.getTarget() + exists(CallInstruction callInstruction | + callInstruction.getAST() = call and + result = Dispatch::viableCallable(callInstruction) + ) } From f9feb05a727bf9640636ca89ae68d0fcbacd25cf Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 5 Nov 2019 17:05:38 +0000 Subject: [PATCH 0243/2538] CPP: Add a test of NtohlArrayNoBoundOpenSource.ql. --- .../NtohlArrayNoBound.expected | 8 ++ .../NtohlArrayNoBound/NtohlArrayNoBound.qlref | 1 + .../NtohlArrayNoBound/test.cpp | 100 ++++++++++++++++++ 3 files changed, 109 insertions(+) create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref create mode 100644 cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected new file mode 100644 index 000000000000..6c2fa97858c2 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.expected @@ -0,0 +1,8 @@ +| test.cpp:12:25:12:29 | call to ntohl | Unchecked use of data from network function $@ | test.cpp:12:25:12:29 | call to ntohl | call to ntohl | +| test.cpp:21:26:21:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:31:26:31:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:61:26:61:29 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:64:9:64:12 | len2 | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:73:10:73:13 | lens | Unchecked use of data from network function $@ | test.cpp:10:16:10:20 | call to ntohl | call to ntohl | +| test.cpp:86:10:86:13 | len3 | Unchecked use of data from network function $@ | test.cpp:85:10:85:14 | call to ntohl | call to ntohl | +| test.cpp:94:9:94:11 | len | Unchecked use of data from network function $@ | test.cpp:99:8:99:12 | call to ntohl | call to ntohl | diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref new file mode 100644 index 000000000000..2647a5479f27 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/NtohlArrayNoBound.qlref @@ -0,0 +1 @@ +Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBoundOpenSource.ql \ No newline at end of file diff --git a/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp new file mode 100644 index 000000000000..e3f01f9ae777 --- /dev/null +++ b/cpp/ql/test/query-tests/Likely Bugs/Memory Management/Buffer Overflow/NtohlArrayNoBound/test.cpp @@ -0,0 +1,100 @@ + +typedef unsigned int size_t; +void *memcpy(void *s1, const void *s2, size_t n); +size_t strlen(const char *s); +int ntohl(int x); + +void test1(const char *source, size_t len) +{ + char buffer[256]; + size_t len2 = ntohl(len); + + memcpy(buffer, source, ntohl(len)); // BAD + + if (len2 < 256) + { + memcpy(buffer, source, len2); // GOOD + } + + if (source != 0) + { + memcpy(buffer, source, len2); // BAD + } + + if ((len2 < 256) && (source != 0)) + { + memcpy(buffer, source, len2); // GOOD + } + + if ((len2 < 256) || (source != 0)) + { + memcpy(buffer, source, len2); // BAD + } + + if (len2 < 256) + { + if (source != 0) + { + memcpy(buffer, source, len2); // GOOD + } + } + + if (len2 >= 256) + { + // fail + } else { + memcpy(buffer, source, len2); // GOOD + } + + if (len2 + 1 < 256) + { + memcpy(buffer, source, len2 + 1); // GOOD + } + + if (strlen(source) < 256) + { + memcpy(buffer, source, strlen(source)); // GOOD + } + + if (strlen(source) < 256) + { + memcpy(buffer, source, len2); // BAD + } + + buffer[len2] = 0; // BAD + + if (len2 < 256) + { + buffer[len2] = 0; // GOOD + } + + { + unsigned short lens = len2; + buffer[lens] = 0; // BAD + } + + if (len2 < 256) + { + unsigned short lens = len2; + buffer[lens] = 0; // GOOD + } + + size_t len3 = 0; + if (len3 < 256) + { + len3 = ntohl(len); + buffer[len3] = 0; // BAD + } +} + +void test2(size_t len) +{ + char buffer[256]; + + buffer[len] = 0; // BAD +} + +void test3(size_t len) +{ + test2(ntohl(len)); +} From b6f16dee81a97f6f50d047beb9a90c0e9f9ee1c5 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 6 Nov 2019 15:14:48 +0100 Subject: [PATCH 0244/2538] Python: Fix bad join order in `py/unused-import` --- python/ql/src/Imports/UnusedImport.ql | 59 +++++++++++++++++---------- 1 file changed, 38 insertions(+), 21 deletions(-) diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index 3ac04e2e4d2f..4049f3d5e41a 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -41,41 +41,58 @@ predicate all_not_understood(Module m) { } predicate imported_module_used_in_doctest(Import imp) { - exists(string modname | + exists(string modname, string docstring | imp.getAName().getAsname().(Name).getId() = modname and // Look for doctests containing the patterns: // >>> …name… // ... …name… - exists(StrConst doc | - doc.getEnclosingModule() = imp.getScope() and - doc.isDocString() and - doc.getText().regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.).*" + modname + "[\\s\\S]*") - ) + docstring = doctest_in_scope(imp.getScope()) and + docstring.regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.).*" + modname + "[\\s\\S]*") + ) +} + +pragma[noinline] +private string doctest_in_scope(Scope scope) { + exists(StrConst doc | + doc.getEnclosingModule() = scope and + doc.isDocString() and + result = doc.getText() and + result.regexpMatch("[\\s\\S]*(>>>|\\.\\.\\.)[\\s\\S]*") + ) +} + +pragma[noinline] +private string typehint_annotation_in_file(File file) { + exists(StrConst annotation | + annotation = any(Arguments a).getAnAnnotation() + or + annotation = any(AnnAssign a).getAnnotation() + | + annotation.pointsTo(Value::forString(result)) and + file = annotation.getLocation().getFile() + ) +} + +pragma[noinline] +private string typehint_comment_in_file(File file) { + exists(Comment typehint | + file = typehint.getLocation().getFile() and + result = typehint.getText() and + result.matches("# type:%") ) } predicate imported_module_used_in_typehint(Import imp) { - exists(string modname, Location loc | + exists(string modname, File file | imp.getAName().getAsname().(Name).getId() = modname and - loc.getFile() = imp.getScope().(Module).getFile() + file = imp.getScope().(Module).getFile() | // Look for type hints containing the patterns: // # type: …name… - exists(Comment typehint | - loc = typehint.getLocation() and - typehint.getText().regexpMatch("# type:.*" + modname + ".*") - ) + typehint_comment_in_file(file).regexpMatch("# type:.*" + modname + ".*") or // Type hint is inside a string annotation, as needed for forward references - exists(string typehint, Expr annotation | - annotation = any(Arguments a).getAnAnnotation() - or - annotation = any(AnnAssign a).getAnnotation() - | - annotation.pointsTo(Value::forString(typehint)) and - loc = annotation.getLocation() and - typehint.regexpMatch(".*\\b" + modname + "\\b.*") - ) + typehint_annotation_in_file(file).regexpMatch(".*\\b" + modname + "\\b.*") ) } From 217ecd3551753708e146d46957d4765842adc3b7 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Wed, 6 Nov 2019 15:50:08 +0100 Subject: [PATCH 0245/2538] C++: Add

    tags to split text into paragraphs Without this, the rendered output is one big paragraph. --- .../Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp index 4d5dfabef142..621ae3273fd1 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.qhelp @@ -21,7 +21,9 @@ Solutions to this problem can be thought of as falling into one of two categories: (1) rewrite the signed expression so that overflow cannot occur but the signedness remains, or (2) rewrite (or cast) the signed expression into unsigned form. +

    +

    Below we list examples of expressions where signed overflow may occur, along with proposed solutions. The list should not be considered exhaustive. @@ -31,21 +33,29 @@ considered exhaustive. Given unsigned short i, delta and i + delta < i, it is possible to rewrite it as (unsigned short)(i + delta) < i. Note that i + deltadoes not actually overflow, due to int promotion +

    +

    Given unsigned short i, delta and i + delta < i, it is also possible to rewrite it as USHORT_MAX - delta. It must be true that delta > 0 and the limits.h or climits header has been included. +

    +

    Given int i, delta and i + delta < i, it is possible to rewrite it as INT_MAX - delta. It must be true that delta > 0 and the limits.h or climits header has been included. +

    +

    Given int i, delta and i + delta < i, it is also possible to rewrite it as (unsigned)i + delta < i. Note that program semantics are affected by this change. +

    +

    Given int i, delta and i + delta < i, it is also possible to rewrite it as unsigned int i, delta and i + delta < i. Note that program semantics are From 43148083ebf7ca19832a5017b88f0853f5559ab9 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 6 Nov 2019 16:36:28 +0100 Subject: [PATCH 0246/2538] Python: Fix bad join order for `global_name_used`. As it turns out, there was a further bad join-order in the `global_name_used` predicate. In this case, there was a common subexpression in the RA that was being factored out and evaluated separately, producing a large number of tuples. --- python/ql/src/Imports/UnusedImport.ql | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/python/ql/src/Imports/UnusedImport.ql b/python/ql/src/Imports/UnusedImport.ql index 3ac04e2e4d2f..3d9163f93203 100644 --- a/python/ql/src/Imports/UnusedImport.ql +++ b/python/ql/src/Imports/UnusedImport.ql @@ -13,17 +13,17 @@ import python import Variables.Definition -predicate global_name_used(Module m, Variable name) { +predicate global_name_used(Module m, string name) { exists(Name u, GlobalVariable v | u.uses(v) and - v.getId() = name.getId() and + v.getId() = name and u.getEnclosingModule() = m ) or // A use of an undefined class local variable, will use the global variable exists(Name u, LocalVariable v | u.uses(v) and - v.getId() = name.getId() and + v.getId() = name and u.getEnclosingModule() = m and not v.getScope().getEnclosingScope*() instanceof Function ) @@ -84,7 +84,7 @@ predicate unused_import(Import imp, Variable name) { not imp.getAnImportedModuleName() = "__future__" and not imp.getEnclosingModule().declaredInAll(name.getId()) and imp.getScope() = imp.getEnclosingModule() and - not global_name_used(imp.getScope(), name) and + not global_name_used(imp.getScope(), name.getId()) and // Imports in `__init__.py` are used to force module loading not imp.getEnclosingModule().isPackageInit() and // Name may be imported for use in epytext documentation From 399ac1f11297d24231ee8daab34daafd7618db0f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 15:57:44 +0000 Subject: [PATCH 0247/2538] CPP: Rename 'getAssertedFalseCondition' to something less misleading. --- .../Security/CWE/CWE-457/InitializationFunctions.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 240bd7aa25e3..1c299b9ad517 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -89,9 +89,9 @@ class ParameterNullCheck extends ParameterCheck { ( va = this.(NotExpr).getOperand() or va = any(EQExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or - va = getAssertedFalseCondition(this) or + va = getCheckedFalseCondition(this) or va = any(NEExpr eq | - eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0" + eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0" ).getAnOperand() ) or @@ -101,7 +101,7 @@ class ParameterNullCheck extends ParameterCheck { va = this or va = any(NEExpr eq | eq = this and eq.getAnOperand().getValue() = "0").getAnOperand() or va = any(EQExpr eq | - eq = getAssertedFalseCondition(this) and eq.getAnOperand().getValue() = "0" + eq = getCheckedFalseCondition(this) and eq.getAnOperand().getValue() = "0" ).getAnOperand() ) ) @@ -669,7 +669,7 @@ FieldAccess getAFieldAccess(Variable v) { } /** - * Gets a condition which is asserted to be false by the given `ne` expression, according to this pattern: + * Gets a condition which is checked to be false by the given `ne` expression, according to this pattern: * ``` * int a = !!result; * if (!a) { // <- ne @@ -677,7 +677,7 @@ FieldAccess getAFieldAccess(Variable v) { * } * ``` */ -Expr getAssertedFalseCondition(NotExpr ne) { +private Expr getCheckedFalseCondition(NotExpr ne) { exists(LocalVariable v | result = v.getInitializer().getExpr().(NotExpr).getOperand().(NotExpr).getOperand() and ne.getOperand() = v.getAnAccess() and From 0c3f4e530f62ce1340c022948f5a2a84108e6353 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:07:28 +0000 Subject: [PATCH 0248/2538] CPP: Make some library predicates private. --- .../src/Security/CWE/CWE-457/InitializationFunctions.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 1c299b9ad517..276b6043901e 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -567,7 +567,7 @@ Expr getAnInitializedArgument(Call call) { result = call.getArgument(initialized * the call, under the given context and evidence. */ pragma[nomagic] -int conditionallyInitializedArgument( +private int conditionallyInitializedArgument( Call call, ConditionalInitializationFunction target, Context c, Evidence e ) { target = getTarget(call) and @@ -588,7 +588,7 @@ Expr getAConditionallyInitializedArgument( /** * Gets the type signature for the functions parameters. */ -string typeSig(Function f) { +private string typeSig(Function f) { result = concat(int i, Type pt | pt = f.getParameter(i).getType() | @@ -599,7 +599,7 @@ string typeSig(Function f) { /** * Holds where qualifiedName and typeSig make up the signature for the function. */ -predicate functionSignature(Function f, string qualifiedName, string typeSig) { +private predicate functionSignature(Function f, string qualifiedName, string typeSig) { qualifiedName = f.getQualifiedName() and typeSig = typeSig(f) } @@ -611,7 +611,7 @@ predicate functionSignature(Function f, string qualifiedName, string typeSig) { * This is useful for identifying call to target dependencies across libraries, where the libraries * are never statically linked together. */ -Function getAPossibleDefinition(Function undefinedFunction) { +private Function getAPossibleDefinition(Function undefinedFunction) { not undefinedFunction.isDefined() and exists(string qn, string typeSig | functionSignature(undefinedFunction, qn, typeSig) and functionSignature(result, qn, typeSig) From 81c58d5a64cdda985da83f0395cca56230b9477c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:17:33 +0000 Subject: [PATCH 0249/2538] CPP: Improve QLDoc comments. --- cpp/ql/src/semmle/code/cpp/NestedFields.qll | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/NestedFields.qll b/cpp/ql/src/semmle/code/cpp/NestedFields.qll index 12109be8ece1..c4be8b8b9ffd 100644 --- a/cpp/ql/src/semmle/code/cpp/NestedFields.qll +++ b/cpp/ql/src/semmle/code/cpp/NestedFields.qll @@ -1,9 +1,8 @@ import cpp /** - * Gets a `Field` that is nested within the given `Struct`. - * - * This identifies `Field`s which are located in the same memory + * Gets a `Field` that is within the given `Struct`, either directly or nested + * inside one or more levels of member structs. */ private Field getANestedField(Struct s) { result = s.getAField() @@ -15,7 +14,7 @@ private Field getANestedField(Struct s) { } /** - * Unwraps a series of field accesses to determine the inner-most qualifier. + * Unwraps a series of field accesses to determine the outer-most qualifier. */ private Expr getUltimateQualifier(FieldAccess fa) { exists(Expr qualifier | qualifier = fa.getQualifier() | From 2b24eb2e7083c7c776dd68b59289b8b6ea0ae479 Mon Sep 17 00:00:00 2001 From: Taus Brock-Nannestad Date: Wed, 6 Nov 2019 17:14:05 +0100 Subject: [PATCH 0250/2538] Python: Fix bad join order for `py/multiple-calls-to-init`. The `multiple_invocation_paths` predicate had a bad join order where we (essentially) joined `i1` with `i2` and only then joined `i1` and `i2` separately to reduce the number of tuples. The join coming from `i1 != i2` had little impact, but `i1.getFunction() = multi` made a big difference (and similarly for `i2`). I factored out the code so that these joins would be done more eagerly. Thus, we went from ``` [2019-11-06 16:53:05] (38s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff/4@2ce75a [2019-11-06 16:53:35] (68s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff: 134547 ~9% {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<0>, I.<2> 235284431 ~3% {4} r2 = JOIN r1 WITH CallGraph::TInvocation#fff AS R ON FIRST 1 OUTPUT r1.<0>, r1.<1>, R.<1>, R.<2> 235149884 ~3% {4} r3 = SELECT r2 ON r2.<3> != r2.<1> 235149884 ~4% {3} r4 = SCAN r3 OUTPUT r3.<1>, r3.<0>, r3.<3> 166753634 ~5% {4} r5 = JOIN r4 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus#swapped AS R ON FIRST 1 OUTPUT R.<1>, r4.<2>, r4.<1>, r4.<0> 129778 ~0% {4} r6 = JOIN r5 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus AS R ON FIRST 2 OUTPUT r5.<0>, r5.<3>, r5.<1>, r5.<2> return r6 [2019-11-06 16:53:35] (68s) Registering MethodCallOrder::multiple_invocation_paths#ffff + [] with content 1705dcbc08kd9aa40rp2g2e9civhv [2019-11-06 16:53:35] (68s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff with 129778 rows and 4 columns. ``` to ``` [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths_helper#ffff/4@586aec [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths_helper#ffff: 134547 ~0% {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<2>, I.<0> 88111 ~4% {3} r2 = JOIN r1 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus#swapped AS R ON FIRST 1 OUTPUT R.<1>, r1.<1>, r1.<0> 761305 ~0% {4} r3 = JOIN r2 WITH #CallGraph::FunctionInvocation::getACallee_dispred#ffPlus AS R ON FIRST 1 OUTPUT r2.<1>, r2.<2>, r2.<0>, R.<1> 673194 ~0% {4} r4 = SELECT r3 ON r3.<3> != r3.<1> 673194 ~0% {4} r5 = SCAN r4 OUTPUT r4.<2>, r4.<1>, r4.<3>, r4.<0> return r5 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths_helper#ffff + [] with content 20edaaecf25nldgp24d9c4et8m3kv [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths_helper#ffff with 673194 rows and 4 columns. [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs/4@9e5441 [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs: 673194 ~0% {4} r1 = SCAN MethodCallOrder::multiple_invocation_paths_helper#ffff AS I OUTPUT I.<2>, I.<3>, I.<0>, I.<1> return r1 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs + [] with content 2069301e655fi9mcovngg9hetfqas [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs with 673194 rows and 4 columns. [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff/4@2f7c34 [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff: 134547 ~0% {2} r1 = SCAN CallGraph::TInvocation#fff AS I OUTPUT I.<2>, I.<0> 129778 ~0% {4} r2 = JOIN r1 WITH MethodCallOrder::multiple_invocation_paths_helper#ffff_2301#join_rhs AS R ON FIRST 2 OUTPUT R.<2>, R.<3>, r1.<0>, r1.<1> return r2 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths#ffff + [] with content 1705dcbc08kd9aa40rp2g2e9civhv [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff with 129778 rows and 4 columns. [2019-11-06 17:22:22] (25s) Starting to evaluate predicate MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs/4@9f9146 [2019-11-06 17:22:22] (25s) Tuple counts for MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs: 129778 ~0% {4} r1 = SCAN MethodCallOrder::multiple_invocation_paths#ffff AS I OUTPUT I.<0>, I.<3>, I.<1>, I.<2> return r1 [2019-11-06 17:22:22] (25s) Registering MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs + [] with content 17c3fe1fcbf6ghhdr7hiukqp41rst [2019-11-06 17:22:22] (25s) >>> Wrote relation MethodCallOrder::multiple_invocation_paths#ffff_0312#join_rhs with 129778 rows and 4 columns. ``` Execution time on `salt` went from 29.5s to somewhere below 299ms (the predicate was not listed in the timing report). --- python/ql/src/Classes/MethodCallOrder.qll | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/python/ql/src/Classes/MethodCallOrder.qll b/python/ql/src/Classes/MethodCallOrder.qll index fe6ef07266a7..5073cefc134e 100644 --- a/python/ql/src/Classes/MethodCallOrder.qll +++ b/python/ql/src/Classes/MethodCallOrder.qll @@ -3,11 +3,16 @@ import python // Helper predicates for multiple call to __init__/__del__ queries. pragma [noinline] -private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { +private predicate multiple_invocation_paths_helper(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { i1 != i2 and i1 = top.getACallee+() and i2 = top.getACallee+() and - i1.getFunction() = multi and + i1.getFunction() = multi +} + +pragma [noinline] +private predicate multiple_invocation_paths(FunctionInvocation top, FunctionInvocation i1, FunctionInvocation i2, FunctionObject multi) { + multiple_invocation_paths_helper(top, i1, i2, multi) and i2.getFunction() = multi } From e886cf729773f9e1f86ff35805e596e5f4274d9f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:27:06 +0000 Subject: [PATCH 0251/2538] CPP: 'i.e.' -> 'that is'. --- cpp/ql/src/Microsoft/SAL.qll | 2 +- cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll | 2 +- .../src/semmle/code/cpp/security/boostorg/asio/protocols.qll | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Microsoft/SAL.qll b/cpp/ql/src/Microsoft/SAL.qll index fe6b455fa9be..963a726ae54c 100644 --- a/cpp/ql/src/Microsoft/SAL.qll +++ b/cpp/ql/src/Microsoft/SAL.qll @@ -126,7 +126,7 @@ class SALParameter extends Parameter { } /** - * A SAL element, i.e. a SAL annotation or a declaration entry + * A SAL element, that is, a SAL annotation or a declaration entry * that may have SAL annotations. */ library class SALElement extends Element { diff --git a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll index 2fa9322843e6..a181c9bb5430 100644 --- a/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll +++ b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatch.qll @@ -63,7 +63,7 @@ module VirtualDispatch { /** * Holds if `c` cannot inherit the member function `f`, - * i.e. `c` or one of its supertypes overrides `f`. + * that is, `c` or one of its supertypes overrides `f`. */ private predicate cannotInherit(Class c, MemberFunction f) { exists(Class overridingType, MemberFunction override | diff --git a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll index ae3733473adc..af1a8eaf8e79 100644 --- a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -56,7 +56,8 @@ module BoostorgAsio { } /** - * returns the value for a approved protocols, but that are hard-coded (i.e. no protocol negotiation) + * returns the value for an approved protocol, but that are hard-coded + * (that is, no protocol negotiation) */ EnumConstant getAnApprovedButHardcodedProtocolConstant() { result = this.getATls12ProtocolConstant() From 54e40a8977f50173dbfd0befae900fa5080208af Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 12:19:09 +0000 Subject: [PATCH 0252/2538] JavaScript: Move `--html all` extractor options into `options` file. --- javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html | 2 +- javascript/ql/test/library-tests/HTML/HtmlText/options | 1 + .../frameworks/AngularJS/expressions/scopes/options | 1 + .../frameworks/AngularJS/expressions/scopes/tst.html | 1 - .../frameworks/AngularJS/expressions/sources/HtmlText.html | 1 - .../frameworks/AngularJS/expressions/sources/options | 1 + 6 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/library-tests/HTML/HtmlText/options create mode 100644 javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options create mode 100644 javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options diff --git a/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html b/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html index 6cf4bfc564ff..0b571650c40f 100644 --- a/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html +++ b/javascript/ql/test/library-tests/HTML/HtmlText/HtmlText.html @@ -1,4 +1,4 @@ -// semmle-extractor-options: --html all + (1) as child #0 diff --git a/javascript/ql/test/library-tests/HTML/HtmlText/options b/javascript/ql/test/library-tests/HTML/HtmlText/options new file mode 100644 index 000000000000..46bf01929459 --- /dev/null +++ b/javascript/ql/test/library-tests/HTML/HtmlText/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options new file mode 100644 index 000000000000..46bf01929459 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html index 23449e03c0e2..29608f2da531 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/scopes/tst.html @@ -17,4 +17,3 @@

    -// semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html index 9678f75e0cc3..87bb928ac4c6 100644 --- a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/HtmlText.html @@ -7,4 +7,3 @@
    {{myExpr3}}
    -semmle-extractor-options: --html all diff --git a/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options new file mode 100644 index 000000000000..46bf01929459 --- /dev/null +++ b/javascript/ql/test/library-tests/frameworks/AngularJS/expressions/sources/options @@ -0,0 +1 @@ +semmle-extractor-options: --html all From 6c38f55e28aa4b9ebff51ccddd6a414fa03f45de Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Wed, 6 Nov 2019 16:31:21 +0000 Subject: [PATCH 0253/2538] CPP: QLDoc protocols.qll. --- .../cpp/security/boostorg/asio/protocols.qll | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll index af1a8eaf8e79..73ccd49e2f8e 100644 --- a/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll +++ b/cpp/ql/src/semmle/code/cpp/security/boostorg/asio/protocols.qll @@ -3,7 +3,7 @@ import semmle.code.cpp.dataflow.DataFlow module BoostorgAsio { /** - * Represents boost::asio::ssl::context enum + * Represents the `boost::asio::ssl::context` enum. */ class SslContextMethod extends Enum { SslContextMethod() { @@ -12,7 +12,7 @@ module BoostorgAsio { } /** - * returns the value for a banned protocol + * Gets an enumeration constant for a banned protocol. */ EnumConstant getABannedProtocolConstant() { result = this.getAnEnumConstant() and @@ -56,15 +56,15 @@ module BoostorgAsio { } /** - * returns the value for an approved protocol, but that are hard-coded - * (that is, no protocol negotiation) + * Gets an enumeration constant for an approved protocol, that is hard-coded + * (no protocol negotiation). */ EnumConstant getAnApprovedButHardcodedProtocolConstant() { result = this.getATls12ProtocolConstant() } /** - * returns the value for a TLS v1.2 protocol + * Gets an enumeration constant for a TLS v1.2 protocol. */ EnumConstant getATls12ProtocolConstant() { result = this.getAnEnumConstant() and @@ -81,7 +81,7 @@ module BoostorgAsio { } /** - * returns the value for a TLS v1.3 protocol + * Gets an enumeration constant for a TLS v1.3 protocol. */ EnumConstant getATls13ProtocolConstant() { result = this.getAnEnumConstant() and @@ -98,7 +98,7 @@ module BoostorgAsio { } /** - * returns the value of a generic TLS or SSL/TLS protocol + * Gets an enumeration constant for a generic TLS or SSL/TLS protocol. */ EnumConstant getAGenericTlsProtocolConstant() { result = this.getAnEnumConstant() and @@ -117,7 +117,7 @@ module BoostorgAsio { } /** - * returns the value of a generic SSL/TLS protocol + * Gets an enumeration constant for a generic SSL/TLS protocol. */ EnumConstant getASslv23ProtocolConstant() { result = this.getAnEnumConstant() and @@ -136,7 +136,9 @@ module BoostorgAsio { } /** - * NOTE: ignore - Modern versions of OpenSSL do not support SSL v2 anymore, so this option is for backwards compatibility only + * Gets the value for the no_sslv2 constant, right shifted by 16 bits. + * + * Note that modern versions of OpelSSL do not support SSL v2, so this option is for backwards compatibility only. */ int getShiftedSslOptionsNoSsl2() { // SSL_OP_NO_SSLv2 was removed from modern OpenSSL versions @@ -144,7 +146,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_sslv3 constant + * Gets the value for the no_sslv3 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoSsl3() { // SSL_OP_NO_SSLv3 == 0x02000000U @@ -152,7 +154,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1 constant + * Gets the value for the no_tlsv1 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1() { // SSL_OP_NO_TLSv1 == 0x04000000U @@ -160,7 +162,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_1 constant + * Gets the value for the no_tlsv1_1 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_1() { // SSL_OP_NO_TLSv1_1 == 0x10000000U @@ -168,7 +170,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_2 constant + * Gets the value for the no_tlsv1_2 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_2() { // SSL_OP_NO_TLSv1_2 == 0x08000000U @@ -176,7 +178,7 @@ module BoostorgAsio { } /** - * RightShift(16) value for no_tlsv1_3 constant + * Gets the value for the no_tlsv1_3 constant, right shifted by 16 bits. */ int getShiftedSslOptionsNoTls1_3() { // SSL_OP_NO_TLSv1_2 == 0x20000000U @@ -184,7 +186,7 @@ module BoostorgAsio { } /** - * Represents boost::asio::ssl::context class + * Represents the `boost::asio::ssl::context` class. */ class SslContextClass extends Class { SslContextClass() { this.getQualifiedName() = "boost::asio::ssl::context" } @@ -197,7 +199,7 @@ module BoostorgAsio { } /** - * Represents boost::asio::ssl::context::set_options member function + * Represents `boost::asio::ssl::context::set_options` member function. */ class SslSetOptionsFunction extends Function { SslSetOptionsFunction() { @@ -206,7 +208,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a banned protocol + * Holds if the expression represents a banned protocol. */ predicate isExprBannedBoostProtocol(Expr e) { exists(Literal va | va = e | @@ -245,7 +247,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a TLS v1.2 protocol + * Holds if the expression represents a TLS v1.2 protocol. */ predicate isExprTls12BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -270,7 +272,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a protocol that requires Crypto Board approval + * Holds if the expression represents a protocol that requires Crypto Board approval. */ predicate isExprTls13BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -295,7 +297,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a generic TLS or SSL/TLS protocol + * Holds if the expression represents a generic TLS or SSL/TLS protocol. */ predicate isExprTlsBoostProtocol(Expr e) { exists(Literal va | va = e | @@ -326,7 +328,7 @@ module BoostorgAsio { } /** - * holds if the expression represents a generic SSl/TLS protocol + * Holds if the expression represents a generic SSl/TLS protocol. */ predicate isExprSslV23BoostProtocol(Expr e) { exists(Literal va | va = e | @@ -352,7 +354,8 @@ module BoostorgAsio { //////////////////////// Dataflow ///////////////////// /** - * Abstract - Protocol value Flows to the first argument of the context constructor + * Abstract class for flows of protocol values to the first argument of a context + * constructor. */ abstract class SslContextCallAbstractConfig extends DataFlow::Configuration { bindingset[this] @@ -367,7 +370,7 @@ module BoostorgAsio { } /** - * any Protocol value Flows to the first argument of the context constructor + * Any protocol value that flows to the first argument of a context constructor. */ class SslContextCallConfig extends SslContextCallAbstractConfig { SslContextCallConfig() { this = "SslContextCallConfig" } @@ -381,7 +384,7 @@ module BoostorgAsio { } /** - * a banned protocol value Flows to the first argument of the context constructor + * A banned protocol value that flows to the first argument of a context constructor. */ class SslContextCallBannedProtocolConfig extends SslContextCallAbstractConfig { SslContextCallBannedProtocolConfig() { this = "SslContextCallBannedProtocolConfig" } @@ -396,7 +399,7 @@ module BoostorgAsio { } /** - * a TLS 1.2 protocol value Flows to the first argument of the context constructor + * A TLS 1.2 protocol value that flows to the first argument of a context constructor. */ class SslContextCallTls12ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls12ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } @@ -411,7 +414,7 @@ module BoostorgAsio { } /** - * a TLS 1.3 protocol value Flows to the first argument of the context constructor + * A TLS 1.3 protocol value that flows to the first argument of a context constructor. */ class SslContextCallTls13ProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTls13ProtocolConfig() { this = "SslContextCallTls12ProtocolConfig" } @@ -426,7 +429,7 @@ module BoostorgAsio { } /** - * a generic TLS protocol value Flows to the first argument of the context constructor + * A generic TLS protocol value that flows to the first argument of a context constructor. */ class SslContextCallTlsProtocolConfig extends SslContextCallAbstractConfig { SslContextCallTlsProtocolConfig() { this = "SslContextCallTlsProtocolConfig" } @@ -441,7 +444,7 @@ module BoostorgAsio { } /** - * a context constructor call flows to a call calling SetOptions() + * A context constructor call that flows to a call to `SetOptions()`. */ class SslContextFlowsToSetOptionConfig extends DataFlow::Configuration { SslContextFlowsToSetOptionConfig() { this = "SslContextFlowsToSetOptionConfig" } @@ -465,7 +468,7 @@ module BoostorgAsio { } /** - * an option value flows to the 1st parameter of SetOptions() + * An option value that flows to the first parameter of a call to `SetOptions()`. */ class SslOptionConfig extends DataFlow::Configuration { SslOptionConfig() { this = "SslOptionConfig" } From 7850d67a782db5160f22122a4b36fc3645635c98 Mon Sep 17 00:00:00 2001 From: Robin Neatherway Date: Wed, 6 Nov 2019 17:47:02 +0000 Subject: [PATCH 0254/2538] Remove TODO comment I've checked Hamcrest versions 1.3, 2.0, 2.1 and 2.2 --- java/ql/src/semmle/code/java/frameworks/Assertions.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/src/semmle/code/java/frameworks/Assertions.qll b/java/ql/src/semmle/code/java/frameworks/Assertions.qll index aac514a26bd4..eb210d5e0d71 100644 --- a/java/ql/src/semmle/code/java/frameworks/Assertions.qll +++ b/java/ql/src/semmle/code/java/frameworks/Assertions.qll @@ -30,7 +30,7 @@ private predicate assertionMethod(Method m, AssertKind kind) { or exists(RefType hamcrest | m.getDeclaringType() = hamcrest and - hamcrest.hasQualifiedName("org.hamcrest", "MatcherAssert") // TODO: Check some older versions of hamcrest + hamcrest.hasQualifiedName("org.hamcrest", "MatcherAssert") | m.hasName("assertThat") and kind = AssertKindThat() ) From a9e3bfbd11476210ff72c95f15866b7f745bae8e Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Wed, 6 Nov 2019 13:08:28 -0700 Subject: [PATCH 0255/2538] C++/C#: Treat string literals like read-only global variables for alias purposes. Previously, we didn't track string literals as known memory locations at all, so they all just got marked as `UnknownMemoryLocation`, just like an aribtrary read from a random pointer. This led to some confusing def-use chains, where it would look like the contents of a string literal were being written to by the side effect of an earlier function call, which of course is impossible. To fix this, I've made two changes. First, each string literal is now given a corresponding `IRVariable` (specifically `IRStringLiteral`), since a string literal behaves more or less as a read-only global variable. Second, the `IRVariable` for each string literal is now marked `isReadOnly()`, which the alias analysis uses to determine that an arbitrary write to aliased memory will not overwrite the contents of a string literal. I originally planned to treat all string literals with the same value as being the same memory location, since this is the usual behavior of modern compilers. However, this made implementing `IRVariable.getAST()` tricky for string literals, so I left them unpooled. --- .../implementation/aliased_ssa/IRVariable.qll | 57 ++++++++++++++----- .../aliased_ssa/Instruction.qll | 10 ++-- .../aliased_ssa/internal/AliasAnalysis.qll | 4 ++ .../aliased_ssa/internal/AliasedSSA.qll | 12 ++-- .../aliased_ssa/internal/SSAConstruction.qll | 5 -- .../implementation/internal/TIRVariable.qll | 6 ++ .../cpp/ir/implementation/raw/IRVariable.qll | 57 ++++++++++++++----- .../cpp/ir/implementation/raw/Instruction.qll | 10 ++-- .../raw/internal/IRConstruction.qll | 23 +++++--- .../unaliased_ssa/IRVariable.qll | 57 ++++++++++++++----- .../unaliased_ssa/Instruction.qll | 10 ++-- .../unaliased_ssa/internal/AliasAnalysis.qll | 4 ++ .../internal/SSAConstruction.qll | 5 -- .../ir/ssa/aliased_ssa_ir.expected | 26 +++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 8 +++ .../ir/ssa/unaliased_ssa_ir.expected | 25 ++++++++ .../implementation/internal/TIRVariable.qll | 6 ++ .../ir/implementation/raw/IRVariable.qll | 57 ++++++++++++++----- .../ir/implementation/raw/Instruction.qll | 10 ++-- .../raw/internal/IRConstruction.qll | 25 +++++--- .../unaliased_ssa/IRVariable.qll | 57 ++++++++++++++----- .../unaliased_ssa/Instruction.qll | 10 ++-- .../internal/SSAConstruction.qll | 5 -- 23 files changed, 359 insertions(+), 130 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll index 1a607f82c29f..e10e266b2ab3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll index 049983c9126f..9f7cf68b0657 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b367..0923ec8f9949 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll @@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getIRVariable() = var and bitOffset = 0 or + // A string literal is just a special read-only global variable. + instr.(StringConstantInstruction).getIRVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll index 955d422cf9a4..0835ffb7da63 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasedSSA.qll @@ -210,17 +210,21 @@ Overlap getOverlap(MemoryLocation def, MemoryLocation use) { def instanceof UnknownVirtualVariable and result instanceof MustTotallyOverlap or - // An UnknownMemoryLocation may partially overlap any Location within the same virtual variable. + // An UnknownMemoryLocation may partially overlap any Location within the same virtual variable, + // unless the location is read-only. def.getVirtualVariable() = use.getVirtualVariable() and def instanceof UnknownMemoryLocation and - result instanceof MayPartiallyOverlap + result instanceof MayPartiallyOverlap and + not use.(VariableMemoryLocation).getVariable().isReadOnly() or // An UnknownNonLocalMemoryLocation may partially overlap any location within the same virtual - // variable, except a local variable. + // variable, except a local variable or read-only variable. def.getVirtualVariable() = use.getVirtualVariable() and def instanceof UnknownNonLocalMemoryLocation and result instanceof MayPartiallyOverlap and - not use.(VariableMemoryLocation).getVariable() instanceof IRAutomaticVariable + not exists(IRVariable var | var = use.(VariableMemoryLocation).getVariable() | + var instanceof IRAutomaticVariable or var.isReadOnly() + ) or exists(VariableMemoryLocation defVariableLocation | defVariableLocation = def and diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a7..c83620982951 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll index fea67ef5ecd1..01c135abf138 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/internal/TIRVariable.qll @@ -9,4 +9,10 @@ newtype TIRVariable = Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) + } or + TIRStringLiteral( + Language::Function func, Language::AST ast, Language::LanguageType type, + Language::StringLiteral literal + ) { + Construction::hasStringLiteral(func, ast, type, literal) } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll index 1a607f82c29f..e10e266b2ab3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll index 049983c9126f..9f7cf68b0657 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll index fbf6b7e3d08d..fe161e5196a1 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/IRConstruction.qll @@ -44,6 +44,13 @@ private module Cached { ) } + cached + predicate hasStringLiteral(Function func, Locatable ast, CppType type, StringLiteral literal) { + literal = ast and + literal.getEnclosingFunction() = func and + getTypeForPRValue(literal.getType()) = type + } + cached predicate hasModeledMemoryResult(Instruction instruction) { none() } @@ -231,8 +238,14 @@ private module Cached { cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionVariable(getInstructionTag(instruction)) + exists(TranslatedElement element, InstructionTag tag | + element = getInstructionTranslatedElement(instruction) and + tag = getInstructionTag(instruction) and + ( + result = element.getInstructionVariable(tag) or + result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) + ) + ) } cached @@ -263,12 +276,6 @@ private module Cached { ) } - cached - StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionStringLiteral(getInstructionTag(instruction)) - } - cached BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getInstructionTranslatedElement(instruction) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll index 1a607f82c29f..e10e266b2ab3 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll index 049983c9126f..9f7cf68b0657 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll index b9aa07c1b367..0923ec8f9949 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll @@ -308,6 +308,10 @@ predicate resultPointsTo(Instruction instr, IRVariable var, IntValue bitOffset) instr.(VariableAddressInstruction).getIRVariable() = var and bitOffset = 0 or + // A string literal is just a special read-only global variable. + instr.(StringConstantInstruction).getIRVariable() = var and + bitOffset = 0 + or exists(Operand operand, IntValue originalBitOffset, IntValue propagatedBitOffset | operand = instr.getAnOperand() and // If an operand is propagated, then the result points to the same variable, diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a7..c83620982951 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 98786207c45b..07faf581d3e7 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -869,3 +869,29 @@ ssa.cpp: # 207| v0_25(void) = UnmodeledUse : mu* # 207| v0_26(void) = AliasedUse : ~m0_1 # 207| v0_27(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| m0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| m0_5(unknown) = ^CallSideEffect : ~m0_1 +# 216| m0_6(unknown) = Chi : total:m0_1, partial:m0_5 +# 218| r0_7(glval) = VariableAddress[s] : +# 218| r0_8(glval) = StringConstant["Literal"] : +# 218| r0_9(char *) = Convert : r0_8 +# 218| m0_10(char *) = Store : &:r0_7, r0_9 +# 219| r0_11(glval) = VariableAddress[#return] : +# 219| r0_12(glval) = VariableAddress[s] : +# 219| r0_13(char *) = Load : &:r0_12, m0_10 +# 219| r0_14(int) = Constant[2] : +# 219| r0_15(glval) = PointerAdd[1] : r0_13, r0_14 +# 219| r0_16(char) = Load : &:r0_15, ~m0_1 +# 219| m0_17(char) = Store : &:r0_11, r0_16 +# 215| r0_18(glval) = VariableAddress[#return] : +# 215| v0_19(void) = ReturnValue : &:r0_18, m0_17 +# 215| v0_20(void) = UnmodeledUse : mu* +# 215| v0_21(void) = AliasedUse : ~m0_6 +# 215| v0_22(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 4dfb0a2f6cdf..8ce2b8900d89 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -210,3 +210,11 @@ int ModeledCallTarget(int x) { return y; } +extern void ExternalFunc(); + +char StringLiteralAliasing() { + ExternalFunc(); + + const char* s = "Literal"; + return s[2]; // Should be defined by `AliasedDefinition`, not `Chi` or `CallSideEffect`. +} diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 5ac06cadb55c..03cf52c2ad6e 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -833,3 +833,28 @@ ssa.cpp: # 207| v0_22(void) = UnmodeledUse : mu* # 207| v0_23(void) = AliasedUse : ~mu0_2 # 207| v0_24(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| mu0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| mu0_5(unknown) = ^CallSideEffect : ~mu0_2 +# 218| r0_6(glval) = VariableAddress[s] : +# 218| r0_7(glval) = StringConstant["Literal"] : +# 218| r0_8(char *) = Convert : r0_7 +# 218| m0_9(char *) = Store : &:r0_6, r0_8 +# 219| r0_10(glval) = VariableAddress[#return] : +# 219| r0_11(glval) = VariableAddress[s] : +# 219| r0_12(char *) = Load : &:r0_11, m0_9 +# 219| r0_13(int) = Constant[2] : +# 219| r0_14(glval) = PointerAdd[1] : r0_12, r0_13 +# 219| r0_15(char) = Load : &:r0_14, ~mu0_2 +# 219| m0_16(char) = Store : &:r0_10, r0_15 +# 215| r0_17(glval) = VariableAddress[#return] : +# 215| v0_18(void) = ReturnValue : &:r0_17, m0_16 +# 215| v0_19(void) = UnmodeledUse : mu* +# 215| v0_20(void) = AliasedUse : ~mu0_2 +# 215| v0_21(void) = ExitFunction : diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll index fea67ef5ecd1..01c135abf138 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/internal/TIRVariable.qll @@ -9,4 +9,10 @@ newtype TIRVariable = Language::Function func, Language::AST ast, TempVariableTag tag, Language::LanguageType type ) { Construction::hasTempVariable(func, ast, tag, type) + } or + TIRStringLiteral( + Language::Function func, Language::AST ast, Language::LanguageType type, + Language::StringLiteral literal + ) { + Construction::hasStringLiteral(func, ast, type, literal) } diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll index 1a607f82c29f..e10e266b2ab3 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll index 049983c9126f..9f7cf68b0657 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll index 0d2627e183f1..72881a7c7208 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/raw/internal/IRConstruction.qll @@ -52,6 +52,15 @@ private module Cached { ) } + cached + predicate hasStringLiteral( + Callable callable, Language::AST ast, CSharpType type, StringLiteral literal + ) { + literal = ast and + literal.getEnclosingCallable() = callable and + getTypeForPRValue(literal.getType()) = type + } + cached predicate hasModeledMemoryResult(Instruction instruction) { none() } @@ -232,8 +241,14 @@ private module Cached { cached IRVariable getInstructionVariable(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionVariable(getInstructionTag(instruction)) + exists(TranslatedElement element, InstructionTag tag | + element = getInstructionTranslatedElement(instruction) and + tag = getInstructionTag(instruction) and + ( + result = element.getInstructionVariable(tag) or + result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag) + ) + ) } cached @@ -265,12 +280,6 @@ private module Cached { .getInstructionConstantValue(getInstructionTag(instruction)) } - cached - StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getInstructionTranslatedElement(instruction) - .getInstructionStringLiteral(getInstructionTag(instruction)) - } - cached CSharpType getInstructionExceptionType(Instruction instruction) { result = getInstructionTranslatedElement(instruction) diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll index 1a607f82c29f..e10e266b2ab3 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/IRVariable.qll @@ -22,6 +22,12 @@ abstract class IRVariable extends TIRVariable { abstract string toString(); + /** + * Holds if this variable's value cannot be changed within a function. Currently used for string + * literals, but could also apply to `const` global and static variables. + */ + predicate isReadOnly() { none() } + /** * Gets the type of the variable. */ @@ -113,34 +119,43 @@ class IRStaticUserVariable extends IRUserVariable { final override Language::StaticVariable getVariable() { result = var } } +abstract class IRGeneratedVariable extends IRVariable { + Language::AST ast; + Language::LanguageType type; + + final override Language::LanguageType getLanguageType() { result = type } + + final override Language::AST getAST() { result = ast } + + override string toString() { result = getBaseString() + getLocationString() } + + override string getUniqueId() { none() } + + final string getLocationString() { + result = ast.getLocation().getStartLine().toString() + ":" + + ast.getLocation().getStartColumn().toString() + } + + string getBaseString() { none() } +} + IRTempVariable getIRTempVariable(Language::AST ast, TempVariableTag tag) { result.getAST() = ast and result.getTag() = tag } -class IRTempVariable extends IRVariable, IRAutomaticVariable, TIRTempVariable { - Language::AST ast; +class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable { TempVariableTag tag; - Language::LanguageType type; IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) } - final override Language::LanguageType getLanguageType() { result = type } - - final override Language::AST getAST() { result = ast } - final override string getUniqueId() { result = "Temp: " + Construction::getTempVariableUniqueId(this) } final TempVariableTag getTag() { result = tag } - override string toString() { - result = getBaseString() + ast.getLocation().getStartLine().toString() + ":" + - ast.getLocation().getStartColumn().toString() - } - - string getBaseString() { result = "#temp" } + override string getBaseString() { result = "#temp" } } class IRReturnVariable extends IRTempVariable { @@ -154,3 +169,19 @@ class IRThrowVariable extends IRTempVariable { override string getBaseString() { result = "#throw" } } + +class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral { + Language::StringLiteral literal; + + IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) } + + final override predicate isReadOnly() { any() } + + final override string getUniqueId() { + result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal) + } + + override string getBaseString() { result = "#string" } + + final Language::StringLiteral getLiteral() { result = literal } +} diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll index 049983c9126f..9f7cf68b0657 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/Instruction.qll @@ -808,14 +808,12 @@ class FloatConstantInstruction extends ConstantInstruction { FloatConstantInstruction() { getResultType() instanceof Language::FloatingPointType } } -class StringConstantInstruction extends Instruction { - Language::StringLiteral value; +class StringConstantInstruction extends VariableInstruction { + override IRStringLiteral var; - StringConstantInstruction() { value = Construction::getInstructionStringLiteral(this) } + final override string getImmediateString() { result = Language::getStringLiteralText(getValue()) } - final override string getImmediateString() { result = Language::getStringLiteralText(value) } - - final Language::StringLiteral getValue() { result = value } + final Language::StringLiteral getValue() { result = var.getLiteral() } } class BinaryInstruction extends Instruction { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll index 7152dec5c4a7..c83620982951 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll @@ -341,11 +341,6 @@ private module Cached { result = getOldInstruction(instruction).(OldIR::ConstantValueInstruction).getValue() } - cached - Language::StringLiteral getInstructionStringLiteral(Instruction instruction) { - result = getOldInstruction(instruction).(OldIR::StringConstantInstruction).getValue() - } - cached Language::BuiltInOperation getInstructionBuiltInOperation(Instruction instruction) { result = getOldInstruction(instruction) From 51c4ef4f7f20f22d45dd90f48f24957c2d885008 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 6 Nov 2019 13:32:35 -0800 Subject: [PATCH 0256/2538] C++: add SSA IR test for array initializers --- .../ir/ssa/aliased_ssa_ir.expected | 71 +++++++++++++++++++ cpp/ql/test/library-tests/ir/ssa/ssa.cpp | 10 +++ .../ir/ssa/unaliased_ssa_ir.expected | 65 +++++++++++++++++ 3 files changed, 146 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 98786207c45b..7345c6a52041 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -869,3 +869,74 @@ ssa.cpp: # 207| v0_25(void) = UnmodeledUse : mu* # 207| v0_26(void) = AliasedUse : ~m0_1 # 207| v0_27(void) = ExitFunction : + +# 213| void InitArray() +# 213| Block 0 +# 213| v0_0(void) = EnterFunction : +# 213| m0_1(unknown) = AliasedDefinition : +# 213| mu0_2(unknown) = UnmodeledDefinition : +# 214| r0_3(glval) = VariableAddress[a_pad] : +# 214| r0_4(glval) = StringConstant[""] : +# 214| r0_5(char[1]) = Load : &:r0_4, ~m0_1 +# 214| m0_6(char[1]) = Store : &:r0_3, r0_5 +# 214| r0_7(unknown[31]) = Constant[0] : +# 214| r0_8(int) = Constant[1] : +# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 +# 214| m0_10(unknown[31]) = Store : &:r0_9, r0_7 +# 215| r0_11(glval) = VariableAddress[a_nopad] : +# 215| r0_12(glval) = StringConstant["foo"] : +# 215| r0_13(char[4]) = Load : &:r0_12, ~m0_1 +# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 +# 216| r0_15(glval) = VariableAddress[a_infer] : +# 216| r0_16(glval) = StringConstant["blah"] : +# 216| r0_17(char[5]) = Load : &:r0_16, ~m0_1 +# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 +# 217| r0_19(glval) = VariableAddress[b] : +# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 +# 218| r0_21(glval) = VariableAddress[c] : +# 218| m0_22(char[2]) = Uninitialized[c] : &:r0_21 +# 218| r0_23(int) = Constant[0] : +# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 +# 218| r0_25(unknown[2]) = Constant[0] : +# 218| m0_26(unknown[2]) = Store : &:r0_24, r0_25 +# 219| r0_27(glval) = VariableAddress[d] : +# 219| m0_28(char[2]) = Uninitialized[d] : &:r0_27 +# 219| r0_29(int) = Constant[0] : +# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 +# 219| r0_31(char) = Constant[0] : +# 219| m0_32(char) = Store : &:r0_30, r0_31 +# 219| m0_33(char[2]) = Chi : total:m0_28, partial:m0_32 +# 219| r0_34(int) = Constant[1] : +# 219| r0_35(glval) = PointerAdd[1] : r0_27, r0_34 +# 219| r0_36(char) = Constant[0] : +# 219| m0_37(char) = Store : &:r0_35, r0_36 +# 219| m0_38(char[2]) = Chi : total:m0_33, partial:m0_37 +# 220| r0_39(glval) = VariableAddress[e] : +# 220| m0_40(char[2]) = Uninitialized[e] : &:r0_39 +# 220| r0_41(int) = Constant[0] : +# 220| r0_42(glval) = PointerAdd[1] : r0_39, r0_41 +# 220| r0_43(char) = Constant[0] : +# 220| m0_44(char) = Store : &:r0_42, r0_43 +# 220| m0_45(char[2]) = Chi : total:m0_40, partial:m0_44 +# 220| r0_46(int) = Constant[1] : +# 220| r0_47(glval) = PointerAdd[1] : r0_39, r0_46 +# 220| r0_48(char) = Constant[1] : +# 220| m0_49(char) = Store : &:r0_47, r0_48 +# 220| m0_50(char[2]) = Chi : total:m0_45, partial:m0_49 +# 221| r0_51(glval) = VariableAddress[f] : +# 221| m0_52(char[3]) = Uninitialized[f] : &:r0_51 +# 221| r0_53(int) = Constant[0] : +# 221| r0_54(glval) = PointerAdd[1] : r0_51, r0_53 +# 221| r0_55(char) = Constant[0] : +# 221| m0_56(char) = Store : &:r0_54, r0_55 +# 221| m0_57(char[3]) = Chi : total:m0_52, partial:m0_56 +# 221| r0_58(int) = Constant[1] : +# 221| r0_59(glval) = PointerAdd[1] : r0_51, r0_58 +# 221| r0_60(unknown[2]) = Constant[0] : +# 221| m0_61(unknown[2]) = Store : &:r0_59, r0_60 +# 221| m0_62(char[3]) = Chi : total:m0_57, partial:m0_61 +# 222| v0_63(void) = NoOp : +# 213| v0_64(void) = ReturnVoid : +# 213| v0_65(void) = UnmodeledUse : mu* +# 213| v0_66(void) = AliasedUse : ~m0_1 +# 213| v0_67(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp index 4dfb0a2f6cdf..a38c66dcaf88 100644 --- a/cpp/ql/test/library-tests/ir/ssa/ssa.cpp +++ b/cpp/ql/test/library-tests/ir/ssa/ssa.cpp @@ -210,3 +210,13 @@ int ModeledCallTarget(int x) { return y; } +void InitArray() { + char a_pad[32] = ""; + char a_nopad[4] = "foo"; + char a_infer[] = "blah"; + char b[2]; + char c[2] = {}; + char d[2] = { 0 }; + char e[2] = { 0, 1 }; + char f[3] = { 0 }; +} \ No newline at end of file diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 5ac06cadb55c..056b0cd5ac7e 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -833,3 +833,68 @@ ssa.cpp: # 207| v0_22(void) = UnmodeledUse : mu* # 207| v0_23(void) = AliasedUse : ~mu0_2 # 207| v0_24(void) = ExitFunction : + +# 213| void InitArray() +# 213| Block 0 +# 213| v0_0(void) = EnterFunction : +# 213| mu0_1(unknown) = AliasedDefinition : +# 213| mu0_2(unknown) = UnmodeledDefinition : +# 214| r0_3(glval) = VariableAddress[a_pad] : +# 214| r0_4(glval) = StringConstant[""] : +# 214| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 +# 214| mu0_6(char[1]) = Store : &:r0_3, r0_5 +# 214| r0_7(unknown[31]) = Constant[0] : +# 214| r0_8(int) = Constant[1] : +# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 +# 214| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 +# 215| r0_11(glval) = VariableAddress[a_nopad] : +# 215| r0_12(glval) = StringConstant["foo"] : +# 215| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 +# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 +# 216| r0_15(glval) = VariableAddress[a_infer] : +# 216| r0_16(glval) = StringConstant["blah"] : +# 216| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 +# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 +# 217| r0_19(glval) = VariableAddress[b] : +# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 +# 218| r0_21(glval) = VariableAddress[c] : +# 218| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 +# 218| r0_23(int) = Constant[0] : +# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 +# 218| r0_25(unknown[2]) = Constant[0] : +# 218| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 +# 219| r0_27(glval) = VariableAddress[d] : +# 219| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 +# 219| r0_29(int) = Constant[0] : +# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 +# 219| r0_31(char) = Constant[0] : +# 219| mu0_32(char) = Store : &:r0_30, r0_31 +# 219| r0_33(int) = Constant[1] : +# 219| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 +# 219| r0_35(char) = Constant[0] : +# 219| mu0_36(char) = Store : &:r0_34, r0_35 +# 220| r0_37(glval) = VariableAddress[e] : +# 220| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 +# 220| r0_39(int) = Constant[0] : +# 220| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 +# 220| r0_41(char) = Constant[0] : +# 220| mu0_42(char) = Store : &:r0_40, r0_41 +# 220| r0_43(int) = Constant[1] : +# 220| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 +# 220| r0_45(char) = Constant[1] : +# 220| mu0_46(char) = Store : &:r0_44, r0_45 +# 221| r0_47(glval) = VariableAddress[f] : +# 221| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 +# 221| r0_49(int) = Constant[0] : +# 221| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 +# 221| r0_51(char) = Constant[0] : +# 221| mu0_52(char) = Store : &:r0_50, r0_51 +# 221| r0_53(int) = Constant[1] : +# 221| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 +# 221| r0_55(unknown[2]) = Constant[0] : +# 221| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 +# 222| v0_57(void) = NoOp : +# 213| v0_58(void) = ReturnVoid : +# 213| v0_59(void) = UnmodeledUse : mu* +# 213| v0_60(void) = AliasedUse : ~mu0_2 +# 213| v0_61(void) = ExitFunction : From 81ad11090ed4291a1671f40b7be8cb32d258bb24 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Wed, 6 Nov 2019 10:54:43 -0800 Subject: [PATCH 0257/2538] C++: uninit instr for string literal initializers --- .../internal/TranslatedDeclarationEntry.qll | 3 +- .../test/library-tests/ir/ir/raw_ir.expected | 119 ++++++++--------- .../ir/ssa/aliased_ssa_ir.expected | 121 +++++++++--------- .../ir/ssa/unaliased_ssa_ir.expected | 119 ++++++++--------- 4 files changed, 187 insertions(+), 175 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index 294a539ec311..c3572bd0e794 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -120,7 +120,8 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali private predicate hasUninitializedInstruction() { not exists(getInitialization()) or - getInitialization() instanceof TranslatedListInitialization + getInitialization() instanceof TranslatedListInitialization or + getInitialization() instanceof TranslatedStringLiteralInitialization } } diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index 90c3061114ef..b4480e1c580b 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2666,64 +2666,67 @@ ir.cpp: # 571| mu0_1(unknown) = AliasedDefinition : # 571| mu0_2(unknown) = UnmodeledDefinition : # 572| r0_3(glval) = VariableAddress[a_pad] : -# 572| r0_4(glval) = StringConstant[""] : -# 572| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 -# 572| mu0_6(char[1]) = Store : &:r0_3, r0_5 -# 572| r0_7(unknown[31]) = Constant[0] : -# 572| r0_8(int) = Constant[1] : -# 572| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 572| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 573| r0_11(glval) = VariableAddress[a_nopad] : -# 573| r0_12(glval) = StringConstant["foo"] : -# 573| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 -# 573| mu0_14(char[4]) = Store : &:r0_11, r0_13 -# 574| r0_15(glval) = VariableAddress[a_infer] : -# 574| r0_16(glval) = StringConstant["blah"] : -# 574| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 -# 574| mu0_18(char[5]) = Store : &:r0_15, r0_17 -# 575| r0_19(glval) = VariableAddress[b] : -# 575| mu0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 576| r0_21(glval) = VariableAddress[c] : -# 576| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 576| r0_23(int) = Constant[0] : -# 576| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 576| r0_25(unknown[2]) = Constant[0] : -# 576| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 577| r0_27(glval) = VariableAddress[d] : -# 577| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 577| r0_29(int) = Constant[0] : -# 577| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 577| r0_31(char) = Constant[0] : -# 577| mu0_32(char) = Store : &:r0_30, r0_31 -# 577| r0_33(int) = Constant[1] : -# 577| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 -# 577| r0_35(char) = Constant[0] : -# 577| mu0_36(char) = Store : &:r0_34, r0_35 -# 578| r0_37(glval) = VariableAddress[e] : -# 578| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 -# 578| r0_39(int) = Constant[0] : -# 578| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 -# 578| r0_41(char) = Constant[0] : -# 578| mu0_42(char) = Store : &:r0_40, r0_41 -# 578| r0_43(int) = Constant[1] : -# 578| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 -# 578| r0_45(char) = Constant[1] : -# 578| mu0_46(char) = Store : &:r0_44, r0_45 -# 579| r0_47(glval) = VariableAddress[f] : -# 579| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 -# 579| r0_49(int) = Constant[0] : -# 579| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 -# 579| r0_51(char) = Constant[0] : -# 579| mu0_52(char) = Store : &:r0_50, r0_51 -# 579| r0_53(int) = Constant[1] : -# 579| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 -# 579| r0_55(unknown[2]) = Constant[0] : -# 579| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 -# 580| v0_57(void) = NoOp : -# 571| v0_58(void) = ReturnVoid : -# 571| v0_59(void) = UnmodeledUse : mu* -# 571| v0_60(void) = AliasedUse : ~mu0_2 -# 571| v0_61(void) = ExitFunction : +# 572| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 572| r0_5(glval) = StringConstant[""] : +# 572| r0_6(char[1]) = Load : &:r0_5, ~mu0_2 +# 572| mu0_7(char[1]) = Store : &:r0_3, r0_6 +# 572| r0_8(unknown[31]) = Constant[0] : +# 572| r0_9(int) = Constant[1] : +# 572| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 +# 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 +# 573| r0_12(glval) = VariableAddress[a_nopad] : +# 573| mu0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 +# 573| r0_14(glval) = StringConstant["foo"] : +# 573| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 +# 573| mu0_16(char[4]) = Store : &:r0_12, r0_15 +# 574| r0_17(glval) = VariableAddress[a_infer] : +# 574| mu0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 +# 574| r0_19(glval) = StringConstant["blah"] : +# 574| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 +# 574| mu0_21(char[5]) = Store : &:r0_17, r0_20 +# 575| r0_22(glval) = VariableAddress[b] : +# 575| mu0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 576| r0_24(glval) = VariableAddress[c] : +# 576| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 576| r0_26(int) = Constant[0] : +# 576| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 +# 576| r0_28(unknown[2]) = Constant[0] : +# 576| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 +# 577| r0_30(glval) = VariableAddress[d] : +# 577| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 577| r0_32(int) = Constant[0] : +# 577| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 +# 577| r0_34(char) = Constant[0] : +# 577| mu0_35(char) = Store : &:r0_33, r0_34 +# 577| r0_36(int) = Constant[1] : +# 577| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 +# 577| r0_38(char) = Constant[0] : +# 577| mu0_39(char) = Store : &:r0_37, r0_38 +# 578| r0_40(glval) = VariableAddress[e] : +# 578| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 +# 578| r0_42(int) = Constant[0] : +# 578| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 +# 578| r0_44(char) = Constant[0] : +# 578| mu0_45(char) = Store : &:r0_43, r0_44 +# 578| r0_46(int) = Constant[1] : +# 578| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 +# 578| r0_48(char) = Constant[1] : +# 578| mu0_49(char) = Store : &:r0_47, r0_48 +# 579| r0_50(glval) = VariableAddress[f] : +# 579| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 +# 579| r0_52(int) = Constant[0] : +# 579| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 +# 579| r0_54(char) = Constant[0] : +# 579| mu0_55(char) = Store : &:r0_53, r0_54 +# 579| r0_56(int) = Constant[1] : +# 579| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 +# 579| r0_58(unknown[2]) = Constant[0] : +# 579| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 +# 580| v0_60(void) = NoOp : +# 571| v0_61(void) = ReturnVoid : +# 571| v0_62(void) = UnmodeledUse : mu* +# 571| v0_63(void) = AliasedUse : ~mu0_2 +# 571| v0_64(void) = ExitFunction : # 584| void VarArgs() # 584| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 7345c6a52041..bc2bea75e113 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -876,67 +876,72 @@ ssa.cpp: # 213| m0_1(unknown) = AliasedDefinition : # 213| mu0_2(unknown) = UnmodeledDefinition : # 214| r0_3(glval) = VariableAddress[a_pad] : -# 214| r0_4(glval) = StringConstant[""] : -# 214| r0_5(char[1]) = Load : &:r0_4, ~m0_1 -# 214| m0_6(char[1]) = Store : &:r0_3, r0_5 -# 214| r0_7(unknown[31]) = Constant[0] : -# 214| r0_8(int) = Constant[1] : -# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 214| m0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 215| r0_11(glval) = VariableAddress[a_nopad] : -# 215| r0_12(glval) = StringConstant["foo"] : -# 215| r0_13(char[4]) = Load : &:r0_12, ~m0_1 -# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 -# 216| r0_15(glval) = VariableAddress[a_infer] : -# 216| r0_16(glval) = StringConstant["blah"] : -# 216| r0_17(char[5]) = Load : &:r0_16, ~m0_1 -# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 -# 217| r0_19(glval) = VariableAddress[b] : -# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 218| r0_21(glval) = VariableAddress[c] : -# 218| m0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 218| r0_23(int) = Constant[0] : -# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 218| r0_25(unknown[2]) = Constant[0] : -# 218| m0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 219| r0_27(glval) = VariableAddress[d] : -# 219| m0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 219| r0_29(int) = Constant[0] : -# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 219| r0_31(char) = Constant[0] : -# 219| m0_32(char) = Store : &:r0_30, r0_31 -# 219| m0_33(char[2]) = Chi : total:m0_28, partial:m0_32 -# 219| r0_34(int) = Constant[1] : -# 219| r0_35(glval) = PointerAdd[1] : r0_27, r0_34 +# 214| m0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 214| r0_5(glval) = StringConstant[""] : +# 214| r0_6(char[1]) = Load : &:r0_5, ~m0_1 +# 214| m0_7(char[1]) = Store : &:r0_3, r0_6 +# 214| m0_8(char[32]) = Chi : total:m0_4, partial:m0_7 +# 214| r0_9(unknown[31]) = Constant[0] : +# 214| r0_10(int) = Constant[1] : +# 214| r0_11(glval) = PointerAdd[1] : r0_3, r0_10 +# 214| m0_12(unknown[31]) = Store : &:r0_11, r0_9 +# 214| m0_13(char[32]) = Chi : total:m0_8, partial:m0_12 +# 215| r0_14(glval) = VariableAddress[a_nopad] : +# 215| m0_15(char[4]) = Uninitialized[a_nopad] : &:r0_14 +# 215| r0_16(glval) = StringConstant["foo"] : +# 215| r0_17(char[4]) = Load : &:r0_16, ~m0_1 +# 215| m0_18(char[4]) = Store : &:r0_14, r0_17 +# 216| r0_19(glval) = VariableAddress[a_infer] : +# 216| m0_20(char[5]) = Uninitialized[a_infer] : &:r0_19 +# 216| r0_21(glval) = StringConstant["blah"] : +# 216| r0_22(char[5]) = Load : &:r0_21, ~m0_1 +# 216| m0_23(char[5]) = Store : &:r0_19, r0_22 +# 217| r0_24(glval) = VariableAddress[b] : +# 217| m0_25(char[2]) = Uninitialized[b] : &:r0_24 +# 218| r0_26(glval) = VariableAddress[c] : +# 218| m0_27(char[2]) = Uninitialized[c] : &:r0_26 +# 218| r0_28(int) = Constant[0] : +# 218| r0_29(glval) = PointerAdd[1] : r0_26, r0_28 +# 218| r0_30(unknown[2]) = Constant[0] : +# 218| m0_31(unknown[2]) = Store : &:r0_29, r0_30 +# 219| r0_32(glval) = VariableAddress[d] : +# 219| m0_33(char[2]) = Uninitialized[d] : &:r0_32 +# 219| r0_34(int) = Constant[0] : +# 219| r0_35(glval) = PointerAdd[1] : r0_32, r0_34 # 219| r0_36(char) = Constant[0] : # 219| m0_37(char) = Store : &:r0_35, r0_36 # 219| m0_38(char[2]) = Chi : total:m0_33, partial:m0_37 -# 220| r0_39(glval) = VariableAddress[e] : -# 220| m0_40(char[2]) = Uninitialized[e] : &:r0_39 -# 220| r0_41(int) = Constant[0] : -# 220| r0_42(glval) = PointerAdd[1] : r0_39, r0_41 -# 220| r0_43(char) = Constant[0] : -# 220| m0_44(char) = Store : &:r0_42, r0_43 -# 220| m0_45(char[2]) = Chi : total:m0_40, partial:m0_44 -# 220| r0_46(int) = Constant[1] : -# 220| r0_47(glval) = PointerAdd[1] : r0_39, r0_46 -# 220| r0_48(char) = Constant[1] : +# 219| r0_39(int) = Constant[1] : +# 219| r0_40(glval) = PointerAdd[1] : r0_32, r0_39 +# 219| r0_41(char) = Constant[0] : +# 219| m0_42(char) = Store : &:r0_40, r0_41 +# 219| m0_43(char[2]) = Chi : total:m0_38, partial:m0_42 +# 220| r0_44(glval) = VariableAddress[e] : +# 220| m0_45(char[2]) = Uninitialized[e] : &:r0_44 +# 220| r0_46(int) = Constant[0] : +# 220| r0_47(glval) = PointerAdd[1] : r0_44, r0_46 +# 220| r0_48(char) = Constant[0] : # 220| m0_49(char) = Store : &:r0_47, r0_48 # 220| m0_50(char[2]) = Chi : total:m0_45, partial:m0_49 -# 221| r0_51(glval) = VariableAddress[f] : -# 221| m0_52(char[3]) = Uninitialized[f] : &:r0_51 -# 221| r0_53(int) = Constant[0] : -# 221| r0_54(glval) = PointerAdd[1] : r0_51, r0_53 -# 221| r0_55(char) = Constant[0] : -# 221| m0_56(char) = Store : &:r0_54, r0_55 -# 221| m0_57(char[3]) = Chi : total:m0_52, partial:m0_56 -# 221| r0_58(int) = Constant[1] : -# 221| r0_59(glval) = PointerAdd[1] : r0_51, r0_58 -# 221| r0_60(unknown[2]) = Constant[0] : -# 221| m0_61(unknown[2]) = Store : &:r0_59, r0_60 +# 220| r0_51(int) = Constant[1] : +# 220| r0_52(glval) = PointerAdd[1] : r0_44, r0_51 +# 220| r0_53(char) = Constant[1] : +# 220| m0_54(char) = Store : &:r0_52, r0_53 +# 220| m0_55(char[2]) = Chi : total:m0_50, partial:m0_54 +# 221| r0_56(glval) = VariableAddress[f] : +# 221| m0_57(char[3]) = Uninitialized[f] : &:r0_56 +# 221| r0_58(int) = Constant[0] : +# 221| r0_59(glval) = PointerAdd[1] : r0_56, r0_58 +# 221| r0_60(char) = Constant[0] : +# 221| m0_61(char) = Store : &:r0_59, r0_60 # 221| m0_62(char[3]) = Chi : total:m0_57, partial:m0_61 -# 222| v0_63(void) = NoOp : -# 213| v0_64(void) = ReturnVoid : -# 213| v0_65(void) = UnmodeledUse : mu* -# 213| v0_66(void) = AliasedUse : ~m0_1 -# 213| v0_67(void) = ExitFunction : +# 221| r0_63(int) = Constant[1] : +# 221| r0_64(glval) = PointerAdd[1] : r0_56, r0_63 +# 221| r0_65(unknown[2]) = Constant[0] : +# 221| m0_66(unknown[2]) = Store : &:r0_64, r0_65 +# 221| m0_67(char[3]) = Chi : total:m0_62, partial:m0_66 +# 222| v0_68(void) = NoOp : +# 213| v0_69(void) = ReturnVoid : +# 213| v0_70(void) = UnmodeledUse : mu* +# 213| v0_71(void) = AliasedUse : ~m0_1 +# 213| v0_72(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 056b0cd5ac7e..93f27b13f02c 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -840,61 +840,64 @@ ssa.cpp: # 213| mu0_1(unknown) = AliasedDefinition : # 213| mu0_2(unknown) = UnmodeledDefinition : # 214| r0_3(glval) = VariableAddress[a_pad] : -# 214| r0_4(glval) = StringConstant[""] : -# 214| r0_5(char[1]) = Load : &:r0_4, ~mu0_2 -# 214| mu0_6(char[1]) = Store : &:r0_3, r0_5 -# 214| r0_7(unknown[31]) = Constant[0] : -# 214| r0_8(int) = Constant[1] : -# 214| r0_9(glval) = PointerAdd[1] : r0_3, r0_8 -# 214| mu0_10(unknown[31]) = Store : &:r0_9, r0_7 -# 215| r0_11(glval) = VariableAddress[a_nopad] : -# 215| r0_12(glval) = StringConstant["foo"] : -# 215| r0_13(char[4]) = Load : &:r0_12, ~mu0_2 -# 215| m0_14(char[4]) = Store : &:r0_11, r0_13 -# 216| r0_15(glval) = VariableAddress[a_infer] : -# 216| r0_16(glval) = StringConstant["blah"] : -# 216| r0_17(char[5]) = Load : &:r0_16, ~mu0_2 -# 216| m0_18(char[5]) = Store : &:r0_15, r0_17 -# 217| r0_19(glval) = VariableAddress[b] : -# 217| m0_20(char[2]) = Uninitialized[b] : &:r0_19 -# 218| r0_21(glval) = VariableAddress[c] : -# 218| mu0_22(char[2]) = Uninitialized[c] : &:r0_21 -# 218| r0_23(int) = Constant[0] : -# 218| r0_24(glval) = PointerAdd[1] : r0_21, r0_23 -# 218| r0_25(unknown[2]) = Constant[0] : -# 218| mu0_26(unknown[2]) = Store : &:r0_24, r0_25 -# 219| r0_27(glval) = VariableAddress[d] : -# 219| mu0_28(char[2]) = Uninitialized[d] : &:r0_27 -# 219| r0_29(int) = Constant[0] : -# 219| r0_30(glval) = PointerAdd[1] : r0_27, r0_29 -# 219| r0_31(char) = Constant[0] : -# 219| mu0_32(char) = Store : &:r0_30, r0_31 -# 219| r0_33(int) = Constant[1] : -# 219| r0_34(glval) = PointerAdd[1] : r0_27, r0_33 -# 219| r0_35(char) = Constant[0] : -# 219| mu0_36(char) = Store : &:r0_34, r0_35 -# 220| r0_37(glval) = VariableAddress[e] : -# 220| mu0_38(char[2]) = Uninitialized[e] : &:r0_37 -# 220| r0_39(int) = Constant[0] : -# 220| r0_40(glval) = PointerAdd[1] : r0_37, r0_39 -# 220| r0_41(char) = Constant[0] : -# 220| mu0_42(char) = Store : &:r0_40, r0_41 -# 220| r0_43(int) = Constant[1] : -# 220| r0_44(glval) = PointerAdd[1] : r0_37, r0_43 -# 220| r0_45(char) = Constant[1] : -# 220| mu0_46(char) = Store : &:r0_44, r0_45 -# 221| r0_47(glval) = VariableAddress[f] : -# 221| mu0_48(char[3]) = Uninitialized[f] : &:r0_47 -# 221| r0_49(int) = Constant[0] : -# 221| r0_50(glval) = PointerAdd[1] : r0_47, r0_49 -# 221| r0_51(char) = Constant[0] : -# 221| mu0_52(char) = Store : &:r0_50, r0_51 -# 221| r0_53(int) = Constant[1] : -# 221| r0_54(glval) = PointerAdd[1] : r0_47, r0_53 -# 221| r0_55(unknown[2]) = Constant[0] : -# 221| mu0_56(unknown[2]) = Store : &:r0_54, r0_55 -# 222| v0_57(void) = NoOp : -# 213| v0_58(void) = ReturnVoid : -# 213| v0_59(void) = UnmodeledUse : mu* -# 213| v0_60(void) = AliasedUse : ~mu0_2 -# 213| v0_61(void) = ExitFunction : +# 214| mu0_4(char[32]) = Uninitialized[a_pad] : &:r0_3 +# 214| r0_5(glval) = StringConstant[""] : +# 214| r0_6(char[1]) = Load : &:r0_5, ~mu0_2 +# 214| mu0_7(char[1]) = Store : &:r0_3, r0_6 +# 214| r0_8(unknown[31]) = Constant[0] : +# 214| r0_9(int) = Constant[1] : +# 214| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 +# 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 +# 215| r0_12(glval) = VariableAddress[a_nopad] : +# 215| m0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 +# 215| r0_14(glval) = StringConstant["foo"] : +# 215| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 +# 215| m0_16(char[4]) = Store : &:r0_12, r0_15 +# 216| r0_17(glval) = VariableAddress[a_infer] : +# 216| m0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 +# 216| r0_19(glval) = StringConstant["blah"] : +# 216| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 +# 216| m0_21(char[5]) = Store : &:r0_17, r0_20 +# 217| r0_22(glval) = VariableAddress[b] : +# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 218| r0_24(glval) = VariableAddress[c] : +# 218| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 218| r0_26(int) = Constant[0] : +# 218| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 +# 218| r0_28(unknown[2]) = Constant[0] : +# 218| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 +# 219| r0_30(glval) = VariableAddress[d] : +# 219| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 219| r0_32(int) = Constant[0] : +# 219| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 +# 219| r0_34(char) = Constant[0] : +# 219| mu0_35(char) = Store : &:r0_33, r0_34 +# 219| r0_36(int) = Constant[1] : +# 219| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 +# 219| r0_38(char) = Constant[0] : +# 219| mu0_39(char) = Store : &:r0_37, r0_38 +# 220| r0_40(glval) = VariableAddress[e] : +# 220| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 +# 220| r0_42(int) = Constant[0] : +# 220| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 +# 220| r0_44(char) = Constant[0] : +# 220| mu0_45(char) = Store : &:r0_43, r0_44 +# 220| r0_46(int) = Constant[1] : +# 220| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 +# 220| r0_48(char) = Constant[1] : +# 220| mu0_49(char) = Store : &:r0_47, r0_48 +# 221| r0_50(glval) = VariableAddress[f] : +# 221| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 +# 221| r0_52(int) = Constant[0] : +# 221| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 +# 221| r0_54(char) = Constant[0] : +# 221| mu0_55(char) = Store : &:r0_53, r0_54 +# 221| r0_56(int) = Constant[1] : +# 221| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 +# 221| r0_58(unknown[2]) = Constant[0] : +# 221| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 +# 222| v0_60(void) = NoOp : +# 213| v0_61(void) = ReturnVoid : +# 213| v0_62(void) = UnmodeledUse : mu* +# 213| v0_63(void) = AliasedUse : ~mu0_2 +# 213| v0_64(void) = ExitFunction : From 0040c9fb4c1defdc206d9558b4e87925f8ca2ce0 Mon Sep 17 00:00:00 2001 From: Sauyon Lee Date: Wed, 6 Nov 2019 05:42:59 -0800 Subject: [PATCH 0258/2538] Update links to OWASP cheat sheet --- cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp | 2 +- .../src/Security Features/CWE-079/XSS.qhelp | 2 +- .../CWE-090/LDAPInjection.qhelp | 2 +- .../CWE-451/MissingXFrameOptions.qhelp | 2 +- .../CWE-601/UrlRedirect.qhelp | 2 +- .../CWE-611/UseXmlSecureResolver.qhelp | 2 +- java/ql/src/Security/CWE/CWE-079/XSS.qhelp | 2 +- .../src/Security/CWE/CWE-089/SqlTainted.qhelp | 2 +- .../Security/CWE/CWE-089/SqlUnescaped.qhelp | 2 +- .../src/Security/CWE/CWE-319/HttpsUrls.qhelp | 2 +- java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp | 2 +- .../CWE/CWE-319/UseSSLSocketFactories.qhelp | 2 +- .../CWE/CWE-502/UnsafeDeserialization.qhelp | 2 +- java/ql/src/Security/CWE/CWE-611/XXE.qhelp | 2 +- .../semmle/code/java/security/XmlParsers.qll | 24 +++++++++---------- .../CWE-020/IncompleteHostnameRegExp.qhelp | 2 +- .../IncompleteUrlSubstringSanitization.qhelp | 2 +- .../CWE-020/MissingRegExpAnchor.qhelp | 2 +- .../src/Security/CWE-079/ReflectedXss.qhelp | 2 +- .../ql/src/Security/CWE-079/StoredXss.qhelp | 2 +- javascript/ql/src/Security/CWE-079/Xss.qhelp | 4 ++-- .../CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- .../CWE-451/MissingXFrameOptions.qhelp | 2 +- .../CWE-502/UnsafeDeserialization.qhelp | 2 +- .../CWE-601/ClientSideUrlRedirect.qhelp | 2 +- .../CWE-601/ServerSideUrlRedirect.qhelp | 2 +- .../CWE-770/MissingRateLimiting.qhelp | 2 +- .../CWE-916/InsufficientPasswordHash.qhelp | 2 +- .../CWE-020/IncompleteHostnameRegExp.qhelp | 2 +- .../IncompleteUrlSubstringSanitization.qhelp | 2 +- .../CWE-079/Jinja2WithoutEscaping.qhelp | 2 +- .../src/Security/CWE-079/ReflectedXss.qhelp | 2 +- .../src/Security/CWE-089/SqlInjection.qhelp | 2 +- .../CWE-327/BrokenCryptoAlgorithm.qhelp | 2 +- .../CWE-502/UnsafeDeserialization.qhelp | 2 +- .../ql/src/Security/CWE-601/UrlRedirect.qhelp | 2 +- 36 files changed, 48 insertions(+), 48 deletions(-) diff --git a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp index ccd297c3b367..4ad7a40fed60 100644 --- a/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp +++ b/cpp/ql/src/Security/CWE/CWE-079/CgiXss.qhelp @@ -34,7 +34,7 @@ characters before writing to the HTML page.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-079/XSS.qhelp b/csharp/ql/src/Security Features/CWE-079/XSS.qhelp index 9a71290694da..409be1030e7a 100644 --- a/csharp/ql/src/Security Features/CWE-079/XSS.qhelp +++ b/csharp/ql/src/Security Features/CWE-079/XSS.qhelp @@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp index 118e91ed4d9e..04f01720ce66 100644 --- a/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp +++ b/csharp/ql/src/Security Features/CWE-090/LDAPInjection.qhelp @@ -33,7 +33,7 @@ the query cannot be changed by a malicious user.

    -
  • OWASP: LDAP Injection Prevention Cheat Sheet.
  • +
  • OWASP: LDAP Injection Prevention Cheat Sheet.
  • OWASP: Preventing LDAP Injection in Java.
  • AntiXSS doc: LdapFilterEncode.
  • AntiXSS doc: LdapDistinguishedNameEncode.
  • diff --git a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp index 7df415aff5b7..6d5d298c8e43 100644 --- a/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp +++ b/csharp/ql/src/Security Features/CWE-451/MissingXFrameOptions.qhelp @@ -51,7 +51,7 @@ This next example shows how to specify the X-Frame-Options header w
  • OWASP: -Clickjacking Defense Cheat Sheet. +Clickjacking Defense Cheat Sheet.
  • Mozilla: diff --git a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp index 989796b67389..3cf3cdaba6ed 100644 --- a/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp +++ b/csharp/ql/src/Security Features/CWE-601/UrlRedirect.qhelp @@ -32,7 +32,7 @@ It also shows how to remedy the problem by validating the user input against a k
  • OWASP: -XSS +XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp index 2e8e4fcf272c..11b1136db4df 100644 --- a/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp +++ b/csharp/ql/src/Security Features/CWE-611/UseXmlSecureResolver.qhelp @@ -38,7 +38,7 @@ The solution is to set the DtdProcessing property to DtdProce
  • OWASP: -XML External Entity (XXE) Prevention Cheat Sheet. +XML External Entity (XXE) Prevention Cheat Sheet.
  • Microsoft Docs: System.XML: Security considerations. diff --git a/java/ql/src/Security/CWE/CWE-079/XSS.qhelp b/java/ql/src/Security/CWE/CWE-079/XSS.qhelp index 85bdfb130fd0..428b44c8db9f 100644 --- a/java/ql/src/Security/CWE/CWE-079/XSS.qhelp +++ b/java/ql/src/Security/CWE/CWE-079/XSS.qhelp @@ -29,7 +29,7 @@ leaving the website vulnerable to cross-site scripting.

  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp b/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp index cab60173a62e..f1ba450d4a09 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp +++ b/java/ql/src/Security/CWE/CWE-089/SqlTainted.qhelp @@ -67,7 +67,7 @@ in the environment variable or user-supplied value are not given any special tre
  • OWASP: -SQL +SQL Injection Prevention Cheat Sheet.
  • The CERT Oracle Secure Coding Standard for Java: diff --git a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp index 7415235610c6..e469415d683c 100644 --- a/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp +++ b/java/ql/src/Security/CWE/CWE-089/SqlUnescaped.qhelp @@ -39,7 +39,7 @@ treatment.

  • OWASP: -SQL +SQL Injection Prevention Cheat Sheet.
  • The CERT Oracle Secure Coding Standard for Java: diff --git a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp index 8b8b0eff847c..2cfdca624fb8 100644 --- a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.qhelp @@ -37,7 +37,7 @@ connection is a secure SSL connection.

    Class HttpsURLConnection.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp b/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp index 5856086330f5..cec4937c8f75 100644 --- a/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/UseSSL.qhelp @@ -38,7 +38,7 @@ Class HttpsURLConnection. Class SSLSocket.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp b/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp index 56e9be973456..bf0dbc0bcacd 100644 --- a/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp +++ b/java/ql/src/Security/CWE/CWE-319/UseSSLSocketFactories.qhelp @@ -33,7 +33,7 @@ uses explicit SSL factories, which are preferable.

    Class SSLSocketFactory.
  • OWASP: -Transport Layer Protection Cheat Sheet. +Transport Layer Protection Cheat Sheet.
  • diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp index 4fb0ad88b453..61b50a986e34 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.qhelp @@ -58,7 +58,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Talks by Chris Frohoff & Gabriel Lawrence: diff --git a/java/ql/src/Security/CWE/CWE-611/XXE.qhelp b/java/ql/src/Security/CWE/CWE-611/XXE.qhelp index 75c5a2d4d7a6..93d420f7495c 100644 --- a/java/ql/src/Security/CWE/CWE-611/XXE.qhelp +++ b/java/ql/src/Security/CWE/CWE-611/XXE.qhelp @@ -52,7 +52,7 @@ OWASP vulnerability description:
  • OWASP guidance on parsing xml files: -XXE Prevention Cheat Sheet. +XXE Prevention Cheat Sheet.
  • Paper by Timothy Morgen: diff --git a/java/ql/src/semmle/code/java/security/XmlParsers.qll b/java/ql/src/semmle/code/java/security/XmlParsers.qll index 37a72f8128e9..1f5824894975 100644 --- a/java/ql/src/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/src/semmle/code/java/security/XmlParsers.qll @@ -49,7 +49,7 @@ abstract class ParserConfig extends MethodAccess { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#DocumentBuilder + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxp-documentbuilderfactory-saxparserfactory-and-dom4j */ /** The class `javax.xml.parsers.DocumentBuilderFactory`. */ @@ -227,7 +227,7 @@ class SafeDocumentBuilder extends DocumentBuilderConstruction { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLInputFactory_.28a_StAX_parser.29 + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlinputfactory-a-stax-parser */ /** The class `javax.xml.stream.XMLInputFactory`. */ @@ -353,7 +353,7 @@ class SafeXmlInputFactory extends VarAccess { } /* - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXBuilder + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxbuilder */ /** @@ -429,7 +429,7 @@ class SafeSAXBuilder extends VarAccess { /* * The case in - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller * will be split into two, one covers a SAXParser as a sink, the other the SAXSource as a sink. */ @@ -545,7 +545,7 @@ class SafeSAXParser extends MethodAccess { } } -/* SAXReader: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXReader */ +/* SAXReader: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxreader */ /** * The class `org.dom4j.io.SAXReader`. */ @@ -621,7 +621,7 @@ class SafeSAXReader extends VarAccess { } } -/* https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XMLReader */ +/* https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xmlreader */ /** The class `org.xml.sax.XMLReader`. */ class XMLReader extends RefType { XMLReader() { this.hasQualifiedName("org.xml.sax", "XMLReader") } @@ -756,7 +756,7 @@ class CreatedSafeXMLReader extends Call { /* * SAXSource in - * https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller + * https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.transform.sax.SAXSource` */ @@ -811,7 +811,7 @@ class SafeSAXSource extends Expr { } } -/* Transformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#TransformerFactory */ +/* Transformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#transformerfactory */ /** An access to a method use for configuring a transformer or schema. */ abstract class TransformerConfig extends MethodAccess { /** Holds if the configuration is disabled */ @@ -975,7 +975,7 @@ class SafeTransformer extends MethodAccess { } /* - * SAXTransformer: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SAXTransformerFactory + * SAXTransformer: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#saxtransformerfactory * Has an extra method called newFilter. */ @@ -996,7 +996,7 @@ class SAXTransformerFactoryNewXMLFilter extends XmlParserCall { } } -/* Schema: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#SchemaFactory */ +/* Schema: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#schemafactory */ /** The class `javax.xml.validation.SchemaFactory`. */ class SchemaFactory extends RefType { SchemaFactory() { this.hasQualifiedName("javax.xml.validation", "SchemaFactory") } @@ -1060,7 +1060,7 @@ class SafeSchemaFactory extends VarAccess { } } -/* Unmarshaller: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#Unmarshaller */ +/* Unmarshaller: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#jaxb-unmarshaller */ /** The class `javax.xml.bind.Unmarshaller`. */ class XmlUnmarshaller extends RefType { XmlUnmarshaller() { this.hasQualifiedName("javax.xml.bind", "Unmarshaller") } @@ -1081,7 +1081,7 @@ class XmlUnmarshal extends XmlParserCall { override predicate isSafe() { none() } } -/* XPathExpression: https://www.owasp.org/index.php/XML_External_Entity_(XXE)_Prevention_Cheat_Sheet#XPathExpression */ +/* XPathExpression: https://cheatsheetseries.owasp.org/cheatsheets/XML_External_Entity_Prevention_Cheat_Sheet.html#xpathexpression */ /** The class `javax.xml.xpath.XPathExpression`. */ class XPathExpression extends RefType { XPathExpression() { this.hasQualifiedName("javax.xml.xpath", "XPathExpression") } diff --git a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp index 771c446c66f5..a5e0a78b8cc4 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp +++ b/javascript/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp @@ -68,6 +68,6 @@
  • MDN: Regular Expressions
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp index b23557aa557d..90e6f2762e2b 100644 --- a/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp +++ b/javascript/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp @@ -83,6 +83,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp index 807574c5898f..015e510f0fb4 100644 --- a/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp +++ b/javascript/ql/src/Security/CWE-020/MissingRegExpAnchor.qhelp @@ -71,6 +71,6 @@
  • MDN: Regular Expressions
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp b/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp index 0502889fba00..dcbf0ba6f071 100644 --- a/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/ReflectedXss.qhelp @@ -37,7 +37,7 @@ Sanitizing the user-controlled data prevents the vulnerability:
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/StoredXss.qhelp b/javascript/ql/src/Security/CWE-079/StoredXss.qhelp index 1c3fde017989..0e6ed6456c97 100644 --- a/javascript/ql/src/Security/CWE-079/StoredXss.qhelp +++ b/javascript/ql/src/Security/CWE-079/StoredXss.qhelp @@ -48,7 +48,7 @@
  • OWASP: - XSS + XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-079/Xss.qhelp b/javascript/ql/src/Security/CWE-079/Xss.qhelp index 34ea1d821b62..c974c87b1882 100644 --- a/javascript/ql/src/Security/CWE-079/Xss.qhelp +++ b/javascript/ql/src/Security/CWE-079/Xss.qhelp @@ -33,12 +33,12 @@ leaving the website vulnerable to cross-site scripting.
  • OWASP: -DOM based +DOM based XSS Prevention Cheat Sheet.
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 9b2308529199..e0ccf71572f7 100644 --- a/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/javascript/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -45,7 +45,7 @@
  • NIST, FIPS 140 Annex a: Approved Security Functions.
  • NIST, SP 800-131A: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • OWASP: Rule + href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule - Use strong approved cryptographic algorithms.
  • diff --git a/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp b/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp index ad659015d67b..e73ea063b5d8 100644 --- a/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp +++ b/javascript/ql/src/Security/CWE-451/MissingXFrameOptions.qhelp @@ -67,7 +67,7 @@
  • OWASP: - Clickjacking Defense Cheat Sheet. + Clickjacking Defense Cheat Sheet.
  • Mozilla: diff --git a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp index e7b956b10f42..5f5b77cbd7de 100644 --- a/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp +++ b/javascript/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp @@ -41,7 +41,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Neal Poole: diff --git a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp index d4d36fe09bc8..392df3e6cbd8 100644 --- a/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp +++ b/javascript/ql/src/Security/CWE-601/ClientSideUrlRedirect.qhelp @@ -31,7 +31,7 @@ website of their choosing, which facilitates phishing attacks: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp index cb54477dde57..2052f16146bc 100644 --- a/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp +++ b/javascript/ql/src/Security/CWE-601/ServerSideUrlRedirect.qhelp @@ -35,7 +35,7 @@ before doing the redirection: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp b/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp index 1832a803a77d..8d4bc0ab5d04 100644 --- a/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp +++ b/javascript/ql/src/Security/CWE-770/MissingRateLimiting.qhelp @@ -36,7 +36,7 @@ can be used:
  • OWASP: -Denial of Service Cheat Sheet. +Denial of Service Cheat Sheet.
  • Wikipedia: Denial-of-service attack. diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp index 2b1d2b02a315..1efdbe694b1d 100644 --- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp +++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp @@ -50,6 +50,6 @@ -
  • OWASP: Password storage.
  • +
  • OWASP: Password storage.
  • diff --git a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp index b542ae252eb1..8eb0f43eb01e 100644 --- a/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp +++ b/python/ql/src/Security/CWE-020/IncompleteHostnameRegExp.qhelp @@ -64,6 +64,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp index 6c783a4f729c..828c71153b55 100644 --- a/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp +++ b/python/ql/src/Security/CWE-020/IncompleteUrlSubstringSanitization.qhelp @@ -80,6 +80,6 @@
  • OWASP: SSRF
  • -
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp b/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp index 4497437aac10..5b4d21bb37ed 100644 --- a/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp +++ b/python/ql/src/Security/CWE-079/Jinja2WithoutEscaping.qhelp @@ -38,7 +38,7 @@ Jinja2: API. Wikipedia: Cross-site scripting.
  • -OWASP: XSS (Cross Site Scripting) Prevention Cheat Sheet. +OWASP: XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-079/ReflectedXss.qhelp b/python/ql/src/Security/CWE-079/ReflectedXss.qhelp index 8cdeb4d3e793..04a83fba6b48 100644 --- a/python/ql/src/Security/CWE-079/ReflectedXss.qhelp +++ b/python/ql/src/Security/CWE-079/ReflectedXss.qhelp @@ -31,7 +31,7 @@ The second view is safe as first_name is escaped, so it is not vuln
  • OWASP: -XSS +XSS (Cross Site Scripting) Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-089/SqlInjection.qhelp b/python/ql/src/Security/CWE-089/SqlInjection.qhelp index 286b71a60475..63941706e840 100644 --- a/python/ql/src/Security/CWE-089/SqlInjection.qhelp +++ b/python/ql/src/Security/CWE-089/SqlInjection.qhelp @@ -51,6 +51,6 @@ vulnerable to SQL injection attacks. In this example, if username w
  • Wikipedia: SQL injection.
  • -
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • +
  • OWASP: SQL Injection Prevention Cheat Sheet.
  • diff --git a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp index 6cc787e52e48..1b4031b1cc50 100644 --- a/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp +++ b/python/ql/src/Security/CWE-327/BrokenCryptoAlgorithm.qhelp @@ -49,7 +49,7 @@
  • NIST, FIPS 140 Annex a: Approved Security Functions.
  • NIST, SP 800-131A: Transitions: Recommendation for Transitioning the Use of Cryptographic Algorithms and Key Lengths.
  • OWASP: Rule + href="https://cheatsheetseries.owasp.org/cheatsheets/Cryptographic_Storage_Cheat_Sheet.html#rule---use-strong-approved-authenticated-encryption">Rule - Use strong approved cryptographic algorithms.
  • diff --git a/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp b/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp index f298e62695f5..8c2660b98655 100644 --- a/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp +++ b/python/ql/src/Security/CWE-502/UnsafeDeserialization.qhelp @@ -49,7 +49,7 @@ OWASP vulnerability description:
  • OWASP guidance on deserializing objects: -Deserialization Cheat Sheet. +Deserialization Cheat Sheet.
  • Talks by Chris Frohoff & Gabriel Lawrence: diff --git a/python/ql/src/Security/CWE-601/UrlRedirect.qhelp b/python/ql/src/Security/CWE-601/UrlRedirect.qhelp index c2e053f030ba..756a43cc1067 100644 --- a/python/ql/src/Security/CWE-601/UrlRedirect.qhelp +++ b/python/ql/src/Security/CWE-601/UrlRedirect.qhelp @@ -35,7 +35,7 @@ before doing the redirection: -
  • OWASP: +
  • OWASP: XSS Unvalidated Redirects and Forwards Cheat Sheet.
  • From e314869e5cb134670d63119749abf286489af670 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Wed, 6 Nov 2019 09:06:39 +0000 Subject: [PATCH 0259/2538] JavaScript: Classify files with names ending in `_min` as minified. We already do the same for `-min` and `.min`. [Here](https://github.com/antoniogarrote/rdfstore-js/blob/master/dist/rdfstore_min.js) is a real-world example. --- change-notes/1.23/analysis-javascript.md | 4 ++-- javascript/ql/src/semmle/javascript/AST.qll | 2 +- .../query-tests/filters/ClassifyFiles/ClassifyFiles.expected | 3 +++ .../ql/test/query-tests/filters/ClassifyFiles/tst-min.js | 0 .../ql/test/query-tests/filters/ClassifyFiles/tst.min.js | 0 .../ql/test/query-tests/filters/ClassifyFiles/tst_min.js | 0 6 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js create mode 100644 javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js diff --git a/change-notes/1.23/analysis-javascript.md b/change-notes/1.23/analysis-javascript.md index 49f527af4242..a7f41473eea6 100644 --- a/change-notes/1.23/analysis-javascript.md +++ b/change-notes/1.23/analysis-javascript.md @@ -2,6 +2,8 @@ ## General improvements +* Automatic classification of generated and minified files has been improved, in particular files generated by Doxygen are now recognized. + * Support for `globalThis` has been added. * Support for the following frameworks and libraries has been improved: @@ -14,8 +16,6 @@ * TypeScript 3.6 and 3.7 features are now supported. -* Automatic classification of generated files has been improved, in particular files generated by Doxygen are now recognized. - ## New queries | **Query** | **Tags** | **Purpose** | diff --git a/javascript/ql/src/semmle/javascript/AST.qll b/javascript/ql/src/semmle/javascript/AST.qll index efc9ef53af34..66a5155458c2 100644 --- a/javascript/ql/src/semmle/javascript/AST.qll +++ b/javascript/ql/src/semmle/javascript/AST.qll @@ -150,7 +150,7 @@ class TopLevel extends @toplevel, StmtContainer { /** Holds if this toplevel is minified. */ predicate isMinified() { // file name contains 'min' (not as part of a longer word) - getFile().getBaseName().regexpMatch(".*[^-.]*[-.]min([-.].*)?\\.\\w+") + getFile().getBaseName().regexpMatch(".*[^-._]*[-._]min([-._].*)?\\.\\w+") or exists(int numstmt | numstmt = strictcount(Stmt s | s.getTopLevel() = this) | // there are more than two statements per line on average diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected index 7c583b1bf398..da235c205ee4 100644 --- a/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected +++ b/javascript/ql/test/query-tests/filters/ClassifyFiles/ClassifyFiles.expected @@ -39,8 +39,11 @@ | textmate.html:0:0:0:0 | textmate.html | generated | | tmpl2.html:0:0:0:0 | tmpl2.html | template | | tmpl.html:0:0:0:0 | tmpl.html | template | +| tst-min.js:0:0:0:0 | tst-min.js | generated | | tst.browserify.js:0:0:0:0 | tst.browserify.js | generated | | tst.dart.js:0:0:0:0 | tst.dart.js | generated | +| tst.min.js:0:0:0:0 | tst.min.js | generated | +| tst_min.js:0:0:0:0 | tst_min.js | generated | | twitter-text.js:0:0:0:0 | twitter-text.js | library | | twitter_text.js:0:0:0:0 | twitter_text.js | library | | unannotated-externs-1.js:0:0:0:0 | unannotated-externs-1.js | externs | diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst-min.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst.min.js new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js b/javascript/ql/test/query-tests/filters/ClassifyFiles/tst_min.js new file mode 100644 index 000000000000..e69de29bb2d1 From 6385528d5fe939df63bf03314206ada09ed4cc19 Mon Sep 17 00:00:00 2001 From: Jonas Jensen Date: Thu, 7 Nov 2019 11:30:18 +0100 Subject: [PATCH 0260/2538] C++/C#: Fix getIRTypeForPRValue join order This predicate was taking 39s on a snapshot of Facebook Fizz because it had disjuncts like this: 43685 ~0% {1} r34 = JOIN Type::FunctionPointerIshType#f AS L WITH Type::Type::getUnspecifiedType_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1> 43685 ~1% {2} r35 = JOIN r34 WITH CppType::getTypeSize#ff AS R ON FIRST 1 OUTPUT R.<1>, r34.<0> 170371500 ~2% {2} r36 = JOIN r35 WITH IRType::IRSizedType#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1>, r35.<1> 43685 ~6% {2} r37 = JOIN r36 WITH IRType::IRFunctionAddressType#class#ff AS R ON FIRST 1 OUTPUT r36.<1>, r36.<0> Instead of fixing the joins in `getIRTypeForPRValue` itself, I've changed the `IRType::getByteSize` predicate such that the optimiser knows how to join with it efficiently. The disjunct shown above now looks like this instead: 43685 ~0% {1} r26 = JOIN Type::FunctionPointerIshType#f AS L WITH Type::Type::getUnspecifiedType_dispred#ff_10#join_rhs AS R ON FIRST 1 OUTPUT R.<1> 43685 ~1% {2} r27 = JOIN r26 WITH CppType::getTypeSize#ff AS R ON FIRST 1 OUTPUT R.<1>, r26.<0> 43685 ~6% {2} r28 = JOIN r27 WITH IRType::IRFunctionAddressType::getByteSize#ff_10#join_rhs AS R ON FIRST 1 OUTPUT r27.<1>, R.<1> --- .../code/cpp/ir/implementation/IRType.qll | 27 +++++++++++++++++-- .../code/csharp/ir/implementation/IRType.qll | 27 +++++++++++++++++-- 2 files changed, 50 insertions(+), 4 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll index 0abfa14023d8..cb652230d2a7 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/IRType.qll @@ -42,6 +42,10 @@ class IRType extends TIRType { * * This will hold for all `IRType` objects except `IRUnknownType`. */ + // This predicate is overridden with `pragma[noinline]` in every leaf subclass. + // This allows callers to ask for things like _the_ floating-point type of + // size 4 without getting a join that first finds all types of size 4 and + // _then_ restricts them to floating-point types. int getByteSize() { none() } /** @@ -104,8 +108,6 @@ private class IRSizedType extends IRType { this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) } - - final override int getByteSize() { result = byteSize } } /** @@ -117,6 +119,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalBooleanType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -141,6 +146,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalSignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -153,6 +161,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalUnsignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -164,6 +175,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFloatingPointType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -178,6 +192,9 @@ class IRAddressType extends IRSizedType, TIRAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -190,6 +207,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFunctionAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -218,6 +238,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType { * same size. */ final Language::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } module IRTypeSanity { diff --git a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll index 0abfa14023d8..cb652230d2a7 100644 --- a/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll +++ b/csharp/ql/src/semmle/code/csharp/ir/implementation/IRType.qll @@ -42,6 +42,10 @@ class IRType extends TIRType { * * This will hold for all `IRType` objects except `IRUnknownType`. */ + // This predicate is overridden with `pragma[noinline]` in every leaf subclass. + // This allows callers to ask for things like _the_ floating-point type of + // size 4 without getting a join that first finds all types of size 4 and + // _then_ restricts them to floating-point types. int getByteSize() { none() } /** @@ -104,8 +108,6 @@ private class IRSizedType extends IRType { this = TIRFunctionAddressType(byteSize) or this = TIROpaqueType(_, byteSize) } - - final override int getByteSize() { result = byteSize } } /** @@ -117,6 +119,9 @@ class IRBooleanType extends IRSizedType, TIRBooleanType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalBooleanType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -141,6 +146,9 @@ class IRSignedIntegerType extends IRNumericType, TIRSignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalSignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -153,6 +161,9 @@ class IRUnsignedIntegerType extends IRNumericType, TIRUnsignedIntegerType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalUnsignedIntegerType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -164,6 +175,9 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFloatingPointType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -178,6 +192,9 @@ class IRAddressType extends IRSizedType, TIRAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -190,6 +207,9 @@ class IRFunctionAddressType extends IRSizedType, TIRFunctionAddressType { final override Language::LanguageType getCanonicalLanguageType() { result = Language::getCanonicalFunctionAddressType(byteSize) } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } /** @@ -218,6 +238,9 @@ class IROpaqueType extends IRSizedType, TIROpaqueType { * same size. */ final Language::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } } module IRTypeSanity { From e4f6f41634924e31f37072e9103edf85eefa13ee Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Wed, 6 Nov 2019 09:49:43 +0100 Subject: [PATCH 0261/2538] add DataFlow::getEnclosingExpr to get the an Expr from a potentially reflective call --- .../src/Statements/UseOfReturnlessFunction.ql | 4 ++-- .../semmle/javascript/dataflow/DataFlow.qll | 22 +++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql index 123515a7cbd3..7fa8e6ddf903 100644 --- a/javascript/ql/src/Statements/UseOfReturnlessFunction.ql +++ b/javascript/ql/src/Statements/UseOfReturnlessFunction.ql @@ -211,9 +211,9 @@ where msg = "the $@ does not return anything, yet the return value from the call to " + call.getCalleeName() + " is used." and name = "callback function" ) and - not benignContext(call.asExpr()) and + not benignContext(call.getEnclosingExpr()) and not lastStatementHasNoEffect(func) and // anonymous one-shot closure. Those are used in weird ways and we ignore them. - not oneshotClosure(call.asExpr()) + not oneshotClosure(call.getEnclosingExpr()) select call, msg, func, name diff --git a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll index 07920cba3c93..1cd8286447fe 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/DataFlow.qll @@ -85,6 +85,18 @@ module DataFlow { /** Gets the expression corresponding to this data flow node, if any. */ Expr asExpr() { this = TValueNode(result) } + /** + * Gets the expression enclosing this data flow node. + * In most cases the result is the same as `asExpr()`, however this method + * additionally the `InvokeExpr` corresponding to reflective calls, and the `Parameter` + * for a `DataFlow::ParameterNode`. + */ + Expr getEnclosingExpr() { + result = asExpr() or + this = DataFlow::reflectiveCallNode(result) or + result = this.(ParameterNode).getParameter() + } + /** Gets the AST node corresponding to this data flow node, if any. */ ASTNode getAstNode() { none() } @@ -950,6 +962,16 @@ module DataFlow { * Gets a pseudo-node representing the root of a global access path. */ DataFlow::Node globalAccessPathRootPseudoNode() { result instanceof TGlobalAccessPathRoot } + + /** + * Gets a data flow node representing the underlying call performed by the given + * call to `Function.prototype.call` or `Function.prototype.apply`. + * + * For example, for an expression `fn.call(x, y)`, this gets a call node with `fn` as the + * callee, `x` as the receiver, and `y` as the first argument. + */ + DataFlow::InvokeNode reflectiveCallNode(InvokeExpr expr) { result = TReflectiveCallNode(expr, _) } + /** * Provides classes representing various kinds of calls. From 232e875274bd1c66b8da6a9a0ff63878fe3c57b3 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 7 Nov 2019 10:59:55 +0100 Subject: [PATCH 0262/2538] add test for getEnclosingExpr --- .../DataFlow/enclosingExpr.expected | 308 ++++++++++++++++++ .../library-tests/DataFlow/enclosingExpr.ql | 4 + 2 files changed, 312 insertions(+) create mode 100644 javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected create mode 100644 javascript/ql/test/library-tests/DataFlow/enclosingExpr.ql diff --git a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected new file mode 100644 index 000000000000..eb50988eacbc --- /dev/null +++ b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected @@ -0,0 +1,308 @@ +| eval.js:1:10:1:10 | k | eval.js:1:10:1:10 | k | +| eval.js:2:7:2:7 | x | eval.js:2:7:2:7 | x | +| eval.js:2:7:2:12 | x = 42 | eval.js:2:7:2:12 | x = 42 | +| eval.js:2:11:2:12 | 42 | eval.js:2:11:2:12 | 42 | +| eval.js:3:3:3:6 | eval | eval.js:3:3:3:6 | eval | +| eval.js:3:3:3:16 | eval("x = 23") | eval.js:3:3:3:16 | eval("x = 23") | +| eval.js:3:8:3:15 | "x = 23" | eval.js:3:8:3:15 | "x = 23" | +| eval.js:4:3:4:3 | x | eval.js:4:3:4:3 | x | +| sources.js:1:1:1:12 | new (x => x) | sources.js:1:1:1:12 | new (x => x) | +| sources.js:1:5:1:12 | (x => x) | sources.js:1:5:1:12 | (x => x) | +| sources.js:1:6:1:6 | x | sources.js:1:6:1:6 | x | +| sources.js:1:6:1:6 | x | sources.js:1:6:1:6 | x | +| sources.js:1:6:1:11 | x => x | sources.js:1:6:1:11 | x => x | +| sources.js:1:11:1:11 | x | sources.js:1:11:1:11 | x | +| sources.js:3:1:5:2 | (functi ... +19;\\n}) | sources.js:3:1:5:2 | (functi ... +19;\\n}) | +| sources.js:3:1:5:6 | (functi ... \\n})(23) | sources.js:3:1:5:6 | (functi ... \\n})(23) | +| sources.js:3:2:5:1 | functio ... x+19;\\n} | sources.js:3:2:5:1 | functio ... x+19;\\n} | +| sources.js:3:11:3:11 | x | sources.js:3:11:3:11 | x | +| sources.js:3:11:3:11 | x | sources.js:3:11:3:11 | x | +| sources.js:4:10:4:10 | x | sources.js:4:10:4:10 | x | +| sources.js:4:10:4:13 | x+19 | sources.js:4:10:4:13 | x+19 | +| sources.js:4:12:4:13 | 19 | sources.js:4:12:4:13 | 19 | +| sources.js:5:4:5:5 | 23 | sources.js:5:4:5:5 | 23 | +| sources.js:7:1:7:3 | /x/ | sources.js:7:1:7:3 | /x/ | +| tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | +| tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | +| tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | +| tst.js:1:20:1:23 | 'fs' | tst.js:1:20:1:23 | 'fs' | +| tst.js:3:5:3:5 | x | tst.js:3:5:3:5 | x | +| tst.js:3:5:3:10 | x = 42 | tst.js:3:5:3:10 | x = 42 | +| tst.js:3:9:3:10 | 42 | tst.js:3:9:3:10 | 42 | +| tst.js:4:5:4:5 | y | tst.js:4:5:4:5 | y | +| tst.js:4:5:4:12 | y = "hi" | tst.js:4:5:4:12 | y = "hi" | +| tst.js:4:9:4:12 | "hi" | tst.js:4:9:4:12 | "hi" | +| tst.js:5:5:5:5 | z | tst.js:5:5:5:5 | z | +| tst.js:5:5:5:5 | z | tst.js:5:5:5:5 | z | +| tst.js:7:1:7:2 | fs | tst.js:7:1:7:2 | fs | +| tst.js:8:1:8:1 | x | tst.js:8:1:8:1 | x | +| tst.js:9:1:9:3 | (x) | tst.js:9:1:9:3 | (x) | +| tst.js:9:2:9:2 | x | tst.js:9:2:9:2 | x | +| tst.js:10:1:10:1 | x | tst.js:10:1:10:1 | x | +| tst.js:10:1:10:4 | x, y | tst.js:10:1:10:4 | x, y | +| tst.js:10:4:10:4 | y | tst.js:10:4:10:4 | y | +| tst.js:11:1:11:1 | x | tst.js:11:1:11:1 | x | +| tst.js:11:1:11:6 | x && y | tst.js:11:1:11:6 | x && y | +| tst.js:11:6:11:6 | y | tst.js:11:6:11:6 | y | +| tst.js:12:1:12:1 | x | tst.js:12:1:12:1 | x | +| tst.js:12:1:12:6 | x \|\| y | tst.js:12:1:12:6 | x \|\| y | +| tst.js:12:6:12:6 | y | tst.js:12:6:12:6 | y | +| tst.js:13:1:13:1 | z | tst.js:13:1:13:1 | z | +| tst.js:13:1:13:5 | z = y | tst.js:13:1:13:5 | z = y | +| tst.js:13:5:13:5 | y | tst.js:13:5:13:5 | y | +| tst.js:14:1:14:1 | z | tst.js:14:1:14:1 | z | +| tst.js:14:1:14:9 | z ? x : y | tst.js:14:1:14:9 | z ? x : y | +| tst.js:14:5:14:5 | x | tst.js:14:5:14:5 | x | +| tst.js:14:9:14:9 | y | tst.js:14:9:14:9 | y | +| tst.js:16:1:20:2 | (functi ... "";\\n}) | tst.js:16:1:20:2 | (functi ... "";\\n}) | +| tst.js:16:1:20:9 | (functi ... ("arg") | tst.js:16:1:20:9 | (functi ... ("arg") | +| tst.js:16:2:20:1 | functio ... n "";\\n} | tst.js:16:2:20:1 | functio ... n "";\\n} | +| tst.js:16:11:16:11 | f | tst.js:16:11:16:11 | f | +| tst.js:16:13:16:13 | a | tst.js:16:13:16:13 | a | +| tst.js:16:13:16:13 | a | tst.js:16:13:16:13 | a | +| tst.js:17:7:17:10 | Math | tst.js:17:7:17:10 | Math | +| tst.js:17:7:17:17 | Math.random | tst.js:17:7:17:17 | Math.random | +| tst.js:17:7:17:19 | Math.random() | tst.js:17:7:17:19 | Math.random() | +| tst.js:17:7:17:25 | Math.random() > 0.5 | tst.js:17:7:17:25 | Math.random() > 0.5 | +| tst.js:17:12:17:17 | random | tst.js:17:12:17:17 | random | +| tst.js:17:23:17:25 | 0.5 | tst.js:17:23:17:25 | 0.5 | +| tst.js:18:12:18:12 | a | tst.js:18:12:18:12 | a | +| tst.js:19:10:19:11 | "" | tst.js:19:10:19:11 | "" | +| tst.js:20:4:20:8 | "arg" | tst.js:20:4:20:8 | "arg" | +| tst.js:22:5:22:20 | { readFileSync } | tst.js:22:5:22:20 | { readFileSync } | +| tst.js:22:5:22:25 | { readF ... } = fs | tst.js:22:5:22:25 | { readF ... } = fs | +| tst.js:22:7:22:18 | readFileSync | tst.js:22:7:22:18 | readFileSync | +| tst.js:22:7:22:18 | readFileSync | tst.js:22:7:22:18 | readFileSync | +| tst.js:22:24:22:25 | fs | tst.js:22:24:22:25 | fs | +| tst.js:23:1:23:12 | readFileSync | tst.js:23:1:23:12 | readFileSync | +| tst.js:25:1:25:3 | ++x | tst.js:25:1:25:3 | ++x | +| tst.js:25:3:25:3 | x | tst.js:25:3:25:3 | x | +| tst.js:26:1:26:1 | x | tst.js:26:1:26:1 | x | +| tst.js:28:1:30:1 | (() =>\\n ... ables\\n) | tst.js:28:1:30:1 | (() =>\\n ... ables\\n) | +| tst.js:28:1:30:3 | (() =>\\n ... les\\n)() | tst.js:28:1:30:3 | (() =>\\n ... les\\n)() | +| tst.js:28:2:29:3 | () =>\\n x | tst.js:28:2:29:3 | () =>\\n x | +| tst.js:29:3:29:3 | x | tst.js:29:3:29:3 | x | +| tst.js:32:10:32:10 | g | tst.js:32:10:32:10 | g | +| tst.js:32:12:32:12 | b | tst.js:32:12:32:12 | b | +| tst.js:32:12:32:12 | b | tst.js:32:12:32:12 | b | +| tst.js:33:10:33:10 | x | tst.js:33:10:33:10 | x | +| tst.js:35:1:35:1 | g | tst.js:35:1:35:1 | g | +| tst.js:35:1:35:7 | g(true) | tst.js:35:1:35:7 | g(true) | +| tst.js:35:3:35:6 | true | tst.js:35:3:35:6 | true | +| tst.js:37:5:37:5 | o | tst.js:37:5:37:5 | o | +| tst.js:37:5:42:1 | o = {\\n ... ;\\n }\\n} | tst.js:37:5:42:1 | o = {\\n ... ;\\n }\\n} | +| tst.js:37:9:42:1 | {\\n x: ... ;\\n }\\n} | tst.js:37:9:42:1 | {\\n x: ... ;\\n }\\n} | +| tst.js:38:3:38:3 | x | tst.js:38:3:38:3 | x | +| tst.js:38:6:38:9 | null | tst.js:38:6:38:9 | null | +| tst.js:39:3:39:3 | m | tst.js:39:3:39:3 | m | +| tst.js:39:4:41:3 | () {\\n this;\\n } | tst.js:39:4:41:3 | () {\\n this;\\n } | +| tst.js:40:5:40:8 | this | tst.js:40:5:40:8 | this | +| tst.js:43:1:43:1 | o | tst.js:43:1:43:1 | o | +| tst.js:43:1:43:3 | o.x | tst.js:43:1:43:3 | o.x | +| tst.js:43:3:43:3 | x | tst.js:43:3:43:3 | x | +| tst.js:44:1:44:1 | o | tst.js:44:1:44:1 | o | +| tst.js:44:1:44:3 | o.m | tst.js:44:1:44:3 | o.m | +| tst.js:44:1:44:5 | o.m() | tst.js:44:1:44:5 | o.m() | +| tst.js:44:3:44:3 | m | tst.js:44:3:44:3 | m | +| tst.js:46:1:46:6 | global | tst.js:46:1:46:6 | global | +| tst.js:46:1:46:11 | global = "" | tst.js:46:1:46:11 | global = "" | +| tst.js:46:10:46:11 | "" | tst.js:46:10:46:11 | "" | +| tst.js:47:1:47:6 | global | tst.js:47:1:47:6 | global | +| tst.js:49:7:49:7 | A | tst.js:49:7:49:7 | A | +| tst.js:49:17:49:17 | B | tst.js:49:17:49:17 | B | +| tst.js:50:3:50:13 | constructor | tst.js:50:3:50:13 | constructor | +| tst.js:50:14:53:3 | () {\\n ... et`\\n } | tst.js:50:14:53:3 | () {\\n ... et`\\n } | +| tst.js:51:5:51:9 | super | tst.js:51:5:51:9 | super | +| tst.js:51:5:51:13 | super(42) | tst.js:51:5:51:13 | super(42) | +| tst.js:51:11:51:12 | 42 | tst.js:51:11:51:12 | 42 | +| tst.js:52:5:52:14 | new.target | tst.js:52:5:52:14 | new.target | +| tst.js:55:1:55:1 | A | tst.js:55:1:55:1 | A | +| tst.js:57:1:57:9 | `x: ${x}` | tst.js:57:1:57:9 | `x: ${x}` | +| tst.js:57:2:57:4 | x: | tst.js:57:2:57:4 | x: | +| tst.js:57:7:57:7 | x | tst.js:57:7:57:7 | x | +| tst.js:58:1:58:3 | tag | tst.js:58:1:58:3 | tag | +| tst.js:58:1:58:13 | tag `x: ${x}` | tst.js:58:1:58:13 | tag `x: ${x}` | +| tst.js:58:5:58:13 | `x: ${x}` | tst.js:58:5:58:13 | `x: ${x}` | +| tst.js:58:6:58:8 | x: | tst.js:58:6:58:8 | x: | +| tst.js:58:11:58:11 | x | tst.js:58:11:58:11 | x | +| tst.js:60:1:60:1 | g | tst.js:60:1:60:1 | g | +| tst.js:61:1:61:5 | ::o.m | tst.js:61:1:61:5 | ::o.m | +| tst.js:61:3:61:3 | o | tst.js:61:3:61:3 | o | +| tst.js:61:3:61:5 | o.m | tst.js:61:3:61:5 | o.m | +| tst.js:61:5:61:5 | m | tst.js:61:5:61:5 | m | +| tst.js:62:1:62:1 | o | tst.js:62:1:62:1 | o | +| tst.js:62:1:62:4 | o::g | tst.js:62:1:62:4 | o::g | +| tst.js:62:4:62:4 | g | tst.js:62:4:62:4 | g | +| tst.js:64:11:64:11 | h | tst.js:64:11:64:11 | h | +| tst.js:65:3:65:10 | yield 42 | tst.js:65:3:65:10 | yield 42 | +| tst.js:65:9:65:10 | 42 | tst.js:65:9:65:10 | 42 | +| tst.js:66:7:66:9 | tmp | tst.js:66:7:66:9 | tmp | +| tst.js:66:7:66:25 | tmp = function.sent | tst.js:66:7:66:25 | tmp = function.sent | +| tst.js:66:13:66:25 | function.sent | tst.js:66:13:66:25 | function.sent | +| tst.js:68:5:68:8 | iter | tst.js:68:5:68:8 | iter | +| tst.js:68:5:68:14 | iter = h() | tst.js:68:5:68:14 | iter = h() | +| tst.js:68:12:68:12 | h | tst.js:68:12:68:12 | h | +| tst.js:68:12:68:14 | h() | tst.js:68:12:68:14 | h() | +| tst.js:69:1:69:4 | iter | tst.js:69:1:69:4 | iter | +| tst.js:69:1:69:9 | iter.next | tst.js:69:1:69:9 | iter.next | +| tst.js:69:1:69:13 | iter.next(23) | tst.js:69:1:69:13 | iter.next(23) | +| tst.js:69:6:69:9 | next | tst.js:69:6:69:9 | next | +| tst.js:69:11:69:12 | 23 | tst.js:69:11:69:12 | 23 | +| tst.js:71:16:71:16 | k | tst.js:71:16:71:16 | k | +| tst.js:72:3:72:11 | await p() | tst.js:72:3:72:11 | await p() | +| tst.js:72:9:72:9 | p | tst.js:72:9:72:9 | p | +| tst.js:72:9:72:11 | p() | tst.js:72:9:72:11 | p() | +| tst.js:75:5:75:5 | m | tst.js:75:5:75:5 | m | +| tst.js:75:5:75:21 | m = import('foo') | tst.js:75:5:75:21 | m = import('foo') | +| tst.js:75:9:75:21 | import('foo') | tst.js:75:9:75:21 | import('foo') | +| tst.js:75:16:75:20 | 'foo' | tst.js:75:16:75:20 | 'foo' | +| tst.js:77:10:77:10 | i | tst.js:77:10:77:10 | i | +| tst.js:77:10:77:10 | i | tst.js:77:10:77:10 | i | +| tst.js:77:15:77:15 | o | tst.js:77:15:77:15 | o | +| tst.js:78:3:78:3 | i | tst.js:78:3:78:3 | i | +| tst.js:80:10:80:10 | v | tst.js:80:10:80:10 | v | +| tst.js:80:10:80:10 | v | tst.js:80:10:80:10 | v | +| tst.js:80:15:80:15 | o | tst.js:80:15:80:15 | o | +| tst.js:81:3:81:3 | v | tst.js:81:3:81:3 | v | +| tst.js:83:5:83:7 | vs1 | tst.js:83:5:83:7 | vs1 | +| tst.js:83:5:83:28 | vs1 = [ ... o) v ] | tst.js:83:5:83:28 | vs1 = [ ... o) v ] | +| tst.js:83:11:83:28 | [ for (v of o) v ] | tst.js:83:11:83:28 | [ for (v of o) v ] | +| tst.js:83:13:83:24 | for (v of o) | tst.js:83:13:83:24 | for (v of o) | +| tst.js:83:18:83:18 | v | tst.js:83:18:83:18 | v | +| tst.js:83:23:83:23 | o | tst.js:83:23:83:23 | o | +| tst.js:83:26:83:26 | v | tst.js:83:26:83:26 | v | +| tst.js:85:5:85:7 | vs2 | tst.js:85:5:85:7 | vs2 | +| tst.js:85:5:85:28 | vs2 = ( ... o) v ) | tst.js:85:5:85:28 | vs2 = ( ... o) v ) | +| tst.js:85:11:85:28 | ( for (v of o) v ) | tst.js:85:11:85:28 | ( for (v of o) v ) | +| tst.js:85:13:85:24 | for (v of o) | tst.js:85:13:85:24 | for (v of o) | +| tst.js:85:18:85:18 | v | tst.js:85:18:85:18 | v | +| tst.js:85:23:85:23 | o | tst.js:85:23:85:23 | o | +| tst.js:85:26:85:26 | v | tst.js:85:26:85:26 | v | +| tst.js:87:1:92:2 | (functi ... + z;\\n}) | tst.js:87:1:92:2 | (functi ... + z;\\n}) | +| tst.js:87:1:96:2 | (functi ... r: 0\\n}) | tst.js:87:1:96:2 | (functi ... r: 0\\n}) | +| tst.js:87:2:92:1 | functio ... + z;\\n} | tst.js:87:2:92:1 | functio ... + z;\\n} | +| tst.js:87:11:87:24 | { p: x, ...o } | tst.js:87:11:87:24 | { p: x, ...o } | +| tst.js:87:11:87:24 | { p: x, ...o } | tst.js:87:11:87:24 | { p: x, ...o } | +| tst.js:87:13:87:13 | p | tst.js:87:13:87:13 | p | +| tst.js:87:16:87:16 | x | tst.js:87:16:87:16 | x | +| tst.js:87:22:87:22 | o | tst.js:87:22:87:22 | o | +| tst.js:88:7:88:14 | { q: y } | tst.js:88:7:88:14 | { q: y } | +| tst.js:88:7:88:18 | { q: y } = o | tst.js:88:7:88:18 | { q: y } = o | +| tst.js:88:9:88:9 | q | tst.js:88:9:88:9 | q | +| tst.js:88:12:88:12 | y | tst.js:88:12:88:12 | y | +| tst.js:88:18:88:18 | o | tst.js:88:18:88:18 | o | +| tst.js:89:7:89:7 | z | tst.js:89:7:89:7 | z | +| tst.js:89:7:89:7 | z | tst.js:89:7:89:7 | z | +| tst.js:90:3:90:16 | ({ r: z } = o) | tst.js:90:3:90:16 | ({ r: z } = o) | +| tst.js:90:4:90:11 | { r: z } | tst.js:90:4:90:11 | { r: z } | +| tst.js:90:4:90:15 | { r: z } = o | tst.js:90:4:90:15 | { r: z } = o | +| tst.js:90:6:90:6 | r | tst.js:90:6:90:6 | r | +| tst.js:90:9:90:9 | z | tst.js:90:9:90:9 | z | +| tst.js:90:15:90:15 | o | tst.js:90:15:90:15 | o | +| tst.js:91:10:91:10 | x | tst.js:91:10:91:10 | x | +| tst.js:91:10:91:14 | x + y | tst.js:91:10:91:14 | x + y | +| tst.js:91:10:91:18 | x + y + z | tst.js:91:10:91:18 | x + y + z | +| tst.js:91:14:91:14 | y | tst.js:91:14:91:14 | y | +| tst.js:91:18:91:18 | z | tst.js:91:18:91:18 | z | +| tst.js:92:4:96:1 | {\\n p: ... r: 0\\n} | tst.js:92:4:96:1 | {\\n p: ... r: 0\\n} | +| tst.js:93:3:93:3 | p | tst.js:93:3:93:3 | p | +| tst.js:93:6:93:7 | 19 | tst.js:93:6:93:7 | 19 | +| tst.js:94:3:94:3 | q | tst.js:94:3:94:3 | q | +| tst.js:94:6:94:7 | 23 | tst.js:94:6:94:7 | 23 | +| tst.js:95:3:95:3 | r | tst.js:95:3:95:3 | r | +| tst.js:95:6:95:6 | 0 | tst.js:95:6:95:6 | 0 | +| tst.js:98:1:103:2 | (functi ... + z;\\n}) | tst.js:98:1:103:2 | (functi ... + z;\\n}) | +| tst.js:98:1:103:17 | (functi ... 3, 0 ]) | tst.js:98:1:103:17 | (functi ... 3, 0 ]) | +| tst.js:98:2:103:1 | functio ... + z;\\n} | tst.js:98:2:103:1 | functio ... + z;\\n} | +| tst.js:98:11:98:24 | [ x, ...rest ] | tst.js:98:11:98:24 | [ x, ...rest ] | +| tst.js:98:11:98:24 | [ x, ...rest ] | tst.js:98:11:98:24 | [ x, ...rest ] | +| tst.js:98:13:98:13 | x | tst.js:98:13:98:13 | x | +| tst.js:98:19:98:22 | rest | tst.js:98:19:98:22 | rest | +| tst.js:99:7:99:11 | [ y ] | tst.js:99:7:99:11 | [ y ] | +| tst.js:99:7:99:18 | [ y ] = rest | tst.js:99:7:99:18 | [ y ] = rest | +| tst.js:99:9:99:9 | y | tst.js:99:9:99:9 | y | +| tst.js:99:15:99:18 | rest | tst.js:99:15:99:18 | rest | +| tst.js:100:7:100:7 | z | tst.js:100:7:100:7 | z | +| tst.js:100:7:100:7 | z | tst.js:100:7:100:7 | z | +| tst.js:101:3:101:9 | [ , z ] | tst.js:101:3:101:9 | [ , z ] | +| tst.js:101:3:101:16 | [ , z ] = rest | tst.js:101:3:101:16 | [ , z ] = rest | +| tst.js:101:7:101:7 | z | tst.js:101:7:101:7 | z | +| tst.js:101:13:101:16 | rest | tst.js:101:13:101:16 | rest | +| tst.js:102:10:102:10 | x | tst.js:102:10:102:10 | x | +| tst.js:102:10:102:14 | x + y | tst.js:102:10:102:14 | x + y | +| tst.js:102:10:102:18 | x + y + z | tst.js:102:10:102:18 | x + y + z | +| tst.js:102:14:102:14 | y | tst.js:102:14:102:14 | y | +| tst.js:102:18:102:18 | z | tst.js:102:18:102:18 | z | +| tst.js:103:4:103:16 | [ 19, 23, 0 ] | tst.js:103:4:103:16 | [ 19, 23, 0 ] | +| tst.js:103:6:103:7 | 19 | tst.js:103:6:103:7 | 19 | +| tst.js:103:10:103:11 | 23 | tst.js:103:10:103:11 | 23 | +| tst.js:103:14:103:14 | 0 | tst.js:103:14:103:14 | 0 | +| tst.js:105:1:105:1 | x | tst.js:105:1:105:1 | x | +| tst.js:105:1:105:6 | x ?? y | tst.js:105:1:105:6 | x ?? y | +| tst.js:105:6:105:6 | y | tst.js:105:6:105:6 | y | +| tst.js:107:1:113:2 | (functi ... v2c;\\n}) | tst.js:107:1:113:2 | (functi ... v2c;\\n}) | +| tst.js:107:2:113:1 | functio ... v2c;\\n} | tst.js:107:2:113:1 | functio ... v2c;\\n} | +| tst.js:108:6:108:32 | {v1a, v ... = o1c} | tst.js:108:6:108:32 | {v1a, v ... = o1c} | +| tst.js:108:6:108:38 | {v1a, v ... } = o1d | tst.js:108:6:108:38 | {v1a, v ... } = o1d | +| tst.js:108:7:108:9 | v1a | tst.js:108:7:108:9 | v1a | +| tst.js:108:7:108:9 | v1a | tst.js:108:7:108:9 | v1a | +| tst.js:108:12:108:14 | v1b | tst.js:108:12:108:14 | v1b | +| tst.js:108:12:108:14 | v1b | tst.js:108:12:108:14 | v1b | +| tst.js:108:18:108:20 | o1b | tst.js:108:18:108:20 | o1b | +| tst.js:108:23:108:25 | v1c | tst.js:108:23:108:25 | v1c | +| tst.js:108:23:108:25 | v1c | tst.js:108:23:108:25 | v1c | +| tst.js:108:29:108:31 | o1c | tst.js:108:29:108:31 | o1c | +| tst.js:108:36:108:38 | o1d | tst.js:108:36:108:38 | o1d | +| tst.js:109:2:109:4 | v1a | tst.js:109:2:109:4 | v1a | +| tst.js:109:2:109:10 | v1a + v1b | tst.js:109:2:109:10 | v1a + v1b | +| tst.js:109:2:109:16 | v1a + v1b + v1c | tst.js:109:2:109:16 | v1a + v1b + v1c | +| tst.js:109:8:109:10 | v1b | tst.js:109:8:109:10 | v1b | +| tst.js:109:14:109:16 | v1c | tst.js:109:14:109:16 | v1c | +| tst.js:111:6:111:32 | [v2a, v ... = o2c] | tst.js:111:6:111:32 | [v2a, v ... = o2c] | +| tst.js:111:6:111:38 | [v2a, v ... ] = o2d | tst.js:111:6:111:38 | [v2a, v ... ] = o2d | +| tst.js:111:7:111:9 | v2a | tst.js:111:7:111:9 | v2a | +| tst.js:111:12:111:14 | v2b | tst.js:111:12:111:14 | v2b | +| tst.js:111:18:111:20 | o2b | tst.js:111:18:111:20 | o2b | +| tst.js:111:23:111:25 | v2c | tst.js:111:23:111:25 | v2c | +| tst.js:111:29:111:31 | o2c | tst.js:111:29:111:31 | o2c | +| tst.js:111:36:111:38 | o2d | tst.js:111:36:111:38 | o2d | +| tst.js:112:2:112:4 | v2a | tst.js:112:2:112:4 | v2a | +| tst.js:112:2:112:10 | v2a + v2b | tst.js:112:2:112:10 | v2a + v2b | +| tst.js:112:2:112:16 | v2a + v2b + v2c | tst.js:112:2:112:16 | v2a + v2b + v2c | +| tst.js:112:8:112:10 | v2b | tst.js:112:8:112:10 | v2b | +| tst.js:112:14:112:16 | v2c | tst.js:112:14:112:16 | v2c | +| tst.js:115:1:115:5 | Array | tst.js:115:1:115:5 | Array | +| tst.js:115:1:115:10 | Array.call | tst.js:115:1:115:10 | Array.call | +| tst.js:115:1:115:12 | Array.call() | tst.js:115:1:115:12 | Array.call() | +| tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | +| tst.js:115:7:115:10 | call | tst.js:115:7:115:10 | call | +| tst.ts:1:11:1:11 | A | tst.ts:1:11:1:11 | A | +| tst.ts:2:14:2:14 | x | tst.ts:2:14:2:14 | x | +| tst.ts:2:14:2:19 | x = 42 | tst.ts:2:14:2:19 | x = 42 | +| tst.ts:2:18:2:19 | 42 | tst.ts:2:18:2:19 | 42 | +| tst.ts:3:3:3:6 | setX | tst.ts:3:3:3:6 | setX | +| tst.ts:3:3:3:8 | setX() | tst.ts:3:3:3:8 | setX() | +| tst.ts:4:3:4:3 | x | tst.ts:4:3:4:3 | x | +| tst.ts:7:10:7:13 | setX | tst.ts:7:10:7:13 | setX | +| tst.ts:8:3:8:3 | A | tst.ts:8:3:8:3 | A | +| tst.ts:8:3:8:5 | A.x | tst.ts:8:3:8:5 | A.x | +| tst.ts:8:3:8:10 | A.x = 23 | tst.ts:8:3:8:10 | A.x = 23 | +| tst.ts:8:5:8:5 | x | tst.ts:8:5:8:5 | x | +| tst.ts:8:9:8:10 | 23 | tst.ts:8:9:8:10 | 23 | +| tst.ts:11:5:11:7 | nd2 | tst.ts:11:5:11:7 | nd2 | +| tst.ts:11:5:11:23 | nd2 = A.x as number | tst.ts:11:5:11:23 | nd2 = A.x as number | +| tst.ts:11:11:11:11 | A | tst.ts:11:11:11:11 | A | +| tst.ts:11:11:11:13 | A.x | tst.ts:11:11:11:13 | A.x | +| tst.ts:11:11:11:23 | A.x as number | tst.ts:11:11:11:23 | A.x as number | +| tst.ts:11:13:11:13 | x | tst.ts:11:13:11:13 | x | +| tst.ts:13:7:13:16 | StringList | tst.ts:13:7:13:16 | StringList | +| tst.ts:13:26:13:29 | List | tst.ts:13:26:13:29 | List | +| tst.ts:13:26:13:37 | List | tst.ts:13:26:13:37 | List | +| tst.ts:13:39:13:38 | (...arg ... rgs); } | tst.ts:13:39:13:38 | (...arg ... rgs); } | +| tst.ts:13:39:13:38 | ...args | tst.ts:13:39:13:38 | ...args | +| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | +| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | +| tst.ts:13:39:13:38 | args | tst.ts:13:39:13:38 | args | +| tst.ts:13:39:13:38 | constructor | tst.ts:13:39:13:38 | constructor | +| tst.ts:13:39:13:38 | super | tst.ts:13:39:13:38 | super | +| tst.ts:13:39:13:38 | super(...args) | tst.ts:13:39:13:38 | super(...args) | diff --git a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.ql b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.ql new file mode 100644 index 000000000000..6b0a506ce798 --- /dev/null +++ b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.ql @@ -0,0 +1,4 @@ +import javascript + +from DataFlow::Node node +select node, node.getEnclosingExpr() From 0c080a82be1baf0f6d60ccf845fa0de61823cfb0 Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Thu, 7 Nov 2019 14:31:09 +0100 Subject: [PATCH 0263/2538] fix expected output --- .../library-tests/DataFlow/enclosingExpr.expected | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected index eb50988eacbc..b7da1347fce9 100644 --- a/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected +++ b/javascript/ql/test/library-tests/DataFlow/enclosingExpr.expected @@ -22,6 +22,19 @@ | sources.js:4:12:4:13 | 19 | sources.js:4:12:4:13 | 19 | | sources.js:5:4:5:5 | 23 | sources.js:5:4:5:5 | 23 | | sources.js:7:1:7:3 | /x/ | sources.js:7:1:7:3 | /x/ | +| sources.js:9:10:9:12 | foo | sources.js:9:10:9:12 | foo | +| sources.js:9:14:9:18 | array | sources.js:9:14:9:18 | array | +| sources.js:9:14:9:18 | array | sources.js:9:14:9:18 | array | +| sources.js:10:12:10:14 | key | sources.js:10:12:10:14 | key | +| sources.js:10:12:10:14 | key | sources.js:10:12:10:14 | key | +| sources.js:10:19:10:23 | array | sources.js:10:19:10:23 | array | +| sources.js:10:28:10:30 | key | sources.js:10:28:10:30 | key | +| sources.js:11:12:11:18 | { key } | sources.js:11:12:11:18 | { key } | +| sources.js:11:12:11:18 | { key } | sources.js:11:12:11:18 | { key } | +| sources.js:11:14:11:16 | key | sources.js:11:14:11:16 | key | +| sources.js:11:14:11:16 | key | sources.js:11:14:11:16 | key | +| sources.js:11:23:11:27 | array | sources.js:11:23:11:27 | array | +| sources.js:11:32:11:34 | key | sources.js:11:32:11:34 | key | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | | tst.js:1:10:1:11 | fs | tst.js:1:10:1:11 | fs | @@ -276,7 +289,7 @@ | tst.js:115:1:115:12 | Array.call() | tst.js:115:1:115:12 | Array.call() | | tst.js:115:1:115:12 | reflective call | tst.js:115:1:115:12 | Array.call() | | tst.js:115:7:115:10 | call | tst.js:115:7:115:10 | call | -| tst.ts:1:11:1:11 | A | tst.ts:1:11:1:11 | A | +| tst.ts:1:18:1:18 | A | tst.ts:1:18:1:18 | A | | tst.ts:2:14:2:14 | x | tst.ts:2:14:2:14 | x | | tst.ts:2:14:2:19 | x = 42 | tst.ts:2:14:2:19 | x = 42 | | tst.ts:2:18:2:19 | 42 | tst.ts:2:18:2:19 | 42 | From c0884e9a888ea8fcde2bb01a85a080533efcdaad Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Thu, 7 Nov 2019 10:34:59 +0000 Subject: [PATCH 0264/2538] C++: Update expected results. --- .../copy_from_prototype.expected | 2 +- .../syntax-zoo/drawDifferent.expected | 161 ++++++++++++------ .../syntax-zoo/tellDifferent.expected | 11 ++ .../elements.expected | 4 +- 4 files changed, 122 insertions(+), 56 deletions(-) diff --git a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected index 9d77efe772f8..f5ef2d77c986 100644 --- a/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected +++ b/cpp/ql/test/library-tests/noexcept/copy_from_prototype/copy_from_prototype.expected @@ -13,7 +13,7 @@ | copy_from_prototype.cpp:13:7:13:7 | c | c::c(const c &) -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(c &&) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:13:7:13:7 | operator= | c::operator=(const c &) -> c & | copy_from_prototype.cpp:13:7:13:7 | c | | -| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | Unknown literal | +| copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | X | | copy_from_prototype.cpp:14:26:14:26 | c | c::c<(unnamed)>() -> void | copy_from_prototype.cpp:13:7:13:7 | c | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d() -> void | copy_from_prototype.cpp:17:7:17:7 | d | | | copy_from_prototype.cpp:17:7:17:7 | d | d::d(const d &) -> void | copy_from_prototype.cpp:17:7:17:7 | d | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected index 00cdd21f9eda..6e255ec81b29 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected @@ -1,53 +1,108 @@ -| staticlocals__staticlocals_f2_extractor | false | 22465 | 22465 | f2 | -| staticlocals__staticlocals_f2_extractor | false | 22470 | 22470 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22472 | 22472 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22474 | 22474 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22476 | 22476 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 22478 | 22478 | return ... | -| staticlocals__staticlocals_f2_extractor | false | 22480 | 22480 | { ... } | -| staticlocals__staticlocals_f2_extractor | false | 22482 | 22482 | call to C | -| staticlocals__staticlocals_f2_extractor | false | 22484 | 22484 | initializer for c | -| staticlocals__staticlocals_f2_extractor | false | 22486 | 22486 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 22490 | 22490 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 22493 | 22493 | initializer for j | -| staticlocals__staticlocals_f2_extractor | false | 22494 | 22494 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 22499 | 22499 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 22500 | 22500 | initializer for two | -| staticlocals__staticlocals_f2_extractor | false | 22503 | 22503 | two | -| staticlocals__staticlocals_f2_extractor | false | 22508 | 22508 | initializer for i | -| staticlocals__staticlocals_f2_extractor | true | 22470 | 22500 | | -| staticlocals__staticlocals_f2_extractor | true | 22472 | 22474 | | -| staticlocals__staticlocals_f2_extractor | true | 22474 | 22476 | | -| staticlocals__staticlocals_f2_extractor | true | 22476 | 22478 | | -| staticlocals__staticlocals_f2_extractor | true | 22478 | 22465 | | -| staticlocals__staticlocals_f2_extractor | true | 22480 | 22470 | | -| staticlocals__staticlocals_f2_extractor | true | 22499 | 22472 | | -| staticlocals__staticlocals_f2_extractor | true | 22500 | 22499 | | -| staticlocals__staticlocals_f2_ql | false | 22465 | 22465 | f2 | -| staticlocals__staticlocals_f2_ql | false | 22470 | 22470 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22472 | 22472 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22474 | 22474 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22476 | 22476 | declaration | -| staticlocals__staticlocals_f2_ql | false | 22478 | 22478 | return ... | -| staticlocals__staticlocals_f2_ql | false | 22480 | 22480 | { ... } | -| staticlocals__staticlocals_f2_ql | false | 22482 | 22482 | call to C | -| staticlocals__staticlocals_f2_ql | false | 22484 | 22484 | initializer for c | -| staticlocals__staticlocals_f2_ql | false | 22486 | 22486 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 22490 | 22490 | 2 | -| staticlocals__staticlocals_f2_ql | false | 22493 | 22493 | initializer for j | -| staticlocals__staticlocals_f2_ql | false | 22494 | 22494 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 22499 | 22499 | 2 | -| staticlocals__staticlocals_f2_ql | false | 22500 | 22500 | initializer for two | -| staticlocals__staticlocals_f2_ql | false | 22503 | 22503 | two | -| staticlocals__staticlocals_f2_ql | false | 22508 | 22508 | initializer for i | -| staticlocals__staticlocals_f2_ql | true | 22470 | 22500 | | -| staticlocals__staticlocals_f2_ql | true | 22472 | 22474 | | -| staticlocals__staticlocals_f2_ql | true | 22474 | 22476 | | -| staticlocals__staticlocals_f2_ql | true | 22476 | 22478 | | -| staticlocals__staticlocals_f2_ql | true | 22476 | 22484 | | -| staticlocals__staticlocals_f2_ql | true | 22478 | 22465 | | -| staticlocals__staticlocals_f2_ql | true | 22480 | 22470 | | -| staticlocals__staticlocals_f2_ql | true | 22482 | 22478 | | -| staticlocals__staticlocals_f2_ql | true | 22484 | 22482 | | -| staticlocals__staticlocals_f2_ql | true | 22499 | 22472 | | -| staticlocals__staticlocals_f2_ql | true | 22500 | 22499 | | +| pointer_to_member__pmIsConstT_extractor | false | 21747 | 21747 | pmIsConstT | +| pointer_to_member__pmIsConstT_extractor | false | 21756 | 21756 | declaration | +| pointer_to_member__pmIsConstT_extractor | false | 21759 | 21759 | return ... | +| pointer_to_member__pmIsConstT_extractor | false | 21762 | 21762 | { ... } | +| pointer_to_member__pmIsConstT_extractor | false | 21766 | 21766 | {...} | +| pointer_to_member__pmIsConstT_extractor | false | 21773 | 21773 | x1 | +| pointer_to_member__pmIsConstT_extractor | false | 21777 | 21777 | & ... | +| pointer_to_member__pmIsConstT_extractor | false | 21784 | 21784 | f1 | +| pointer_to_member__pmIsConstT_extractor | false | 21788 | 21788 | & ... | +| pointer_to_member__pmIsConstT_extractor | false | 21791 | 21791 | initializer for pms | +| pointer_to_member__pmIsConstT_extractor | true | 21756 | 21759 | | +| pointer_to_member__pmIsConstT_extractor | true | 21759 | 21747 | | +| pointer_to_member__pmIsConstT_extractor | true | 21762 | 21756 | | +| pointer_to_member__pmIsConstT_ql | false | 21747 | 21747 | pmIsConstT | +| pointer_to_member__pmIsConstT_ql | false | 21756 | 21756 | declaration | +| pointer_to_member__pmIsConstT_ql | false | 21759 | 21759 | return ... | +| pointer_to_member__pmIsConstT_ql | false | 21762 | 21762 | { ... } | +| pointer_to_member__pmIsConstT_ql | false | 21766 | 21766 | {...} | +| pointer_to_member__pmIsConstT_ql | false | 21773 | 21773 | x1 | +| pointer_to_member__pmIsConstT_ql | false | 21777 | 21777 | & ... | +| pointer_to_member__pmIsConstT_ql | false | 21784 | 21784 | f1 | +| pointer_to_member__pmIsConstT_ql | false | 21788 | 21788 | & ... | +| pointer_to_member__pmIsConstT_ql | false | 21791 | 21791 | initializer for pms | +| pointer_to_member__pmIsConstT_ql | true | 21756 | 21791 | | +| pointer_to_member__pmIsConstT_ql | true | 21759 | 21747 | | +| pointer_to_member__pmIsConstT_ql | true | 21762 | 21756 | | +| pointer_to_member__pmIsConstT_ql | true | 21766 | 21759 | | +| pointer_to_member__pmIsConstT_ql | true | 21773 | 21777 | | +| pointer_to_member__pmIsConstT_ql | true | 21777 | 21784 | | +| pointer_to_member__pmIsConstT_ql | true | 21784 | 21788 | | +| pointer_to_member__pmIsConstT_ql | true | 21788 | 21766 | | +| pointer_to_member__pmIsConstT_ql | true | 21791 | 21773 | | +| staticlocals__staticlocals_f2_extractor | false | 31503 | 31503 | f2 | +| staticlocals__staticlocals_f2_extractor | false | 31509 | 31509 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31512 | 31512 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31515 | 31515 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31518 | 31518 | declaration | +| staticlocals__staticlocals_f2_extractor | false | 31521 | 31521 | return ... | +| staticlocals__staticlocals_f2_extractor | false | 31524 | 31524 | { ... } | +| staticlocals__staticlocals_f2_extractor | false | 31527 | 31527 | call to C | +| staticlocals__staticlocals_f2_extractor | false | 31530 | 31530 | initializer for c | +| staticlocals__staticlocals_f2_extractor | false | 31533 | 31533 | call to addOne | +| staticlocals__staticlocals_f2_extractor | false | 31539 | 31539 | 2 | +| staticlocals__staticlocals_f2_extractor | false | 31544 | 31544 | initializer for j | +| staticlocals__staticlocals_f2_extractor | false | 31546 | 31546 | call to addOne | +| staticlocals__staticlocals_f2_extractor | false | 31554 | 31554 | 2 | +| staticlocals__staticlocals_f2_extractor | false | 31556 | 31556 | initializer for two | +| staticlocals__staticlocals_f2_extractor | false | 31560 | 31560 | two | +| staticlocals__staticlocals_f2_extractor | false | 31568 | 31568 | initializer for i | +| staticlocals__staticlocals_f2_extractor | true | 31509 | 31556 | | +| staticlocals__staticlocals_f2_extractor | true | 31512 | 31515 | | +| staticlocals__staticlocals_f2_extractor | true | 31515 | 31518 | | +| staticlocals__staticlocals_f2_extractor | true | 31518 | 31521 | | +| staticlocals__staticlocals_f2_extractor | true | 31521 | 31503 | | +| staticlocals__staticlocals_f2_extractor | true | 31524 | 31509 | | +| staticlocals__staticlocals_f2_extractor | true | 31554 | 31512 | | +| staticlocals__staticlocals_f2_extractor | true | 31556 | 31554 | | +| staticlocals__staticlocals_f2_ql | false | 31503 | 31503 | f2 | +| staticlocals__staticlocals_f2_ql | false | 31509 | 31509 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31512 | 31512 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31515 | 31515 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31518 | 31518 | declaration | +| staticlocals__staticlocals_f2_ql | false | 31521 | 31521 | return ... | +| staticlocals__staticlocals_f2_ql | false | 31524 | 31524 | { ... } | +| staticlocals__staticlocals_f2_ql | false | 31527 | 31527 | call to C | +| staticlocals__staticlocals_f2_ql | false | 31530 | 31530 | initializer for c | +| staticlocals__staticlocals_f2_ql | false | 31533 | 31533 | call to addOne | +| staticlocals__staticlocals_f2_ql | false | 31539 | 31539 | 2 | +| staticlocals__staticlocals_f2_ql | false | 31544 | 31544 | initializer for j | +| staticlocals__staticlocals_f2_ql | false | 31546 | 31546 | call to addOne | +| staticlocals__staticlocals_f2_ql | false | 31554 | 31554 | 2 | +| staticlocals__staticlocals_f2_ql | false | 31556 | 31556 | initializer for two | +| staticlocals__staticlocals_f2_ql | false | 31560 | 31560 | two | +| staticlocals__staticlocals_f2_ql | false | 31568 | 31568 | initializer for i | +| staticlocals__staticlocals_f2_ql | true | 31509 | 31556 | | +| staticlocals__staticlocals_f2_ql | true | 31512 | 31515 | | +| staticlocals__staticlocals_f2_ql | true | 31515 | 31518 | | +| staticlocals__staticlocals_f2_ql | true | 31518 | 31521 | | +| staticlocals__staticlocals_f2_ql | true | 31518 | 31530 | | +| staticlocals__staticlocals_f2_ql | true | 31521 | 31503 | | +| staticlocals__staticlocals_f2_ql | true | 31524 | 31509 | | +| staticlocals__staticlocals_f2_ql | true | 31527 | 31521 | | +| staticlocals__staticlocals_f2_ql | true | 31530 | 31527 | | +| staticlocals__staticlocals_f2_ql | true | 31554 | 31512 | | +| staticlocals__staticlocals_f2_ql | true | 31556 | 31554 | | +| staticlocals__staticlocals_f3_extractor | false | 31473 | 31473 | f3 | +| staticlocals__staticlocals_f3_extractor | false | 31477 | 31477 | declaration | +| staticlocals__staticlocals_f3_extractor | false | 31480 | 31480 | return ... | +| staticlocals__staticlocals_f3_extractor | false | 31483 | 31483 | { ... } | +| staticlocals__staticlocals_f3_extractor | false | 31492 | 31492 | value | +| staticlocals__staticlocals_f3_extractor | false | 31496 | 31496 | (int)... | +| staticlocals__staticlocals_f3_extractor | false | 31498 | 31498 | initializer for i | +| staticlocals__staticlocals_f3_extractor | true | 31477 | 31480 | | +| staticlocals__staticlocals_f3_extractor | true | 31480 | 31473 | | +| staticlocals__staticlocals_f3_extractor | true | 31483 | 31477 | | +| staticlocals__staticlocals_f3_ql | false | 31473 | 31473 | f3 | +| staticlocals__staticlocals_f3_ql | false | 31477 | 31477 | declaration | +| staticlocals__staticlocals_f3_ql | false | 31480 | 31480 | return ... | +| staticlocals__staticlocals_f3_ql | false | 31483 | 31483 | { ... } | +| staticlocals__staticlocals_f3_ql | false | 31492 | 31492 | value | +| staticlocals__staticlocals_f3_ql | false | 31496 | 31496 | (int)... | +| staticlocals__staticlocals_f3_ql | false | 31498 | 31498 | initializer for i | +| staticlocals__staticlocals_f3_ql | true | 31477 | 31480 | | +| staticlocals__staticlocals_f3_ql | true | 31477 | 31498 | | +| staticlocals__staticlocals_f3_ql | true | 31480 | 31473 | | +| staticlocals__staticlocals_f3_ql | true | 31483 | 31477 | | +| staticlocals__staticlocals_f3_ql | true | 31492 | 31480 | | +| staticlocals__staticlocals_f3_ql | true | 31498 | 31492 | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected index 0e06bb202c4b..ae6f34298925 100644 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected +++ b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected @@ -1,3 +1,14 @@ +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:44:11:44:28 | initializer for pms | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from extractor | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | initializer for pms | pointer_to_member.cpp:44:14:44:18 | x1 | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | {...} | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:13:44:18 | & ... | pointer_to_member.cpp:44:22:44:26 | f1 | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:14:44:18 | x1 | pointer_to_member.cpp:44:13:44:18 | & ... | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:21:44:26 | & ... | pointer_to_member.cpp:44:11:44:28 | {...} | Standard edge, only from QL | uninstantiated | +| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:22:44:26 | f1 | pointer_to_member.cpp:44:21:44:26 | & ... | Standard edge, only from QL | uninstantiated | | staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | | | staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | | | staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | | +| staticlocals__staticlocals_f3 | staticlocals.cpp:39:3:39:34 | declaration | staticlocals.cpp:39:18:39:33 | initializer for i | Standard edge, only from QL | uninstantiated | +| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | initializer for i | staticlocals.cpp:39:18:39:33 | value | Standard edge, only from QL | uninstantiated | +| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | value | staticlocals.cpp:40:1:40:1 | return ... | Standard edge, only from QL | uninstantiated | diff --git a/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected b/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected index 802903a40b6d..99a6201c59c9 100644 --- a/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected +++ b/cpp/ql/test/library-tests/templates/instantiations_functions/elements.expected @@ -317,8 +317,8 @@ | test.cpp:19:9:19:24 | call to expression | | test.cpp:19:9:19:25 | ExprStmt | | test.cpp:19:9:19:25 | ExprStmt | -| test.cpp:19:15:19:18 | Unknown literal | | test.cpp:19:15:19:18 | call to funx | +| test.cpp:19:15:19:18 | funx | | test.cpp:19:20:19:23 | (reference to) | | test.cpp:19:20:19:23 | valx | | test.cpp:19:20:19:23 | valx | @@ -356,8 +356,8 @@ | test.cpp:30:13:30:22 | call to expression | | test.cpp:30:13:30:23 | ExprStmt | | test.cpp:30:13:30:23 | ExprStmt | -| test.cpp:30:15:30:20 | Unknown literal | | test.cpp:30:15:30:20 | call to eparse | +| test.cpp:30:15:30:20 | eparse | | test.cpp:31:9:31:9 | return ... | | test.cpp:31:9:31:9 | return ... | | test.cpp:34:6:34:11 | define | From ddf1ef8a7d65ceb869fae56b83be92da6a768c0c Mon Sep 17 00:00:00 2001 From: Matthew Gretton-Dann Date: Thu, 7 Nov 2019 10:35:26 +0000 Subject: [PATCH 0265/2538] C++: Add new test case for template member change We now output literals for accesses to members of template parameters: So for `foo` in the following example: ``` template void bar(T& t) { T.foo(1) } ``` --- .../CPP-172-template-members/test.cpp | 19 +++++++++++++++++++ .../CPP-172-template-members/test.expected | 2 ++ .../CPP-172-template-members/test.ql | 4 ++++ 3 files changed, 25 insertions(+) create mode 100644 cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp create mode 100644 cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected create mode 100644 cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp new file mode 100644 index 000000000000..9a624d5d9f04 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.cpp @@ -0,0 +1,19 @@ + + +class A { +public: + void foo(); + int k; +}; + +class B { +public: + template + B(T x) { + int k = x.k; + x.foo(); + } +}; + +A a; +B b(a); diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected new file mode 100644 index 000000000000..29d00dc147aa --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.expected @@ -0,0 +1,2 @@ +| test.cpp:13:15:13:15 | k | +| test.cpp:14:7:14:9 | foo | diff --git a/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql new file mode 100644 index 000000000000..233c7cdce8d4 --- /dev/null +++ b/cpp/ql/test/library-tests/templates/CPP-172-template-members/test.ql @@ -0,0 +1,4 @@ +import cpp + +from Literal l +select l From db2039d8a75cdd76bc31c35be122d579d9015584 Mon Sep 17 00:00:00 2001 From: james Date: Thu, 7 Nov 2019 13:17:57 +0000 Subject: [PATCH 0266/2538] docs: learn codeql terminology note --- docs/language/learn-ql/index.rst | 12 +++++++++ docs/language/learn-ql/terminology-note.rst | 27 +++++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 docs/language/learn-ql/terminology-note.rst diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 766498901314..5a3c70c45803 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -9,6 +9,18 @@ Here, you can query open source projects directly, without having to download Co CodeQL is based on a powerful query language called QL. The following topics help you understand QL in general, as well as how to use it when analyzing code with CodeQL. +.. pull-quote:: + + Important + + If you've previously used QL, you may notice some slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. + +.. toctree:: + :hidden: + + terminology-note + + .. _getting-started: Getting started diff --git a/docs/language/learn-ql/terminology-note.rst b/docs/language/learn-ql/terminology-note.rst new file mode 100644 index 000000000000..794106d57055 --- /dev/null +++ b/docs/language/learn-ql/terminology-note.rst @@ -0,0 +1,27 @@ +Recent terminology changes +=========================== + +We recently started using new terminology to make it clearer to users what our products do. +This note gives some information about what has changed. + +CodeQL +------ + +CodeQL is the code analysis platform formerly known as QL. +CodeQL treats code as data, and CodeQL analysis is based on running queries against your code to check for errors and find bugs and vulnerabilities. +The CodeQL product includes the tools, scripts, queries, and libraries used in CodeQL analysis. + +QL +--- + +Previously we used the term QL to refer to the whole code analysis platform, which has been renamed CodeQL. +The name QL now only refers to the query language that powers CodeQL analysis. + +The CodeQL queries and libraries used to analyze source code are written in QL. +These queries and libraries are open source, and can be found in the `CodeQL repository `__. +QL is a general-purpose, object-oriented language that can be used to query any kind of data. + +CodeQL databases +---------------- + +QL snapshots have been renamed CodeQL databases. CodeQL databases contain relational data created and analyzed using CodeQL. They are the equivalent of QL snapshots, but have been optimized for use with the CodeQL tools. From 8544850945898dee993de50e7f909e22f711f79c Mon Sep 17 00:00:00 2001 From: Asger F Date: Tue, 5 Nov 2019 12:00:50 +0000 Subject: [PATCH 0267/2538] JS: Generalize StringOps::Includes to ::InclusionTest --- javascript/ql/src/javascript.qll | 1 + .../src/semmle/javascript/InclusionTests.qll | 173 ++++++++++++++++++ .../ql/src/semmle/javascript/StringOps.qll | 157 +--------------- .../javascript/dataflow/TaintTracking.qll | 13 +- 4 files changed, 187 insertions(+), 157 deletions(-) create mode 100644 javascript/ql/src/semmle/javascript/InclusionTests.qll diff --git a/javascript/ql/src/javascript.qll b/javascript/ql/src/javascript.qll index 9e75e032b1c5..a6df138c592d 100644 --- a/javascript/ql/src/javascript.qll +++ b/javascript/ql/src/javascript.qll @@ -28,6 +28,7 @@ import semmle.javascript.Functions import semmle.javascript.GlobalAccessPaths import semmle.javascript.HTML import semmle.javascript.HtmlSanitizers +import semmle.javascript.InclusionTests import semmle.javascript.JSDoc import semmle.javascript.JSON import semmle.javascript.JsonParsers diff --git a/javascript/ql/src/semmle/javascript/InclusionTests.qll b/javascript/ql/src/semmle/javascript/InclusionTests.qll new file mode 100644 index 000000000000..7a90dbf15837 --- /dev/null +++ b/javascript/ql/src/semmle/javascript/InclusionTests.qll @@ -0,0 +1,173 @@ +/** + * Contains classes for recognizing array and string inclusion tests. + */ +private import javascript + +/** + * A expression that checks if an element is contained in an array + * or is a substring of another string. + * + * Examples: + * ``` + * A.includes(B) + * A.indexOf(B) !== -1 + * A.indexOf(B) >= 0 + * ~A.indexOf(B) + * ``` + */ +class InclusionTest extends DataFlow::Node { + InclusionTest::Range range; + + InclusionTest() { this = range } + + /** Gets the `A` in `A.includes(B)`. */ + DataFlow::Node getContainerNode() { result = range.getContainerNode() } + + /** Gets the `B` in `A.includes(B)`. */ + DataFlow::Node getContainedNode() { result = range.getContainedNode() } + + /** + * Gets the polarity of the check. + * + * If the polarity is `false` the check returns `true` if the container does not contain + * the given element. + */ + boolean getPolarity() { result = range.getPolarity() } +} + +module InclusionTest { + /** + * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. + * + * Note that this also includes calls to the array method named `includes`. + */ + abstract class Range extends DataFlow::Node { + /** Gets the `A` in `A.includes(B)`. */ + abstract DataFlow::Node getContainerNode(); + + /** Gets the `B` in `A.includes(B)`. */ + abstract DataFlow::Node getContainedNode(); + + /** + * Gets the polarity of the check. + * + * If the polarity is `false` the check returns `true` if the container does not contain + * the given element. + */ + boolean getPolarity() { result = true } + } + + /** + * A call to a method named `includes`, assumed to refer to `String.prototype.includes` + * or `Array.prototype.includes`. + */ + private class Includes_Native extends Range, DataFlow::MethodCallNode { + Includes_Native() { + getMethodName() = "includes" and + getNumArgument() = 1 + } + + override DataFlow::Node getContainerNode() { result = getReceiver() } + + override DataFlow::Node getContainedNode() { result = getArgument(0) } + } + + /** + * A call to `_.includes` or similar, assumed to operate on strings. + */ + private class Includes_Library extends Range, DataFlow::CallNode { + Includes_Library() { + exists(string name | + this = LodashUnderscore::member(name).getACall() and + (name = "includes" or name = "include" or name = "contains") + or + this = Closure::moduleImport("goog.string." + name).getACall() and + (name = "contains" or name = "caseInsensitiveContains") + ) + } + + override DataFlow::Node getContainerNode() { result = getArgument(0) } + + override DataFlow::Node getContainedNode() { result = getArgument(1) } + } + + /** + * A check of form `A.indexOf(B) !== -1` or similar. + */ + private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override EqualityTest astNode; + + Includes_IndexOfEquals() { + exists(Expr index | astNode.hasOperands(indexOf, index) | + // one operand is of the form `whitelist.indexOf(x)` + indexOf.getMethodName() = "indexOf" and + // and the other one is -1 + index.getIntValue() = -1 + ) + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + + override boolean getPolarity() { result = astNode.getPolarity().booleanNot() } + } + + /** + * A check of form `A.indexOf(B) >= 0` or similar. + */ + private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override RelationalComparison astNode; + boolean polarity; + + Includes_IndexOfRelational() { + exists(Expr lesser, Expr greater | + astNode.getLesserOperand() = lesser and + astNode.getGreaterOperand() = greater and + indexOf.getMethodName() = "indexOf" and + indexOf.getNumArgument() = 1 + | + polarity = true and + greater = indexOf and + ( + lesser.getIntValue() = 0 and astNode.isInclusive() + or + lesser.getIntValue() = -1 and not astNode.isInclusive() + ) + or + polarity = false and + lesser = indexOf and + ( + greater.getIntValue() = -1 and astNode.isInclusive() + or + greater.getIntValue() = 0 and not astNode.isInclusive() + ) + ) + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + + override boolean getPolarity() { result = polarity } + } + + /** + * An expression of form `~A.indexOf(B)` which, when coerced to a boolean, is equivalent to `A.includes(B)`. + */ + private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode { + MethodCallExpr indexOf; + override BitNotExpr astNode; + + Includes_IndexOfBitwise() { + astNode.getOperand() = indexOf and + indexOf.getMethodName() = "indexOf" + } + + override DataFlow::Node getContainerNode() { result = indexOf.getReceiver().flow() } + + override DataFlow::Node getContainedNode() { result = indexOf.getArgument(0).flow() } + } +} diff --git a/javascript/ql/src/semmle/javascript/StringOps.qll b/javascript/ql/src/semmle/javascript/StringOps.qll index f33dbd9f74da..d916e8e469d2 100644 --- a/javascript/ql/src/semmle/javascript/StringOps.qll +++ b/javascript/ql/src/semmle/javascript/StringOps.qll @@ -185,162 +185,15 @@ module StringOps { /** * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. * - * Note that this also includes calls to the array method named `includes`. + * Note that this class is equivalent to `InclusionTest`, which also matches + * inclusion tests on array objects. */ - class Includes extends DataFlow::Node { - Includes::Range range; - - Includes() { this = range } - + class Includes extends InclusionTest { /** Gets the `A` in `A.includes(B)`. */ - DataFlow::Node getBaseString() { result = range.getBaseString() } + DataFlow::Node getBaseString() { result = getContainerNode() } /** Gets the `B` in `A.includes(B)`. */ - DataFlow::Node getSubstring() { result = range.getSubstring() } - - /** - * Gets the polarity of the check. - * - * If the polarity is `false` the check returns `true` if the string does not contain - * the given substring. - */ - boolean getPolarity() { result = range.getPolarity() } - } - - module Includes { - /** - * A expression that is equivalent to `A.includes(B)` or `!A.includes(B)`. - * - * Note that this also includes calls to the array method named `includes`. - */ - abstract class Range extends DataFlow::Node { - /** Gets the `A` in `A.includes(B)`. */ - abstract DataFlow::Node getBaseString(); - - /** Gets the `B` in `A.includes(B)`. */ - abstract DataFlow::Node getSubstring(); - - /** - * Gets the polarity of the check. - * - * If the polarity is `false` the check returns `true` if the string does not contain - * the given substring. - */ - boolean getPolarity() { result = true } - } - - /** - * A call to a method named `includes`, assumed to refer to `String.prototype.includes`. - */ - private class Includes_Native extends Range, DataFlow::MethodCallNode { - Includes_Native() { - getMethodName() = "includes" and - getNumArgument() = 1 - } - - override DataFlow::Node getBaseString() { result = getReceiver() } - - override DataFlow::Node getSubstring() { result = getArgument(0) } - } - - /** - * A call to `_.includes` or similar, assumed to operate on strings. - */ - private class Includes_Library extends Range, DataFlow::CallNode { - Includes_Library() { - exists(string name | - this = LodashUnderscore::member(name).getACall() and - (name = "includes" or name = "include" or name = "contains") - or - this = Closure::moduleImport("goog.string." + name).getACall() and - (name = "contains" or name = "caseInsensitiveContains") - ) - } - - override DataFlow::Node getBaseString() { result = getArgument(0) } - - override DataFlow::Node getSubstring() { result = getArgument(1) } - } - - /** - * A check of form `A.indexOf(B) !== -1` or similar. - */ - private class Includes_IndexOfEquals extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override EqualityTest astNode; - - Includes_IndexOfEquals() { - exists(Expr index | astNode.hasOperands(indexOf, index) | - // one operand is of the form `whitelist.indexOf(x)` - indexOf.getMethodName() = "indexOf" and - // and the other one is -1 - index.getIntValue() = -1 - ) - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - - override boolean getPolarity() { result = astNode.getPolarity().booleanNot() } - } - - /** - * A check of form `A.indexOf(B) >= 0` or similar. - */ - private class Includes_IndexOfRelational extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override RelationalComparison astNode; - boolean polarity; - - Includes_IndexOfRelational() { - exists(Expr lesser, Expr greater | - astNode.getLesserOperand() = lesser and - astNode.getGreaterOperand() = greater and - indexOf.getMethodName() = "indexOf" and - indexOf.getNumArgument() = 1 - | - polarity = true and - greater = indexOf and - ( - lesser.getIntValue() = 0 and astNode.isInclusive() - or - lesser.getIntValue() = -1 and not astNode.isInclusive() - ) - or - polarity = false and - lesser = indexOf and - ( - greater.getIntValue() = -1 and astNode.isInclusive() - or - greater.getIntValue() = 0 and not astNode.isInclusive() - ) - ) - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - - override boolean getPolarity() { result = polarity } - } - - /** - * An expression of form `~A.indexOf(B)` which, when coerced to a boolean, is equivalent to `A.includes(B)`. - */ - private class Includes_IndexOfBitwise extends Range, DataFlow::ValueNode { - MethodCallExpr indexOf; - override BitNotExpr astNode; - - Includes_IndexOfBitwise() { - astNode.getOperand() = indexOf and - indexOf.getMethodName() = "indexOf" - } - - override DataFlow::Node getBaseString() { result = indexOf.getReceiver().flow() } - - override DataFlow::Node getSubstring() { result = indexOf.getArgument(0).flow() } - } + DataFlow::Node getSubstring() { result = getContainedNode() } } /** diff --git a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll index 06a0d9042613..a8a8356e6e20 100644 --- a/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll +++ b/javascript/ql/src/semmle/javascript/dataflow/TaintTracking.qll @@ -781,15 +781,18 @@ module TaintTracking { override predicate appliesTo(Configuration cfg) { any() } } + /** DEPRECATED. This class has been renamed to `InclusionSanitizer`. */ + deprecated class StringInclusionSanitizer = InclusionSanitizer; + /** A check of the form `whitelist.includes(x)` or equivalent, which sanitizes `x` in its "then" branch. */ - class StringInclusionSanitizer extends AdditionalSanitizerGuardNode { - StringOps::Includes includes; + class InclusionSanitizer extends AdditionalSanitizerGuardNode { + InclusionTest inclusion; - StringInclusionSanitizer() { this = includes } + InclusionSanitizer() { this = inclusion } override predicate sanitizes(boolean outcome, Expr e) { - outcome = includes.getPolarity() and - e = includes.getSubstring().asExpr() + outcome = inclusion.getPolarity() and + e = inclusion.getContainedNode().asExpr() } override predicate appliesTo(Configuration cfg) { any() } From d31ec56ea68b5354d458924a360b36675222935a Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 7 Nov 2019 14:39:52 +0000 Subject: [PATCH 0268/2538] Update docs/language/learn-ql/index.rst Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/index.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/learn-ql/index.rst b/docs/language/learn-ql/index.rst index 5a3c70c45803..add850f58061 100644 --- a/docs/language/learn-ql/index.rst +++ b/docs/language/learn-ql/index.rst @@ -13,7 +13,7 @@ CodeQL is based on a powerful query language called QL. The following topics hel Important - If you've previously used QL, you may notice some slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. + If you've previously used QL, you may notice slight changes in terms we use to describe some important concepts. For more information, see our note about :doc:`Recent terminology changes `. .. toctree:: :hidden: @@ -98,4 +98,4 @@ Search .. * :ref:`genindex` remove index for the time being as we currently have no tags -* :ref:`search` \ No newline at end of file +* :ref:`search` From 8178e3e67117ed4af20b7a2c5320a01ae86c811f Mon Sep 17 00:00:00 2001 From: James Fletcher <42464962+jf205@users.noreply.github.com> Date: Thu, 7 Nov 2019 14:40:04 +0000 Subject: [PATCH 0269/2538] Update docs/language/learn-ql/terminology-note.rst Co-Authored-By: shati-patel <42641846+shati-patel@users.noreply.github.com> --- docs/language/learn-ql/terminology-note.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/language/learn-ql/terminology-note.rst b/docs/language/learn-ql/terminology-note.rst index 794106d57055..552d7b2789cd 100644 --- a/docs/language/learn-ql/terminology-note.rst +++ b/docs/language/learn-ql/terminology-note.rst @@ -24,4 +24,4 @@ QL is a general-purpose, object-oriented language that can be used to query any CodeQL databases ---------------- -QL snapshots have been renamed CodeQL databases. CodeQL databases contain relational data created and analyzed using CodeQL. They are the equivalent of QL snapshots, but have been optimized for use with the CodeQL tools. +QL snapshots have been renamed CodeQL databases. :doc:`CodeQL databases ` contain relational data created and analyzed using CodeQL. They are the equivalent of QL snapshots, but have been optimized for use with the CodeQL tools. From 812ee34bbc14ecefee6d09024e4907479e666678 Mon Sep 17 00:00:00 2001 From: Asger F Date: Thu, 7 Nov 2019 15:53:29 +0000 Subject: [PATCH 0270/2538] JS: Use Files.exists() instead --- javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index e67c4095e19d..0f5c4ffbfd67 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -666,7 +666,7 @@ public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { if (!dir.equals(currentRoot[0]) && (excludes.contains(dir) || dir.toFile().isHidden())) return FileVisitResult.SKIP_SUBTREE; - if (dir.resolve("codeql-database.yml").toFile().exists()) { + if (Files.exists(dir.resolve("codeql-database.yml"))) { return FileVisitResult.SKIP_SUBTREE; } return super.preVisitDirectory(dir, attrs); From b5af4e5acd50d5cd19c22c398247fc8a99b11c31 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Thu, 7 Nov 2019 16:32:18 +0000 Subject: [PATCH 0271/2538] C++: Remove tests for CFG differences Now that we have switched over, they are no longer interesting. --- .../syntax-zoo/drawDifferent.expected | 108 ------------------ .../library-tests/syntax-zoo/drawDifferent.ql | 10 -- .../syntax-zoo/tellDifferent.expected | 14 --- .../library-tests/syntax-zoo/tellDifferent.ql | 13 --- 4 files changed, 145 deletions(-) delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected delete mode 100644 cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected deleted file mode 100644 index 6e255ec81b29..000000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.expected +++ /dev/null @@ -1,108 +0,0 @@ -| pointer_to_member__pmIsConstT_extractor | false | 21747 | 21747 | pmIsConstT | -| pointer_to_member__pmIsConstT_extractor | false | 21756 | 21756 | declaration | -| pointer_to_member__pmIsConstT_extractor | false | 21759 | 21759 | return ... | -| pointer_to_member__pmIsConstT_extractor | false | 21762 | 21762 | { ... } | -| pointer_to_member__pmIsConstT_extractor | false | 21766 | 21766 | {...} | -| pointer_to_member__pmIsConstT_extractor | false | 21773 | 21773 | x1 | -| pointer_to_member__pmIsConstT_extractor | false | 21777 | 21777 | & ... | -| pointer_to_member__pmIsConstT_extractor | false | 21784 | 21784 | f1 | -| pointer_to_member__pmIsConstT_extractor | false | 21788 | 21788 | & ... | -| pointer_to_member__pmIsConstT_extractor | false | 21791 | 21791 | initializer for pms | -| pointer_to_member__pmIsConstT_extractor | true | 21756 | 21759 | | -| pointer_to_member__pmIsConstT_extractor | true | 21759 | 21747 | | -| pointer_to_member__pmIsConstT_extractor | true | 21762 | 21756 | | -| pointer_to_member__pmIsConstT_ql | false | 21747 | 21747 | pmIsConstT | -| pointer_to_member__pmIsConstT_ql | false | 21756 | 21756 | declaration | -| pointer_to_member__pmIsConstT_ql | false | 21759 | 21759 | return ... | -| pointer_to_member__pmIsConstT_ql | false | 21762 | 21762 | { ... } | -| pointer_to_member__pmIsConstT_ql | false | 21766 | 21766 | {...} | -| pointer_to_member__pmIsConstT_ql | false | 21773 | 21773 | x1 | -| pointer_to_member__pmIsConstT_ql | false | 21777 | 21777 | & ... | -| pointer_to_member__pmIsConstT_ql | false | 21784 | 21784 | f1 | -| pointer_to_member__pmIsConstT_ql | false | 21788 | 21788 | & ... | -| pointer_to_member__pmIsConstT_ql | false | 21791 | 21791 | initializer for pms | -| pointer_to_member__pmIsConstT_ql | true | 21756 | 21791 | | -| pointer_to_member__pmIsConstT_ql | true | 21759 | 21747 | | -| pointer_to_member__pmIsConstT_ql | true | 21762 | 21756 | | -| pointer_to_member__pmIsConstT_ql | true | 21766 | 21759 | | -| pointer_to_member__pmIsConstT_ql | true | 21773 | 21777 | | -| pointer_to_member__pmIsConstT_ql | true | 21777 | 21784 | | -| pointer_to_member__pmIsConstT_ql | true | 21784 | 21788 | | -| pointer_to_member__pmIsConstT_ql | true | 21788 | 21766 | | -| pointer_to_member__pmIsConstT_ql | true | 21791 | 21773 | | -| staticlocals__staticlocals_f2_extractor | false | 31503 | 31503 | f2 | -| staticlocals__staticlocals_f2_extractor | false | 31509 | 31509 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31512 | 31512 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31515 | 31515 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31518 | 31518 | declaration | -| staticlocals__staticlocals_f2_extractor | false | 31521 | 31521 | return ... | -| staticlocals__staticlocals_f2_extractor | false | 31524 | 31524 | { ... } | -| staticlocals__staticlocals_f2_extractor | false | 31527 | 31527 | call to C | -| staticlocals__staticlocals_f2_extractor | false | 31530 | 31530 | initializer for c | -| staticlocals__staticlocals_f2_extractor | false | 31533 | 31533 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 31539 | 31539 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 31544 | 31544 | initializer for j | -| staticlocals__staticlocals_f2_extractor | false | 31546 | 31546 | call to addOne | -| staticlocals__staticlocals_f2_extractor | false | 31554 | 31554 | 2 | -| staticlocals__staticlocals_f2_extractor | false | 31556 | 31556 | initializer for two | -| staticlocals__staticlocals_f2_extractor | false | 31560 | 31560 | two | -| staticlocals__staticlocals_f2_extractor | false | 31568 | 31568 | initializer for i | -| staticlocals__staticlocals_f2_extractor | true | 31509 | 31556 | | -| staticlocals__staticlocals_f2_extractor | true | 31512 | 31515 | | -| staticlocals__staticlocals_f2_extractor | true | 31515 | 31518 | | -| staticlocals__staticlocals_f2_extractor | true | 31518 | 31521 | | -| staticlocals__staticlocals_f2_extractor | true | 31521 | 31503 | | -| staticlocals__staticlocals_f2_extractor | true | 31524 | 31509 | | -| staticlocals__staticlocals_f2_extractor | true | 31554 | 31512 | | -| staticlocals__staticlocals_f2_extractor | true | 31556 | 31554 | | -| staticlocals__staticlocals_f2_ql | false | 31503 | 31503 | f2 | -| staticlocals__staticlocals_f2_ql | false | 31509 | 31509 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31512 | 31512 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31515 | 31515 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31518 | 31518 | declaration | -| staticlocals__staticlocals_f2_ql | false | 31521 | 31521 | return ... | -| staticlocals__staticlocals_f2_ql | false | 31524 | 31524 | { ... } | -| staticlocals__staticlocals_f2_ql | false | 31527 | 31527 | call to C | -| staticlocals__staticlocals_f2_ql | false | 31530 | 31530 | initializer for c | -| staticlocals__staticlocals_f2_ql | false | 31533 | 31533 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 31539 | 31539 | 2 | -| staticlocals__staticlocals_f2_ql | false | 31544 | 31544 | initializer for j | -| staticlocals__staticlocals_f2_ql | false | 31546 | 31546 | call to addOne | -| staticlocals__staticlocals_f2_ql | false | 31554 | 31554 | 2 | -| staticlocals__staticlocals_f2_ql | false | 31556 | 31556 | initializer for two | -| staticlocals__staticlocals_f2_ql | false | 31560 | 31560 | two | -| staticlocals__staticlocals_f2_ql | false | 31568 | 31568 | initializer for i | -| staticlocals__staticlocals_f2_ql | true | 31509 | 31556 | | -| staticlocals__staticlocals_f2_ql | true | 31512 | 31515 | | -| staticlocals__staticlocals_f2_ql | true | 31515 | 31518 | | -| staticlocals__staticlocals_f2_ql | true | 31518 | 31521 | | -| staticlocals__staticlocals_f2_ql | true | 31518 | 31530 | | -| staticlocals__staticlocals_f2_ql | true | 31521 | 31503 | | -| staticlocals__staticlocals_f2_ql | true | 31524 | 31509 | | -| staticlocals__staticlocals_f2_ql | true | 31527 | 31521 | | -| staticlocals__staticlocals_f2_ql | true | 31530 | 31527 | | -| staticlocals__staticlocals_f2_ql | true | 31554 | 31512 | | -| staticlocals__staticlocals_f2_ql | true | 31556 | 31554 | | -| staticlocals__staticlocals_f3_extractor | false | 31473 | 31473 | f3 | -| staticlocals__staticlocals_f3_extractor | false | 31477 | 31477 | declaration | -| staticlocals__staticlocals_f3_extractor | false | 31480 | 31480 | return ... | -| staticlocals__staticlocals_f3_extractor | false | 31483 | 31483 | { ... } | -| staticlocals__staticlocals_f3_extractor | false | 31492 | 31492 | value | -| staticlocals__staticlocals_f3_extractor | false | 31496 | 31496 | (int)... | -| staticlocals__staticlocals_f3_extractor | false | 31498 | 31498 | initializer for i | -| staticlocals__staticlocals_f3_extractor | true | 31477 | 31480 | | -| staticlocals__staticlocals_f3_extractor | true | 31480 | 31473 | | -| staticlocals__staticlocals_f3_extractor | true | 31483 | 31477 | | -| staticlocals__staticlocals_f3_ql | false | 31473 | 31473 | f3 | -| staticlocals__staticlocals_f3_ql | false | 31477 | 31477 | declaration | -| staticlocals__staticlocals_f3_ql | false | 31480 | 31480 | return ... | -| staticlocals__staticlocals_f3_ql | false | 31483 | 31483 | { ... } | -| staticlocals__staticlocals_f3_ql | false | 31492 | 31492 | value | -| staticlocals__staticlocals_f3_ql | false | 31496 | 31496 | (int)... | -| staticlocals__staticlocals_f3_ql | false | 31498 | 31498 | initializer for i | -| staticlocals__staticlocals_f3_ql | true | 31477 | 31480 | | -| staticlocals__staticlocals_f3_ql | true | 31477 | 31498 | | -| staticlocals__staticlocals_f3_ql | true | 31480 | 31473 | | -| staticlocals__staticlocals_f3_ql | true | 31483 | 31477 | | -| staticlocals__staticlocals_f3_ql | true | 31492 | 31480 | | -| staticlocals__staticlocals_f3_ql | true | 31498 | 31492 | | diff --git a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql deleted file mode 100644 index 5b80f3c92a0c..000000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/drawDifferent.ql +++ /dev/null @@ -1,10 +0,0 @@ -// query-type: graph -import Compare - -from - Element scopeElement, string scopeString, boolean isEdge, ControlFlowNode x, ControlFlowNode y, - string label -where - AllCFG::qltestGraph(scopeElement, scopeString, isEdge, x, y, label) and - differentScope(scopeElement) -select scopeString, isEdge, x, y, label diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected deleted file mode 100644 index ae6f34298925..000000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.expected +++ /dev/null @@ -1,14 +0,0 @@ -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:44:11:44:28 | initializer for pms | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:41:3:44:29 | declaration | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from extractor | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | initializer for pms | pointer_to_member.cpp:44:14:44:18 | x1 | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:11:44:28 | {...} | pointer_to_member.cpp:45:1:45:1 | return ... | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:13:44:18 | & ... | pointer_to_member.cpp:44:22:44:26 | f1 | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:14:44:18 | x1 | pointer_to_member.cpp:44:13:44:18 | & ... | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:21:44:26 | & ... | pointer_to_member.cpp:44:11:44:28 | {...} | Standard edge, only from QL | uninstantiated | -| pointer_to_member__pmIsConstT | pointer_to_member.cpp:44:22:44:26 | f1 | pointer_to_member.cpp:44:21:44:26 | & ... | Standard edge, only from QL | uninstantiated | -| staticlocals__staticlocals_f2 | file://:0:0:0:0 | call to C | staticlocals.cpp:30:1:30:1 | return ... | Standard edge, only from QL | | -| staticlocals__staticlocals_f2 | file://:0:0:0:0 | initializer for c | file://:0:0:0:0 | call to C | Standard edge, only from QL | | -| staticlocals__staticlocals_f2 | staticlocals.cpp:29:5:29:17 | declaration | file://:0:0:0:0 | initializer for c | Standard edge, only from QL | | -| staticlocals__staticlocals_f3 | staticlocals.cpp:39:3:39:34 | declaration | staticlocals.cpp:39:18:39:33 | initializer for i | Standard edge, only from QL | uninstantiated | -| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | initializer for i | staticlocals.cpp:39:18:39:33 | value | Standard edge, only from QL | uninstantiated | -| staticlocals__staticlocals_f3 | staticlocals.cpp:39:18:39:33 | value | staticlocals.cpp:40:1:40:1 | return ... | Standard edge, only from QL | uninstantiated | diff --git a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql b/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql deleted file mode 100644 index f4b2509c17b1..000000000000 --- a/cpp/ql/test/library-tests/syntax-zoo/tellDifferent.ql +++ /dev/null @@ -1,13 +0,0 @@ -import Compare - -string describeTemplate(ControlFlowNode node) { - node.isFromTemplateInstantiation(_) and - result = "instantiation" - or - node.isFromUninstantiatedTemplate(_) and - result = "uninstantiated" -} - -from ControlFlowNode n1, ControlFlowNode n2, string msg -where differentEdge(n1, n2, msg) -select getScopeName(n1), n1, n2, msg, concat(describeTemplate(n1), ", ") From ae1377447e925f17a4b61db23f8231dcae1f6915 Mon Sep 17 00:00:00 2001 From: Robert Marsh Date: Thu, 7 Nov 2019 13:55:49 -0800 Subject: [PATCH 0272/2538] C++: only generate uninits when needed --- .../internal/TranslatedDeclarationEntry.qll | 2 +- .../raw/internal/TranslatedInitialization.qll | 2 +- .../test/library-tests/ir/ir/raw_ir.expected | 102 ++++++++-------- .../ir/ssa/aliased_ssa_ir.expected | 114 +++++++++--------- .../ir/ssa/unaliased_ssa_ir.expected | 102 ++++++++-------- 5 files changed, 158 insertions(+), 164 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll index c3572bd0e794..15b5db3ef74e 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedDeclarationEntry.qll @@ -121,7 +121,7 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali private predicate hasUninitializedInstruction() { not exists(getInitialization()) or getInitialization() instanceof TranslatedListInitialization or - getInitialization() instanceof TranslatedStringLiteralInitialization + getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _) } } diff --git a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll index 21ad11513bd0..c6911a048c74 100644 --- a/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll +++ b/cpp/ql/src/semmle/code/cpp/ir/implementation/raw/internal/TranslatedInitialization.qll @@ -340,7 +340,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati * Holds if the `elementCount` array elements starting at `startIndex` must be * zero initialized. */ - private predicate zeroInitRange(int startIndex, int elementCount) { + predicate zeroInitRange(int startIndex, int elementCount) { exists(int targetCount | startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and diff --git a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected index b4480e1c580b..e763b3c1263a 100644 --- a/cpp/ql/test/library-tests/ir/ir/raw_ir.expected +++ b/cpp/ql/test/library-tests/ir/ir/raw_ir.expected @@ -2675,58 +2675,56 @@ ir.cpp: # 572| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 # 572| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 # 573| r0_12(glval) = VariableAddress[a_nopad] : -# 573| mu0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 -# 573| r0_14(glval) = StringConstant["foo"] : -# 573| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 -# 573| mu0_16(char[4]) = Store : &:r0_12, r0_15 -# 574| r0_17(glval) = VariableAddress[a_infer] : -# 574| mu0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 -# 574| r0_19(glval) = StringConstant["blah"] : -# 574| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 -# 574| mu0_21(char[5]) = Store : &:r0_17, r0_20 -# 575| r0_22(glval) = VariableAddress[b] : -# 575| mu0_23(char[2]) = Uninitialized[b] : &:r0_22 -# 576| r0_24(glval) = VariableAddress[c] : -# 576| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 -# 576| r0_26(int) = Constant[0] : -# 576| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 -# 576| r0_28(unknown[2]) = Constant[0] : -# 576| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 -# 577| r0_30(glval) = VariableAddress[d] : -# 577| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 -# 577| r0_32(int) = Constant[0] : -# 577| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 -# 577| r0_34(char) = Constant[0] : -# 577| mu0_35(char) = Store : &:r0_33, r0_34 -# 577| r0_36(int) = Constant[1] : -# 577| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 -# 577| r0_38(char) = Constant[0] : -# 577| mu0_39(char) = Store : &:r0_37, r0_38 -# 578| r0_40(glval) = VariableAddress[e] : -# 578| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 -# 578| r0_42(int) = Constant[0] : -# 578| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 -# 578| r0_44(char) = Constant[0] : -# 578| mu0_45(char) = Store : &:r0_43, r0_44 -# 578| r0_46(int) = Constant[1] : -# 578| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 -# 578| r0_48(char) = Constant[1] : -# 578| mu0_49(char) = Store : &:r0_47, r0_48 -# 579| r0_50(glval) = VariableAddress[f] : -# 579| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 -# 579| r0_52(int) = Constant[0] : -# 579| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 -# 579| r0_54(char) = Constant[0] : -# 579| mu0_55(char) = Store : &:r0_53, r0_54 -# 579| r0_56(int) = Constant[1] : -# 579| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 -# 579| r0_58(unknown[2]) = Constant[0] : -# 579| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 -# 580| v0_60(void) = NoOp : -# 571| v0_61(void) = ReturnVoid : -# 571| v0_62(void) = UnmodeledUse : mu* -# 571| v0_63(void) = AliasedUse : ~mu0_2 -# 571| v0_64(void) = ExitFunction : +# 573| r0_13(glval) = StringConstant["foo"] : +# 573| r0_14(char[4]) = Load : &:r0_13, ~mu0_2 +# 573| mu0_15(char[4]) = Store : &:r0_12, r0_14 +# 574| r0_16(glval) = VariableAddress[a_infer] : +# 574| r0_17(glval) = StringConstant["blah"] : +# 574| r0_18(char[5]) = Load : &:r0_17, ~mu0_2 +# 574| mu0_19(char[5]) = Store : &:r0_16, r0_18 +# 575| r0_20(glval) = VariableAddress[b] : +# 575| mu0_21(char[2]) = Uninitialized[b] : &:r0_20 +# 576| r0_22(glval) = VariableAddress[c] : +# 576| mu0_23(char[2]) = Uninitialized[c] : &:r0_22 +# 576| r0_24(int) = Constant[0] : +# 576| r0_25(glval) = PointerAdd[1] : r0_22, r0_24 +# 576| r0_26(unknown[2]) = Constant[0] : +# 576| mu0_27(unknown[2]) = Store : &:r0_25, r0_26 +# 577| r0_28(glval) = VariableAddress[d] : +# 577| mu0_29(char[2]) = Uninitialized[d] : &:r0_28 +# 577| r0_30(int) = Constant[0] : +# 577| r0_31(glval) = PointerAdd[1] : r0_28, r0_30 +# 577| r0_32(char) = Constant[0] : +# 577| mu0_33(char) = Store : &:r0_31, r0_32 +# 577| r0_34(int) = Constant[1] : +# 577| r0_35(glval) = PointerAdd[1] : r0_28, r0_34 +# 577| r0_36(char) = Constant[0] : +# 577| mu0_37(char) = Store : &:r0_35, r0_36 +# 578| r0_38(glval) = VariableAddress[e] : +# 578| mu0_39(char[2]) = Uninitialized[e] : &:r0_38 +# 578| r0_40(int) = Constant[0] : +# 578| r0_41(glval) = PointerAdd[1] : r0_38, r0_40 +# 578| r0_42(char) = Constant[0] : +# 578| mu0_43(char) = Store : &:r0_41, r0_42 +# 578| r0_44(int) = Constant[1] : +# 578| r0_45(glval) = PointerAdd[1] : r0_38, r0_44 +# 578| r0_46(char) = Constant[1] : +# 578| mu0_47(char) = Store : &:r0_45, r0_46 +# 579| r0_48(glval) = VariableAddress[f] : +# 579| mu0_49(char[3]) = Uninitialized[f] : &:r0_48 +# 579| r0_50(int) = Constant[0] : +# 579| r0_51(glval) = PointerAdd[1] : r0_48, r0_50 +# 579| r0_52(char) = Constant[0] : +# 579| mu0_53(char) = Store : &:r0_51, r0_52 +# 579| r0_54(int) = Constant[1] : +# 579| r0_55(glval) = PointerAdd[1] : r0_48, r0_54 +# 579| r0_56(unknown[2]) = Constant[0] : +# 579| mu0_57(unknown[2]) = Store : &:r0_55, r0_56 +# 580| v0_58(void) = NoOp : +# 571| v0_59(void) = ReturnVoid : +# 571| v0_60(void) = UnmodeledUse : mu* +# 571| v0_61(void) = AliasedUse : ~mu0_2 +# 571| v0_62(void) = ExitFunction : # 584| void VarArgs() # 584| Block 0 diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index bc2bea75e113..893f1a1dd192 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -887,61 +887,59 @@ ssa.cpp: # 214| m0_12(unknown[31]) = Store : &:r0_11, r0_9 # 214| m0_13(char[32]) = Chi : total:m0_8, partial:m0_12 # 215| r0_14(glval) = VariableAddress[a_nopad] : -# 215| m0_15(char[4]) = Uninitialized[a_nopad] : &:r0_14 -# 215| r0_16(glval) = StringConstant["foo"] : -# 215| r0_17(char[4]) = Load : &:r0_16, ~m0_1 -# 215| m0_18(char[4]) = Store : &:r0_14, r0_17 -# 216| r0_19(glval) = VariableAddress[a_infer] : -# 216| m0_20(char[5]) = Uninitialized[a_infer] : &:r0_19 -# 216| r0_21(glval) = StringConstant["blah"] : -# 216| r0_22(char[5]) = Load : &:r0_21, ~m0_1 -# 216| m0_23(char[5]) = Store : &:r0_19, r0_22 -# 217| r0_24(glval) = VariableAddress[b] : -# 217| m0_25(char[2]) = Uninitialized[b] : &:r0_24 -# 218| r0_26(glval) = VariableAddress[c] : -# 218| m0_27(char[2]) = Uninitialized[c] : &:r0_26 -# 218| r0_28(int) = Constant[0] : -# 218| r0_29(glval) = PointerAdd[1] : r0_26, r0_28 -# 218| r0_30(unknown[2]) = Constant[0] : -# 218| m0_31(unknown[2]) = Store : &:r0_29, r0_30 -# 219| r0_32(glval) = VariableAddress[d] : -# 219| m0_33(char[2]) = Uninitialized[d] : &:r0_32 -# 219| r0_34(int) = Constant[0] : -# 219| r0_35(glval) = PointerAdd[1] : r0_32, r0_34 -# 219| r0_36(char) = Constant[0] : -# 219| m0_37(char) = Store : &:r0_35, r0_36 -# 219| m0_38(char[2]) = Chi : total:m0_33, partial:m0_37 -# 219| r0_39(int) = Constant[1] : -# 219| r0_40(glval) = PointerAdd[1] : r0_32, r0_39 -# 219| r0_41(char) = Constant[0] : -# 219| m0_42(char) = Store : &:r0_40, r0_41 -# 219| m0_43(char[2]) = Chi : total:m0_38, partial:m0_42 -# 220| r0_44(glval) = VariableAddress[e] : -# 220| m0_45(char[2]) = Uninitialized[e] : &:r0_44 -# 220| r0_46(int) = Constant[0] : -# 220| r0_47(glval) = PointerAdd[1] : r0_44, r0_46 -# 220| r0_48(char) = Constant[0] : -# 220| m0_49(char) = Store : &:r0_47, r0_48 -# 220| m0_50(char[2]) = Chi : total:m0_45, partial:m0_49 -# 220| r0_51(int) = Constant[1] : -# 220| r0_52(glval) = PointerAdd[1] : r0_44, r0_51 -# 220| r0_53(char) = Constant[1] : -# 220| m0_54(char) = Store : &:r0_52, r0_53 -# 220| m0_55(char[2]) = Chi : total:m0_50, partial:m0_54 -# 221| r0_56(glval) = VariableAddress[f] : -# 221| m0_57(char[3]) = Uninitialized[f] : &:r0_56 -# 221| r0_58(int) = Constant[0] : -# 221| r0_59(glval) = PointerAdd[1] : r0_56, r0_58 -# 221| r0_60(char) = Constant[0] : -# 221| m0_61(char) = Store : &:r0_59, r0_60 -# 221| m0_62(char[3]) = Chi : total:m0_57, partial:m0_61 -# 221| r0_63(int) = Constant[1] : -# 221| r0_64(glval) = PointerAdd[1] : r0_56, r0_63 -# 221| r0_65(unknown[2]) = Constant[0] : -# 221| m0_66(unknown[2]) = Store : &:r0_64, r0_65 -# 221| m0_67(char[3]) = Chi : total:m0_62, partial:m0_66 -# 222| v0_68(void) = NoOp : -# 213| v0_69(void) = ReturnVoid : -# 213| v0_70(void) = UnmodeledUse : mu* -# 213| v0_71(void) = AliasedUse : ~m0_1 -# 213| v0_72(void) = ExitFunction : +# 215| r0_15(glval) = StringConstant["foo"] : +# 215| r0_16(char[4]) = Load : &:r0_15, ~m0_1 +# 215| m0_17(char[4]) = Store : &:r0_14, r0_16 +# 216| r0_18(glval) = VariableAddress[a_infer] : +# 216| r0_19(glval) = StringConstant["blah"] : +# 216| r0_20(char[5]) = Load : &:r0_19, ~m0_1 +# 216| m0_21(char[5]) = Store : &:r0_18, r0_20 +# 217| r0_22(glval) = VariableAddress[b] : +# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 +# 218| r0_24(glval) = VariableAddress[c] : +# 218| m0_25(char[2]) = Uninitialized[c] : &:r0_24 +# 218| r0_26(int) = Constant[0] : +# 218| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 +# 218| r0_28(unknown[2]) = Constant[0] : +# 218| m0_29(unknown[2]) = Store : &:r0_27, r0_28 +# 219| r0_30(glval) = VariableAddress[d] : +# 219| m0_31(char[2]) = Uninitialized[d] : &:r0_30 +# 219| r0_32(int) = Constant[0] : +# 219| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 +# 219| r0_34(char) = Constant[0] : +# 219| m0_35(char) = Store : &:r0_33, r0_34 +# 219| m0_36(char[2]) = Chi : total:m0_31, partial:m0_35 +# 219| r0_37(int) = Constant[1] : +# 219| r0_38(glval) = PointerAdd[1] : r0_30, r0_37 +# 219| r0_39(char) = Constant[0] : +# 219| m0_40(char) = Store : &:r0_38, r0_39 +# 219| m0_41(char[2]) = Chi : total:m0_36, partial:m0_40 +# 220| r0_42(glval) = VariableAddress[e] : +# 220| m0_43(char[2]) = Uninitialized[e] : &:r0_42 +# 220| r0_44(int) = Constant[0] : +# 220| r0_45(glval) = PointerAdd[1] : r0_42, r0_44 +# 220| r0_46(char) = Constant[0] : +# 220| m0_47(char) = Store : &:r0_45, r0_46 +# 220| m0_48(char[2]) = Chi : total:m0_43, partial:m0_47 +# 220| r0_49(int) = Constant[1] : +# 220| r0_50(glval) = PointerAdd[1] : r0_42, r0_49 +# 220| r0_51(char) = Constant[1] : +# 220| m0_52(char) = Store : &:r0_50, r0_51 +# 220| m0_53(char[2]) = Chi : total:m0_48, partial:m0_52 +# 221| r0_54(glval) = VariableAddress[f] : +# 221| m0_55(char[3]) = Uninitialized[f] : &:r0_54 +# 221| r0_56(int) = Constant[0] : +# 221| r0_57(glval) = PointerAdd[1] : r0_54, r0_56 +# 221| r0_58(char) = Constant[0] : +# 221| m0_59(char) = Store : &:r0_57, r0_58 +# 221| m0_60(char[3]) = Chi : total:m0_55, partial:m0_59 +# 221| r0_61(int) = Constant[1] : +# 221| r0_62(glval) = PointerAdd[1] : r0_54, r0_61 +# 221| r0_63(unknown[2]) = Constant[0] : +# 221| m0_64(unknown[2]) = Store : &:r0_62, r0_63 +# 221| m0_65(char[3]) = Chi : total:m0_60, partial:m0_64 +# 222| v0_66(void) = NoOp : +# 213| v0_67(void) = ReturnVoid : +# 213| v0_68(void) = UnmodeledUse : mu* +# 213| v0_69(void) = AliasedUse : ~m0_1 +# 213| v0_70(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 93f27b13f02c..0014e15c7841 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -849,55 +849,53 @@ ssa.cpp: # 214| r0_10(glval) = PointerAdd[1] : r0_3, r0_9 # 214| mu0_11(unknown[31]) = Store : &:r0_10, r0_8 # 215| r0_12(glval) = VariableAddress[a_nopad] : -# 215| m0_13(char[4]) = Uninitialized[a_nopad] : &:r0_12 -# 215| r0_14(glval) = StringConstant["foo"] : -# 215| r0_15(char[4]) = Load : &:r0_14, ~mu0_2 -# 215| m0_16(char[4]) = Store : &:r0_12, r0_15 -# 216| r0_17(glval) = VariableAddress[a_infer] : -# 216| m0_18(char[5]) = Uninitialized[a_infer] : &:r0_17 -# 216| r0_19(glval) = StringConstant["blah"] : -# 216| r0_20(char[5]) = Load : &:r0_19, ~mu0_2 -# 216| m0_21(char[5]) = Store : &:r0_17, r0_20 -# 217| r0_22(glval) = VariableAddress[b] : -# 217| m0_23(char[2]) = Uninitialized[b] : &:r0_22 -# 218| r0_24(glval) = VariableAddress[c] : -# 218| mu0_25(char[2]) = Uninitialized[c] : &:r0_24 -# 218| r0_26(int) = Constant[0] : -# 218| r0_27(glval) = PointerAdd[1] : r0_24, r0_26 -# 218| r0_28(unknown[2]) = Constant[0] : -# 218| mu0_29(unknown[2]) = Store : &:r0_27, r0_28 -# 219| r0_30(glval) = VariableAddress[d] : -# 219| mu0_31(char[2]) = Uninitialized[d] : &:r0_30 -# 219| r0_32(int) = Constant[0] : -# 219| r0_33(glval) = PointerAdd[1] : r0_30, r0_32 -# 219| r0_34(char) = Constant[0] : -# 219| mu0_35(char) = Store : &:r0_33, r0_34 -# 219| r0_36(int) = Constant[1] : -# 219| r0_37(glval) = PointerAdd[1] : r0_30, r0_36 -# 219| r0_38(char) = Constant[0] : -# 219| mu0_39(char) = Store : &:r0_37, r0_38 -# 220| r0_40(glval) = VariableAddress[e] : -# 220| mu0_41(char[2]) = Uninitialized[e] : &:r0_40 -# 220| r0_42(int) = Constant[0] : -# 220| r0_43(glval) = PointerAdd[1] : r0_40, r0_42 -# 220| r0_44(char) = Constant[0] : -# 220| mu0_45(char) = Store : &:r0_43, r0_44 -# 220| r0_46(int) = Constant[1] : -# 220| r0_47(glval) = PointerAdd[1] : r0_40, r0_46 -# 220| r0_48(char) = Constant[1] : -# 220| mu0_49(char) = Store : &:r0_47, r0_48 -# 221| r0_50(glval) = VariableAddress[f] : -# 221| mu0_51(char[3]) = Uninitialized[f] : &:r0_50 -# 221| r0_52(int) = Constant[0] : -# 221| r0_53(glval) = PointerAdd[1] : r0_50, r0_52 -# 221| r0_54(char) = Constant[0] : -# 221| mu0_55(char) = Store : &:r0_53, r0_54 -# 221| r0_56(int) = Constant[1] : -# 221| r0_57(glval) = PointerAdd[1] : r0_50, r0_56 -# 221| r0_58(unknown[2]) = Constant[0] : -# 221| mu0_59(unknown[2]) = Store : &:r0_57, r0_58 -# 222| v0_60(void) = NoOp : -# 213| v0_61(void) = ReturnVoid : -# 213| v0_62(void) = UnmodeledUse : mu* -# 213| v0_63(void) = AliasedUse : ~mu0_2 -# 213| v0_64(void) = ExitFunction : +# 215| r0_13(glval) = StringConstant["foo"] : +# 215| r0_14(char[4]) = Load : &:r0_13, ~mu0_2 +# 215| m0_15(char[4]) = Store : &:r0_12, r0_14 +# 216| r0_16(glval) = VariableAddress[a_infer] : +# 216| r0_17(glval) = StringConstant["blah"] : +# 216| r0_18(char[5]) = Load : &:r0_17, ~mu0_2 +# 216| m0_19(char[5]) = Store : &:r0_16, r0_18 +# 217| r0_20(glval) = VariableAddress[b] : +# 217| m0_21(char[2]) = Uninitialized[b] : &:r0_20 +# 218| r0_22(glval) = VariableAddress[c] : +# 218| mu0_23(char[2]) = Uninitialized[c] : &:r0_22 +# 218| r0_24(int) = Constant[0] : +# 218| r0_25(glval) = PointerAdd[1] : r0_22, r0_24 +# 218| r0_26(unknown[2]) = Constant[0] : +# 218| mu0_27(unknown[2]) = Store : &:r0_25, r0_26 +# 219| r0_28(glval) = VariableAddress[d] : +# 219| mu0_29(char[2]) = Uninitialized[d] : &:r0_28 +# 219| r0_30(int) = Constant[0] : +# 219| r0_31(glval) = PointerAdd[1] : r0_28, r0_30 +# 219| r0_32(char) = Constant[0] : +# 219| mu0_33(char) = Store : &:r0_31, r0_32 +# 219| r0_34(int) = Constant[1] : +# 219| r0_35(glval) = PointerAdd[1] : r0_28, r0_34 +# 219| r0_36(char) = Constant[0] : +# 219| mu0_37(char) = Store : &:r0_35, r0_36 +# 220| r0_38(glval) = VariableAddress[e] : +# 220| mu0_39(char[2]) = Uninitialized[e] : &:r0_38 +# 220| r0_40(int) = Constant[0] : +# 220| r0_41(glval) = PointerAdd[1] : r0_38, r0_40 +# 220| r0_42(char) = Constant[0] : +# 220| mu0_43(char) = Store : &:r0_41, r0_42 +# 220| r0_44(int) = Constant[1] : +# 220| r0_45(glval) = PointerAdd[1] : r0_38, r0_44 +# 220| r0_46(char) = Constant[1] : +# 220| mu0_47(char) = Store : &:r0_45, r0_46 +# 221| r0_48(glval) = VariableAddress[f] : +# 221| mu0_49(char[3]) = Uninitialized[f] : &:r0_48 +# 221| r0_50(int) = Constant[0] : +# 221| r0_51(glval) = PointerAdd[1] : r0_48, r0_50 +# 221| r0_52(char) = Constant[0] : +# 221| mu0_53(char) = Store : &:r0_51, r0_52 +# 221| r0_54(int) = Constant[1] : +# 221| r0_55(glval) = PointerAdd[1] : r0_48, r0_54 +# 221| r0_56(unknown[2]) = Constant[0] : +# 221| mu0_57(unknown[2]) = Store : &:r0_55, r0_56 +# 222| v0_58(void) = NoOp : +# 213| v0_59(void) = ReturnVoid : +# 213| v0_60(void) = UnmodeledUse : mu* +# 213| v0_61(void) = AliasedUse : ~mu0_2 +# 213| v0_62(void) = ExitFunction : From 4ea8569081e003e4fb274c3d03e709ea7ba86fe4 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Thu, 7 Nov 2019 16:40:03 -0800 Subject: [PATCH 0273/2538] [CPP-434] Squelch query alerts if ALL files were compiled with `-fwrapv` or `-fno-strict-overflow` --- cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql index bd79a1141726..648846a7dc15 100644 --- a/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql +++ b/cpp/ql/src/Likely Bugs/Arithmetic/SignedOverflowCheck.ql @@ -23,5 +23,9 @@ where globalValueNumber(expr1) = globalValueNumber(expr2) and add.getUnspecifiedType().(IntegralType).isSigned() and not exists(MacroInvocation mi | mi.getAnAffectedElement() = add) and - exprMightOverflowPositively(add) + exprMightOverflowPositively(add) and + exists(Compilation c | c.getAFileCompiled() = ro.getFile() | + not c.getAnArgument() = "-fwrapv" and + not c.getAnArgument() = "-fno-strict-overflow" + ) select ro, "Testing for signed overflow may produce undefined results." From 17f76c251679acdb09ff7dc30ccc71aa6c2aa7c2 Mon Sep 17 00:00:00 2001 From: Dave Bartolomeo Date: Thu, 7 Nov 2019 22:02:15 -0700 Subject: [PATCH 0274/2538] C++: Fix merge conflicts --- .../ir/ssa/aliased_ssa_ir.expected | 26 +++++++++++++++++++ .../ir/ssa/unaliased_ssa_ir.expected | 25 ++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected index 46f8cf19aea8..f306d3e14c2b 100644 --- a/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/aliased_ssa_ir.expected @@ -877,3 +877,29 @@ ssa.cpp: # 207| v0_27(void) = UnmodeledUse : mu* # 207| v0_28(void) = AliasedUse : ~m0_1 # 207| v0_29(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| m0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| m0_5(unknown) = ^CallSideEffect : ~m0_1 +# 216| m0_6(unknown) = Chi : total:m0_1, partial:m0_5 +# 218| r0_7(glval) = VariableAddress[s] : +# 218| r0_8(glval) = StringConstant["Literal"] : +# 218| r0_9(char *) = Convert : r0_8 +# 218| m0_10(char *) = Store : &:r0_7, r0_9 +# 219| r0_11(glval) = VariableAddress[#return] : +# 219| r0_12(glval) = VariableAddress[s] : +# 219| r0_13(char *) = Load : &:r0_12, m0_10 +# 219| r0_14(int) = Constant[2] : +# 219| r0_15(glval) = PointerAdd[1] : r0_13, r0_14 +# 219| r0_16(char) = Load : &:r0_15, ~m0_1 +# 219| m0_17(char) = Store : &:r0_11, r0_16 +# 215| r0_18(glval) = VariableAddress[#return] : +# 215| v0_19(void) = ReturnValue : &:r0_18, m0_17 +# 215| v0_20(void) = UnmodeledUse : mu* +# 215| v0_21(void) = AliasedUse : ~m0_6 +# 215| v0_22(void) = ExitFunction : diff --git a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected index 7aae6b70dfd1..48d698a1291d 100644 --- a/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected +++ b/cpp/ql/test/library-tests/ir/ssa/unaliased_ssa_ir.expected @@ -841,3 +841,28 @@ ssa.cpp: # 207| v0_24(void) = UnmodeledUse : mu* # 207| v0_25(void) = AliasedUse : ~mu0_2 # 207| v0_26(void) = ExitFunction : + +# 215| char StringLiteralAliasing() +# 215| Block 0 +# 215| v0_0(void) = EnterFunction : +# 215| mu0_1(unknown) = AliasedDefinition : +# 215| mu0_2(unknown) = UnmodeledDefinition : +# 216| r0_3(glval) = FunctionAddress[ExternalFunc] : +# 216| v0_4(void) = Call : func:r0_3 +# 216| mu0_5(unknown) = ^CallSideEffect : ~mu0_2 +# 218| r0_6(glval) = VariableAddress[s] : +# 218| r0_7(glval) = StringConstant["Literal"] : +# 218| r0_8(char *) = Convert : r0_7 +# 218| m0_9(char *) = Store : &:r0_6, r0_8 +# 219| r0_10(glval) = VariableAddress[#return] : +# 219| r0_11(glval) = VariableAddress[s] : +# 219| r0_12(char *) = Load : &:r0_11, m0_9 +# 219| r0_13(int) = Constant[2] : +# 219| r0_14(glval) = PointerAdd[1] : r0_12, r0_13 +# 219| r0_15(char) = Load : &:r0_14, ~mu0_2 +# 219| m0_16(char) = Store : &:r0_10, r0_15 +# 215| r0_17(glval) = VariableAddress[#return] : +# 215| v0_18(void) = ReturnValue : &:r0_17, m0_16 +# 215| v0_19(void) = UnmodeledUse : mu* +# 215| v0_20(void) = AliasedUse : ~mu0_2 +# 215| v0_21(void) = ExitFunction : From e8510fe71a3c4fc1eab65e9a1f6095213dacb3b2 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Fri, 8 Nov 2019 09:17:05 +0000 Subject: [PATCH 0275/2538] TypeScript: Skip Touchstone files. --- .../semmle/js/extractor/FileExtractor.java | 28 +++++++++++++------ .../tests/ts/input/touchstone-file.ts | 2 ++ .../tests/ts/input/touchstone-file2.ts | 1 + 3 files changed, 22 insertions(+), 9 deletions(-) create mode 100644 javascript/extractor/tests/ts/input/touchstone-file.ts create mode 100644 javascript/extractor/tests/ts/input/touchstone-file2.ts diff --git a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java index d80ddeaf303b..278a7ec2e63f 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java +++ b/javascript/extractor/src/com/semmle/js/extractor/FileExtractor.java @@ -1,5 +1,16 @@ package com.semmle.js.extractor; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.IOException; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.regex.Pattern; + import com.semmle.js.extractor.ExtractionMetrics.ExtractionPhase; import com.semmle.js.extractor.trapcache.CachingTrapWriter; import com.semmle.js.extractor.trapcache.ITrapCache; @@ -10,15 +21,6 @@ import com.semmle.util.io.WholeIO; import com.semmle.util.trap.TrapWriter; import com.semmle.util.trap.TrapWriter.Label; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileReader; -import java.io.IOException; -import java.nio.charset.Charset; -import java.util.LinkedHashSet; -import java.util.Set; -import java.util.regex.Pattern; /** * The file extractor extracts a single file and handles source archive population and TRAP caching; @@ -167,6 +169,9 @@ private boolean hasBadFileHeader(File f, String lcExt, ExtractorConfig config) { return true; } + // Avoid Touchstone files + if (isTouchstone(bytes, length)) return true; + return false; } catch (IOException e) { Exceptions.ignore(e, "Let extractor handle this one."); @@ -198,6 +203,11 @@ private boolean isXml(byte[] bytes, int length) { return false; } + private boolean isTouchstone(byte[] bytes, int length) { + String s = new String(bytes, 0, length, StandardCharsets.US_ASCII); + return s.startsWith("! TOUCHSTONE file ") || s.startsWith("[Version] 2.0"); + } + /** * Returns true if the byte sequence contains invalid UTF-8 or unprintable ASCII characters. */ diff --git a/javascript/extractor/tests/ts/input/touchstone-file.ts b/javascript/extractor/tests/ts/input/touchstone-file.ts new file mode 100644 index 000000000000..a72a1dc56afb --- /dev/null +++ b/javascript/extractor/tests/ts/input/touchstone-file.ts @@ -0,0 +1,2 @@ +! TOUCHSTONE file generated by me +[Version] 2.0 diff --git a/javascript/extractor/tests/ts/input/touchstone-file2.ts b/javascript/extractor/tests/ts/input/touchstone-file2.ts new file mode 100644 index 000000000000..d642e0260b1d --- /dev/null +++ b/javascript/extractor/tests/ts/input/touchstone-file2.ts @@ -0,0 +1 @@ +[Version] 2.0 From dee4ddbb5ba533586c3ac51da067196f4442a6cc Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Thu, 7 Nov 2019 14:14:36 +0100 Subject: [PATCH 0276/2538] C#: Only set `UseSharedCompilation=false` in autobuilder when needed Since we are now able to trace shared compilation builds on Linux and macOS (starting from .NET Core 3), and always were able to on Windows, there is no need to set `UseSharedCompilation=false` in those cases. This may have a positive performance impact, as shared compilation is generally faster then non-shared compilation. --- .../Semmle.Autobuild.Tests/BuildScripts.cs | 47 ++++++++++----- .../Semmle.Autobuild/Autobuilder.cs | 13 +++- .../Semmle.Autobuild/BuildActions.cs | 8 +-- .../Semmle.Autobuild/BuildScript.cs | 34 ++++++----- .../Semmle.Autobuild/CommandBuilder.cs | 7 ++- .../Semmle.Autobuild/DotNetRule.cs | 59 ++++++++++++++++--- 6 files changed, 118 insertions(+), 50 deletions(-) diff --git a/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs index 20d19a3525cd..8037cf980655 100644 --- a/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs +++ b/csharp/autobuilder/Semmle.Autobuild.Tests/BuildScripts.cs @@ -185,7 +185,7 @@ public class BuildScriptTests // Records the arguments passed to StartCallback. IList StartCallbackIn = new List(); - void StartCallback(string s) + void StartCallback(string s, bool silent) { StartCallbackIn.Add(s); } @@ -194,7 +194,7 @@ void StartCallback(string s) IList EndCallbackIn = new List(); IList EndCallbackReturn = new List(); - void EndCallback(int ret, string s) + void EndCallback(int ret, string s, bool silent) { EndCallbackReturn.Add(ret); EndCallbackIn.Add(s); @@ -203,7 +203,7 @@ void EndCallback(int ret, string s) [Fact] public void TestBuildCommand() { - var cmd = BuildScript.Create("abc", "def ghi", null, null); + var cmd = BuildScript.Create("abc", "def ghi", false, null, null); Actions.RunProcess["abc def ghi"] = 1; cmd.Run(Actions, StartCallback, EndCallback); @@ -216,7 +216,7 @@ public void TestBuildCommand() [Fact] public void TestAnd1() { - var cmd = BuildScript.Create("abc", "def ghi", null, null) & BuildScript.Create("odasa", null, null, null); + var cmd = BuildScript.Create("abc", "def ghi", false, null, null) & BuildScript.Create("odasa", null, false, null, null); Actions.RunProcess["abc def ghi"] = 1; cmd.Run(Actions, StartCallback, EndCallback); @@ -230,7 +230,7 @@ public void TestAnd1() [Fact] public void TestAnd2() { - var cmd = BuildScript.Create("odasa", null, null, null) & BuildScript.Create("abc", "def ghi", null, null); + var cmd = BuildScript.Create("odasa", null, false, null, null) & BuildScript.Create("abc", "def ghi", false, null, null); Actions.RunProcess["abc def ghi"] = 1; Actions.RunProcess["odasa "] = 0; @@ -250,7 +250,7 @@ public void TestAnd2() [Fact] public void TestOr1() { - var cmd = BuildScript.Create("odasa", null, null, null) | BuildScript.Create("abc", "def ghi", null, null); + var cmd = BuildScript.Create("odasa", null, false, null, null) | BuildScript.Create("abc", "def ghi", false, null, null); Actions.RunProcess["abc def ghi"] = 1; Actions.RunProcess["odasa "] = 0; @@ -266,7 +266,7 @@ public void TestOr1() [Fact] public void TestOr2() { - var cmd = BuildScript.Create("abc", "def ghi", null, null) | BuildScript.Create("odasa", null, null, null); + var cmd = BuildScript.Create("abc", "def ghi", false, null, null) | BuildScript.Create("odasa", null, false, null, null); Actions.RunProcess["abc def ghi"] = 1; Actions.RunProcess["odasa "] = 0; @@ -375,7 +375,7 @@ public void TestDefaultCSharpAutoBuilder() Actions.RunProcess["cmd.exe /C dotnet --info"] = 0; Actions.RunProcess["cmd.exe /C dotnet clean test.csproj"] = 0; Actions.RunProcess["cmd.exe /C dotnet restore test.csproj"] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto dotnet build --no-incremental test.csproj"] = 0; Actions.RunProcess[@"cmd.exe /C C:\codeql\tools\java\bin\java -jar C:\codeql\csharp\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; @@ -404,6 +404,9 @@ public void TestLinuxCSharpAutoBuilder() Actions.RunProcess["dotnet --info"] = 0; Actions.RunProcess["dotnet clean test.csproj"] = 0; Actions.RunProcess["dotnet restore test.csproj"] = 0; + Actions.RunProcess["dotnet --list-runtimes"] = 0; + Actions.RunProcessOut["dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.NETCore.App 2.2.5 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]"; Actions.RunProcess[@"C:\odasa/tools/odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0; @@ -424,7 +427,7 @@ public void TestLinuxCSharpAutoBuilder() Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", false); - TestAutobuilderScript(autobuilder, 0, 6); + TestAutobuilderScript(autobuilder, 0, 7); } [Fact] @@ -748,7 +751,7 @@ public void TestWindowCSharpMsBuild() TestAutobuilderScript(autobuilder, 0, 6); } - [Fact] + [Fact] public void TestWindowCSharpMsBuildMultipleSolutions() { Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\csharp\nuget\nuget.exe restore test1.csproj"] = 0; @@ -874,6 +877,9 @@ public void TestSkipNugetDotnet() Actions.RunProcess["dotnet --info"] = 0; Actions.RunProcess["dotnet clean test.csproj"] = 0; Actions.RunProcess["dotnet restore test.csproj"] = 0; + Actions.RunProcess["dotnet --list-runtimes"] = 0; + Actions.RunProcessOut["dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.NETCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]"; Actions.RunProcess[@"C:\odasa/tools/odasa index --auto dotnet build --no-incremental /p:UseSharedCompilation=false --no-restore test.csproj"] = 0; Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0; @@ -894,7 +900,7 @@ public void TestSkipNugetDotnet() Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", false, dotnetArguments: "--no-restore"); // nugetRestore=false does not work for now. - TestAutobuilderScript(autobuilder, 0, 6); + TestAutobuilderScript(autobuilder, 0, 7); } [Fact] @@ -909,7 +915,10 @@ public void TestDotnetVersionNotInstalled() Actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0; Actions.RunProcess[@"C:\Project/.dotnet/dotnet clean test.csproj"] = 0; Actions.RunProcess[@"C:\Project/.dotnet/dotnet restore test.csproj"] = 0; - Actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; + Actions.RunProcess[@"C:\Project/.dotnet/dotnet --list-runtimes"] = 0; + Actions.RunProcessOut[@"C:\Project/.dotnet/dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 3.0.0 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.NETCore.App 3.0.0 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]"; + Actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/.dotnet/dotnet build --no-incremental test.csproj"] = 0; Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; @@ -930,14 +939,15 @@ public void TestDotnetVersionNotInstalled() Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", false, dotnetVersion: "2.1.3"); - TestAutobuilderScript(autobuilder, 0, 11); + TestAutobuilderScript(autobuilder, 0, 12); } [Fact] public void TestDotnetVersionAlreadyInstalled() { Actions.RunProcess["dotnet --list-sdks"] = 0; - Actions.RunProcessOut["dotnet --list-sdks"] = "2.1.3 [C:\\Program Files\\dotnet\\sdks]\n2.1.4 [C:\\Program Files\\dotnet\\sdks]"; + Actions.RunProcessOut["dotnet --list-sdks"] = @"2.1.3 [C:\Program Files\dotnet\sdks] +2.1.4 [C:\Program Files\dotnet\sdks]"; Actions.RunProcess[@"curl -L -sO https://dot.net/v1/dotnet-install.sh"] = 0; Actions.RunProcess[@"chmod u+x dotnet-install.sh"] = 0; Actions.RunProcess[@"./dotnet-install.sh --channel release --version 2.1.3 --install-dir C:\Project/.dotnet"] = 0; @@ -945,6 +955,11 @@ public void TestDotnetVersionAlreadyInstalled() Actions.RunProcess[@"C:\Project/.dotnet/dotnet --info"] = 0; Actions.RunProcess[@"C:\Project/.dotnet/dotnet clean test.csproj"] = 0; Actions.RunProcess[@"C:\Project/.dotnet/dotnet restore test.csproj"] = 0; + Actions.RunProcess[@"C:\Project/.dotnet/dotnet --list-runtimes"] = 0; + Actions.RunProcessOut[@"C:\Project/.dotnet/dotnet --list-runtimes"] = @"Microsoft.AspNetCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.AspNetCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.AspNetCore.App] +Microsoft.NETCore.App 2.1.3 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App] +Microsoft.NETCore.App 2.1.4 [/usr/local/share/dotnet/shared/Microsoft.NETCore.App]"; Actions.RunProcess[@"C:\odasa/tools/odasa index --auto C:\Project/.dotnet/dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; Actions.RunProcess[@"C:\codeql\tools\java/bin/java -jar C:\codeql\csharp/tools/extractor-asp.jar ."] = 0; Actions.RunProcess[@"C:\odasa/tools/odasa index --xml --extensions config csproj props xml"] = 0; @@ -966,7 +981,7 @@ public void TestDotnetVersionAlreadyInstalled() Actions.LoadXml["test.csproj"] = xml; var autobuilder = CreateAutoBuilder("csharp", false, dotnetVersion: "2.1.3"); - TestAutobuilderScript(autobuilder, 0, 11); + TestAutobuilderScript(autobuilder, 0, 12); } [Fact] @@ -979,7 +994,7 @@ public void TestDotnetVersionWindows() Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet --info"] = 0; Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet clean test.csproj"] = 0; Actions.RunProcess[@"cmd.exe /C C:\Project\.dotnet\dotnet restore test.csproj"] = 0; - Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental /p:UseSharedCompilation=false test.csproj"] = 0; + Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --auto C:\Project\.dotnet\dotnet build --no-incremental test.csproj"] = 0; Actions.RunProcess[@"cmd.exe /C C:\codeql\tools\java\bin\java -jar C:\codeql\csharp\tools\extractor-asp.jar ."] = 0; Actions.RunProcess[@"cmd.exe /C C:\odasa\tools\odasa index --xml --extensions config csproj props xml"] = 0; Actions.FileExists["csharp.log"] = true; diff --git a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs index 001934f489d2..71653f0a93b8 100644 --- a/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/Autobuilder.cs @@ -214,8 +214,17 @@ public int AttemptBuild() if (Options.IgnoreErrors) script |= BuildScript.Success; - void startCallback(string s) => Log(Severity.Info, $"\nRunning {s}"); - void exitCallback(int ret, string msg) => Log(Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}"); + void startCallback(string s, bool silent) + { + if (!silent) Log(Severity.Info, $"\nRunning {s}"); + } + + void exitCallback(int ret, string msg, bool silent) + { + if (!silent) + Log(Severity.Info, $"Exit code {ret}{(string.IsNullOrEmpty(msg) ? "" : $": {msg}")}"); + } + return script.Run(Actions, startCallback, exitCallback); } diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs index edf4fc752c1c..837f6e3f69e2 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildActions.cs @@ -141,12 +141,8 @@ ProcessStartInfo GetProcessStartInfo(string exe, string arguments, string workin pi.WorkingDirectory = workingDirectory; // Environment variables can only be used when not redirecting stdout - if (!redirectStandardOutput) - { - pi.Environment["UseSharedCompilation"] = "false"; - if (environment != null) - environment.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value); - } + if (!redirectStandardOutput && environment != null) + environment.ForEach(kvp => pi.Environment[kvp.Key] = kvp.Value); return pi; } diff --git a/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs index a41011e159f3..93ea941d58bb 100644 --- a/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs +++ b/csharp/autobuilder/Semmle.Autobuild/BuildScript.cs @@ -25,7 +25,7 @@ public abstract class BuildScript /// an exit message. /// /// The exit code from this build script. - public abstract int Run(IBuildActions actions, Action startCallback, Action exitCallBack); + public abstract int Run(IBuildActions actions, Action startCallback, Action exitCallBack); /// /// Run this build command. @@ -44,33 +44,36 @@ public abstract class BuildScript /// /// Contents of standard out. /// The exit code from this build script. - public abstract int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout); + public abstract int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout); class BuildCommand : BuildScript { readonly string exe, arguments, workingDirectory; readonly IDictionary environment; + readonly bool silent; /// /// Create a simple build command. /// /// The executable to run. /// The arguments to the executable, or null. + /// Whether this command should run silently. /// The working directory (null for current directory). /// Additional environment variables. - public BuildCommand(string exe, string argumentsOpt, string workingDirectory = null, IDictionary environment = null) + public BuildCommand(string exe, string argumentsOpt, bool silent, string workingDirectory = null, IDictionary environment = null) { this.exe = exe; this.arguments = argumentsOpt ?? ""; + this.silent = silent; this.workingDirectory = workingDirectory; this.environment = environment; } public override string ToString() => exe + " " + arguments; - public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack) + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack) { - startCallback(this.ToString()); + startCallback(this.ToString(), silent); var ret = 1; var retMessage = ""; try @@ -83,13 +86,13 @@ public override int Run(IBuildActions actions, Action startCallback, Act retMessage = ex.Message; } - exitCallBack(ret, retMessage); + exitCallBack(ret, retMessage, silent); return ret; } - public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) { - startCallback(this.ToString()); + startCallback(this.ToString(), silent); var ret = 1; var retMessage = ""; try @@ -102,7 +105,7 @@ public override int Run(IBuildActions actions, Action startCallback, Act retMessage = ex.Message; stdout = new string[0]; } - exitCallBack(ret, retMessage); + exitCallBack(ret, retMessage, silent); return ret; } @@ -116,9 +119,9 @@ public ReturnBuildCommand(Func func) this.func = func; } - public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack) => func(actions); + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack) => func(actions); - public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) { stdout = new string[0]; return func(actions); @@ -142,7 +145,7 @@ public BindBuildScript(BuildScript s1, Func s2) this.s2b = s2; } - public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack) + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack) { int ret1; if (s2a != null) @@ -155,7 +158,7 @@ public override int Run(IBuildActions actions, Action startCallback, Act return s2b(ret1).Run(actions, startCallback, exitCallBack); } - public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) + public override int Run(IBuildActions actions, Action startCallback, Action exitCallBack, out IList stdout) { var ret1 = s1.Run(actions, startCallback, exitCallBack, out var stdout1); var ret2 = (s2a != null ? s2a(stdout1, ret1) : s2b(ret1)).Run(actions, startCallback, exitCallBack, out var stdout2); @@ -171,10 +174,11 @@ public override int Run(IBuildActions actions, Action startCallback, Act /// Creates a simple build script that runs the specified exe. /// /// The arguments to the executable, or null. + /// Whether the executable should run silently. /// The working directory (null for current directory). /// Additional environment variables. - public static BuildScript Create(string exe, string argumentsOpt, string workingDirectory, IDictionary environment) => - new BuildCommand(exe, argumentsOpt, workingDirectory, environment); + public static BuildScript Create(string exe, string argumentsOpt, bool silent, string workingDirectory, IDictionary environment) => + new BuildCommand(exe, argumentsOpt, silent, workingDirectory, environment); /// /// Creates a simple build script that runs the specified function. diff --git a/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs index 273cc52b0362..7b95e4956973 100644 --- a/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs +++ b/csharp/autobuilder/Semmle.Autobuild/CommandBuilder.cs @@ -17,13 +17,15 @@ enum EscapeMode { Process, Cmd }; readonly EscapeMode escapingMode; readonly string workingDirectory; readonly IDictionary environment; + readonly bool silent; /// /// Initializes a new instance of the class. /// /// The working directory (null for current directory). /// Additional environment variables. - public CommandBuilder(IBuildActions actions, string workingDirectory = null, IDictionary environment = null) + /// Whether this command should be run silently. + public CommandBuilder(IBuildActions actions, string workingDirectory = null, IDictionary environment = null, bool silent = false) { arguments = new StringBuilder(); if (actions.IsWindows()) @@ -40,6 +42,7 @@ public CommandBuilder(IBuildActions actions, string workingDirectory = null, IDi firstCommand = true; this.workingDirectory = workingDirectory; this.environment = environment; + this.silent = silent; } void OdasaIndex(string odasa) @@ -190,6 +193,6 @@ public CommandBuilder RunCommand(string exe, string argumentsOpt = null) /// /// Returns a build script that contains just this command. /// - public BuildScript Script => BuildScript.Create(executable, arguments.ToString(), workingDirectory, environment); + public BuildScript Script => BuildScript.Create(executable, arguments.ToString(), silent, workingDirectory, environment); } } diff --git a/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs index 789d68db30a0..d44f32e4b566 100644 --- a/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs +++ b/csharp/autobuilder/Semmle.Autobuild/DotNetRule.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.IO; using Semmle.Util; +using System.Text.RegularExpressions; namespace Semmle.Autobuild { @@ -47,9 +48,7 @@ public BuildScript Analyse(Autobuilder builder, bool auto) restoreCommand.QuoteArgument(projectOrSolution.FullPath); var restore = restoreCommand.Script; - var buildCommand = GetBuildCommand(builder, dotNet); - buildCommand.QuoteArgument(projectOrSolution.FullPath); - var build = buildCommand.Script; + var build = GetBuildScript(builder, dotNet, projectOrSolution.FullPath); ret &= clean & BuildScript.Try(restore) & build; } @@ -225,7 +224,7 @@ public bool CheckValidationResult(ServicePoint srvPoint, X509Certificate certifi static BuildScript GetInstalledSdksScript(IBuildActions actions) { - var listSdks = new CommandBuilder(actions). + var listSdks = new CommandBuilder(actions, silent: true). RunCommand("dotnet"). Argument("--list-sdks"); return listSdks.Script; @@ -258,14 +257,56 @@ CommandBuilder GetRestoreCommand(IBuildActions actions, (string DotNetPath, IDic return restore; } - CommandBuilder GetBuildCommand(Autobuilder builder, (string DotNetPath, IDictionary Environment)? arg) + static BuildScript GetInstalledRuntimesScript(IBuildActions actions, (string DotNetPath, IDictionary Environment)? arg) + { + var listSdks = new CommandBuilder(actions, environment: arg?.Environment, silent: true). + RunCommand(DotNetCommand(actions, arg?.DotNetPath)). + Argument("--list-runtimes"); + return listSdks.Script; + } + + /// + /// Gets the `dotnet build` script. + /// + /// The CLR tracer only works on .NET Core >= 3 on Linux and macOS (see + /// https://github.com/dotnet/coreclr/issues/19622), so in case we are + /// running on an older .NET Core, we disable shared compilation (and + /// hence the need for CLR tracing), by adding a + /// `/p:UseSharedCompilation=false` argument. + /// + BuildScript GetBuildScript(Autobuilder builder, (string DotNetPath, IDictionary Environment)? arg, string projOrSln) { var build = new CommandBuilder(builder.Actions, null, arg?.Environment); - return builder.MaybeIndex(build, DotNetCommand(builder.Actions, arg?.DotNetPath)). + var script = builder.MaybeIndex(build, DotNetCommand(builder.Actions, arg?.DotNetPath)). Argument("build"). - Argument("--no-incremental"). - Argument("/p:UseSharedCompilation=false"). - Argument(builder.Options.DotNetArguments); + Argument("--no-incremental"); + + if (builder.Actions.IsWindows()) + return script.Argument(builder.Options.DotNetArguments). + QuoteArgument(projOrSln). + Script; + + return BuildScript.Bind(GetInstalledRuntimesScript(builder.Actions, arg), (runtimes, runtimesRet) => + { + var compatibleClr = false; + if (runtimesRet == 0) + { + var regex = new Regex(@"Microsoft\.NETCore\.App (\d)"); + compatibleClr = runtimes. + Select(runtime => regex.Match(runtime)). + Where(m => m.Success). + Any(m => int.TryParse(m.Groups[1].Value, out var version) && version >= 3); + } + + return compatibleClr ? + script.Argument(builder.Options.DotNetArguments). + QuoteArgument(projOrSln). + Script : + script.Argument("/p:UseSharedCompilation=false"). + Argument(builder.Options.DotNetArguments). + QuoteArgument(projOrSln). + Script; + }); } } } From 0554de06a13b5ded396d693a8f218f310587f790 Mon Sep 17 00:00:00 2001 From: james Date: Fri, 8 Nov 2019 09:32:20 +0000 Subject: [PATCH 0277/2538] docs: update banner links --- docs/language/global-sphinx-files/_templates/layout.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/language/global-sphinx-files/_templates/layout.html b/docs/language/global-sphinx-files/_templates/layout.html index de3b189e1ee3..000503e57985 100644 --- a/docs/language/global-sphinx-files/_templates/layout.html +++ b/docs/language/global-sphinx-files/_templates/layout.html @@ -62,8 +62,8 @@ protected static void BuildMethodId(Method m, TextWriter trapFile) { + // AddSignatureTypeToId(m.Context, trapFile, m.symbol, m.ContainingType.symbol, false); trapFile.WriteSubId(m.ContainingType); AddExplicitInterfaceQualifierToId(m.Context, trapFile, m.symbol.ExplicitInterfaceImplementations); @@ -129,7 +130,7 @@ protected static void BuildMethodId(Method m, TextWriter trapFile) // Type arguments with different nullability can result in // a constructed method with different nullability of its parameters and return type, // so we need to create a distinct database entity for it. - trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); }); + trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, TypeNameContext.MethodName); trapFile.Write((int)ta.Nullability); }); trapFile.Write('>'); } } @@ -199,12 +200,12 @@ public override void WriteId(TextWriter trapFile) /// to make the reference to #3 in the label definition #4 for /// T valid. /// - protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type) + protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, TypeNameContext assemblyPrefix) { if (type.ContainsTypeParameters(cx, method)) - type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); + type.BuildTypeId(cx, trapFile, (cx0, tb0, type0, _) => AddSignatureTypeToId(cx, tb0, method, type0, assemblyPrefix), assemblyPrefix, method); else - trapFile.WriteSubId(Type.Create(cx, type)); + trapFile.WriteSubId(Type.Create(cx, type).TypeRef); } protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) @@ -215,13 +216,13 @@ protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethod if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, TypeNameContext.MethodParam); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type); + AddSignatureTypeToId(cx, trapFile, method, param.Type, TypeNameContext.MethodParam); switch (param.RefKind) { case RefKind.Out: @@ -345,11 +346,10 @@ protected void PopulateGenerics(TextWriter trapFile) foreach (var tp in symbol.GetAnnotatedTypeArguments()) { trapFile.type_arguments(Type.Create(Context, tp.Symbol), child, this); - var ta = tp.Nullability.GetTypeAnnotation(); - if (ta != Kinds.TypeAnnotation.None) - trapFile.type_argument_annotation(this, child, ta); child++; } + + trapFile.type_nullability(this, NullabilityEntity.Create(Context, new Nullability(symbol))); } else { @@ -380,7 +380,7 @@ protected void PopulateMethod(TextWriter trapFile) PopulateMethodBody(trapFile); PopulateGenerics(trapFile); PopulateMetadataHandle(trapFile); - PopulateNullability(trapFile, symbol.ReturnNullableAnnotation); + PopulateNullability(trapFile, symbol.GetAnnotatedReturnType()); } public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.PushesLabel; diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs index efb88840e037..c353ea34c163 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs @@ -86,7 +86,8 @@ public override void WriteId(TextWriter trapFile) trapFile.Write(";parameter"); } - public override bool NeedsPopulation => true; + // If we don't have the type of the parameter, do not populate it. + public override bool NeedsPopulation => symbol.Type.TypeKind != TypeKind.Error; string Name { @@ -103,7 +104,7 @@ string Name public override void Populate(TextWriter trapFile) { PopulateAttributes(); - PopulateNullability(trapFile, symbol.NullableAnnotation); + PopulateNullability(trapFile, symbol.GetAnnotatedType()); PopulateRefKind(trapFile, symbol.RefKind); if (symbol.Name != Original.symbol.Name) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index 900a313fe921..e1822504120b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -15,6 +15,7 @@ protected Property(Context cx, IPropertySymbol init) public override void WriteId(TextWriter trapFile) { + // trapFile.WriteSubId(ContainingType.TypeRef); trapFile.WriteSubId(ContainingType); trapFile.Write('.'); Method.AddExplicitInterfaceQualifierToId(Context, trapFile, symbol.ExplicitInterfaceImplementations); @@ -28,7 +29,7 @@ public override void Populate(TextWriter trapFile) PopulateAttributes(); PopulateModifiers(trapFile); BindComments(); - PopulateNullability(trapFile, symbol.NullableAnnotation); + PopulateNullability(trapFile, symbol.GetAnnotatedType()); PopulateRefKind(trapFile, symbol.RefKind); var type = Type.Create(Context, symbol.Type); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs index ddd1c79faf8f..4d37d4f1d38c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs @@ -28,11 +28,14 @@ protected void PopulateAttributes() Attribute.ExtractAttributes(Context, symbol, this); } - protected void PopulateNullability(TextWriter trapFile, NullableAnnotation annotation) + protected void PopulateNullability(TextWriter trapFile, AnnotatedTypeSymbol type) { - var ta = annotation.GetTypeAnnotation(); - if (ta != Kinds.TypeAnnotation.None) - trapFile.type_annotation(this, ta); + var ta = type.Nullability.GetTypeAnnotation(); + var n = NullabilityEntity.Create(Context, Nullability.Create(type)); + if (ta != Kinds.TypeAnnotation.None || !type.HasConsistentNullability()) + { + trapFile.type_nullability(this, n); + } } protected void PopulateRefKind(TextWriter trapFile, RefKind kind) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs index 6e7b6f4d92c9..c4a79a7764b0 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/ArrayType.cs @@ -27,13 +27,11 @@ public override void Populate(TextWriter trapFile) { trapFile.array_element_type(this, Dimension, Rank, element.Type.TypeRef); PopulateType(trapFile); - PopulateNullability(trapFile, symbol.ElementNullableAnnotation); } public override void WriteId(TextWriter trapFile) { trapFile.WriteSubId(element.Type); - trapFile.Write((int)symbol.ElementNullableAnnotation); symbol.BuildArraySuffix(trapFile); trapFile.Write(";type"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 416fb34f224b..ca82da2ecc46 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -57,9 +57,6 @@ public override void Populate(TextWriter trapFile) for (int i = 0; i < symbol.TypeArguments.Length; ++i) { - var ta = symbol.TypeArgumentsNullableAnnotations[i].GetTypeAnnotation(); - if (ta != Kinds.TypeAnnotation.None) - trapFile.type_argument_annotation(this, i, ta); trapFile.type_arguments(TypeArguments[i].TypeRef, i, this); } } @@ -114,7 +111,7 @@ public override IEnumerable Locations public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeNameContext.TypeName, symbol); trapFile.Write(";type"); } @@ -154,33 +151,40 @@ class NamedTypeFactory : ICachedEntityFactory public NamedType Create(Context cx, INamedTypeSymbol init) => new NamedType(cx, init); } - public override Type TypeRef => NamedTypeRef.Create(Context, symbol); + public override Type TypeRef => NamedTypeRef.Create(Context, this, symbol); } - class NamedTypeRef : Type + class NamedTypeRef : Type { readonly Type referencedType; - public NamedTypeRef(Context cx, INamedTypeSymbol symbol) : base(cx, symbol) + public NamedTypeRef(Context cx, Type type, ITypeSymbol symbol) : base(cx, symbol) { - referencedType = Type.Create(cx, symbol); + referencedType = type; } - public static NamedTypeRef Create(Context cx, INamedTypeSymbol type) => NamedTypeRefFactory.Instance.CreateEntity2(cx, type); + public static NamedTypeRef Create(Context cx, Type referencedType, ITypeSymbol type) => + NamedTypeRefFactory.Instance.CreateEntity2(cx, (referencedType, type)); - class NamedTypeRefFactory : ICachedEntityFactory + class NamedTypeRefFactory : ICachedEntityFactory<(Type, ITypeSymbol), NamedTypeRef> { public static readonly NamedTypeRefFactory Instance = new NamedTypeRefFactory(); - public NamedTypeRef Create(Context cx, INamedTypeSymbol init) => new NamedTypeRef(cx, init); + public NamedTypeRef Create(Context cx, (Type, ITypeSymbol) init) => new NamedTypeRef(cx, init.Item1, init.Item2); } public override bool NeedsPopulation => true; public override void WriteId(TextWriter trapFile) { - trapFile.WriteSubId(referencedType); - trapFile.Write(";typeRef"); + void ExpandType(Context cx0, TextWriter tb0, ITypeSymbol sub, ISymbol gc) + { + sub.BuildTypeId(cx0, tb0, ExpandType, TypeNameContext.TypeRef, gc); + } + + // Prefix anonymous types because they shouldn't be visible outside of the current assembly. + symbol.BuildTypeId(Context, trapFile, ExpandType, TypeNameContext.TypeRef, symbol); + trapFile.Write(";typeref"); } public override void Populate(TextWriter trapFile) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index de6ea2170849..7adfa6ab8e74 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -32,7 +32,7 @@ class TupleTypeFactory : ICachedEntityFactory public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); + symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeNameContext.TypeName, symbol); trapFile.Write(";tuple"); } @@ -42,7 +42,7 @@ public override void Populate(TextWriter trapFile) PopulateGenerics(); var underlyingType = NamedType.Create(Context, symbol.TupleUnderlyingType); - trapFile.tuple_underlying_type(this, underlyingType); + trapFile.tuple_underlying_type(this, underlyingType.TypeRef); int index = 0; foreach (var element in TupleElements) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index 4b4a8f919ec3..d541febee6db 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -95,6 +95,7 @@ protected void PopulateType(TextWriter trapFile) var baseTypes = new List(); if (symbol.BaseType != null) { + // !! Do not extend "object" if the base type is missing :-( Type baseKey = Create(Context, symbol.BaseType); trapFile.extend(this, baseKey.TypeRef); if (symbol.TypeKind != TypeKind.Struct) @@ -268,6 +269,10 @@ public void ExtractRecursive(TextWriter trapFile, IEntity parent) public static Type Create(Context cx, ITypeSymbol type) { type = type.DisambiguateType(); + + if (type is INamedTypeSymbol nt && nt.IsEvilTwin()) + type = nt.ConstructedFrom; + const bool errorTypeIsNull = false; return type == null || (errorTypeIsNull && type.TypeKind == TypeKind.Error) ? NullType.Create(cx).Type : (Type)cx.CreateEntity(type); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index 2a64a29fa0d2..1e9d1c214f7c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -51,7 +51,7 @@ public override Type ContainingType public override void WriteId(TextWriter trapFile) { - AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type. + AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, TypeNameContext.MethodParam); // Needed for op_explicit(), which differs only by return type. trapFile.Write(' '); BuildMethodId(this, trapFile); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs index 7ca12e00f26b..fadcbd8127b9 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs @@ -120,7 +120,8 @@ public static ExitCode Run(string[] args) var syntaxTrees = new List(); var syntaxTreeTasks = ReadSyntaxTrees( compilerArguments.SourceFiles. - Select(src => canonicalPathCache.GetCanonicalPath(src.Path)), + Select(src => canonicalPathCache.GetCanonicalPath(src.Path)). + Where(f => !f.EndsWith(".dll")), analyser, compilerArguments.ParseOptions, compilerArguments.Encoding, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 5bd9c90cc76c..f22d5137f6ab 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -4,6 +4,8 @@ using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Cryptography; +using System.Text; namespace Semmle.Extraction.CSharp { @@ -25,6 +27,16 @@ public AnnotatedTypeSymbol(ITypeSymbol symbol, NullableAnnotation nullability) } } + public enum TypeNameContext + { + TypeName, + TypeRef, + AnonymousType, + MethodName, + MethodParam + } + + static class SymbolExtensions { /// @@ -131,17 +143,36 @@ public static bool ContainsTypeParameters(this ITypeSymbol type, Context cx, ISy /// The extraction context. /// The trap builder used to store the result. /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, TypeNameContext assemblyPrefix, ISymbol genericContext) { - if (type.SpecialType != SpecialType.None) + switch(type.SpecialType) { - /* - * Use the keyword ("int" etc) for the built-in types. - * This makes the IDs shorter and means that all built-in types map to - * the same entities (even when using multiple versions of mscorlib). - */ - trapFile.Write(type.ToDisplayString()); - return; + case SpecialType.System_Object: + case SpecialType.System_Void: + case SpecialType.System_Boolean: + case SpecialType.System_Char: + case SpecialType.System_SByte: + case SpecialType.System_Byte: + case SpecialType.System_Int16: + case SpecialType.System_UInt16: + case SpecialType.System_Int32: + case SpecialType.System_UInt32: + case SpecialType.System_Int64: + case SpecialType.System_UInt64: + case SpecialType.System_Decimal: + case SpecialType.System_Single: + case SpecialType.System_Double: + case SpecialType.System_String: + case SpecialType.System_IntPtr: + case SpecialType.System_UIntPtr: + + /* + * Use the keyword ("int" etc) for the built-in types. + * This makes the IDs shorter and means that all built-in types map to + * the same entities (even when using multiple versions of mscorlib). + */ + trapFile.Write(type.ToDisplayString()); + return; } using (cx.StackGuard) @@ -150,7 +181,9 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra { case TypeKind.Array: var array = (IArrayTypeSymbol)type; - subTermAction(cx, trapFile, array.ElementType); + subTermAction(cx, trapFile, array.ElementType, genericContext); + if(assemblyPrefix == TypeNameContext.TypeName) + trapFile.Write((int)array.ElementNullableAnnotation); array.BuildArraySuffix(trapFile); return; case TypeKind.Class: @@ -160,16 +193,29 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, subTermAction); + named.BuildNamedTypeId(cx, trapFile, subTermAction, assemblyPrefix, genericContext); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; - subTermAction(cx, trapFile, ptr.PointedAtType); - trapFile.Write('*'); + subTermAction(cx, trapFile, ptr.PointedAtType, genericContext); + trapFile.Write("*"); return; case TypeKind.TypeParameter: var tp = (ITypeParameterSymbol)type; - trapFile.Write(tp.Name); + switch(tp.TypeParameterKind) + { + case TypeParameterKind.Method: + if(!Equals(genericContext, tp.DeclaringMethod)) + trapFile.WriteSubId(Method.Create(cx, tp.DeclaringMethod)); + trapFile.Write("!!"); + break; + case TypeParameterKind.Type: + if(!Equals(genericContext,tp.DeclaringType)) + subTermAction(cx, trapFile, tp.DeclaringType, genericContext); + trapFile.Write("!"); + break; + } + trapFile.Write(tp.Ordinal); return; case TypeKind.Dynamic: trapFile.Write("dynamic"); @@ -193,8 +239,34 @@ public static void BuildArraySuffix(this IArrayTypeSymbol array, TextWriter trap trapFile.Write(']'); } - static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) + private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool extraPrecise = false) + { + var assembly = asm.Identity; + trapFile.Write(assembly.Name); + trapFile.Write('_'); + trapFile.Write(assembly.Version.Major); + trapFile.Write('.'); + trapFile.Write(assembly.Version.Minor); + trapFile.Write('.'); + trapFile.Write(assembly.Version.Build); + if (extraPrecise) + { + trapFile.Write('.'); + trapFile.Write(assembly.Version.Revision); + } + trapFile.Write("::"); + } + + public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction, TypeNameContext assemblyPrefix, ISymbol genericContext) { + bool prefixAssembly = false; + if (named.IsAnonymous()) prefixAssembly = true; + else if(assemblyPrefix == TypeNameContext.TypeName && cx.Extractor.Identifiers != IdentifierMode.Imprecise) prefixAssembly = true; + if (named.ContainingAssembly is null) prefixAssembly = false; + + if (prefixAssembly) + BuildAssembly(named.ContainingAssembly, trapFile); + if (named.IsTupleType) { trapFile.Write('('); @@ -203,7 +275,7 @@ static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter { trapFile.Write(f.Name); trapFile.Write(":"); - subTermAction(cx, tb0, f.Type); + subTermAction(cx, tb0, f.Type, genericContext); } ); trapFile.Write(")"); @@ -212,16 +284,16 @@ static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter if (named.ContainingType != null) { - subTermAction(cx, trapFile, named.ContainingType); + subTermAction(cx, trapFile, named.ContainingType, genericContext); trapFile.Write('.'); } - else if (named.ContainingNamespace != null) + else if (named.ContainingNamespace != null && !named.IsConstructedGeneric()) { named.ContainingNamespace.BuildNamespace(cx, trapFile); } if (named.IsAnonymousType) - named.BuildAnonymousName(cx, trapFile, subTermAction, true); + named.BuildAnonymousName(cx, trapFile, subTermAction, true, genericContext); else if (named.TypeParameters.IsEmpty) trapFile.Write(named.Name); else if (IsReallyUnbound(named)) @@ -232,7 +304,7 @@ static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter } else { - subTermAction(cx, trapFile, named.ConstructedFrom); + subTermAction(cx, trapFile, named.ConstructedFrom, genericContext); trapFile.Write('<'); // Encode the nullability of the type arguments in the label. // Type arguments with different nullability can result in @@ -245,40 +317,20 @@ static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter static void BuildNamespace(this INamespaceSymbol ns, Context cx, TextWriter trapFile) { - // Only include the assembly information in each type ID - // for normal extractions. This is because standalone extractions - // lack assembly information or may be ambiguous. - bool prependAssemblyToTypeId = !cx.Extractor.Standalone && ns.ContainingAssembly != null; - - if (prependAssemblyToTypeId) - { - // Note that we exclude the revision number as this has - // been observed to be unstable. - var assembly = ns.ContainingAssembly.Identity; - trapFile.Write(assembly.Name); - trapFile.Write('_'); - trapFile.Write(assembly.Version.Major); - trapFile.Write('.'); - trapFile.Write(assembly.Version.Minor); - trapFile.Write('.'); - trapFile.Write(assembly.Version.Build); - trapFile.Write("::"); - } - trapFile.WriteSubId(Namespace.Create(cx, ns)); trapFile.Write('.'); } - static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName) + static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName, ISymbol genericContext) { var buildParam = includeParamName ? (prop, tb0) => { tb0.Write(prop.Name); - trapFile.Write(' '); - subTermAction(cx, tb0, prop.Type); + tb0.Write(' '); + subTermAction(cx, tb0, prop.Type, genericContext); } - : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type)); + : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type, genericContext)); int memberCount = type.GetMembers().OfType().Count(); int hackTypeNumber = memberCount == 1 ? 1 : 0; trapFile.Write("<>__AnonType"); @@ -350,15 +402,16 @@ public static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Co if (namedType.IsAnonymousType) { - namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false); + namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub, _) => sub.BuildDisplayName(cx0, tb0), false, namedType); } trapFile.Write(namedType.Name); - if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any()) + if (namedType.IsGenericType && /* namedType.TypeKind != TypeKind.Error && */ namedType.TypeArguments.Any()) { trapFile.Write('<'); trapFile.BuildList(",", namedType.TypeArguments, (p, tb0) => { + // tb0.Write(p.Name); if (IsReallyBound(namedType)) p.BuildDisplayName(cx, tb0); }); @@ -490,12 +543,6 @@ public static AnnotatedTypeSymbol GetType(this Context cx, Microsoft.CodeAnalysi return new AnnotatedTypeSymbol(info.Type.DisambiguateType(), info.Nullability.Annotation); } - /// - /// Gets the annotated type of an ILocalSymbol. - /// This has not yet been exposed on the public API. - /// - public static AnnotatedTypeSymbol GetAnnotatedType(this ILocalSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); - /// /// Gets the annotated type of an IPropertySymbol. /// This has not yet been exposed on the public API. diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 836a21312fb9..96639dd9beeb 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -381,6 +381,16 @@ internal static void nullable_underlying_type(this TextWriter trapFile, Type nul trapFile.WriteTuple("nullable_underlying_type", nullableType, underlyingType); } + internal static void nullability(this TextWriter trapFile, NullabilityEntity nullability, int annotation) + { + trapFile.WriteTuple("nullability", nullability, annotation); + } + + internal static void nullability_member(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity child) + { + trapFile.WriteTuple(nameof(nullability_member), nullability, index, child); + } + internal static void numlines(this TextWriter trapFile, IEntity label, LineCounts lineCounts) { trapFile.WriteTuple("numlines", label, lineCounts.Total, lineCounts.Code, lineCounts.Comment); @@ -471,7 +481,7 @@ internal static void tuple_element(this TextWriter trapFile, TupleType type, int trapFile.WriteTuple("tuple_element", type, index, field); } - internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, NamedType underlying) + internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, Type underlying) { trapFile.WriteTuple("tuple_underlying_type", type, underlying); } @@ -481,9 +491,14 @@ internal static void type_annotation(this TextWriter trapFile, IEntity element, trapFile.WriteTuple("type_annotation", element, (int)annotation); } - internal static void type_argument_annotation(this TextWriter trapFile, IEntity element, int index, Kinds.TypeAnnotation annotation) + internal static void type_arguments(this TextWriter trapFile, Type arg, int n, IEntity typeOrMethod) + { + trapFile.WriteTuple("type_arguments", arg, n, typeOrMethod); + } + + internal static void type_location(this TextWriter trapFile, Type type, Location location) { - trapFile.WriteTuple("type_argument_annotation", element, index, (int)annotation); + trapFile.WriteTuple("type_location", type, location); } internal static void type_mention(this TextWriter trapFile, TypeMention ta, Type type, IEntity parent) @@ -496,14 +511,9 @@ internal static void type_mention_location(this TextWriter trapFile, TypeMention trapFile.WriteTuple("type_mention_location", ta, loc); } - internal static void type_arguments(this TextWriter trapFile, Type arg, int n, IEntity typeOrMethod) - { - trapFile.WriteTuple("type_arguments", arg, n, typeOrMethod); - } - - internal static void type_location(this TextWriter trapFile, Type type, Location location) + internal static void type_nullability(this TextWriter trapFile, IEntity element, NullabilityEntity nullability) { - trapFile.WriteTuple("type_location", type, location); + trapFile.WriteTuple("type_nullability", element, nullability); } internal static void type_parameter_constraints(this TextWriter trapFile, TypeParameterConstraints constraints, TypeParameter typeParam) diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index e470d3258ece..449f8e183040 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -87,6 +87,16 @@ public interface IExtractor /// The extraction scope (what to include in this trap file). /// Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope); + + IdentifierMode Identifiers { get; } + } + + public enum IdentifierMode + { + Imprecise, + Flexible, + Precise, + ExtraPrecise } /// @@ -112,6 +122,7 @@ public bool Standalone public Extractor(bool standalone, string outputPath, ILogger logger) { Standalone = standalone; + if (Standalone) Identifiers = IdentifierMode.Imprecise; OutputPath = outputPath; Logger = logger; } @@ -197,5 +208,7 @@ public string OutputPath public ILogger Logger { get; private set; } public static string Version => $"{ThisAssembly.Git.BaseTag} ({ThisAssembly.Git.Sha})"; + + public IdentifierMode Identifiers { get; } = IdentifierMode.Imprecise; } } diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index 14a88830ad24..80c4d1250ca4 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -8,7 +8,8 @@ import csharp -private module Annotations { +// private +module Annotations { newtype TAnnotation = TNotNullableRefType() or TNullableRefType() or @@ -77,24 +78,28 @@ private module Annotations { } newtype TAnnotations = - TAnnotationFlags(int flags) { - flags = getElementTypeFlags(_) or - flags = getTypeArgumentFlags(_, _) or - flags = getTypeParameterFlags(_, _) + TAnnotationFlags(int flags, Nullability n) { + exists(Element e | flags = getElementTypeFlags(e) and n = getElementNullability(e)) + or + flags = getTypeParameterFlags(_, _) and n instanceof DefaultOblivious + or + flags = 0 // n is unbound } - /** A set of annotations on a type. */ class TypeAnnotations extends TAnnotations { int flags; - TypeAnnotations() { this = TAnnotationFlags(flags) } + Nullability nullability; - /** Gets an annotation in this set of annotations. */ - TypeAnnotation getAnAnnotation() { isSet(result.getBit()) } + TypeAnnotations() { this = TAnnotationFlags(flags, nullability) } - private predicate isSet(int bit) { - isBit(bit) and - exists(int mask | mask = getBitMask(bit) | flags.bitAnd(mask) = mask) + int getFlags() { result = flags } + + Nullability getNullability() { result = nullability } + + bindingset[i] + TypeAnnotations getChild(int i) { + result.getFlags() = 0 and result.getNullability() = this.getNullability().getMember(i) } /** Gets text to be displayed before the type. */ @@ -117,13 +122,53 @@ private module Annotations { /** Gets a textual representation of this type annotation. */ string toString() { result = getTypePrefix() + getTypeSuffix() } + + private predicate isSet(int bit) { + isBit(bit) and + exists(int mask | mask = getBitMask(bit) | flags.bitAnd(mask) = mask) + } + + /** Gets an annotation in this set of annotations. */ + TypeAnnotation getAnAnnotation() { + isSet(result.getBit()) + or + nullability instanceof AnnotatedNullability and result instanceof NullableRefType + or + nullability instanceof NotAnnotatedNullability and result instanceof NonNullableRefType + } + } + + // A structure to encode the nullability of various types. For example + class Nullability extends @nullability { + abstract string toString(); + + bindingset[i] + Nullability getMember(int i) { + if nullability_member(this, i, _) then nullability_member(this, i, result) else result = this + } + } + + class ObliviousNullability extends Nullability, @oblivious { + override string toString() { result = "oblivious" } + } + + class DefaultOblivious extends ObliviousNullability { + DefaultOblivious() { not nullability_member(this, _, _) } + } + + class AnnotatedNullability extends Nullability, @annotated { + override string toString() { result = "annotated" } + } + + class NotAnnotatedNullability extends Nullability, @not_annotated { + override string toString() { result = "not annotated" } } /** Holds if the type annotations `annotations` apply to type `type` on element `element`. */ predicate elementTypeAnnotations( @has_type_annotation element, Type type, TypeAnnotations annotations ) { - annotations = TAnnotationFlags(getElementTypeFlags(element)) and + annotations = TAnnotationFlags(getElementTypeFlags(element), getElementNullability(element)) and ( type = element.(Assignable).getType() or @@ -131,8 +176,8 @@ private module Annotations { or type = element.(Expr).getType() or - type = element.(ArrayType).getElementType() - or + // or + // type = element.(ArrayType).getElementType() type = element.(DelegateType).getReturnType() ) } @@ -150,26 +195,37 @@ private int getElementTypeFlags(@has_type_annotation element) { result = sum(int b | type_annotation(element, b) | b) } -private int getTypeArgumentFlags(ConstructedGeneric generic, int argument) { - exists(generic.getTypeArgument(argument)) and - result = sum(int b | type_argument_annotation(generic, argument, b) | b) -} - private int getTypeParameterFlags(TypeParameterConstraints constraints, Type type) { specific_type_parameter_annotation(constraints, getTypeRef(type), _) and result = sum(int b | specific_type_parameter_annotation(constraints, getTypeRef(type), b) | b) } +private Annotations::Nullability getElementNullability(@has_type_annotation element) { + if type_nullability(element, _) + then type_nullability(element, result) + else result instanceof Annotations::DefaultOblivious +} + private newtype TAnnotatedType = TAnnotatedTypeNullability(Type type, Annotations::TypeAnnotations annotations) { Annotations::elementTypeAnnotations(_, type, annotations) or - exists(ConstructedGeneric c, int i | - type = c.getTypeArgument(i) and - annotations = Annotations::TAnnotationFlags(getTypeArgumentFlags(c, i)) + exists(AnnotatedConstructedType c, int i | + type = c.getType().(ConstructedType).getTypeArgument(i) and + annotations = c.getAnnotations().getChild(i) ) or - annotations = Annotations::TAnnotationFlags(getTypeParameterFlags(_, type)) + annotations.getFlags() = getTypeParameterFlags(_, type) and + annotations.getNullability() instanceof Annotations::DefaultOblivious + or + // All types + annotations.getFlags() = 0 and + annotations.getNullability() instanceof Annotations::DefaultOblivious + or + exists(AnnotatedArrayType at | + type = at.getType().(ArrayType).getElementType() and + annotations = at.getAnnotations().getChild(0) + ) } /** A type with additional information. */ @@ -192,7 +248,7 @@ class AnnotatedType extends TAnnotatedType { * Gets the unannotated type, for example `string` in `string?`. * Note that this might be a nullable value type (`System.Nullable`). */ - final Type getType() { result = type } + Type getType() { result = type } /** * Gets the underlying type, for example `string` in `string?` @@ -206,7 +262,7 @@ class AnnotatedType extends TAnnotatedType { } /** Gets the type annotation set of this annotated type. */ - private Annotations::TypeAnnotations getAnnotations() { result = annotations } + Annotations::TypeAnnotations getAnnotations() { result = annotations } /** Gets a type annotation of this annotated type. */ private Annotations::TypeAnnotation getAnAnnotation() { @@ -233,14 +289,70 @@ class AnnotatedType extends TAnnotatedType { /** Holds if this annotated type applies to element `e`. */ predicate appliesTo(Element e) { Annotations::elementTypeAnnotations(e, type, annotations) } + /** Holds if this annotated type is the type argument 'i' of constructed generic 'g'. */ + predicate appliesToTypeArgument(ConstructedGeneric g, int i) { + this.getAnnotations().getFlags() = 0 and + this.getAnnotations().getNullability() = getElementNullability(g).getMember(i) and + this.getType() = g.getTypeArgument(i) + } + /** Holds if this annotated type applies to type parameter constraints `constraints`. */ predicate appliesToTypeConstraint(TypeParameterConstraints constraints) { - annotations = Annotations::TAnnotationFlags(getTypeParameterFlags(constraints, type)) + annotations.getFlags() = getTypeParameterFlags(constraints, type) } +} - /** Holds if this annotated type applies to the `i`th type argument of constructed generic `g`. */ - predicate appliesToTypeArgument(ConstructedGeneric g, int i) { - type = g.getTypeArgument(i) and - this.getAnnotations() = Annotations::TAnnotationFlags(getTypeArgumentFlags(g, i)) +/** An array type with additional information. */ +class AnnotatedArrayType extends AnnotatedType { + override ArrayType type; + + /** Gets the annotated element type of this array, for example `int?` in `int?[]`. */ + final AnnotatedType getElementType() { + result.getType() = type.getElementType() and + result.getAnnotations() = this.getAnnotations().getChild(0) + } + + private string getDimensionString(AnnotatedType elementType) { + exists(AnnotatedType et, string res | + et = getElementType() and + res = "[" + type.getRankString(0) + "]" and + if et.getUnderlyingType() instanceof ArrayType and not et.isNullableRefType() + then result = res + et.(AnnotatedArrayType).getDimensionString(elementType) + else ( + result = res and elementType = et + ) + ) + } + + override string toString() { + exists(AnnotatedType elementType | + result = annotations.getTypePrefix() + elementType.toString() + + this.getDimensionString(elementType) + annotations.getTypeSuffix() + ) + } +} + +/** A constructed type with additional information. */ +class AnnotatedConstructedType extends AnnotatedType { + override ConstructedType type; + + /** Gets the `i`th type argument of this constructed type. */ + AnnotatedType getTypeArgument(int i) { + result.getType() = type.getTypeArgument(i) and + result.getAnnotations() = this.getAnnotations().getChild(i) + } + + override string toString() { + result = annotations.getTypePrefix() + type.getUnboundGeneric().getNameWithoutBrackets() + "<" + + this.getTypeArgumentsString() + ">" + annotations.getTypeSuffix() + } + + language[monotonicAggregates] + private string getTypeArgumentsString() { + result = concat(int i | + exists(this.getTypeArgument(i)) + | + this.getTypeArgument(i).toString(), ", " order by i + ) } } diff --git a/csharp/ql/src/semmle/code/csharp/Generics.qll b/csharp/ql/src/semmle/code/csharp/Generics.qll index cab7a520df40..29fd083aec57 100644 --- a/csharp/ql/src/semmle/code/csharp/Generics.qll +++ b/csharp/ql/src/semmle/code/csharp/Generics.qll @@ -370,21 +370,21 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric { override UnboundGenericType getUnboundGeneric() { constructed_generic(this, getTypeRef(result)) } + override string toStringWithTypes() { + result = getUnboundGeneric().getNameWithoutBrackets() + "<" + this.getTypeArgumentsString() + + ">" + } + + final override Type getChild(int n) { result = getTypeArgument(n) } + language[monotonicAggregates] - private string annotatedTypeArgumentsToString() { + private string getTypeArgumentsString() { result = concat(int i | - exists(this.getAnnotatedTypeArgument(i)) + exists(this.getTypeArgument(i)) | - this.getAnnotatedTypeArgument(i).toString(), ", " order by i + this.getTypeArgument(i).toString(), ", " order by i ) } - - override string toStringWithTypes() { - result = getUnboundGeneric().getNameWithoutBrackets() + "<" + - this.annotatedTypeArgumentsToString() + ">" - } - - final override Type getChild(int n) { result = getTypeArgument(n) } } /** diff --git a/csharp/ql/src/semmle/code/csharp/Type.qll b/csharp/ql/src/semmle/code/csharp/Type.qll index bdd28d8a0af9..c723cc9fc0ea 100644 --- a/csharp/ql/src/semmle/code/csharp/Type.qll +++ b/csharp/ql/src/semmle/code/csharp/Type.qll @@ -821,26 +821,23 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { /** Gets the element type of this array, for example `int` in `int[]`. */ override Type getElementType() { array_element_type(this, _, _, getTypeRef(result)) } - /** Gets the annotated element type of this array, for example `int?` in `int?[]`. */ - final AnnotatedType getAnnotatedElementType() { result.appliesTo(this) } - /** Holds if this array type has the same shape (dimension and rank) as `that` array type. */ predicate hasSameShapeAs(ArrayType that) { getDimension() = that.getDimension() and getRank() = that.getRank() } - private string getRankString(int i) { + string getRankString(int i) { i in [0 .. getRank() - 1] and if i = getRank() - 1 then result = "" else result = "," + getRankString(i + 1) } - private string getDimensionString(AnnotatedType elementType) { - exists(AnnotatedType et, string res | - et = getAnnotatedElementType() and + private string getDimensionString(Type elementType) { + exists(Type et, string res | + et = this.getElementType() and res = "[" + getRankString(0) + "]" and - if et.getUnderlyingType() instanceof ArrayType and not et.isNullableRefType() - then result = res + et.getUnderlyingType().(ArrayType).getDimensionString(elementType) + if et instanceof ArrayType + then result = res + et.(ArrayType).getDimensionString(elementType) else ( result = res and elementType = et ) @@ -848,7 +845,7 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type { } override string toStringWithTypes() { - exists(AnnotatedType elementType | + exists(Type elementType | result = elementType.toString() + this.getDimensionString(elementType) ) } @@ -905,7 +902,7 @@ class UnknownType extends Type, @unknown_type { } */ class TupleType extends ValueType, @tuple_type { /** Gets the underlying type of this tuple, which is of type `System.ValueTuple`. */ - ConstructedStruct getUnderlyingType() { tuple_underlying_type(this, result) } + ConstructedStruct getUnderlyingType() { tuple_underlying_type(this, getTypeRef(result)) } /** * Gets the `n`th element of this tuple, indexed from 0. diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index f93793ee5f6b..e8b3d5aca883 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -244,7 +244,7 @@ locations_default( @sourceline = @file | @callable | @xmllocatable; numlines( - unique int element_id: @sourceline ref, + int element_id: @sourceline ref, int num_lines: int ref, int num_code: int ref, int num_comment: int ref); @@ -381,7 +381,7 @@ typerefs( varchar(900) name: string ref); typeref_type( - unique int id: @typeref ref, + int id: @typeref ref, unique int typeId: @type ref); @type_or_ref = @type | @typeref; @@ -424,7 +424,7 @@ type_location( tuple_underlying_type( unique int tuple: @tuple_type ref, - int struct: @struct_type ref); + int struct: @type_or_ref ref); #keyset[tuple, index] tuple_element( @@ -452,7 +452,7 @@ type_mention_location( unique int id: @type_mention ref, int loc: @location ref); -@has_type_annotation = @assignable | @type_parameter | @callable | @array_type | @expr | @delegate_type; +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; /** * A direct annotation on an entity, for example `string? x;`. @@ -472,8 +472,18 @@ type_mention_location( */ type_annotation(int id: @has_type_annotation ref, int annotation: int ref); -/** The annotation of type arguments of a constructed type or method. */ -type_argument_annotation(int constructedgeneric: @generic ref, int position: int ref, int annotation: int ref); +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[nullability, index] +nullability_member(int nullability: @nullability ref, int index: int ref, int child: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref) /** GENERICS **/ @@ -633,8 +643,8 @@ operator_location( int loc: @location ref); constant_value( - unique int id: @variable ref, - varchar(900) value: string ref); + int id: @variable ref, + string value: string ref); /** CALLABLES **/ @@ -674,7 +684,7 @@ destructor_location( int loc: @location ref); overrides( - unique int id: @callable ref, + int id: @callable ref, int base_id: @callable ref); explicitly_implements( diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql index f9bda91b349d..c0febaa2afa3 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql @@ -28,10 +28,10 @@ query predicate assignableTypes(Assignable a, AnnotatedType t) { t = a.getAnnotatedType() } -query predicate arrayElements(Variable v, ArrayType array, AnnotatedType elementType) { +query predicate arrayElements(Variable v, AnnotatedArrayType array, AnnotatedType elementType) { v.getFile().getBaseName() = "NullableRefTypes.cs" and - array = v.getType() and - elementType = array.getAnnotatedElementType() + array = v.getAnnotatedType() and + elementType = array.getElementType() } query predicate returnTypes(Callable c, string t) { @@ -39,13 +39,13 @@ query predicate returnTypes(Callable c, string t) { t = c.getAnnotatedReturnType().toString() } -query predicate typeArguments(ConstructedGeneric generic, int arg, string argument) { +query predicate typeArguments(AnnotatedConstructedType generic, int arg, string argument) { ( - generic = any(Variable v | v.fromSource()).getType() - or - generic = any(MethodCall mc).getTarget() + generic.getType() = any(Variable v | v.fromSource()).getType() + //or + // generic.getType() = any(MethodCall mc).getTarget() ) and - argument = generic.getAnnotatedTypeArgument(arg).toString() + argument = generic.getTypeArgument(arg).toString() } query predicate nullableTypeParameters(TypeParameter p) { @@ -56,3 +56,5 @@ query predicate annotatedTypeConstraints(TypeParameter p, AnnotatedType t) { t = p.getConstraints().getAnAnnotatedTypeConstraint() and t.getLocation() instanceof SourceLocation } + +query predicate typeNotAnnotated(Type type) { not exists(AnnotatedType at | at.getType() = type) } From 9fd4a9ceb65131cc0a0c407d08e0d802c73d3a33 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Fri, 27 Sep 2019 14:52:55 +0100 Subject: [PATCH 0343/2538] C#: Implement NullabilityEntity to model structured nullability on the side --- .../Semmle.Extraction.CIL/Entities/Type.cs | 2 +- .../Semmle.Extraction.CSharp/Analyser.cs | 4 +- .../Entities/LocalFunction.cs | 2 +- .../Entities/Method.cs | 11 +- .../Entities/Property.cs | 1 - .../Entities/Symbol.cs | 2 +- .../Entities/Types/NamedType.cs | 21 +- .../Entities/Types/TupleType.cs | 2 +- .../Entities/Types/TypeParameter.cs | 8 +- .../Entities/UserOperator.cs | 2 +- .../SymbolExtensions.cs | 33 +- .../Semmle.Extraction.CSharp/Tuples.cs | 8 +- .../extractor/Semmle.Extraction/Extractor.cs | 22 +- .../src/semmle/code/csharp/AnnotatedType.qll | 98 +++-- csharp/ql/src/semmlecode.csharp.dbscheme | 4 +- .../csharp8/NullCoalescingAssignment.expected | 2 +- .../library-tests/csharp8/NullableRefTypes.cs | 6 + .../csharp8/NullableRefTypes.expected | 360 ++++++++++-------- .../library-tests/csharp8/NullableRefTypes.ql | 23 +- 19 files changed, 352 insertions(+), 259 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs index 1f6f07023f7c..04b25553b6b7 100644 --- a/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CIL/Entities/Type.cs @@ -1208,7 +1208,7 @@ public void WriteId(TextWriter trapFile, GenericContext gc) { elementType.WriteId(trapFile, gc); trapFile.Write('['); - for(int i=1; i AddSignatureTypeToId(Context, tb0, symbol, ta, TypeNameContext.MethodName)); + trapFile.BuildList(",", symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(Context, tb0, symbol, ta, TypeIdentifierContext.MethodName)); trapFile.Write('>'); } trapFile.Write(";localfunction"); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index dac490f98b28..18aec3b05ecc 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -108,7 +108,6 @@ public void Overrides(TextWriter trapFile) /// protected static void BuildMethodId(Method m, TextWriter trapFile) { - // AddSignatureTypeToId(m.Context, trapFile, m.symbol, m.ContainingType.symbol, false); trapFile.WriteSubId(m.ContainingType); AddExplicitInterfaceQualifierToId(m.Context, trapFile, m.symbol.ExplicitInterfaceImplementations); @@ -130,7 +129,7 @@ protected static void BuildMethodId(Method m, TextWriter trapFile) // Type arguments with different nullability can result in // a constructed method with different nullability of its parameters and return type, // so we need to create a distinct database entity for it. - trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, TypeNameContext.MethodName); trapFile.Write((int)ta.Nullability); }); + trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, TypeIdentifierContext.MethodName); trapFile.Write((int)ta.Nullability); }); trapFile.Write('>'); } } @@ -200,10 +199,10 @@ public override void WriteId(TextWriter trapFile) /// to make the reference to #3 in the label definition #4 for /// T valid. /// - protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, TypeNameContext assemblyPrefix) + protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, TypeIdentifierContext tic) { if (type.ContainsTypeParameters(cx, method)) - type.BuildTypeId(cx, trapFile, (cx0, tb0, type0, _) => AddSignatureTypeToId(cx, tb0, method, type0, assemblyPrefix), assemblyPrefix, method); + type.BuildTypeId(cx, trapFile, (cx0, tb0, type0, _) => AddSignatureTypeToId(cx, tb0, method, type0, tic), tic, method); else trapFile.WriteSubId(Type.Create(cx, type).TypeRef); } @@ -216,13 +215,13 @@ protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethod if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, TypeNameContext.MethodParam); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, TypeIdentifierContext.MethodParam); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type, TypeNameContext.MethodParam); + AddSignatureTypeToId(cx, trapFile, method, param.Type, TypeIdentifierContext.MethodParam); switch (param.RefKind) { case RefKind.Out: diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs index e1822504120b..bcb971ae7998 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Property.cs @@ -15,7 +15,6 @@ protected Property(Context cx, IPropertySymbol init) public override void WriteId(TextWriter trapFile) { - // trapFile.WriteSubId(ContainingType.TypeRef); trapFile.WriteSubId(ContainingType); trapFile.Write('.'); Method.AddExplicitInterfaceQualifierToId(Context, trapFile, symbol.ExplicitInterfaceImplementations); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs index 4d37d4f1d38c..6d0f5dd80c8f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs @@ -32,7 +32,7 @@ protected void PopulateNullability(TextWriter trapFile, AnnotatedTypeSymbol type { var ta = type.Nullability.GetTypeAnnotation(); var n = NullabilityEntity.Create(Context, Nullability.Create(type)); - if (ta != Kinds.TypeAnnotation.None || !type.HasConsistentNullability()) + if (!type.HasObliviousNullability()) { trapFile.type_nullability(this, n); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index ca82da2ecc46..28b1e37514ae 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -29,7 +29,7 @@ public override void Populate(TextWriter trapFile) return; } - trapFile.typeref_type((NamedTypeRef)TypeRef, this); + trapFile.typeref_type((TypeRef)TypeRef, this); if (symbol.IsGenericType) { @@ -111,7 +111,7 @@ public override IEnumerable Locations public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeNameContext.TypeName, symbol); + symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeIdentifierContext.TypeName, symbol); trapFile.Write(";type"); } @@ -151,26 +151,26 @@ class NamedTypeFactory : ICachedEntityFactory public NamedType Create(Context cx, INamedTypeSymbol init) => new NamedType(cx, init); } - public override Type TypeRef => NamedTypeRef.Create(Context, this, symbol); + public override Type TypeRef => Entities.TypeRef.Create(Context, this, symbol); } - class NamedTypeRef : Type + class TypeRef : Type { readonly Type referencedType; - public NamedTypeRef(Context cx, Type type, ITypeSymbol symbol) : base(cx, symbol) + public TypeRef(Context cx, Type type, ITypeSymbol symbol) : base(cx, symbol) { referencedType = type; } - public static NamedTypeRef Create(Context cx, Type referencedType, ITypeSymbol type) => + public static TypeRef Create(Context cx, Type referencedType, ITypeSymbol type) => NamedTypeRefFactory.Instance.CreateEntity2(cx, (referencedType, type)); - class NamedTypeRefFactory : ICachedEntityFactory<(Type, ITypeSymbol), NamedTypeRef> + class NamedTypeRefFactory : ICachedEntityFactory<(Type, ITypeSymbol), TypeRef> { public static readonly NamedTypeRefFactory Instance = new NamedTypeRefFactory(); - public NamedTypeRef Create(Context cx, (Type, ITypeSymbol) init) => new NamedTypeRef(cx, init.Item1, init.Item2); + public TypeRef Create(Context cx, (Type, ITypeSymbol) init) => new TypeRef(cx, init.Item1, init.Item2); } public override bool NeedsPopulation => true; @@ -179,11 +179,10 @@ public override void WriteId(TextWriter trapFile) { void ExpandType(Context cx0, TextWriter tb0, ITypeSymbol sub, ISymbol gc) { - sub.BuildTypeId(cx0, tb0, ExpandType, TypeNameContext.TypeRef, gc); + sub.BuildTypeId(cx0, tb0, ExpandType, TypeIdentifierContext.TypeRef, gc); } - // Prefix anonymous types because they shouldn't be visible outside of the current assembly. - symbol.BuildTypeId(Context, trapFile, ExpandType, TypeNameContext.TypeRef, symbol); + symbol.BuildTypeId(Context, trapFile, ExpandType, TypeIdentifierContext.TypeRef, symbol); trapFile.Write(";typeref"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index 7adfa6ab8e74..8da87ba318df 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -32,7 +32,7 @@ class TupleTypeFactory : ICachedEntityFactory public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeNameContext.TypeName, symbol); + symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeIdentifierContext.TypeName, symbol); trapFile.Write(";tuple"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs index 6377c5d49c7b..2fdb8cd3a834 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TypeParameter.cs @@ -51,11 +51,11 @@ public override void Populate(TextWriter trapFile) baseType = abase.Symbol; var t = Create(Context, abase.Symbol); trapFile.specific_type_parameter_constraints(constraints, t.TypeRef); - if (abase.Nullability.GetTypeAnnotation() != Kinds.TypeAnnotation.None) - trapFile.specific_type_parameter_annotation(constraints, t.TypeRef, abase.Nullability.GetTypeAnnotation()); + if (!abase.HasObliviousNullability()) + trapFile.specific_type_parameter_nullability(constraints, t.TypeRef, NullabilityEntity.Create(Context, Nullability.Create(abase))); } - trapFile.types(this, Semmle.Extraction.Kinds.TypeKind.TYPE_PARAMETER, symbol.Name); + trapFile.types(this, Kinds.TypeKind.TYPE_PARAMETER, symbol.Name); trapFile.extend(this, Create(Context, baseType).TypeRef); Namespace parentNs = Namespace.Create(Context, symbol.TypeParameterKind == TypeParameterKind.Method ? Context.Compilation.GlobalNamespace : symbol.ContainingNamespace); @@ -66,7 +66,7 @@ public override void Populate(TextWriter trapFile) trapFile.type_location(this, Context.Create(l)); } - if (this.IsSourceDeclaration) + if (IsSourceDeclaration) { var declSyntaxReferences = symbol.DeclaringSyntaxReferences.Select(d => d.GetSyntax()). Select(s => s.Parent).Where(p => p != null).Select(p => p.Parent).ToArray(); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index 1e9d1c214f7c..5ac9c3015e0c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -51,7 +51,7 @@ public override Type ContainingType public override void WriteId(TextWriter trapFile) { - AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, TypeNameContext.MethodParam); // Needed for op_explicit(), which differs only by return type. + AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, TypeIdentifierContext.MethodParam); // Needed for op_explicit(), which differs only by return type. trapFile.Write(' '); BuildMethodId(this, trapFile); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index f22d5137f6ab..a5a5dc3aa839 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -27,7 +27,11 @@ public AnnotatedTypeSymbol(ITypeSymbol symbol, NullableAnnotation nullability) } } - public enum TypeNameContext + /// + /// Marks where a type identifier is being generated, which could change + /// the way that the identifier is generated. + /// + public enum TypeIdentifierContext { TypeName, TypeRef, @@ -36,7 +40,6 @@ public enum TypeNameContext MethodParam } - static class SymbolExtensions { /// @@ -143,7 +146,7 @@ public static bool ContainsTypeParameters(this ITypeSymbol type, Context cx, ISy /// The extraction context. /// The trap builder used to store the result. /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, TypeNameContext assemblyPrefix, ISymbol genericContext) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, TypeIdentifierContext tic, ISymbol genericContext) { switch(type.SpecialType) { @@ -182,8 +185,6 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra case TypeKind.Array: var array = (IArrayTypeSymbol)type; subTermAction(cx, trapFile, array.ElementType, genericContext); - if(assemblyPrefix == TypeNameContext.TypeName) - trapFile.Write((int)array.ElementNullableAnnotation); array.BuildArraySuffix(trapFile); return; case TypeKind.Class: @@ -193,7 +194,7 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, subTermAction, assemblyPrefix, genericContext); + named.BuildNamedTypeId(cx, trapFile, subTermAction, tic, genericContext); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; @@ -205,12 +206,12 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra switch(tp.TypeParameterKind) { case TypeParameterKind.Method: - if(!Equals(genericContext, tp.DeclaringMethod)) + if (!Equals(genericContext, tp.DeclaringMethod)) trapFile.WriteSubId(Method.Create(cx, tp.DeclaringMethod)); trapFile.Write("!!"); break; case TypeParameterKind.Type: - if(!Equals(genericContext,tp.DeclaringType)) + if (!Equals(genericContext,tp.DeclaringType)) subTermAction(cx, trapFile, tp.DeclaringType, genericContext); trapFile.Write("!"); break; @@ -257,11 +258,11 @@ private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool trapFile.Write("::"); } - public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction, TypeNameContext assemblyPrefix, ISymbol genericContext) + public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction, TypeIdentifierContext tic, ISymbol genericContext) { bool prefixAssembly = false; if (named.IsAnonymous()) prefixAssembly = true; - else if(assemblyPrefix == TypeNameContext.TypeName && cx.Extractor.Identifiers != IdentifierMode.Imprecise) prefixAssembly = true; + else if(tic == TypeIdentifierContext.TypeName && cx.Extractor.TrapIdentifiers != TrapIdenfierMode.Imprecise) prefixAssembly = true; if (named.ContainingAssembly is null) prefixAssembly = false; if (prefixAssembly) @@ -310,7 +311,9 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex // Type arguments with different nullability can result in // a constructed type with different nullability of its members and methods, // so we need to create a distinct database entity for it. - trapFile.BuildList(",", named.GetAnnotatedTypeArguments(), (ta, tb0) => { subTermAction(cx, tb0, ta.Symbol); trapFile.Write((int)ta.Nullability); }); + trapFile.BuildList(",", named.GetAnnotatedTypeArguments(), + (ta, tb0) => subTermAction(cx, tb0, ta.Symbol, genericContext) + ); trapFile.Write('>'); } } @@ -406,12 +409,11 @@ public static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Co } trapFile.Write(namedType.Name); - if (namedType.IsGenericType && /* namedType.TypeKind != TypeKind.Error && */ namedType.TypeArguments.Any()) + if (namedType.IsGenericType && namedType.TypeArguments.Any()) { trapFile.Write('<'); trapFile.BuildList(",", namedType.TypeArguments, (p, tb0) => { - // tb0.Write(p.Name); if (IsReallyBound(namedType)) p.BuildDisplayName(cx, tb0); }); @@ -554,6 +556,10 @@ public static AnnotatedTypeSymbol GetType(this Context cx, Microsoft.CodeAnalysi /// This has not yet been exposed on the public API. /// public static AnnotatedTypeSymbol GetAnnotatedType(this IFieldSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); + private static bool IsSpecialized(this IMethodSymbol method) => + method.IsGenericMethod && + !ReferenceEquals(method, method.OriginalDefinition) && + method.TypeParameters.Zip(method.TypeArguments, (a, b) => !ReferenceEquals(a, b)).Any(b => b); /// /// Gets the annotated return type of an IMethodSymbol. @@ -607,6 +613,7 @@ public static IEnumerable GetAnnotatedTypeConstraints(this /// /// Creates an AnnotatedTypeSymbol from an ITypeSymbol. + /// Note: not currently used but might be useful. /// public static AnnotatedTypeSymbol WithAnnotation(this ITypeSymbol symbol, NullableAnnotation annotation) => new AnnotatedTypeSymbol(symbol, annotation); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index 96639dd9beeb..c239d4f0bb20 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -456,9 +456,9 @@ internal static void specific_type_parameter_constraints(this TextWriter trapFil trapFile.WriteTuple("specific_type_parameter_constraints", constraints, baseType); } - internal static void specific_type_parameter_annotation(this TextWriter trapFile, TypeParameterConstraints constraints, Type baseType, TypeAnnotation annotation) + internal static void specific_type_parameter_nullability(this TextWriter trapFile, TypeParameterConstraints constraints, Type baseType, NullabilityEntity nullability) { - trapFile.WriteTuple("specific_type_parameter_annotation", constraints, baseType, (int)annotation); + trapFile.WriteTuple("specific_type_parameter_nullability", constraints, baseType, nullability); } internal static void stmt_location(this TextWriter trapFile, Statement stmt, Location location) @@ -526,12 +526,12 @@ internal static void type_parameters(this TextWriter trapFile, TypeParameter par trapFile.WriteTuple("type_parameters", param, child, typeOrMethod, (int)param.Variance); } - internal static void typeref_type(this TextWriter trapFile, NamedTypeRef typeref, Type type) + internal static void typeref_type(this TextWriter trapFile, TypeRef typeref, Type type) { trapFile.WriteTuple("typeref_type", typeref, type); } - internal static void typerefs(this TextWriter trapFile, NamedTypeRef type, string name) + internal static void typerefs(this TextWriter trapFile, TypeRef type, string name) { trapFile.WriteTuple("typerefs", type, name); } diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index 449f8e183040..fd8aee723e30 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -88,15 +88,21 @@ public interface IExtractor /// Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope); - IdentifierMode Identifiers { get; } + /// + /// Adjusts the algorithm used to generate identifiers in trap files. + /// + TrapIdenfierMode TrapIdentifiers { get; } } - public enum IdentifierMode + /// + /// Configures how to generate identifiers in trap files. + /// + public enum TrapIdenfierMode { - Imprecise, - Flexible, - Precise, - ExtraPrecise + Imprecise, // Names are not qualified by assembly version + Flexible, // Some names are qualified by assembly versions - typerefs are not however. + Precise, // All names are qualified by their partial assembly version (excludes build number) + ExtraPrecise // All names are qualified by their full assembly version. } /// @@ -122,7 +128,7 @@ public bool Standalone public Extractor(bool standalone, string outputPath, ILogger logger) { Standalone = standalone; - if (Standalone) Identifiers = IdentifierMode.Imprecise; + if (Standalone) TrapIdentifiers = TrapIdenfierMode.Imprecise; OutputPath = outputPath; Logger = logger; } @@ -209,6 +215,6 @@ public string OutputPath public static string Version => $"{ThisAssembly.Git.BaseTag} ({ThisAssembly.Git.Sha})"; - public IdentifierMode Identifiers { get; } = IdentifierMode.Imprecise; + public TrapIdenfierMode TrapIdentifiers { get; } = TrapIdenfierMode.Imprecise; } } diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index 80c4d1250ca4..afa80c43ae6b 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -8,8 +8,7 @@ import csharp -// private -module Annotations { +private module Annotations { newtype TAnnotation = TNotNullableRefType() or TNullableRefType() or @@ -81,8 +80,6 @@ module Annotations { TAnnotationFlags(int flags, Nullability n) { exists(Element e | flags = getElementTypeFlags(e) and n = getElementNullability(e)) or - flags = getTypeParameterFlags(_, _) and n instanceof DefaultOblivious - or flags = 0 // n is unbound } @@ -93,10 +90,17 @@ module Annotations { TypeAnnotations() { this = TAnnotationFlags(flags, nullability) } + /** Gets the flags (as a bitset) of this type annotation. */ int getFlags() { result = flags } + /** Gets the nullability of this type annotation. */ Nullability getNullability() { result = nullability } + /** + * Gets the `i`th "child" of this type annotation. + * This is used to represent structured datatypes, where the structure + * of the type annotation mirrors the structure of the annotated type. + */ bindingset[i] TypeAnnotations getChild(int i) { result.getFlags() = 0 and result.getNullability() = this.getNullability().getMember(i) @@ -138,30 +142,68 @@ module Annotations { } } - // A structure to encode the nullability of various types. For example + /** + * A structured type annotation representing type nullability. + * For example, `IDictionary?` has nullability `?`. + */ class Nullability extends @nullability { - abstract string toString(); + string toString() { result = getMemberString() + getSelfNullability() } + + language[monotonicAggregates] + private string getMemberString() { + if nullability_member(this, _, _) + then + result = "<" + + concat(int i, Nullability child | + nullability_member(this, i, child) + | + child.toString(), "," order by i + ) + ">" + else result = "" + } + /** + * Gets the `i`th member of this annotation. + * Returns `this` if the nullability is not explicitly + * stored in the database, since many type annotations will have consistent + * nullability. + */ bindingset[i] Nullability getMember(int i) { if nullability_member(this, i, _) then nullability_member(this, i, result) else result = this } + + /** Gets a string representing the nullability. */ + abstract string getSelfNullability(); } + /** + * A type that is "oblivious", either because nullability is not + * applicable, because the code was not compiled in a nullable context, or + * because the C# language version is less than 8. + */ class ObliviousNullability extends Nullability, @oblivious { - override string toString() { result = "oblivious" } + override string getSelfNullability() { result = "_" } } - class DefaultOblivious extends ObliviousNullability { - DefaultOblivious() { not nullability_member(this, _, _) } + /** + * A type that is "fully" oblivious. The type itself is oblivious + * and all type arguments are oblivious. + */ + class NoNullability extends ObliviousNullability { + NoNullability() { not nullability_member(this, _, _) } } + /** A type with annotated nullablity, `?`. */ class AnnotatedNullability extends Nullability, @annotated { - override string toString() { result = "annotated" } + override string getSelfNullability() { result = "?" } } + /** + * A ref type not annotated with `?` in a nullable context. + */ class NotAnnotatedNullability extends Nullability, @not_annotated { - override string toString() { result = "not annotated" } + override string getSelfNullability() { result = "!" } } /** Holds if the type annotations `annotations` apply to type `type` on element `element`. */ @@ -176,8 +218,6 @@ module Annotations { or type = element.(Expr).getType() or - // or - // type = element.(ArrayType).getElementType() type = element.(DelegateType).getReturnType() ) } @@ -195,15 +235,21 @@ private int getElementTypeFlags(@has_type_annotation element) { result = sum(int b | type_annotation(element, b) | b) } -private int getTypeParameterFlags(TypeParameterConstraints constraints, Type type) { - specific_type_parameter_annotation(constraints, getTypeRef(type), _) and - result = sum(int b | specific_type_parameter_annotation(constraints, getTypeRef(type), b) | b) +private Annotations::Nullability getTypeParameterNullability( + TypeParameterConstraints constraints, Type type +) { + if specific_type_parameter_nullability(constraints, getTypeRef(type), _) + then specific_type_parameter_nullability(constraints, getTypeRef(type), result) + else ( + specific_type_parameter_constraints(constraints, type) and + result instanceof Annotations::NoNullability + ) } private Annotations::Nullability getElementNullability(@has_type_annotation element) { if type_nullability(element, _) then type_nullability(element, result) - else result instanceof Annotations::DefaultOblivious + else result instanceof Annotations::NoNullability } private newtype TAnnotatedType = @@ -215,12 +261,12 @@ private newtype TAnnotatedType = annotations = c.getAnnotations().getChild(i) ) or - annotations.getFlags() = getTypeParameterFlags(_, type) and - annotations.getNullability() instanceof Annotations::DefaultOblivious + annotations.getFlags() = 0 and + annotations.getNullability() = getTypeParameterNullability(_, type) or - // All types + // All types exist as AnnotatedTypes with NoNullability. annotations.getFlags() = 0 and - annotations.getNullability() instanceof Annotations::DefaultOblivious + annotations.getNullability() instanceof Annotations::NoNullability or exists(AnnotatedArrayType at | type = at.getType().(ArrayType).getElementType() and @@ -228,9 +274,10 @@ private newtype TAnnotatedType = ) } -/** A type with additional information. */ +/** A type with additional type information. */ class AnnotatedType extends TAnnotatedType { Type type; + Annotations::TypeAnnotations annotations; AnnotatedType() { this = TAnnotatedTypeNullability(type, annotations) } @@ -298,11 +345,12 @@ class AnnotatedType extends TAnnotatedType { /** Holds if this annotated type applies to type parameter constraints `constraints`. */ predicate appliesToTypeConstraint(TypeParameterConstraints constraints) { - annotations.getFlags() = getTypeParameterFlags(constraints, type) + this.getAnnotations().getFlags() = 0 and + this.getAnnotations().getNullability() = getTypeParameterNullability(constraints, type) } } -/** An array type with additional information. */ +/** An array type with additional type information. */ class AnnotatedArrayType extends AnnotatedType { override ArrayType type; @@ -332,7 +380,7 @@ class AnnotatedArrayType extends AnnotatedType { } } -/** A constructed type with additional information. */ +/** A constructed type with additional type information. */ class AnnotatedConstructedType extends AnnotatedType { override ConstructedType type; diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index e8b3d5aca883..a26548ca2427 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -527,10 +527,10 @@ specific_type_parameter_constraints( int id: @type_parameter_constraints ref, int base_id: @type_or_ref ref); -specific_type_parameter_annotation( +specific_type_parameter_nullability( int id: @type_parameter_constraints ref, int base_id: @type_or_ref ref, - int annotation: int ref); + int nullability: @nullability ref); /** MODIFIERS */ diff --git a/csharp/ql/test/library-tests/csharp8/NullCoalescingAssignment.expected b/csharp/ql/test/library-tests/csharp8/NullCoalescingAssignment.expected index 04ae7641c05d..d388d2fdb7c2 100644 --- a/csharp/ql/test/library-tests/csharp8/NullCoalescingAssignment.expected +++ b/csharp/ql/test/library-tests/csharp8/NullCoalescingAssignment.expected @@ -1,5 +1,5 @@ nullcoalescing | NullCoalescingAssignment.cs:8:9:8:18 | ... ?? ... | -| NullableRefTypes.cs:88:17:88:25 | ... ?? ... | +| NullableRefTypes.cs:94:17:94:25 | ... ?? ... | assignments | NullCoalescingAssignment.cs:8:9:8:18 | ... ??= ... | NullCoalescingAssignment.cs:8:9:8:18 | ... = ... | diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.cs b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.cs index 21847241a06b..0d1a12ccfee9 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.cs +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.cs @@ -55,6 +55,12 @@ class Generic where T1: class? where T2: MyClass? where T3: clas { } + class Generic2 + where T1: MyClass + where T2: Generic, MyClass> + { + } + // Nullable type arguments Generic items2; diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected index b310a0f52d57..4ea99349aa83 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected @@ -1,150 +1,150 @@ suppressNullableWarnings -| NullableRefTypes.cs:79:20:79:21 | ...! | NullableRefTypes.cs:79:20:79:20 | access to local variable x | -| NullableRefTypes.cs:80:13:80:14 | ...! | NullableRefTypes.cs:80:13:80:13 | access to local variable x | -| NullableRefTypes.cs:80:13:80:15 | ...! | NullableRefTypes.cs:80:13:80:14 | ...! | -| NullableRefTypes.cs:82:13:82:14 | ...! | NullableRefTypes.cs:82:13:82:13 | access to local variable x | -| NullableRefTypes.cs:107:36:107:44 | ...! | NullableRefTypes.cs:107:36:107:43 | access to field Property | +| NullableRefTypes.cs:85:20:85:21 | ...! | NullableRefTypes.cs:85:20:85:20 | access to local variable x | +| NullableRefTypes.cs:86:13:86:14 | ...! | NullableRefTypes.cs:86:13:86:13 | access to local variable x | +| NullableRefTypes.cs:86:13:86:15 | ...! | NullableRefTypes.cs:86:13:86:14 | ...! | +| NullableRefTypes.cs:88:13:88:14 | ...! | NullableRefTypes.cs:88:13:88:13 | access to local variable x | +| NullableRefTypes.cs:113:36:113:44 | ...! | NullableRefTypes.cs:113:36:113:43 | access to field Property | nullableDataFlow -| NullableRefTypes.cs:78:17:78:28 | SSA def(x) | NullableRefTypes.cs:79:20:79:20 | access to local variable x | -| NullableRefTypes.cs:78:21:78:28 | "source" | NullableRefTypes.cs:78:17:78:28 | SSA def(x) | -| NullableRefTypes.cs:79:20:79:20 | access to local variable x | NullableRefTypes.cs:79:20:79:21 | ...! | -| NullableRefTypes.cs:79:20:79:20 | access to local variable x | NullableRefTypes.cs:80:13:80:13 | access to local variable x | -| NullableRefTypes.cs:80:13:80:13 | access to local variable x | NullableRefTypes.cs:80:13:80:14 | ...! | -| NullableRefTypes.cs:80:13:80:14 | ...! | NullableRefTypes.cs:80:13:80:15 | ...! | -| NullableRefTypes.cs:81:9:81:16 | SSA def(x) | NullableRefTypes.cs:82:13:82:13 | access to local variable x | -| NullableRefTypes.cs:81:13:81:16 | null | NullableRefTypes.cs:81:9:81:16 | SSA def(x) | -| NullableRefTypes.cs:82:13:82:13 | access to local variable x | NullableRefTypes.cs:82:13:82:14 | ...! | +| NullableRefTypes.cs:84:17:84:28 | SSA def(x) | NullableRefTypes.cs:85:20:85:20 | access to local variable x | +| NullableRefTypes.cs:84:21:84:28 | "source" | NullableRefTypes.cs:84:17:84:28 | SSA def(x) | +| NullableRefTypes.cs:85:20:85:20 | access to local variable x | NullableRefTypes.cs:85:20:85:21 | ...! | +| NullableRefTypes.cs:85:20:85:20 | access to local variable x | NullableRefTypes.cs:86:13:86:13 | access to local variable x | +| NullableRefTypes.cs:86:13:86:13 | access to local variable x | NullableRefTypes.cs:86:13:86:14 | ...! | +| NullableRefTypes.cs:86:13:86:14 | ...! | NullableRefTypes.cs:86:13:86:15 | ...! | +| NullableRefTypes.cs:87:9:87:16 | SSA def(x) | NullableRefTypes.cs:88:13:88:13 | access to local variable x | +| NullableRefTypes.cs:87:13:87:16 | null | NullableRefTypes.cs:87:9:87:16 | SSA def(x) | +| NullableRefTypes.cs:88:13:88:13 | access to local variable x | NullableRefTypes.cs:88:13:88:14 | ...! | nullableControlFlow -| NullableRefTypes.cs:76:10:76:40 | enter TestSuppressNullableWarningExpr | NullableRefTypes.cs:77:5:83:5 | {...} | successor | -| NullableRefTypes.cs:77:5:83:5 | {...} | NullableRefTypes.cs:78:9:78:29 | ... ...; | successor | -| NullableRefTypes.cs:78:9:78:29 | ... ...; | NullableRefTypes.cs:78:21:78:28 | "source" | successor | -| NullableRefTypes.cs:78:17:78:28 | String x = ... | NullableRefTypes.cs:79:9:79:22 | ... ...; | successor | -| NullableRefTypes.cs:78:21:78:28 | "source" | NullableRefTypes.cs:78:17:78:28 | String x = ... | successor | -| NullableRefTypes.cs:79:9:79:22 | ... ...; | NullableRefTypes.cs:79:20:79:20 | access to local variable x | successor | -| NullableRefTypes.cs:79:16:79:21 | String y = ... | NullableRefTypes.cs:80:9:80:16 | ...; | successor | -| NullableRefTypes.cs:79:20:79:20 | access to local variable x | NullableRefTypes.cs:79:20:79:21 | ...! | successor | -| NullableRefTypes.cs:79:20:79:21 | ...! | NullableRefTypes.cs:79:16:79:21 | String y = ... | successor | -| NullableRefTypes.cs:80:9:80:15 | ... = ... | NullableRefTypes.cs:81:9:81:17 | ...; | successor | -| NullableRefTypes.cs:80:9:80:16 | ...; | NullableRefTypes.cs:80:13:80:13 | access to local variable x | successor | -| NullableRefTypes.cs:80:13:80:13 | access to local variable x | NullableRefTypes.cs:80:13:80:14 | ...! | successor | -| NullableRefTypes.cs:80:13:80:14 | ...! | NullableRefTypes.cs:80:13:80:15 | ...! | successor | -| NullableRefTypes.cs:80:13:80:15 | ...! | NullableRefTypes.cs:80:9:80:15 | ... = ... | successor | -| NullableRefTypes.cs:81:9:81:16 | ... = ... | NullableRefTypes.cs:82:9:82:15 | ...; | successor | -| NullableRefTypes.cs:81:9:81:17 | ...; | NullableRefTypes.cs:81:13:81:16 | null | successor | -| NullableRefTypes.cs:81:13:81:16 | null | NullableRefTypes.cs:81:9:81:16 | ... = ... | successor | -| NullableRefTypes.cs:82:9:82:14 | ... = ... | NullableRefTypes.cs:76:10:76:40 | exit TestSuppressNullableWarningExpr | successor | -| NullableRefTypes.cs:82:9:82:15 | ...; | NullableRefTypes.cs:82:13:82:13 | access to local variable x | successor | -| NullableRefTypes.cs:82:13:82:13 | access to local variable x | NullableRefTypes.cs:82:13:82:14 | ...! | successor | -| NullableRefTypes.cs:82:13:82:14 | ...! | NullableRefTypes.cs:82:9:82:14 | ... = ... | successor | +| NullableRefTypes.cs:82:10:82:40 | enter TestSuppressNullableWarningExpr | NullableRefTypes.cs:83:5:89:5 | {...} | successor | +| NullableRefTypes.cs:83:5:89:5 | {...} | NullableRefTypes.cs:84:9:84:29 | ... ...; | successor | +| NullableRefTypes.cs:84:9:84:29 | ... ...; | NullableRefTypes.cs:84:21:84:28 | "source" | successor | +| NullableRefTypes.cs:84:17:84:28 | String x = ... | NullableRefTypes.cs:85:9:85:22 | ... ...; | successor | +| NullableRefTypes.cs:84:21:84:28 | "source" | NullableRefTypes.cs:84:17:84:28 | String x = ... | successor | +| NullableRefTypes.cs:85:9:85:22 | ... ...; | NullableRefTypes.cs:85:20:85:20 | access to local variable x | successor | +| NullableRefTypes.cs:85:16:85:21 | String y = ... | NullableRefTypes.cs:86:9:86:16 | ...; | successor | +| NullableRefTypes.cs:85:20:85:20 | access to local variable x | NullableRefTypes.cs:85:20:85:21 | ...! | successor | +| NullableRefTypes.cs:85:20:85:21 | ...! | NullableRefTypes.cs:85:16:85:21 | String y = ... | successor | +| NullableRefTypes.cs:86:9:86:15 | ... = ... | NullableRefTypes.cs:87:9:87:17 | ...; | successor | +| NullableRefTypes.cs:86:9:86:16 | ...; | NullableRefTypes.cs:86:13:86:13 | access to local variable x | successor | +| NullableRefTypes.cs:86:13:86:13 | access to local variable x | NullableRefTypes.cs:86:13:86:14 | ...! | successor | +| NullableRefTypes.cs:86:13:86:14 | ...! | NullableRefTypes.cs:86:13:86:15 | ...! | successor | +| NullableRefTypes.cs:86:13:86:15 | ...! | NullableRefTypes.cs:86:9:86:15 | ... = ... | successor | +| NullableRefTypes.cs:87:9:87:16 | ... = ... | NullableRefTypes.cs:88:9:88:15 | ...; | successor | +| NullableRefTypes.cs:87:9:87:17 | ...; | NullableRefTypes.cs:87:13:87:16 | null | successor | +| NullableRefTypes.cs:87:13:87:16 | null | NullableRefTypes.cs:87:9:87:16 | ... = ... | successor | +| NullableRefTypes.cs:88:9:88:14 | ... = ... | NullableRefTypes.cs:82:10:82:40 | exit TestSuppressNullableWarningExpr | successor | +| NullableRefTypes.cs:88:9:88:15 | ...; | NullableRefTypes.cs:88:13:88:13 | access to local variable x | successor | +| NullableRefTypes.cs:88:13:88:13 | access to local variable x | NullableRefTypes.cs:88:13:88:14 | ...! | successor | +| NullableRefTypes.cs:88:13:88:14 | ...! | NullableRefTypes.cs:88:9:88:14 | ... = ... | successor | nonNullExpressions -| NullableRefTypes.cs:78:21:78:28 | "source" | -| NullableRefTypes.cs:79:20:79:20 | access to local variable x | -| NullableRefTypes.cs:79:20:79:21 | ...! | -| NullableRefTypes.cs:80:9:80:15 | ... = ... | -| NullableRefTypes.cs:80:13:80:13 | access to local variable x | -| NullableRefTypes.cs:80:13:80:14 | ...! | -| NullableRefTypes.cs:80:13:80:15 | ...! | -| NullableRefTypes.cs:82:9:82:14 | ... = ... | -| NullableRefTypes.cs:82:13:82:14 | ...! | +| NullableRefTypes.cs:84:21:84:28 | "source" | +| NullableRefTypes.cs:85:20:85:20 | access to local variable x | +| NullableRefTypes.cs:85:20:85:21 | ...! | +| NullableRefTypes.cs:86:9:86:15 | ... = ... | +| NullableRefTypes.cs:86:13:86:13 | access to local variable x | +| NullableRefTypes.cs:86:13:86:14 | ...! | +| NullableRefTypes.cs:86:13:86:15 | ...! | +| NullableRefTypes.cs:88:9:88:14 | ... = ... | +| NullableRefTypes.cs:88:13:88:14 | ...! | assignableTypes -| NullableRefTypes.cs:9:14:9:14 | A | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:10:13:10:13 | B | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:13:14:13:14 | C | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:14:13:14:13 | D | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:17:14:17:17 | Item | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:18:13:18:16 | Item | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:19:13:19:16 | Item | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:19:27:19:27 | i | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:19:27:19:27 | i | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:22:16:22:17 | G1 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | -| NullableRefTypes.cs:23:17:23:18 | G2 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | -| NullableRefTypes.cs:24:16:24:17 | G3 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | -| NullableRefTypes.cs:25:18:25:18 | H | NullableRefTypes.cs:6:7:6:13 | MyClass?[][]! | -| NullableRefTypes.cs:26:38:26:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass![]?[]! | -| NullableRefTypes.cs:27:38:27:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass?[][]! | -| NullableRefTypes.cs:32:20:32:20 | a | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:32:31:32:31 | b | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:37:17:37:17 | a | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:38:18:38:18 | b | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:39:21:39:21 | c | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | -| NullableRefTypes.cs:40:22:40:22 | d | NullableRefTypes.cs:6:7:6:13 | ref MyClass? | -| NullableRefTypes.cs:47:35:47:35 | x | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:47:35:47:35 | x | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:47:35:47:35 | x | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:48:16:48:16 | P | NullableRefTypes.cs:47:23:47:25 | Del? | -| NullableRefTypes.cs:48:16:48:16 | value | NullableRefTypes.cs:47:23:47:25 | Del? | -| NullableRefTypes.cs:48:16:48:16 | value | NullableRefTypes.cs:47:23:47:25 | Del? | -| NullableRefTypes.cs:51:19:51:19 | t | NullableRefTypes.cs:6:7:6:13 | MyClass | -| NullableRefTypes.cs:51:19:51:19 | t | NullableRefTypes.cs:51:14:51:14 | T! | -| NullableRefTypes.cs:59:54:59:59 | items2 | NullableRefTypes.cs:54:11:54:33 | Generic! | -| NullableRefTypes.cs:61:25:61:25 | x | NullableRefTypes.cs:6:7:6:13 | MyClass | -| NullableRefTypes.cs:61:25:61:25 | x | NullableRefTypes.cs:61:20:61:20 | T! | -| NullableRefTypes.cs:67:18:67:18 | x | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:97:42:97:42 | r | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | -| NullableRefTypes.cs:98:42:98:42 | r | NullableRefTypes.cs:6:7:6:13 | ref MyClass? | -| NullableRefTypes.cs:99:51:99:51 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass? | -| NullableRefTypes.cs:100:50:100:50 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass! | -| NullableRefTypes.cs:101:49:101:49 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass! | -| NullableRefTypes.cs:102:50:102:50 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass? | -| NullableRefTypes.cs:104:34:104:35 | p1 | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | -| NullableRefTypes.cs:104:51:104:52 | p2 | NullableRefTypes.cs:6:7:6:13 | out MyClass? | -| NullableRefTypes.cs:106:14:106:21 | Property | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:107:17:107:27 | RefProperty | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | -| NullableRefTypes.cs:112:15:112:15 | a | NullableRefTypes.cs:159:8:159:15 | MyStruct? | -| NullableRefTypes.cs:113:17:113:17 | b | NullableRefTypes.cs:159:8:159:15 | MyStruct![]? | -| NullableRefTypes.cs:114:17:114:17 | c | NullableRefTypes.cs:159:8:159:15 | MyStruct?[]! | -| NullableRefTypes.cs:115:18:115:18 | d | NullableRefTypes.cs:159:8:159:15 | MyStruct?[]? | -| NullableRefTypes.cs:117:14:117:14 | e | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:118:16:118:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | -| NullableRefTypes.cs:119:16:119:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass![]? | -| NullableRefTypes.cs:120:17:120:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | -| NullableRefTypes.cs:122:23:122:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass![,,]?[,][]! | -| NullableRefTypes.cs:123:22:123:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass![,,][,][]! | -| NullableRefTypes.cs:124:27:124:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass![,,,][][,][,,]! | -| NullableRefTypes.cs:125:29:125:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]?[,,]! | -| NullableRefTypes.cs:132:15:132:15 | a | NullableRefTypes.cs:159:8:159:15 | MyStruct? | -| NullableRefTypes.cs:133:17:133:17 | b | NullableRefTypes.cs:159:8:159:15 | MyStruct![]? | -| NullableRefTypes.cs:134:17:134:17 | c | NullableRefTypes.cs:159:8:159:15 | MyStruct?[] | -| NullableRefTypes.cs:135:18:135:18 | d | NullableRefTypes.cs:159:8:159:15 | MyStruct?[]? | -| NullableRefTypes.cs:137:14:137:14 | e | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:138:16:138:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass?[] | -| NullableRefTypes.cs:139:16:139:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass[]? | -| NullableRefTypes.cs:140:17:140:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | -| NullableRefTypes.cs:142:23:142:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass[,,]?[,][] | -| NullableRefTypes.cs:143:22:143:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][,][] | -| NullableRefTypes.cs:144:27:144:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass[,,,][][,][,,] | -| NullableRefTypes.cs:145:29:145:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]?[,,] | -| NullableRefTypes.cs:150:13:150:14 | f1 | NullableRefTypes.cs:6:7:6:13 | MyClass | -| NullableRefTypes.cs:151:13:151:13 | P | NullableRefTypes.cs:6:7:6:13 | MyClass | -| NullableRefTypes.cs:152:24:152:24 | p | NullableRefTypes.cs:6:7:6:13 | MyClass | -| NullableRefTypes.cs:154:17:154:17 | a | NullableRefTypes.cs:6:7:6:13 | MyClass | +| NullableRefTypes.cs:9:14:9:14 | A | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:10:13:10:13 | B | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:13:14:13:14 | C | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:14:13:14:13 | D | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:17:14:17:17 | Item | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:18:13:18:16 | Item | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:19:13:19:16 | Item | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:19:27:19:27 | i | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:19:27:19:27 | i | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:22:16:22:17 | G1 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | ! | +| NullableRefTypes.cs:23:17:23:18 | G2 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | ? | +| NullableRefTypes.cs:24:16:24:17 | G3 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | ! | +| NullableRefTypes.cs:25:18:25:18 | H | NullableRefTypes.cs:6:7:6:13 | MyClass?[][]! | <!>! | +| NullableRefTypes.cs:26:38:26:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass![]?[]! | <?>! | +| NullableRefTypes.cs:27:38:27:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass?[][]! | <!>! | +| NullableRefTypes.cs:32:20:32:20 | a | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:32:31:32:31 | b | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:37:17:37:17 | a | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:38:18:38:18 | b | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:39:21:39:21 | c | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | ! | +| NullableRefTypes.cs:40:22:40:22 | d | NullableRefTypes.cs:6:7:6:13 | ref MyClass? | ? | +| NullableRefTypes.cs:47:35:47:35 | x | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:47:35:47:35 | x | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:47:35:47:35 | x | NullableRefTypes.cs:6:7:6:13 | MyClass! | ! | +| NullableRefTypes.cs:48:16:48:16 | P | NullableRefTypes.cs:47:23:47:25 | Del? | ? | +| NullableRefTypes.cs:48:16:48:16 | value | NullableRefTypes.cs:47:23:47:25 | Del? | ? | +| NullableRefTypes.cs:48:16:48:16 | value | NullableRefTypes.cs:47:23:47:25 | Del? | ? | +| NullableRefTypes.cs:51:19:51:19 | t | NullableRefTypes.cs:6:7:6:13 | MyClass | _ | +| NullableRefTypes.cs:51:19:51:19 | t | NullableRefTypes.cs:51:14:51:14 | T! | ! | +| NullableRefTypes.cs:65:54:65:59 | items2 | NullableRefTypes.cs:54:11:54:33 | Generic! | ! | +| NullableRefTypes.cs:67:25:67:25 | x | NullableRefTypes.cs:6:7:6:13 | MyClass | _ | +| NullableRefTypes.cs:67:25:67:25 | x | NullableRefTypes.cs:67:20:67:20 | T! | ! | +| NullableRefTypes.cs:73:18:73:18 | x | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:103:42:103:42 | r | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | ! | +| NullableRefTypes.cs:104:42:104:42 | r | NullableRefTypes.cs:6:7:6:13 | ref MyClass? | ? | +| NullableRefTypes.cs:105:51:105:51 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass? | ? | +| NullableRefTypes.cs:106:50:106:50 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass! | ! | +| NullableRefTypes.cs:107:49:107:49 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass! | ! | +| NullableRefTypes.cs:108:50:108:50 | r | NullableRefTypes.cs:6:7:6:13 | readonly MyClass? | ? | +| NullableRefTypes.cs:110:34:110:35 | p1 | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | ! | +| NullableRefTypes.cs:110:51:110:52 | p2 | NullableRefTypes.cs:6:7:6:13 | out MyClass? | ? | +| NullableRefTypes.cs:112:14:112:21 | Property | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:113:17:113:27 | RefProperty | NullableRefTypes.cs:6:7:6:13 | ref MyClass! | ! | +| NullableRefTypes.cs:118:15:118:15 | a | NullableRefTypes.cs:165:8:165:15 | MyStruct? | <_>? | +| NullableRefTypes.cs:119:17:119:17 | b | NullableRefTypes.cs:165:8:165:15 | MyStruct![]? | ? | +| NullableRefTypes.cs:120:17:120:17 | c | NullableRefTypes.cs:165:8:165:15 | MyStruct?[]! | <<_>?>! | +| NullableRefTypes.cs:121:18:121:18 | d | NullableRefTypes.cs:165:8:165:15 | MyStruct?[]? | <<_>?>? | +| NullableRefTypes.cs:123:14:123:14 | e | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:124:16:124:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | ! | +| NullableRefTypes.cs:125:16:125:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass![]? | ? | +| NullableRefTypes.cs:126:17:126:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | ? | +| NullableRefTypes.cs:128:23:128:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass![,,]?[,][]! | <<?>!>! | +| NullableRefTypes.cs:129:22:129:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass![,,][,][]! | ! | +| NullableRefTypes.cs:130:27:130:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass![,,,][][,][,,]! | ! | +| NullableRefTypes.cs:131:29:131:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]?[,,]! | <<<!>!>?>! | +| NullableRefTypes.cs:138:15:138:15 | a | NullableRefTypes.cs:165:8:165:15 | MyStruct? | <_>? | +| NullableRefTypes.cs:139:17:139:17 | b | NullableRefTypes.cs:165:8:165:15 | MyStruct[]? | <_>? | +| NullableRefTypes.cs:140:17:140:17 | c | NullableRefTypes.cs:165:8:165:15 | MyStruct?[] | <<_>?>_ | +| NullableRefTypes.cs:141:18:141:18 | d | NullableRefTypes.cs:165:8:165:15 | MyStruct?[]? | <<_>?>? | +| NullableRefTypes.cs:143:14:143:14 | e | NullableRefTypes.cs:6:7:6:13 | MyClass? | ? | +| NullableRefTypes.cs:144:16:144:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass?[] | _ | +| NullableRefTypes.cs:145:16:145:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass[]? | <_>? | +| NullableRefTypes.cs:146:17:146:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | ? | +| NullableRefTypes.cs:148:23:148:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass[,,]?[,][] | <<<_>?>_>_ | +| NullableRefTypes.cs:149:22:149:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][,][] | _ | +| NullableRefTypes.cs:150:27:150:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass[,,,][][,][,,] | _ | +| NullableRefTypes.cs:151:29:151:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]?[,,] | <<<_>_>?>_ | +| NullableRefTypes.cs:156:13:156:14 | f1 | NullableRefTypes.cs:6:7:6:13 | MyClass | _ | +| NullableRefTypes.cs:157:13:157:13 | P | NullableRefTypes.cs:6:7:6:13 | MyClass | _ | +| NullableRefTypes.cs:158:24:158:24 | p | NullableRefTypes.cs:6:7:6:13 | MyClass | _ | +| NullableRefTypes.cs:160:17:160:17 | a | NullableRefTypes.cs:6:7:6:13 | MyClass | _ | arrayElements -| NullableRefTypes.cs:22:16:22:17 | G1 | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:23:17:23:18 | G2 | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:24:16:24:17 | G3 | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:25:18:25:18 | H | NullableRefTypes.cs:6:7:6:13 | MyClass[][] | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | -| NullableRefTypes.cs:26:38:26:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass[][] | NullableRefTypes.cs:6:7:6:13 | MyClass![]? | -| NullableRefTypes.cs:27:38:27:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass[][] | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | -| NullableRefTypes.cs:113:17:113:17 | b | NullableRefTypes.cs:159:8:159:15 | MyStruct[] | NullableRefTypes.cs:159:8:159:15 | MyStruct! | -| NullableRefTypes.cs:114:17:114:17 | c | NullableRefTypes.cs:159:8:159:15 | Nullable | NullableRefTypes.cs:159:8:159:15 | MyStruct? | -| NullableRefTypes.cs:115:18:115:18 | d | NullableRefTypes.cs:159:8:159:15 | Nullable | NullableRefTypes.cs:159:8:159:15 | MyStruct? | -| NullableRefTypes.cs:118:16:118:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:119:16:119:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass! | -| NullableRefTypes.cs:120:17:120:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:122:23:122:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][][,] | NullableRefTypes.cs:6:7:6:13 | MyClass![,,]?[]! | -| NullableRefTypes.cs:123:22:123:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass[][,][,,] | NullableRefTypes.cs:6:7:6:13 | MyClass![,][]! | -| NullableRefTypes.cs:124:27:124:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][,][][,,,] | NullableRefTypes.cs:6:7:6:13 | MyClass![][,][,,]! | -| NullableRefTypes.cs:125:29:125:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass[,][][,,,][,,] | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]? | -| NullableRefTypes.cs:133:17:133:17 | b | NullableRefTypes.cs:159:8:159:15 | MyStruct[] | NullableRefTypes.cs:159:8:159:15 | MyStruct! | -| NullableRefTypes.cs:134:17:134:17 | c | NullableRefTypes.cs:159:8:159:15 | Nullable | NullableRefTypes.cs:159:8:159:15 | MyStruct? | -| NullableRefTypes.cs:135:18:135:18 | d | NullableRefTypes.cs:159:8:159:15 | Nullable | NullableRefTypes.cs:159:8:159:15 | MyStruct? | -| NullableRefTypes.cs:138:16:138:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:139:16:139:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass | -| NullableRefTypes.cs:140:17:140:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | -| NullableRefTypes.cs:142:23:142:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][][,] | NullableRefTypes.cs:6:7:6:13 | MyClass[,,]?[] | -| NullableRefTypes.cs:143:22:143:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass[][,][,,] | NullableRefTypes.cs:6:7:6:13 | MyClass[,][] | -| NullableRefTypes.cs:144:27:144:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][,][][,,,] | NullableRefTypes.cs:6:7:6:13 | MyClass[][,][,,] | -| NullableRefTypes.cs:145:29:145:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass[,][][,,,][,,] | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]? | +| NullableRefTypes.cs:22:16:22:17 | G1 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:23:17:23:18 | G2 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:24:16:24:17 | G3 | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:25:18:25:18 | H | NullableRefTypes.cs:6:7:6:13 | MyClass?[][]! | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | +| NullableRefTypes.cs:26:38:26:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass![]?[]! | NullableRefTypes.cs:6:7:6:13 | MyClass![]? | +| NullableRefTypes.cs:27:38:27:38 | x | NullableRefTypes.cs:6:7:6:13 | MyClass?[][]! | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | +| NullableRefTypes.cs:119:17:119:17 | b | NullableRefTypes.cs:165:8:165:15 | MyStruct![]? | NullableRefTypes.cs:165:8:165:15 | MyStruct! | +| NullableRefTypes.cs:120:17:120:17 | c | NullableRefTypes.cs:165:8:165:15 | MyStruct?[]! | NullableRefTypes.cs:165:8:165:15 | MyStruct? | +| NullableRefTypes.cs:121:18:121:18 | d | NullableRefTypes.cs:165:8:165:15 | MyStruct?[]? | NullableRefTypes.cs:165:8:165:15 | MyStruct? | +| NullableRefTypes.cs:124:16:124:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass?[]! | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:125:16:125:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass![]? | NullableRefTypes.cs:6:7:6:13 | MyClass! | +| NullableRefTypes.cs:126:17:126:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:128:23:128:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass![,,]?[,][]! | NullableRefTypes.cs:6:7:6:13 | MyClass![,,]?[]! | +| NullableRefTypes.cs:129:22:129:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass![,,][,][]! | NullableRefTypes.cs:6:7:6:13 | MyClass![,][]! | +| NullableRefTypes.cs:130:27:130:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass![,,,][][,][,,]! | NullableRefTypes.cs:6:7:6:13 | MyClass![][,][,,]! | +| NullableRefTypes.cs:131:29:131:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]?[,,]! | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]? | +| NullableRefTypes.cs:139:17:139:17 | b | NullableRefTypes.cs:165:8:165:15 | MyStruct[]? | NullableRefTypes.cs:165:8:165:15 | MyStruct | +| NullableRefTypes.cs:140:17:140:17 | c | NullableRefTypes.cs:165:8:165:15 | MyStruct?[] | NullableRefTypes.cs:165:8:165:15 | MyStruct? | +| NullableRefTypes.cs:141:18:141:18 | d | NullableRefTypes.cs:165:8:165:15 | MyStruct?[]? | NullableRefTypes.cs:165:8:165:15 | MyStruct? | +| NullableRefTypes.cs:144:16:144:16 | f | NullableRefTypes.cs:6:7:6:13 | MyClass?[] | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:145:16:145:16 | g | NullableRefTypes.cs:6:7:6:13 | MyClass[]? | NullableRefTypes.cs:6:7:6:13 | MyClass | +| NullableRefTypes.cs:146:17:146:17 | h | NullableRefTypes.cs:6:7:6:13 | MyClass?[]? | NullableRefTypes.cs:6:7:6:13 | MyClass? | +| NullableRefTypes.cs:148:23:148:23 | i | NullableRefTypes.cs:6:7:6:13 | MyClass[,,]?[,][] | NullableRefTypes.cs:6:7:6:13 | MyClass[,,]?[] | +| NullableRefTypes.cs:149:22:149:22 | j | NullableRefTypes.cs:6:7:6:13 | MyClass[,,][,][] | NullableRefTypes.cs:6:7:6:13 | MyClass[,][] | +| NullableRefTypes.cs:150:27:150:27 | k | NullableRefTypes.cs:6:7:6:13 | MyClass[,,,][][,][,,] | NullableRefTypes.cs:6:7:6:13 | MyClass[][,][,,] | +| NullableRefTypes.cs:151:29:151:29 | l | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]?[,,] | NullableRefTypes.cs:6:7:6:13 | MyClass?[,,,][][,]? | returnTypes | NullableRefTypes.cs:6:7:6:13 | MyClass | Void | | NullableRefTypes.cs:13:19:13:22 | get_C | MyClass? | @@ -168,40 +168,64 @@ returnTypes | NullableRefTypes.cs:47:23:47:25 | Invoke | MyClass? | | NullableRefTypes.cs:48:16:48:16 | add_P | Void | | NullableRefTypes.cs:48:16:48:16 | remove_P | Void | +| NullableRefTypes.cs:51:12:51:15 | Q | object | | NullableRefTypes.cs:51:12:51:15 | Q | object! | | NullableRefTypes.cs:51:12:51:15 | Q | object! | | NullableRefTypes.cs:54:11:54:33 | Generic | Void | -| NullableRefTypes.cs:61:10:61:21 | GenericFn | Void! | -| NullableRefTypes.cs:61:10:61:21 | GenericFn | Void! | -| NullableRefTypes.cs:65:14:65:18 | CallF | MyStruct! | -| NullableRefTypes.cs:74:7:74:22 | NullableRefTypes | Void | -| NullableRefTypes.cs:76:10:76:40 | TestSuppressNullableWarningExpr | Void! | -| NullableRefTypes.cs:85:10:85:34 | FunctionInNullableContext | Void! | -| NullableRefTypes.cs:94:7:94:14 | RefTypes | Void | -| NullableRefTypes.cs:97:18:97:28 | ReturnsRef1 | ref MyClass? | -| NullableRefTypes.cs:98:17:98:27 | ReturnsRef2 | ref MyClass! | -| NullableRefTypes.cs:99:27:99:37 | ReturnsRef3 | readonly MyClass? | -| NullableRefTypes.cs:100:27:100:37 | ReturnsRef4 | readonly MyClass? | -| NullableRefTypes.cs:101:26:101:36 | ReturnsRef5 | readonly MyClass! | -| NullableRefTypes.cs:102:26:102:36 | ReturnsRef6 | readonly MyClass! | -| NullableRefTypes.cs:104:10:104:20 | Parameters1 | Void! | -| NullableRefTypes.cs:107:32:107:44 | get_RefProperty | MyClass! | -| NullableRefTypes.cs:110:7:110:23 | ToStringWithTypes | Void | -| NullableRefTypes.cs:130:7:130:24 | ToStringWithTypes2 | Void | -| NullableRefTypes.cs:148:7:148:25 | DisabledNullability | Void | -| NullableRefTypes.cs:151:18:151:30 | get_P | MyClass | -| NullableRefTypes.cs:152:13:152:14 | Fn | MyClass | -| NullableRefTypes.cs:159:8:159:15 | MyStruct | Void | -typeArguments +| NullableRefTypes.cs:58:11:58:26 | Generic2 | Void | +| NullableRefTypes.cs:67:10:67:21 | GenericFn | Void | +| NullableRefTypes.cs:67:10:67:21 | GenericFn | Void! | +| NullableRefTypes.cs:67:10:67:21 | GenericFn | Void! | +| NullableRefTypes.cs:71:14:71:18 | CallF | MyStruct! | +| NullableRefTypes.cs:80:7:80:22 | NullableRefTypes | Void | +| NullableRefTypes.cs:82:10:82:40 | TestSuppressNullableWarningExpr | Void! | +| NullableRefTypes.cs:91:10:91:34 | FunctionInNullableContext | Void! | +| NullableRefTypes.cs:100:7:100:14 | RefTypes | Void | +| NullableRefTypes.cs:103:18:103:28 | ReturnsRef1 | ref MyClass? | +| NullableRefTypes.cs:104:17:104:27 | ReturnsRef2 | ref MyClass! | +| NullableRefTypes.cs:105:27:105:37 | ReturnsRef3 | readonly MyClass? | +| NullableRefTypes.cs:106:27:106:37 | ReturnsRef4 | readonly MyClass? | +| NullableRefTypes.cs:107:26:107:36 | ReturnsRef5 | readonly MyClass! | +| NullableRefTypes.cs:108:26:108:36 | ReturnsRef6 | readonly MyClass! | +| NullableRefTypes.cs:110:10:110:20 | Parameters1 | Void! | +| NullableRefTypes.cs:113:32:113:44 | get_RefProperty | MyClass! | +| NullableRefTypes.cs:116:7:116:23 | ToStringWithTypes | Void | +| NullableRefTypes.cs:136:7:136:24 | ToStringWithTypes2 | Void | +| NullableRefTypes.cs:154:7:154:25 | DisabledNullability | Void | +| NullableRefTypes.cs:157:18:157:30 | get_P | MyClass | +| NullableRefTypes.cs:158:13:158:14 | Fn | MyClass | +| NullableRefTypes.cs:165:8:165:15 | MyStruct | Void | +methodTypeArguments | NullableRefTypes.cs:51:12:51:15 | Q | 0 | MyClass | -| NullableRefTypes.cs:54:11:54:33 | Generic | 0 | MyClass? | -| NullableRefTypes.cs:54:11:54:33 | Generic | 1 | MyClass! | -| NullableRefTypes.cs:54:11:54:33 | Generic | 2 | IDisposable! | -| NullableRefTypes.cs:54:11:54:33 | Generic | 3 | MyClass! | -| NullableRefTypes.cs:61:10:61:21 | GenericFn | 0 | MyClass | +| NullableRefTypes.cs:51:12:51:15 | Q | 0 | MyClass! | +| NullableRefTypes.cs:67:10:67:21 | GenericFn | 0 | MyClass | +| NullableRefTypes.cs:67:10:67:21 | GenericFn | 0 | MyClass! | +constructedTypes +| AsyncStreams.cs:34:15:34:37 | IAsyncEnumerable | 0 | int | _ | +| AsyncStreams.cs:39:15:39:37 | IAsyncEnumerator | 0 | T | _ | +| AsyncStreams.cs:39:15:39:37 | IAsyncEnumerator | 0 | int | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic | 0 | MyClass | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic | 1 | MyClass | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic | 2 | IDisposable | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic | 3 | MyClass | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic! | 0 | MyClass? | ! | +| NullableRefTypes.cs:54:11:54:33 | Generic! | 1 | MyClass! | ! | +| NullableRefTypes.cs:54:11:54:33 | Generic! | 2 | IDisposable! | ! | +| NullableRefTypes.cs:54:11:54:33 | Generic! | 3 | MyClass! | ! | +| NullableRefTypes.cs:54:11:54:33 | Generic, MyClass> | 0 | string | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic, MyClass> | 1 | T1 | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic, MyClass> | 2 | IEnumerable | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic, MyClass> | 3 | MyClass | _ | +| NullableRefTypes.cs:54:11:54:33 | Generic!, MyClass!>! | 0 | string? | !,!>! | +| NullableRefTypes.cs:54:11:54:33 | Generic!, MyClass!>! | 1 | T1? | !,!>! | +| NullableRefTypes.cs:54:11:54:33 | Generic!, MyClass!>! | 2 | IEnumerable! | !,!>! | +| NullableRefTypes.cs:54:11:54:33 | Generic!, MyClass!>! | 3 | MyClass! | !,!>! | nullableTypeParameters | NullableRefTypes.cs:54:19:54:20 | T1 | annotatedTypeConstraints | NullableRefTypes.cs:51:14:51:14 | T | NullableRefTypes.cs:6:7:6:13 | MyClass? | | NullableRefTypes.cs:54:23:54:24 | T2 | NullableRefTypes.cs:6:7:6:13 | MyClass? | | NullableRefTypes.cs:54:31:54:32 | T4 | NullableRefTypes.cs:6:7:6:13 | MyClass! | +| NullableRefTypes.cs:58:20:58:21 | T1 | NullableRefTypes.cs:6:7:6:13 | MyClass! | +| NullableRefTypes.cs:58:24:58:25 | T2 | NullableRefTypes.cs:54:11:54:33 | Generic!, MyClass!>! | +typeNotAnnotated diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql index c0febaa2afa3..cf5d320ca915 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql @@ -21,11 +21,12 @@ query predicate nonNullExpressions(NonNullExpr e) { e.getEnclosingCallable().getName() = "TestSuppressNullableWarningExpr" } -query predicate assignableTypes(Assignable a, AnnotatedType t) { +query predicate assignableTypes(Assignable a, AnnotatedType t, string n) { a.getFile().getBaseName() = "NullableRefTypes.cs" and t.getLocation() instanceof SourceLocation and a.getLocation() instanceof SourceLocation and - t = a.getAnnotatedType() + t = a.getAnnotatedType() and + n = t.getAnnotations().getNullability().toString() } query predicate arrayElements(Variable v, AnnotatedArrayType array, AnnotatedType elementType) { @@ -39,13 +40,17 @@ query predicate returnTypes(Callable c, string t) { t = c.getAnnotatedReturnType().toString() } -query predicate typeArguments(AnnotatedConstructedType generic, int arg, string argument) { - ( - generic.getType() = any(Variable v | v.fromSource()).getType() - //or - // generic.getType() = any(MethodCall mc).getTarget() - ) and - argument = generic.getTypeArgument(arg).toString() +query predicate methodTypeArguments(ConstructedGeneric generic, int arg, string argument) { + generic = any(MethodCall mc).getTarget() and + argument = generic.getAnnotatedTypeArgument(arg).toString() +} + +query predicate constructedTypes( + AnnotatedConstructedType at, int i, string arg, string nullability +) { + arg = at.getTypeArgument(i).toString() and + at.getLocation() instanceof SourceLocation and + nullability = at.getAnnotations().getNullability().toString() } query predicate nullableTypeParameters(TypeParameter p) { From 163b931d49040d9c461cdd745d99524323d69349 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 1 Oct 2019 15:16:39 +0100 Subject: [PATCH 0344/2538] C#: Update db stats --- .../ql/src/semmlecode.csharp.dbscheme.stats | 16925 ++++++++-------- 1 file changed, 8654 insertions(+), 8271 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 5e5b32342cc9..426949c20613 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -1,15 +1,15 @@ @compilation -641 +1057 @diagnostic -7036 +12070 @extractor_message -264 +57 @externalDefect @@ -21,47 +21,47 @@ @externalDataElement -8 +9 @duplication -13480 +20134 @similarity -124007 +149289 @location_default -7339237 +11787435 @assembly -1870 +2863 @file -15550 +24954 @folder -4611 +7016 @namespace -5457 +6505 @namespace_declaration -14700 +22696 @using_namespace_directive -85929 +106992 @using_static_directive -253 +321 @bool_type @@ -117,23 +117,23 @@ @enum_type -8356 +8073 @struct_type -37594 +31632 @class_type -142002 +126692 @interface_type -176859 +137173 @delegate_type -49262 +40645 @null_type @@ -141,19 +141,19 @@ @type_parameter -80545 +58090 @pointer_type -272 +383 @nullable_type -2027 +1382 @array_type -7951 +7961 @void_type @@ -168,36 +168,48 @@ 1 -@arglist_type -1 - - @tuple_type -2476 +1768 @uint_ptr_type 0 +@arglist_type +0 + + @unknown_type 0 @typeref -427553 +349451 @attribute -120784 +152979 @type_mention -1477122 +2269573 + + +@oblivious +58 + + +@not_annotated +47 + + +@annotated +11 @type_parameter_constraints -330908 +389563 @modifier @@ -205,531 +217,535 @@ @property -277986 +268986 @indexer -23786 +25314 @getter -291486 +286438 @setter -45608 +50195 @event -6046 +8976 @add_event_accessor -6013 +7857 @remove_event_accessor -6013 +7857 @operator -14355 +13320 @method -1076961 +990339 @constructor -154830 +149144 @destructor -461 +388 @local_function -1174 +1201 @addressable_field -160511 +178578 @constant -122762 +106769 @addressable_local_variable -238799 +307769 @local_constant -1223 +1627 @local_variable_ref -11 +54 @parameter -1873820 +1662795 @block_stmt -262647 +483215 @expr_stmt -328762 +510339 @if_stmt -71396 +158006 @switch_stmt -5510 +8021 @while_stmt -1696 +4304 @do_stmt -179 +794 @for_stmt -3370 +8189 @foreach_stmt -9035 +11629 @break_stmt -7981 +17068 @continue_stmt -1828 +3270 @goto_stmt -115 +1200 @goto_case_stmt -95 +330 @goto_default_stmt -148 +252 @throw_stmt -10708 +62807 @return_stmt -107422 +172166 @yield_stmt -1155 +1334 @try_stmt -2439 +6286 @checked_stmt -8 +234 @unchecked_stmt -76 +186 @lock_stmt -656 +1831 @using_block_stmt -5182 +6120 @var_decl_stmt -213042 +269815 @const_decl_stmt -1222 +1623 @empty_stmt -149 +349 @unsafe_stmt -22 +301 @fixed_stmt -54 +783 @label_stmt -69 +439 @catch -2055 +4711 @case_stmt -34567 +53160 @local_function_stmt -1305 +1199 @using_decl_stmt -17 +18 @bool_literal_expr -51125 +83252 @char_literal_expr -6799 +16894 @decimal_literal_expr -126 +134 @int_literal_expr -183666 +268458 @long_literal_expr -83 +178 @uint_literal_expr -239 +2083 @ulong_literal_expr -165 +227 @float_literal_expr -64 +631 @double_literal_expr -319 +656 @string_literal_expr -342808 +402840 @null_literal_expr -58357 +141562 @this_access_expr -266101 +489938 @base_access_expr -2766 +5239 @local_variable_access_expr -756875 +1050542 @parameter_access_expr -348197 +579372 @field_access_expr -387345 +712366 @property_access_expr -331895 +473246 @method_access_expr -5754 +7270 @event_access_expr -1952 +2309 @indexer_access_expr -20850 +31604 @array_access_expr -10320 +25694 @type_access_expr -496066 +724742 @typeof_expr -7384 +26440 @method_invocation_expr -726337 +928336 @delegate_invocation_expr -2920 +4558 @operator_invocation_expr -30533 +41161 @cast_expr -138001 +212776 @object_creation_expr -62254 +104367 @explicit_delegate_creation_expr -200 +1190 @implicit_delegate_creation_expr -3424 +3755 @array_creation_expr -17336 +22244 @default_expr -5647 +8135 @plus_expr -40 +73 @minus_expr -2712 +6795 @bit_not_expr -257 +715 @log_not_expr -14848 +27569 @post_incr_expr -4717 +12713 @post_decr_expr -363 +1368 @pre_incr_expr -321 +1215 @pre_decr_expr -48 +294 @mul_expr -700 +4053 @div_expr -278 +1258 @rem_expr -174 +573 @add_expr -15490 +32765 @sub_expr -3359 +10607 @lshift_expr -252 +1678 @rshift_expr -160 +1075 @lt_expr -4871 +15042 @gt_expr -4360 +10187 @le_expr -1131 +3530 @ge_expr -2035 +5467 @eq_expr -38255 +78231 @ne_expr -24659 +53191 @bit_and_expr -1845 +5903 @bit_xor_expr -165 +507 @bit_or_expr -3840 +11954 @log_and_expr -16596 +31285 @log_or_expr -11990 +21875 @is_expr -4906 +8517 @as_expr -4522 +7102 @null_coalescing_expr -2632 +4350 @conditional_expr -8632 +14417 @simple_assign_expr -87603 +207337 @assign_add_expr -1029 +3522 @assign_sub_expr -111 +619 @assign_mul_expr -20 +123 @assign_div_expr -4 +49 + + +@assign_rem_expr +8 @assign_and_expr -152 +374 @assign_xor_expr -8 +88 @assign_or_expr -687 +1706 @assign_lshift_expr -6 +69 @assign_rshift_expr -7 +97 @object_init_expr -4760 +5120 @collection_init_expr -1260 +1313 @array_init_expr -16761 +19188 @checked_expr -37 +369 @unchecked_expr -255 +1872 @constructor_init_expr -5737 +9978 @add_event_expr -736 +877 @remove_event_expr -306 +408 @local_var_decl_expr -240135 +309563 @lambda_expr -23385 +24042 @anonymous_method_expr -118 +192 @dynamic_element_access_expr @@ -741,55 +757,51 @@ @pointer_indirection_expr -54 +2768 @address_of_expr -31 +717 @sizeof_expr -120 +746 @await_expr -26351 +27405 @nameof_expr -7589 - - -@namespace_access_expr -1000 +18016 @interpolated_string_expr -3470 +4321 @unknown_expr -22558 +22532 @throw_expr -381 +917 @tuple_expr -1841 +2152 @local_function_invocation_expr -2365 +2317 @ref_expr -31 +108 @discard_expr -372 +471 @switch_expr @@ -809,15 +821,19 @@ @switch_case_expr -135 +142 @assign_coalesce_expr 14 -@assign_rem_expr -0 +@suppress_nullable_warning_expr +252 + + +@namespace_access_expr +435 @par_expr @@ -836,10 +852,6 @@ 0 -@suppress_nullable_warning_expr -0 - - @xmldtd 2 @@ -865,19 +877,19 @@ @singlelinecomment -190700 +330391 @xmldoccomment -155568 +276055 @multilinecomment -2025 +12000 @commentblock -142586 +247138 @asp_close_tag @@ -921,31 +933,31 @@ @cil_ceq -71085 +150958 @cil_cgt -5097 +14265 @cil_cgt_un -29102 +58842 @cil_clt -6821 +21999 @cil_clt_un -152 +760 @cil_ldftn -31039 +34640 @cil_ldvirtftn -452 +572 @cil_ldarg @@ -965,219 +977,219 @@ @cil_localloc -158 +1296 @cil_endfilter -742 +901 @cil_volatile -4322 +8933 @cil_initobj -42348 +50442 @cil_constrained -10563 +13699 @cil_rethrow -1557 +2702 @cil_sizeof -509 +1663 @cil_refanytype -3 +9 @cil_readonly -22 +55 @cil_stsfld -39335 +50533 @cil_stobj -3560 +5663 @cil_conv_ovf_i1_un -11 +12 @cil_conv_ovf_i2_un -9 +10 @cil_conv_ovf_i4_un -18 +46 @cil_conv_ovf_i8_un -9 +18 @cil_conv_ovf_u1_un -13 +16 @cil_conv_ovf_u2_un -9 +11 @cil_conv_ovf_u4_un -7 +12 @cil_conv_ovf_i_un -27 +30 @cil_conv_ovf_u_un -1 +3 @cil_box -34001 +49494 @cil_newarr -30964 +42488 @cil_ldlen -16074 +29621 @cil_ldelema -3250 +7817 @cil_ldelem_i1 -16 +43 @cil_ldelem_u1 -1746 +3997 @cil_ldelem_i2 -39 +96 @cil_ldelem_u2 -716 +2501 @cil_ldelem_i4 -1404 +3022 @cil_ldelem_u4 -249 +725 @cil_ldelem_i8 -156 +271 @cil_ldelem_i -30 +56 @cil_ldelem_r4 -6 +80 @cil_ldelem_r8 -72 +136 @cil_ldelem_ref -8789 +17540 @cil_stelem_i -28 +51 @cil_stelem_i1 -2283 +4466 @cil_stelem_i2 -2131 +3032 @cil_stelem_i4 -1186 +2382 @cil_stelem_i8 -82 +112 @cil_stelem_r4 -7 +48 @cil_stelem_r8 -49 +68 @cil_stelem_ref -52243 +72262 @cil_ldelem -1244 +2491 @cil_stelem -2784 +5239 @cil_unbox_any -7679 +12659 @cil_conv_ovf_i1 -16 +27 @cil_conv_ovf_u1 -74 +116 @cil_conv_ovf_i2 -10 +34 @cil_conv_ovf_u2 -36 +73 @cil_conv_ovf_i4 -25 +97 @cil_conv_ovf_u4 -37 +43 @cil_conv_ovf_i8 -5 +13 @cil_conv_ovf_u8 -20 +46 @cil_mkrefany @@ -1185,23 +1197,23 @@ @cil_ldtoken -16408 +30884 @cil_conv_u2 -1623 +3231 @cil_conv_u1 -2397 +5205 @cil_conv_i -2539 +6279 @cil_conv_ovf_i -83 +151 @cil_conv_ovf_u @@ -1209,531 +1221,531 @@ @cil_add_ovf -576 +1079 @cil_add_ovf_un -67 +107 @cil_mul_ovf -112 +302 @cil_mul_ovf_un -160 +572 @cil_sub_ovf -127 +197 @cil_sub_ovf_un -16 +20 @cil_endfinally -27093 +36918 @cil_leave -12636 +16770 @cil_leave_s -52174 +71780 @cil_stind_i -170 +372 @cil_conv_u -2784 +11293 @cil_nop -421589 +1058352 @cil_ldarg_0 -1219505 +1761435 @cil_ldarg_1 -470021 +666051 @cil_ldarg_2 -179471 +260505 @cil_ldarg_3 -87409 +124504 @cil_ldloc_0 -370059 +552028 @cil_ldloc_1 -198298 +295756 @cil_ldloc_2 -132619 +198557 @cil_ldloc_3 -89670 +138205 @cil_stloc_0 -249999 +366179 @cil_stloc_1 -128061 +199127 @cil_stloc_2 -93078 +148560 @cil_stloc_3 -64772 +104523 @cil_ldarg_s -108039 +141946 @cil_ldarga_s -41249 +60259 @cil_starg_s -8831 +15145 @cil_ldloc_s -322360 +554029 @cil_ldloca_s -248663 +306809 @cil_stloc_s -242364 +421486 @cil_ldnull -367434 +527874 @cil_ldc_i4_m1 -25408 +37403 @cil_ldc_i4_0 -286505 +452737 @cil_ldc_i4_1 -180607 +273764 @cil_ldc_i4_2 -38368 +61963 @cil_ldc_i4_3 -16972 +26360 @cil_ldc_i4_4 -15394 +25516 @cil_ldc_i4_5 -10633 +15555 @cil_ldc_i4_6 -5988 +9146 @cil_ldc_i4_7 -4801 +7875 @cil_ldc_i4_8 -6847 +12587 @cil_ldc_i4_s -93556 +153320 @cil_ldc_i4 -101313 +127757 @cil_ldc_i8 -804 +1844 @cil_ldc_r4 -391 +1819 @cil_ldc_r8 -2592 +4211 @cil_dup -133065 +175646 @cil_pop -63274 +84451 @cil_call -1032059 +1478944 @cil_ret -629053 +867422 @cil_br_s -278770 +460982 @cil_brfalse_s -241287 +397704 @cil_brtrue_s -157059 +202600 @cil_beq_s -41579 +55540 @cil_bge_s -9364 +13561 @cil_bgt_s -4692 +7322 @cil_ble_s -10134 +13335 @cil_blt_s -15628 +23707 @cil_bne_un_s -36167 +44432 @cil_bge_un_s -462 +1087 @cil_bgt_un_s -3796 +5045 @cil_ble_un_s -4164 +5587 @cil_blt_un_s -402 +833 @cil_br -48655 +80292 @cil_brfalse -14223 +23259 @cil_brtrue -11832 +16446 @cil_beq -8957 +11212 @cil_bge -460 +568 @cil_bgt -531 +638 @cil_ble -1040 +1163 @cil_blt -1840 +2379 @cil_bne_un -2234 +2606 @cil_bge_un -76 +351 @cil_bgt_un -649 +726 @cil_ble_un -1094 +1209 @cil_blt_un -68 +157 @cil_switch -8423 +11344 @cil_ldind_i1 -66 +171 @cil_ldind_u1 -1972 +4812 @cil_ldind_i2 -47 +135 @cil_ldind_u2 -882 +3540 @cil_ldind_i4 -3656 +6599 @cil_ldind_u4 -419 +857 @cil_ldind_i8 -338 +786 @cil_ldind_i -240 +602 @cil_ldind_r4 -52 +166 @cil_ldind_r8 -79 +173 @cil_ldind_ref -6458 +9006 @cil_stind_ref -10649 +14083 @cil_stind_i1 -3593 +7192 @cil_stind_i2 -435 +2098 @cil_stind_i4 -5789 +11327 @cil_stind_i8 -419 +974 @cil_stind_r4 -28 +213 @cil_stind_r8 -135 +291 @cil_add -45802 +91505 @cil_sub -27733 +48903 @cil_mul -6208 +15702 @cil_div -1845 +4122 @cil_div_un -62 +298 @cil_rem -927 +1798 @cil_rem_un -60 +183 @cil_and -12636 +22304 @cil_or -7591 +12425 @cil_xor -1069 +1745 @cil_shl -2632 +4680 @cil_shr -972 +2069 @cil_shr_un -1202 +2226 @cil_neg -440 +1101 @cil_not -346 +562 @cil_conv_i1 -229 +594 @cil_conv_i2 -368 +846 @cil_conv_i4 -14947 +29360 @cil_conv_i8 -7691 +17068 @cil_conv_r4 -264 +612 @cil_conv_r8 -1003 +1987 @cil_conv_u4 -441 +1227 @cil_conv_u8 -1780 +4327 @cil_callvirt -767609 +1047788 @cil_ldobj -2907 +5059 @cil_ldstr -170165 +267378 @cil_newobj -204904 +283677 @cil_castclass -54510 +68061 @cil_isinst -31244 +42709 @cil_conv_r_un -103 +209 @cil_unbox -179 +263 @cil_throw -267455 +387689 @cil_ldfld -483765 +733616 @cil_ldflda -66802 +96244 @cil_stfld -269151 +373661 @cil_ldsfld -115160 +153187 @cil_ldsflda -1318 +2353 @cil_break @@ -1789,80 +1801,80 @@ @cil_valueorreftype -236158 +249378 @cil_typeparameter -98272 +53658 @cil_array_type -8222 +6961 @cil_pointer_type -440 +638 @cil_method -982868 +1164170 @cil_method_implementation -1040241 +1351436 @cil_field -373454 +459117 @cil_parameter -1904597 +2241273 @cil_property -166215 +232995 @cil_event -3719 +6340 @cil_local_variable -624672 +989635 @cil_catch_handler -10888 +16252 @cil_filter_handler -742 +901 @cil_finally_handler -26292 +35985 @cil_fault_handler -799 +931 @cil_attribute -140634 +248346 compilations -641 +1057 id -641 +1057 cwd -129 +494 @@ -1876,7 +1888,7 @@ 1 2 -641 +1057 @@ -1892,27 +1904,22 @@ 1 2 -71 +409 2 3 -21 +45 3 -14 -10 - - -14 -15 -23 +24 +38 -15 +28 29 -4 +2 @@ -1922,11 +1929,11 @@ compilation_args -2574 +4654 id -641 +1057 num @@ -1934,7 +1941,7 @@ arg -645 +1058 @@ -1951,6 +1958,11 @@ 636 +5 +6 +416 + + 6 7 5 @@ -1972,6 +1984,11 @@ 636 +5 +6 +416 + + 6 7 5 @@ -1990,11 +2007,16 @@ 5 6 -2 +1 + + +421 +422 +1 -641 -642 +1057 +1058 4 @@ -2009,14 +2031,14 @@ 12 -1 -2 -1 - - 2 3 -3 +2 + + +3 +4 +1 5 @@ -2024,8 +2046,13 @@ 1 -635 -636 +413 +414 +1 + + +637 +638 1 @@ -2042,12 +2069,12 @@ 1 2 -637 +1045 2 -642 -8 +1058 +13 @@ -2063,12 +2090,12 @@ 1 2 -643 +1054 2 3 -2 +4 @@ -2078,11 +2105,11 @@ compilation_compiling_files -11459 +21036 id -641 +1057 num @@ -2090,7 +2117,7 @@ file -9738 +18151 @@ -2108,18 +2135,33 @@ 2 -11 -50 +3 +11 -11 -50 -49 +3 +4 +224 -54 +4 +6 +82 + + +6 +18 +80 + + +18 +64 +80 + + +64 1094 -41 +79 @@ -2139,18 +2181,33 @@ 2 -11 -50 +3 +11 -11 -50 -49 +3 +4 +224 -54 +4 +6 +82 + + +6 +18 +80 + + +18 +64 +80 + + +64 1094 -41 +79 @@ -2176,37 +2233,47 @@ 4 5 -313 +213 5 -7 -38 +6 +100 -7 +6 8 -95 +38 8 9 -212 +95 9 -21 -86 +10 +151 -21 -47 -88 +10 +20 +90 -48 -642 -37 +20 +55 +83 + + +56 +160 +82 + + +165 +1058 +17 @@ -2232,37 +2299,47 @@ 4 5 -313 +213 5 -7 -38 +6 +100 -7 +6 8 -95 +38 8 9 -212 +95 9 -21 -86 +10 +151 -21 -46 +10 +20 +90 + + +20 +54 82 -46 -635 -43 +54 +152 +82 + + +156 +1042 +18 @@ -2278,17 +2355,17 @@ 1 2 -8450 +16413 2 -3 -1005 +4 +1541 -3 -12 -283 +4 +129 +197 @@ -2304,17 +2381,17 @@ 1 2 -8531 +16536 2 -3 -961 +4 +1447 -3 -11 -246 +4 +77 +168 @@ -2324,11 +2401,11 @@ compilation_referencing_files -86469 +94271 id -641 +1056 num @@ -2336,7 +2413,7 @@ file -1126 +1701 @@ -2348,74 +2425,69 @@ 12 -3 -71 -55 - - -72 -76 -41 +1 +2 +70 -79 -120 -47 +2 +3 +82 -121 -123 -43 +3 +5 +96 -123 -126 -37 +5 +11 +84 -126 -129 -48 +11 +46 +90 -129 -131 -59 +46 +80 +88 -132 -137 -56 +100 +124 +84 -138 -153 -57 +124 +130 +94 -153 -158 -49 +130 +137 +85 -161 -184 -49 +138 +157 +77 -184 -212 -46 +157 +181 +80 -218 -234 -49 +181 +219 +86 -241 +219 272 -5 +40 @@ -2429,74 +2501,69 @@ 12 -3 -71 -55 - - -72 -75 -41 +1 +2 +70 -78 -120 -47 +2 +3 +82 -121 -123 -43 +3 +5 +96 -123 -126 -51 +5 +11 +84 -126 -129 -34 +11 +46 +90 -129 -131 -59 +46 +79 +88 -132 -137 -56 +100 +124 +84 -138 -153 -57 +124 +130 +94 -153 -158 -49 +130 +137 +85 -161 -183 -49 +138 +157 +78 -184 -212 -46 +157 +182 +80 -218 -234 -49 +182 +219 +85 -241 +219 272 -5 +40 @@ -2526,53 +2593,58 @@ 55 -98 -25 +112 +21 -98 -148 -24 +112 +172 +21 -148 -252 +173 +270 21 -252 -499 -22 +270 +401 +21 -499 -518 -19 +416 +545 +14 + + +545 +546 +13 -518 -519 +546 +547 21 -545 -603 +573 +631 18 -603 -621 -17 +631 +651 +22 -621 -622 -37 +651 +679 +21 -623 -642 -7 +681 +1057 +18 @@ -2588,66 +2660,66 @@ 1 4 -20 +17 4 -8 +6 21 -8 -27 -23 - - -27 -39 +6 +28 21 -39 -64 +28 +49 21 -64 -94 +49 +79 21 -95 -136 +79 +101 21 -138 -155 -22 +101 +141 +21 -155 -165 -22 +146 +168 +23 -165 -172 +168 +180 21 -172 -187 -21 +180 +191 +24 -187 -193 +191 +196 22 -193 -201 +196 +203 +23 + + +203 +226 15 @@ -2664,27 +2736,37 @@ 1 2 -240 +323 2 3 -110 +142 3 -11 -86 +4 +84 -11 +4 +5 +214 + + +5 +23 +130 + + +23 28 -85 +132 28 47 -50 +101 47 @@ -2693,38 +2775,23 @@ 48 -100 -66 - - -100 -176 -85 +106 +128 -177 +108 181 -7 +50 184 -185 -115 - - -187 -284 -23 - - -284 -285 -107 +219 +128 -332 +253 478 -7 +124 @@ -2740,57 +2807,57 @@ 1 2 -243 +332 2 3 -124 +173 3 -7 -85 +4 +164 -7 -16 -95 +4 +5 +130 -16 -20 -85 +5 +12 +129 -20 -23 -85 +12 +17 +144 -23 -29 -89 +17 +21 +145 -29 -38 -97 +21 +26 +134 -38 -52 -85 +26 +35 +141 -52 -104 -90 +35 +96 +132 -104 -120 -48 +96 +116 +77 @@ -2800,11 +2867,11 @@ compilation_time -4487 +7399 id -641 +1057 num @@ -2816,7 +2883,7 @@ seconds -2410 +3864 @@ -2830,7 +2897,7 @@ 1 2 -641 +1057 @@ -2846,7 +2913,7 @@ 7 8 -641 +1057 @@ -2862,12 +2929,12 @@ 6 7 -17 +6 7 8 -624 +1051 @@ -2881,8 +2948,8 @@ 12 -641 -642 +1057 +1058 1 @@ -2913,8 +2980,8 @@ 12 -2410 -2411 +3864 +3865 1 @@ -2929,8 +2996,8 @@ 12 -641 -642 +1057 +1058 7 @@ -2961,39 +3028,34 @@ 12 -171 -172 -1 - - -173 -174 +312 +313 1 -188 -189 +328 +329 1 -202 -203 +369 +370 1 -616 -617 +416 +417 1 -639 -640 +1005 +1006 1 -641 -642 -1 +1056 +1057 +2 @@ -3009,17 +3071,17 @@ 1 2 -2169 +3350 2 -14 -184 +6 +321 -14 -78 -57 +6 +71 +193 @@ -3035,7 +3097,7 @@ 1 2 -2410 +3864 @@ -3051,12 +3113,17 @@ 1 2 -2240 +3460 2 +4 +336 + + +4 5 -170 +68 @@ -3066,15 +3133,15 @@ diagnostic_for -7036 +12070 diagnostic -7036 +12070 compilation -138 +328 file_number @@ -3082,7 +3149,7 @@ file_number_diagnostic_number -1028 +1099 @@ -3096,7 +3163,7 @@ 1 2 -7036 +12070 @@ -3112,7 +3179,7 @@ 1 2 -7036 +12070 @@ -3128,7 +3195,7 @@ 1 2 -7036 +12070 @@ -3142,69 +3209,64 @@ 12 +1 +2 +2 + + 2 3 -2 +53 + + +3 +4 +27 4 5 -26 +41 5 -6 -5 - - -6 7 -12 +29 7 -8 -7 - - -8 -11 -11 +9 +25 -11 -14 -11 +9 +13 +28 -15 -20 -12 +13 +19 +26 -20 -32 -11 +19 +28 +26 -33 +28 57 -12 - - -59 -106 -11 +25 -123 -193 -12 +57 +154 +25 -232 -1029 -6 +160 +1100 +21 @@ -3220,7 +3282,7 @@ 1 2 -138 +328 @@ -3234,69 +3296,64 @@ 12 +1 +2 +2 + + 2 3 -2 +53 + + +3 +4 +27 4 5 -26 +41 5 -6 -5 - - -6 7 -12 +29 7 -8 -7 - - -8 -11 -11 +9 +25 -11 -14 -11 +9 +13 +28 -15 -20 -12 +13 +19 +26 -20 -32 -11 +19 +28 +26 -33 +28 57 -12 - - -59 -106 -11 +25 -123 -193 -12 +57 +154 +25 -232 -1029 -6 +160 +1100 +21 @@ -3310,8 +3367,8 @@ 12 -7036 -7037 +12070 +12071 1 @@ -3326,8 +3383,8 @@ 12 -138 -139 +328 +329 1 @@ -3342,8 +3399,8 @@ 12 -1028 -1029 +1099 +1100 1 @@ -3360,32 +3417,42 @@ 1 2 -488 +71 2 3 -147 +488 3 4 -150 +147 4 -10 -79 +5 +82 -10 -26 -90 +5 +12 +88 -26 -139 -74 +12 +24 +89 + + +25 +52 +84 + + +52 +329 +50 @@ -3401,32 +3468,42 @@ 1 2 -488 +71 2 3 -147 +488 3 4 -150 +147 4 -10 -79 +5 +82 -10 -26 -90 +5 +12 +88 -26 -139 -74 +12 +24 +89 + + +25 +52 +84 + + +52 +329 +50 @@ -3442,7 +3519,7 @@ 1 2 -1028 +1099 @@ -3452,31 +3529,31 @@ diagnostics -7036 +12070 id -7036 +12070 severity -1 +2 error_tag -2 +6 error_message -2 +6 full_error_message -2 +27 location -5748 +10395 @@ -3490,7 +3567,7 @@ 1 2 -7036 +12070 @@ -3506,7 +3583,7 @@ 1 2 -7036 +12070 @@ -3522,7 +3599,7 @@ 1 2 -7036 +12070 @@ -3538,7 +3615,7 @@ 1 2 -7036 +12070 @@ -3554,7 +3631,7 @@ 1 2 -7036 +12070 @@ -3568,8 +3645,13 @@ 12 -7036 -7037 +242 +243 +1 + + +11828 +11829 1 @@ -3588,6 +3670,11 @@ 3 1 + +4 +5 +1 + @@ -3604,6 +3691,11 @@ 3 1 + +4 +5 +1 + @@ -3620,6 +3712,11 @@ 3 1 + +25 +26 +1 + @@ -3632,8 +3729,13 @@ 12 -5748 -5749 +236 +237 +1 + + +10159 +10160 1 @@ -3648,13 +3750,33 @@ 12 +2 +3 +1 + + 4 5 1 -7032 -7033 +6 +7 +1 + + +33 +34 +1 + + +201 +202 +1 + + +11824 +11825 1 @@ -3671,7 +3793,7 @@ 1 2 -2 +6 @@ -3687,7 +3809,7 @@ 1 2 -2 +6 @@ -3705,6 +3827,21 @@ 2 2 + +2 +3 +1 + + +5 +6 +2 + + +13 +14 +1 + @@ -3719,11 +3856,26 @@ 2 3 +2 + + +6 +7 +1 + + +27 +28 +1 + + +201 +202 1 -5746 -5747 +10157 +10158 1 @@ -3738,13 +3890,33 @@ 12 +2 +3 +1 + + 4 5 1 -7032 -7033 +6 +7 +1 + + +33 +34 +1 + + +201 +202 +1 + + +11824 +11825 1 @@ -3761,7 +3933,7 @@ 1 2 -2 +6 @@ -3777,7 +3949,7 @@ 1 2 -2 +6 @@ -3795,6 +3967,21 @@ 2 2 + +2 +3 +1 + + +5 +6 +2 + + +13 +14 +1 + @@ -3809,11 +3996,26 @@ 2 3 +2 + + +6 +7 1 -5746 -5747 +27 +28 +1 + + +201 +202 +1 + + +10157 +10158 1 @@ -3828,15 +4030,65 @@ 12 -4 -5 +1 +2 +6 + + +2 +3 1 -7032 -7033 +3 +4 +2 + + +4 +6 +2 + + +6 +8 +2 + + +9 +11 +2 + + +11 +12 1 + +14 +15 +2 + + +16 +17 +3 + + +17 +18 +2 + + +21 +23 +2 + + +27 +11825 +2 + @@ -3851,7 +4103,7 @@ 1 2 -2 +27 @@ -3867,7 +4119,7 @@ 1 2 -2 +27 @@ -3883,7 +4135,7 @@ 1 2 -2 +27 @@ -3897,14 +4149,59 @@ 12 +1 +2 +6 + + 2 3 -1 +2 -5746 -5747 -1 +3 +4 +2 + + +5 +7 +2 + + +7 +10 +2 + + +10 +12 +2 + + +14 +15 +2 + + +16 +17 +3 + + +17 +18 +2 + + +21 +23 +2 + + +27 +10158 +2 @@ -3920,17 +4217,17 @@ 1 2 -4674 +9120 2 3 -920 +1031 3 12 -154 +244 @@ -3946,7 +4243,7 @@ 1 2 -5748 +10395 @@ -3962,7 +4259,7 @@ 1 2 -5748 +10395 @@ -3978,7 +4275,7 @@ 1 2 -5748 +10395 @@ -3994,7 +4291,12 @@ 1 2 -5748 +10389 + + +2 +3 +6 @@ -4004,11 +4306,11 @@ extractor_messages -264 +57 id -264 +57 severity @@ -4020,19 +4322,19 @@ text -8 +4 entity -143 +23 location -241 +34 stack_trace -30 +3 @@ -4046,7 +4348,7 @@ 1 2 -264 +57 @@ -4062,7 +4364,7 @@ 1 2 -264 +57 @@ -4078,7 +4380,7 @@ 1 2 -264 +57 @@ -4094,7 +4396,7 @@ 1 2 -264 +57 @@ -4110,7 +4412,7 @@ 1 2 -264 +57 @@ -4126,7 +4428,7 @@ 1 2 -264 +57 @@ -4140,18 +4442,18 @@ 12 -15 -16 +6 +7 1 -35 -36 +15 +16 1 -214 -215 +36 +37 1 @@ -4187,8 +4489,8 @@ 2 -6 -7 +2 +3 1 @@ -4208,13 +4510,13 @@ 1 -16 -17 +5 +6 1 -126 -127 +17 +18 1 @@ -4234,13 +4536,13 @@ 1 -26 -27 +6 +7 1 -214 -215 +27 +28 1 @@ -4260,8 +4562,8 @@ 2 -29 -30 +2 +3 1 @@ -4276,8 +4578,8 @@ 12 -264 -265 +57 +58 1 @@ -4308,8 +4610,8 @@ 12 -8 -9 +4 +5 1 @@ -4324,8 +4626,8 @@ 12 -143 -144 +23 +24 1 @@ -4340,8 +4642,8 @@ 12 -241 -242 +34 +35 1 @@ -4356,8 +4658,8 @@ 12 -30 -31 +3 +4 1 @@ -4372,11 +4674,6 @@ 12 -1 -2 -2 - - 2 3 1 @@ -4387,23 +4684,13 @@ 1 -12 -13 -1 - - 15 16 1 -35 -36 -1 - - -194 -195 +36 +37 1 @@ -4420,7 +4707,7 @@ 1 2 -8 +4 @@ -4436,7 +4723,7 @@ 1 2 -8 +4 @@ -4452,7 +4739,7 @@ 1 2 -4 +2 4 @@ -4460,18 +4747,8 @@ 1 -6 -7 -1 - - -16 -17 -1 - - -113 -114 +17 +18 1 @@ -4488,7 +4765,7 @@ 1 2 -3 +1 2 @@ -4501,18 +4778,8 @@ 1 -12 -13 -1 - - -26 -27 -1 - - -194 -195 +27 +28 1 @@ -4529,12 +4796,7 @@ 1 2 -7 - - -25 -26 -1 +4 @@ -4550,22 +4812,27 @@ 1 2 -96 +11 2 3 -32 +6 3 -6 -12 +4 +2 -6 -40 -3 +4 +5 +2 + + +5 +16 +2 @@ -4581,7 +4848,7 @@ 1 2 -143 +23 @@ -4597,7 +4864,7 @@ 1 2 -143 +23 @@ -4613,7 +4880,7 @@ 1 2 -143 +23 @@ -4629,17 +4896,17 @@ 1 2 -101 +16 2 3 -31 +5 3 -40 -11 +6 +2 @@ -4655,12 +4922,7 @@ 1 2 -141 - - -2 -5 -2 +23 @@ -4676,12 +4938,17 @@ 1 2 -231 +24 2 +3 +9 + + +15 16 -10 +1 @@ -4697,7 +4964,7 @@ 1 2 -241 +34 @@ -4713,7 +4980,7 @@ 1 2 -241 +34 @@ -4729,7 +4996,7 @@ 1 2 -241 +34 @@ -4745,7 +5012,7 @@ 1 2 -241 +34 @@ -4761,7 +5028,7 @@ 1 2 -241 +34 @@ -4775,59 +5042,19 @@ 12 -1 -2 -9 - - 2 3 -3 - - -3 -4 -3 +1 4 5 -2 - - -5 -6 1 -6 -7 -2 - - -8 -9 -2 - - -9 -11 -2 - - -12 -13 -2 - - -24 -25 -2 - - -50 -59 -2 +51 +52 +1 @@ -4843,7 +5070,7 @@ 1 2 -29 +2 2 @@ -4864,7 +5091,7 @@ 1 2 -30 +3 @@ -4880,12 +5107,12 @@ 1 2 -28 +2 2 3 -2 +1 @@ -4901,41 +5128,16 @@ 1 2 -15 - - -2 -3 -5 - - -3 -4 1 4 5 -2 - - -5 -6 1 -6 -7 -3 - - -17 -21 -2 - - -51 -52 +18 +19 1 @@ -4950,59 +5152,19 @@ 12 -1 -2 -9 - - 2 3 -3 - - -3 -4 -3 +1 4 5 -2 - - -5 -6 1 -6 -7 -2 - - -8 -9 -2 - - -9 -11 -2 - - -12 -13 -2 - - -24 -25 -2 - - -27 -59 -2 +28 +29 +1 @@ -5012,19 +5174,19 @@ compilation_finished -641 +1057 id -641 +1057 cpu_seconds -248 +509 elapsed_seconds -641 +1056 @@ -5038,7 +5200,7 @@ 1 2 -641 +1057 @@ -5054,7 +5216,7 @@ 1 2 -641 +1057 @@ -5070,32 +5232,27 @@ 1 2 -154 +299 2 3 -19 +93 3 -5 -22 +4 +41 -5 +4 6 -17 +41 6 -8 -18 - - -8 -15 -18 +14 +35 @@ -5111,32 +5268,27 @@ 1 2 -154 +299 2 3 -19 +93 3 -5 -22 +4 +41 -5 +4 6 -17 +41 6 -8 -18 - - -8 -15 -18 +14 +35 @@ -5152,7 +5304,12 @@ 1 2 -641 +1055 + + +2 +3 +1 @@ -5168,7 +5325,12 @@ 1 2 -641 +1055 + + +2 +3 +1 @@ -5592,11 +5754,11 @@ externalData -16 +18 id -8 +9 path @@ -5608,7 +5770,7 @@ value -16 +18 @@ -5622,7 +5784,7 @@ 1 2 -8 +9 @@ -5638,7 +5800,7 @@ 2 3 -8 +9 @@ -5654,7 +5816,7 @@ 2 3 -8 +9 @@ -5668,8 +5830,8 @@ 12 -8 -9 +9 +10 1 @@ -5700,8 +5862,8 @@ 12 -16 -17 +18 +19 1 @@ -5716,8 +5878,8 @@ 12 -8 -9 +9 +10 2 @@ -5748,8 +5910,8 @@ 12 -8 -9 +9 +10 2 @@ -5766,7 +5928,7 @@ 1 2 -16 +18 @@ -5782,7 +5944,7 @@ 1 2 -16 +18 @@ -5798,7 +5960,7 @@ 1 2 -16 +18 @@ -5830,19 +5992,19 @@ duplicateCode -13480 +20134 id -13480 +20134 relativePath -1215 +2570 equivClass -4735 +7291 @@ -5856,7 +6018,7 @@ 1 2 -13480 +20134 @@ -5872,7 +6034,7 @@ 1 2 -13480 +20134 @@ -5888,42 +6050,37 @@ 1 2 -483 +1164 2 3 -249 +511 3 4 -81 +177 4 -5 -81 - - -5 -8 -108 +6 +237 -8 -16 -97 +6 +11 +217 -16 -70 -92 +11 +41 +194 -71 +41 1047 -24 +70 @@ -5939,37 +6096,32 @@ 1 2 -624 +1401 2 3 -173 +377 3 4 -107 +217 4 -5 -71 - - -5 -8 -111 +6 +225 -8 -23 -94 +6 +12 +206 -23 +12 405 -35 +144 @@ -5985,32 +6137,32 @@ 1 2 -2 +5 2 3 -3064 +4859 3 4 -717 +1105 4 5 -431 +632 5 -8 -361 +9 +574 -8 +9 11 -160 +116 @@ -6026,17 +6178,22 @@ 1 2 -3704 +4521 2 3 -800 +2071 3 +6 +603 + + +6 11 -231 +96 @@ -6046,19 +6203,19 @@ similarCode -124007 +149289 id -124007 +149289 relativePath -3653 +5832 equivClass -34919 +43184 @@ -6072,7 +6229,7 @@ 1 2 -124007 +149289 @@ -6088,7 +6245,7 @@ 1 2 -124007 +149289 @@ -6104,57 +6261,57 @@ 1 2 -819 +1266 2 3 -561 +999 3 4 -253 +428 4 5 -240 +427 5 -7 -328 +6 +317 -7 -10 -303 +6 +8 +460 -10 -16 -290 +8 +12 +464 -16 -27 -280 +12 +19 +445 -27 -63 -277 +19 +40 +450 -63 -540 -274 +40 +158 +438 -563 +158 10255 -28 +138 @@ -6170,47 +6327,47 @@ 1 2 -1136 +1794 2 3 -509 +875 3 4 -343 +565 4 5 -248 +436 5 7 -327 +540 7 10 -285 +473 10 17 -289 +467 17 -39 -283 +45 +443 -39 +45 3151 -233 +239 @@ -6226,37 +6383,37 @@ 1 2 -27 +33 2 3 -15700 +20582 3 4 -6717 +8089 4 5 -4246 +4987 5 6 -2523 +2926 6 8 -3121 +3616 8 11 -2585 +2951 @@ -6272,22 +6429,22 @@ 1 2 -24135 +29024 2 3 -7080 +9400 3 5 -2744 +3481 5 11 -960 +1279 @@ -6297,11 +6454,11 @@ tokens -16303051 +20596077 id -137487 +169423 offset @@ -6313,7 +6470,7 @@ beginColumn -1273 +1275 endLine @@ -6321,7 +6478,7 @@ endColumn -1281 +1282 @@ -6335,72 +6492,72 @@ 100 101 -14059 +17349 101 102 -11347 +14013 102 103 -9867 +11330 103 104 -7193 +8613 104 105 -7011 +8343 105 107 -11281 +13200 107 109 -9402 +11207 109 112 -11634 +13800 112 116 -11231 +13475 116 122 -10975 +13227 122 132 -11245 +13847 132 -151 -10714 +150 +13094 -151 -246 -10322 +150 +200 +12774 -246 +200 24726 -1206 +5151 @@ -6416,77 +6573,72 @@ 3 8 -9658 +15571 8 10 -10203 +13241 10 12 -12464 +14984 12 13 -7171 +8221 13 14 -8457 +9518 14 15 -8662 +10126 15 16 -7359 +8365 16 -17 -6734 - - -17 -19 -12294 +18 +15128 -19 -21 -11808 +18 +20 +14382 -21 -23 -10152 +20 +22 +13269 -23 -25 -9076 +22 +24 +10793 -25 -29 -12371 +24 +27 +14004 -29 -50 -10359 +27 +33 +13393 -50 +33 4516 -719 +8428 @@ -6501,68 +6653,68 @@ 3 -31 -11905 +30 +13731 -31 -36 -11061 +30 +35 +12960 -36 +35 40 -10541 +15615 40 44 -11491 +13732 44 48 -12544 +15209 48 51 -9774 +11686 51 54 -10252 +12470 54 57 -10130 +12211 57 61 -12505 +15141 61 65 -11020 +13198 65 71 -11742 +14162 71 83 -10362 +13148 83 356 -4160 +6160 @@ -6578,82 +6730,77 @@ 3 8 -9693 +15606 8 10 -10246 +13284 10 11 -6305 +7617 11 12 -6863 +8071 12 13 -7917 +8967 13 14 -8978 +10039 14 15 -8596 +10060 15 16 -7157 +8163 16 -17 -6534 - - -17 18 -6305 +15038 18 -19 -6514 +20 +15158 -19 -21 -12394 +20 +22 +13995 -21 -23 -10926 +22 +24 +11189 -23 -25 -9003 +24 +27 +13173 -25 -29 -10845 +27 +35 +13285 -29 +35 4516 -9211 +5778 @@ -6668,68 +6815,68 @@ 3 -33 -11758 +32 +13965 -33 +32 38 -10683 +14984 38 -42 -10267 +43 +15403 -42 -46 -11227 +43 +47 +13368 -46 -50 -11885 +47 +51 +14461 -50 -54 -12367 +51 +55 +15157 -54 -57 -9677 +55 +58 +11849 -57 -60 -9829 +58 +62 +15331 -60 -64 -11875 +62 +66 +13741 -64 -68 -10641 +66 +71 +14501 -68 -73 -10560 +71 +78 +13414 -73 -82 -10400 +78 +120 +12726 -82 +120 363 -6318 +523 @@ -6745,16 +6892,26 @@ 2 3 -21440 +10300 4 -9 +5 +8833 + + +7 +8 +2307 + + +9 +30 1856 -12 -137488 +33 +169424 1429 @@ -6771,16 +6928,26 @@ 2 3 -21440 +10300 -4 -9 +3 +4 +8833 + + +5 +6 +2307 + + +7 +24 1856 -10 -27395 +24 +27429 1429 @@ -6797,17 +6964,27 @@ 1 2 -21460 +10430 2 -7 -1942 +3 +8777 -7 -470 -1323 +3 +4 +2244 + + +4 +15 +1894 + + +15 +489 +1380 @@ -6823,16 +7000,26 @@ 2 3 -21440 +10300 -4 -9 +3 +4 +8833 + + +5 +6 +2307 + + +7 +24 1856 -10 -27361 +24 +27395 1429 @@ -6849,17 +7036,27 @@ 1 2 -21457 +10382 2 -7 -1939 +3 +8807 -7 -479 -1329 +3 +4 +2264 + + +4 +15 +1897 + + +15 +494 +1375 @@ -6895,57 +7092,57 @@ 5 6 -4514 +4513 6 7 -4085 +4086 7 8 -3742 +3748 8 9 -3307 +3319 9 11 -5783 +5799 11 14 -5837 +5802 14 19 -5467 +5476 19 32 -5251 +5188 32 -76 -5025 +80 +5056 -76 -1383 +80 +1828 5022 -1384 -3597 -208 +1830 +5217 +232 @@ -6986,42 +7183,47 @@ 26 35 -5332 +5342 35 45 -5040 +5030 45 57 -5140 +5139 57 72 -5093 +5082 72 91 -5148 +5111 91 114 -5184 +5123 114 -149 -5124 +153 +5067 -149 -441 -4975 +153 +499 +5022 + + +499 +605 +120 @@ -7047,7 +7249,7 @@ 4 6 -4829 +4828 6 @@ -7057,7 +7259,7 @@ 9 12 -5032 +5031 12 @@ -7067,32 +7269,32 @@ 16 20 -5344 +5337 20 26 -5672 +5654 26 35 -5331 +5318 35 -53 -5120 +54 +5192 -53 -93 -5098 +54 +99 +5040 -93 -313 -3993 +99 +340 +4019 @@ -7149,47 +7351,47 @@ 6 9 -6096 +6095 9 12 -5031 +5032 12 16 -5544 +5541 16 20 -5294 +5289 20 26 -5618 +5602 26 35 -5225 +5213 35 53 -5146 +5023 53 -92 -5094 +94 +5029 -92 -319 -4369 +94 +342 +4593 @@ -7205,73 +7407,68 @@ 1 2 -102 +101 2 3 -76 +77 3 5 -104 +103 5 -8 -94 +9 +118 -8 -11 -94 +9 +12 +93 -11 -14 -90 +12 +16 +99 -14 -18 -100 +16 +22 +107 -18 -28 +22 +49 97 -28 -91 +49 +154 96 -92 -263 +155 +460 96 -264 -835 +460 +2842 96 -851 -12397 +2886 +34163 96 -12702 -67475 +34851 +133446 96 - -68233 -114514 -36 - @@ -7286,67 +7483,67 @@ 1 2 -104 +102 2 3 -84 +86 3 5 -112 +111 5 8 -94 +86 8 11 -117 +116 11 -14 -99 - - -14 -19 -101 +15 +112 -19 -39 -99 +15 +21 +102 -40 -82 +21 +46 97 -82 -126 +46 +99 98 -126 -213 -99 +99 +152 +96 + + +153 +273 +96 -215 -449 +274 +708 96 -453 -3387 -73 +708 +3646 +77 @@ -7362,62 +7559,62 @@ 1 2 -243 +240 2 3 -98 +85 3 4 -112 +115 4 5 -79 +69 5 -6 -84 +7 +118 -6 -8 -107 +7 +10 +97 -8 -23 -96 +10 +33 +97 -23 -54 -97 +33 +80 +96 -54 -144 +80 +216 96 -145 -1392 +216 +1785 96 -1447 -10372 +1861 +10566 96 -10475 -36610 -69 +10669 +36636 +70 @@ -7433,62 +7630,62 @@ 1 2 -243 +240 2 3 -98 +85 3 4 -112 +115 4 5 -79 +69 5 -6 -84 +7 +118 -6 -8 -107 +7 +10 +97 -8 -23 -96 +10 +33 +97 -23 -54 -97 +33 +80 +96 -54 -144 +80 +216 96 -145 -1392 +216 +1785 96 -1447 -10375 +1861 +10566 96 -10476 -36609 -69 +10670 +36635 +70 @@ -7504,52 +7701,52 @@ 1 2 -321 +313 2 3 -178 +162 3 4 -164 +154 4 5 -81 +75 5 9 -117 +113 9 15 -97 +102 15 22 -98 +106 22 -44 -96 +35 +98 -44 -88 -96 +35 +75 +98 -89 +75 176 -25 +54 @@ -7585,57 +7782,57 @@ 5 6 -4460 +4459 6 7 -4053 +4054 7 8 -3674 +3680 8 9 -3252 +3264 9 11 -5618 +5635 11 14 -5654 +5618 14 19 -5335 +5343 19 32 -5179 +5112 32 -75 -4971 +78 +4956 -75 -1119 +78 +1307 4932 -1121 -3579 -273 +1308 +5199 +348 @@ -7656,22 +7853,22 @@ 5 9 -5454 +5457 9 15 -5692 +5689 15 22 -5387 +5386 22 30 -5043 +5047 30 @@ -7681,37 +7878,37 @@ 39 50 -5193 +5190 50 63 -5119 +5112 63 79 -4956 +4943 79 99 -5007 +4966 99 125 -5078 +4992 125 -163 -4979 +173 +4964 -163 -441 -3294 +173 +605 +3456 @@ -7768,52 +7965,52 @@ 5 7 -5672 +5671 7 10 -4870 +4871 10 14 -6007 +6004 14 17 -5141 +5140 17 22 -5202 +5191 22 28 -5339 +5324 28 39 -5222 +5191 39 -61 -5007 +62 +5013 -61 -109 -4976 +62 +118 +4937 -109 -313 -2739 +118 +340 +2833 @@ -7844,52 +8041,52 @@ 5 7 -5488 +5487 7 10 -4894 +4895 10 14 -5975 +5972 14 17 -5079 +5077 17 22 -5183 +5177 22 28 -5298 +5282 28 39 -5141 +5107 39 -61 -5028 +62 +5051 -61 -107 -4991 +62 +115 +4947 -107 -318 -3089 +115 +342 +3171 @@ -7905,72 +8102,72 @@ 1 2 -103 +100 2 3 -75 +73 3 5 -109 +112 5 8 -99 +93 8 11 -99 +94 11 15 -109 +102 15 21 -99 +100 21 -38 -97 +36 +100 -38 -127 +36 +132 97 -128 -343 -98 +133 +348 +97 -344 -1906 +350 +1580 97 -1964 -25254 +1614 +21369 97 -25838 -92921 +21416 +97489 97 -95159 -100909 -5 +97674 +119719 +23 @@ -7986,67 +8183,72 @@ 1 2 -106 +102 2 3 -80 +79 3 4 -91 +92 4 8 -118 +115 8 10 -90 +83 10 14 -117 +108 14 19 -102 +105 19 -33 +32 99 -33 -78 +32 +81 +98 + + +81 +133 97 -80 -122 -98 +133 +232 +97 -122 -200 +232 +491 97 -200 -398 +491 +1764 97 -398 -2279 -89 +1819 +3367 +13 @@ -8062,62 +8264,62 @@ 1 2 -248 +239 2 3 -109 +99 3 4 -89 +94 4 5 -98 +89 5 -6 -74 +7 +108 -6 -8 -101 +7 +11 +105 -8 -22 -97 +11 +39 +98 -22 -51 -98 +39 +87 +97 -51 -133 +88 +251 97 -133 -1225 +256 +2289 97 -1290 -10635 +2295 +11901 97 -10679 -26467 -76 +12187 +26471 +62 @@ -8133,52 +8335,52 @@ 1 2 -319 +309 2 3 -191 +177 3 4 -147 +136 4 -6 -117 +5 +71 -6 -11 -108 +5 +9 +111 -11 -18 -101 +9 +16 +110 -18 -30 -99 +16 +25 +101 -30 -53 -98 +25 +38 +97 -53 -75 -98 +38 +66 +103 -76 +66 110 -3 +67 @@ -8194,62 +8396,62 @@ 1 2 -248 +239 2 3 -109 +99 3 4 -89 +94 4 5 -98 +89 5 -6 -74 +7 +108 -6 -8 -101 +7 +11 +105 -8 -22 -97 +11 +39 +98 -22 -51 -98 +39 +87 +97 -51 -133 +88 +251 97 -133 -1225 +256 +2289 97 -1290 -10635 +2295 +11901 97 -10679 -26467 -76 +12187 +26471 +62 @@ -8259,15 +8461,15 @@ locations_default -7339237 +11787435 id -7339237 +11787435 file -13679 +22092 beginLine @@ -8275,7 +8477,7 @@ beginColumn -1126 +1161 endLine @@ -8283,7 +8485,7 @@ endColumn -1207 +1237 @@ -8297,7 +8499,7 @@ 1 2 -7339237 +11787435 @@ -8313,7 +8515,7 @@ 1 2 -7339237 +11787435 @@ -8329,7 +8531,7 @@ 1 2 -7339237 +11787435 @@ -8345,7 +8547,7 @@ 1 2 -7339237 +11787435 @@ -8361,7 +8563,7 @@ 1 2 -7339237 +11787435 @@ -8376,73 +8578,73 @@ 1 -18 -1049 +16 +1739 -18 -29 -908 +16 +27 +1704 -29 -34 -1032 +27 +35 +1622 -34 -52 -1072 +35 +48 +1689 -52 -74 -1062 +48 +70 +1725 -74 -101 -1043 +70 +98 +1659 -101 -140 -1035 +98 +141 +1671 -140 -194 -1027 +141 +199 +1668 -194 -271 -1035 +199 +286 +1657 -271 -392 -1026 +286 +425 +1666 -392 -601 -1029 +425 +680 +1657 -601 -1067 -1026 +680 +1245 +1658 -1068 -3393 -1026 +1245 +4832 +1657 -3400 -167164 -309 +4835 +167166 +320 @@ -8457,68 +8659,68 @@ 1 -10 -1072 +9 +1729 -10 -15 -1074 +9 +14 +1933 -15 -20 -949 +14 +19 +1627 -20 -23 -1180 +19 +22 +1911 -23 -30 -1114 +22 +29 +1670 -30 +29 39 -1056 +1774 39 -51 -1049 +52 +1707 -51 -69 -1049 +52 +71 +1664 -69 -93 -1048 +71 +99 +1676 -93 -133 -1044 +99 +145 +1659 -133 -204 -1028 +145 +229 +1660 -204 -378 -1027 +229 +454 +1657 -378 +454 44061 -989 +1425 @@ -8534,67 +8736,67 @@ 1 7 -698 +1536 7 -10 -1112 +11 +1891 -10 -16 -1138 +11 +15 +1732 -16 -22 -1222 +15 +21 +1867 -22 -28 -1170 +21 +27 +1695 -28 +27 34 -1044 +1796 34 -41 -1063 +42 +1791 -41 -49 -1065 +42 +51 +1809 -49 -59 -1107 +51 +62 +1803 -59 -70 -1042 +62 +75 +1792 -70 -85 -1080 +75 +91 +1700 -85 -107 -1026 +91 +119 +1673 -107 +119 781 -912 +1007 @@ -8609,68 +8811,68 @@ 1 -10 -1068 +9 +1728 -10 -15 -1066 +9 +14 +1924 -15 -20 -959 +14 +19 +1631 -20 -23 -1174 +19 +22 +1915 -23 +22 30 -1103 +1877 30 -39 -1060 +40 +1726 -39 -51 -1062 +40 +53 +1657 -51 -69 -1061 +53 +73 +1687 -69 -93 -1036 +73 +102 +1684 -93 -133 -1039 +102 +150 +1678 -133 -204 -1033 +150 +242 +1659 -204 -379 -1030 +242 +504 +1659 -380 +504 46103 -988 +1267 @@ -8685,68 +8887,68 @@ 1 -15 -1084 +13 +1769 -15 -23 -1091 +13 +20 +1667 -23 -27 -1154 +20 +25 +1751 -27 -36 -1104 +25 +31 +1697 -36 -44 -1053 +31 +40 +1705 -44 -54 -1096 +40 +50 +1773 -54 -65 -1080 +50 +61 +1688 -65 -77 -1097 +61 +73 +1741 -77 -90 -1064 +73 +86 +1709 -90 -104 -1053 +86 +100 +1727 -104 -121 -1056 +100 +117 +1754 -121 -149 -1043 +117 +142 +1670 -149 +142 883 -704 +1441 @@ -8772,17 +8974,17 @@ 3 4 -4194 +4193 4 5 -3819 +3818 5 7 -6300 +6302 7 @@ -8792,7 +8994,7 @@ 8 10 -4991 +4990 10 @@ -8802,27 +9004,27 @@ 13 18 -5837 +5836 18 28 -5563 +5541 28 -60 -5469 +65 +5497 -60 -223 +65 +290 5443 -223 -25138 -3711 +290 +39954 +3707 @@ -8853,22 +9055,22 @@ 4 6 -5614 +5612 6 12 -5659 +5460 12 -39 -5507 +46 +5480 -39 -13512 -4467 +46 +21923 +4695 @@ -8894,7 +9096,7 @@ 3 4 -5401 +5400 4 @@ -8904,7 +9106,7 @@ 5 6 -5787 +5788 6 @@ -8914,32 +9116,32 @@ 7 9 -6496 +6494 9 12 -6083 +6072 12 18 -5599 +5518 18 -34 -5493 +39 +5563 -34 -90 -5481 +39 +110 +5455 -90 -337 -1877 +110 +373 +1927 @@ -8955,32 +9157,32 @@ 1 2 -33221 +33201 2 3 -21100 +21035 3 4 -6051 +5962 4 -8 -5780 +9 +6100 -8 -34 -5457 +9 +46 +5486 -34 -89 -914 +46 +367 +739 @@ -9006,7 +9208,7 @@ 3 4 -4747 +4746 4 @@ -9016,7 +9218,7 @@ 5 6 -3954 +3955 6 @@ -9026,12 +9228,12 @@ 7 8 -4764 +4762 8 10 -4965 +4966 10 @@ -9041,27 +9243,27 @@ 13 18 -5782 +5776 18 29 -5697 +5626 29 -58 -5476 +64 +5542 -58 -133 -5488 +64 +149 +5479 -133 -377 -1748 +149 +413 +1769 @@ -9077,57 +9279,62 @@ 1 2 -313 +312 2 3 -85 +82 3 4 -67 +61 4 5 -71 +67 5 -7 -78 +8 +107 -7 -13 -92 +8 +17 +90 -13 -38 +17 +55 88 -38 -123 -86 +55 +175 +88 -127 -1194 -85 +176 +1176 +88 -1236 -15406 -85 +1256 +16999 +88 -15727 -1094594 -76 +17523 +646623 +88 + + +1430464 +1573394 +2 @@ -9143,47 +9350,52 @@ 1 2 -386 +369 2 3 -155 +129 3 4 -91 +75 4 6 -82 +88 6 -12 -90 +13 +88 -12 -45 -85 +13 +29 +91 -48 -536 -85 +29 +106 +88 -542 -3990 -85 +110 +1029 +88 -4076 -13387 -67 +1033 +7700 +88 + + +7907 +21381 +57 @@ -9199,57 +9411,57 @@ 1 2 -351 +345 2 3 -96 +89 3 4 -65 +58 4 -5 -61 +6 +100 -5 -8 -100 +6 +11 +96 -8 -18 -86 +11 +29 +90 -18 -52 -87 +30 +94 +91 -52 -307 -85 +94 +413 +88 -314 -2787 -85 +415 +2920 +88 -2849 -9082 -85 +2932 +9215 +88 -9434 -50357 -25 +9290 +50368 +28 @@ -9265,57 +9477,57 @@ 1 2 -351 +345 2 3 -96 +89 3 4 -65 +58 4 -5 -61 +6 +100 -5 -8 -100 +6 +11 +96 -8 -18 -86 +11 +29 +90 -18 -52 -87 +30 +94 +91 -52 -307 -85 +94 +413 +88 -319 -2788 -85 +415 +2918 +88 -2852 -9085 -85 +2936 +9228 +88 -9525 -53426 -25 +9288 +53430 +28 @@ -9331,52 +9543,57 @@ 1 2 -359 +352 2 3 -105 +101 3 4 -85 +76 4 6 -85 +91 6 11 -90 +94 11 -22 +24 89 -22 -40 -87 +24 +41 +89 -40 -76 -86 +41 +68 +89 -76 -197 -85 +68 +162 +88 -199 -453 -55 +162 +383 +88 + + +429 +454 +4 @@ -9402,7 +9619,7 @@ 3 4 -5876 +5875 4 @@ -9432,22 +9649,22 @@ 18 29 -5851 +5819 29 -66 -5624 +73 +5604 -66 -290 -5556 +73 +410 +5557 -290 -24298 -3085 +410 +38993 +3137 @@ -9473,27 +9690,27 @@ 3 4 -7358 +7357 4 6 -5646 +5645 6 12 -5903 +5743 12 -39 -5621 +46 +5573 -39 -13508 -4602 +46 +21919 +4812 @@ -9509,32 +9726,32 @@ 1 2 -37930 +37920 2 3 -17510 +17451 3 4 -5827 +5698 4 -7 -5571 +8 +6068 -7 -25 -5561 +8 +35 +5571 -25 -72 -1650 +35 +82 +1341 @@ -9560,12 +9777,12 @@ 3 4 -6607 +6605 4 5 -3869 +3870 5 @@ -9580,32 +9797,32 @@ 7 9 -6712 +6711 9 12 -6169 +6159 12 18 -5741 +5659 18 -35 -5704 +39 +5609 -35 -97 -5588 +39 +113 +5569 -97 -337 -1602 +113 +373 +1810 @@ -9631,7 +9848,7 @@ 3 5 -6505 +6504 5 @@ -9651,32 +9868,32 @@ 10 13 -5916 +5915 13 18 -5691 +5686 18 30 -5804 +5717 30 -62 -5589 +68 +5606 -62 -149 +68 +166 5572 -149 -378 -1103 +166 +413 +1180 @@ -9692,57 +9909,57 @@ 1 2 -303 +305 2 3 -101 +103 3 4 -86 +82 4 6 -107 +100 6 10 -93 +98 10 -30 +32 94 -30 -76 -91 +32 +90 +93 -76 -274 -91 +90 +312 +93 -290 -4787 -91 +318 +3282 +93 -4919 -54258 -91 +3320 +47350 +93 -56076 -183228 -59 +48707 +290233 +83 @@ -9758,47 +9975,52 @@ 1 2 -399 +385 2 3 -159 +150 3 4 -101 +79 4 -9 -97 +7 +99 -9 -20 +7 +23 +95 + + +23 +47 94 -20 -55 -91 +47 +204 +93 -55 -650 -91 +212 +1974 +93 -651 -5179 -91 +2010 +11406 +93 -5249 -10698 -84 +11549 +16182 +56 @@ -9814,57 +10036,57 @@ 1 2 -339 +344 2 3 -112 +103 3 4 -78 +73 4 6 -107 +95 6 -13 -98 +11 +102 -13 -32 -91 +11 +37 +95 -32 -93 -92 +37 +110 +94 -93 -691 -91 +110 +456 +93 -729 -5319 -91 +460 +3065 +93 -5513 -13620 -91 +3078 +11825 +93 -13631 -22565 -17 +11842 +22748 +52 @@ -9880,52 +10102,57 @@ 1 2 -334 +333 2 3 -140 +136 3 4 -91 +87 4 -6 -83 +7 +112 -6 -12 -99 +7 +15 +95 -12 -27 -94 +15 +35 +96 -27 -53 -91 +35 +68 +94 -53 -81 -91 +68 +93 +95 -81 -123 +93 +138 93 -123 -169 -91 +138 +177 +94 + + +177 +179 +2 @@ -9941,57 +10168,57 @@ 1 2 -341 +346 2 3 -112 +103 3 4 -76 +71 4 6 -107 +95 6 -13 -98 +11 +103 -13 -32 -91 +11 +37 +94 -32 -92 -91 +37 +110 +94 -92 -665 -91 +110 +450 +93 -686 -5235 -91 +452 +3056 +93 -5316 -13328 -91 +3072 +11597 +93 -13356 -22538 -18 +11609 +22648 +52 @@ -10001,23 +10228,23 @@ numlines -213180 +344316 element_id -213180 +321238 num_lines -1200 +1544 num_code -1005 +1300 num_comment -387 +506 @@ -10031,7 +10258,12 @@ 1 2 -213180 +298186 + + +2 +4 +23052 @@ -10047,7 +10279,12 @@ 1 2 -213180 +298202 + + +2 +4 +23036 @@ -10063,7 +10300,12 @@ 1 2 -213180 +318086 + + +2 +4 +3152 @@ -10079,47 +10321,42 @@ 1 2 -505 +638 2 3 -154 +199 3 4 -92 +118 4 6 -84 +114 6 10 -94 +123 10 20 -90 +121 20 -81 -90 - - -81 -26473 -90 +76 +116 -33985 -33986 -1 +77 +72660 +115 @@ -10135,42 +10372,42 @@ 1 2 -506 +640 2 3 -158 +201 3 4 -91 +117 4 6 -87 +124 6 10 -104 +126 10 18 -101 +124 18 -32 -92 +34 +116 -32 -47 -61 +34 +53 +96 @@ -10186,42 +10423,42 @@ 1 2 -507 +640 2 3 -158 +199 3 4 -90 +117 4 6 -94 +122 6 10 -96 +131 10 -16 -94 +17 +120 -16 -27 -98 +17 +30 +116 -27 -38 -63 +30 +44 +99 @@ -10237,42 +10474,42 @@ 1 2 -407 +523 2 3 -128 +165 3 4 -78 +102 4 6 -81 +114 6 11 -88 +103 11 23 -77 +98 23 -92 -76 +82 +98 -98 -43772 -70 +84 +101108 +97 @@ -10288,42 +10525,42 @@ 1 2 -407 +524 2 3 -130 +169 3 4 -79 +99 4 6 -82 +116 6 -10 -80 +11 +107 -10 -19 -77 +11 +22 +104 -19 -36 -79 +22 +45 +101 -36 -53 -71 +45 +60 +80 @@ -10339,42 +10576,42 @@ 1 2 -409 +526 2 3 -133 +163 3 4 -76 +103 4 6 -85 +118 6 -10 -82 +11 +113 -10 -18 -79 +11 +21 +100 -18 -30 -80 +21 +36 +99 -30 -45 -61 +36 +51 +78 @@ -10390,47 +10627,47 @@ 1 2 -156 +192 2 3 -47 +61 3 4 -31 +45 4 6 -29 +43 6 10 -33 +40 10 -25 -30 +21 +40 -26 -94 -30 +21 +69 +39 -98 -11994 -30 +69 +1913 +38 -166744 -166745 -1 +1919 +255606 +8 @@ -10446,47 +10683,47 @@ 1 2 -156 +193 2 3 -47 +60 3 4 -32 +45 4 6 -30 +43 6 10 -31 +41 10 -24 -30 +21 +39 -24 -74 -30 +21 +57 +38 -74 -231 -30 +58 +227 +38 -365 -366 -1 +227 +375 +9 @@ -10502,42 +10739,47 @@ 1 2 -156 +193 2 3 -47 +60 3 4 -31 +45 4 6 -30 +43 6 10 -32 +40 10 -24 -31 +21 +42 -25 -75 -30 +22 +64 +38 -78 -327 -30 +66 +210 +38 + + +211 +333 +7 @@ -10547,27 +10789,27 @@ assemblies -1870 +2863 id -1870 +2863 file -1870 +2861 fullname -1246 +1321 name -556 +605 version -115 +124 @@ -10581,7 +10823,7 @@ 1 2 -1870 +2863 @@ -10597,7 +10839,7 @@ 1 2 -1870 +2863 @@ -10613,7 +10855,7 @@ 1 2 -1870 +2863 @@ -10629,7 +10871,7 @@ 1 2 -1870 +2863 @@ -10645,7 +10887,12 @@ 1 2 -1870 +2859 + + +2 +3 +2 @@ -10661,7 +10908,12 @@ 1 2 -1870 +2859 + + +2 +3 +2 @@ -10677,7 +10929,7 @@ 1 2 -1870 +2861 @@ -10693,7 +10945,7 @@ 1 2 -1870 +2861 @@ -10709,22 +10961,27 @@ 1 2 -798 +782 2 3 -349 +234 3 -9 -97 +4 +92 -9 -10 -2 +4 +7 +114 + + +7 +13 +99 @@ -10740,22 +10997,27 @@ 1 2 -798 +782 2 3 -349 +234 3 -9 -97 +4 +92 -9 -10 -2 +4 +7 +114 + + +7 +13 +99 @@ -10771,7 +11033,7 @@ 1 2 -1246 +1321 @@ -10787,7 +11049,7 @@ 1 2 -1246 +1321 @@ -10803,42 +11065,47 @@ 1 2 -238 +231 2 3 -85 +70 3 4 -57 +52 4 -5 -49 +6 +55 -5 -7 -38 +6 +9 +53 -7 -8 -42 +9 +11 +43 -8 -14 -44 +11 +13 +39 -26 +13 +15 +56 + + +15 27 -3 +6 @@ -10854,42 +11121,47 @@ 1 2 -238 +231 2 3 -85 +71 3 4 -57 +52 4 -5 -49 +6 +54 -5 -7 -38 +6 +9 +53 -7 -8 -42 +9 +11 +43 -8 -14 -44 +11 +13 +39 -26 +13 +15 +56 + + +15 27 -3 +6 @@ -10905,22 +11177,22 @@ 1 2 -376 +416 2 3 -66 +61 3 4 -37 +48 4 6 -42 +45 13 @@ -10941,22 +11213,22 @@ 1 2 -411 +452 2 3 -66 +61 3 4 -37 +47 4 6 -42 +45 @@ -10972,37 +11244,47 @@ 1 2 -49 +47 2 3 -20 +16 3 4 -11 +9 4 -7 +6 9 -7 +6 +8 +9 + + +8 10 -7 +9 10 -31 +28 10 -33 +28 +103 +10 + + +147 756 -9 +5 @@ -11018,37 +11300,47 @@ 1 2 -49 +47 2 3 -20 +17 3 4 -11 +9 4 -7 +6 +8 + + +6 +8 9 -7 +8 10 -7 +9 10 -31 +28 10 -33 +28 +103 +10 + + +147 756 -9 +5 @@ -11064,7 +11356,7 @@ 1 2 -64 +68 2 @@ -11073,23 +11365,28 @@ 3 -5 +4 9 -5 -8 -9 +4 +7 +10 -8 -23 +7 +20 10 -25 +22 +71 +10 + + +123 586 -8 +2 @@ -11105,32 +11402,37 @@ 1 2 -64 +69 2 3 -15 +14 3 -5 +4 9 -5 -8 -9 +4 +7 +10 -8 -23 +7 +20 10 -25 +22 +71 +10 + + +122 166 -8 +2 @@ -11140,23 +11442,23 @@ files -15550 +24954 id -15550 +24954 name -15550 +24954 simple -12907 +20050 ext -7 +8 fromSource @@ -11174,7 +11476,7 @@ 1 2 -15550 +24954 @@ -11190,7 +11492,7 @@ 1 2 -15550 +24954 @@ -11206,7 +11508,7 @@ 1 2 -15550 +24954 @@ -11222,7 +11524,7 @@ 1 2 -15550 +24954 @@ -11238,7 +11540,7 @@ 1 2 -15550 +24954 @@ -11254,7 +11556,7 @@ 1 2 -15550 +24954 @@ -11270,7 +11572,7 @@ 1 2 -15550 +24954 @@ -11286,7 +11588,7 @@ 1 2 -15550 +24954 @@ -11302,12 +11604,12 @@ 1 2 -12092 +18724 2 -79 -815 +417 +1326 @@ -11323,12 +11625,12 @@ 1 2 -12092 +18724 2 -79 -815 +417 +1326 @@ -11344,12 +11646,12 @@ 1 2 -12862 +19838 2 4 -45 +212 @@ -11365,7 +11667,7 @@ 1 2 -12907 +20050 @@ -11384,6 +11686,11 @@ 1 +2 +3 +1 + + 9 10 1 @@ -11404,13 +11711,13 @@ 1 -1853 -1854 +2842 +2843 1 -13460 -13461 +21873 +21874 1 @@ -11430,6 +11737,11 @@ 1 +2 +3 +1 + + 9 10 1 @@ -11450,13 +11762,13 @@ 1 -1853 -1854 +2842 +2843 1 -13460 -13461 +21873 +21874 1 @@ -11473,7 +11785,7 @@ 1 2 -1 +2 7 @@ -11496,13 +11808,13 @@ 1 -549 -550 +597 +598 1 -12271 -12272 +19532 +19533 1 @@ -11519,7 +11831,7 @@ 1 2 -7 +8 @@ -11533,8 +11845,8 @@ 12 -15550 -15551 +24954 +24955 1 @@ -11549,8 +11861,8 @@ 12 -15550 -15551 +24954 +24955 1 @@ -11565,8 +11877,8 @@ 12 -12907 -12908 +20050 +20051 1 @@ -11581,8 +11893,8 @@ 12 -7 -8 +8 +9 1 @@ -11593,19 +11905,19 @@ folders -4611 +7016 id -4611 +7016 name -4528 +6927 simple -1557 +1989 @@ -11619,7 +11931,7 @@ 1 2 -4611 +7016 @@ -11635,7 +11947,7 @@ 1 2 -4611 +7016 @@ -11651,12 +11963,12 @@ 1 2 -4445 +6838 2 3 -83 +89 @@ -11672,7 +11984,7 @@ 1 2 -4528 +6927 @@ -11688,27 +12000,27 @@ 1 2 -929 +1079 2 3 -312 +347 3 4 -146 +258 4 -9 -122 +6 +170 -9 -243 -48 +6 +352 +135 @@ -11724,27 +12036,27 @@ 1 2 -964 +1114 2 3 -300 +334 3 4 -138 +252 4 -12 -118 +6 +156 -12 -243 -37 +6 +352 +133 @@ -11754,15 +12066,15 @@ containerparent -20158 +31967 parent -4611 +7016 child -20158 +31967 @@ -11776,32 +12088,32 @@ 1 2 -2359 +3597 2 3 -965 +1293 3 4 -276 +556 4 -7 -385 +6 +568 -7 -15 -347 +6 +14 +536 -15 -226 -279 +14 +229 +466 @@ -11817,7 +12129,7 @@ 1 2 -20158 +31967 @@ -11827,11 +12139,11 @@ file_extraction_mode -15330 +24734 file -15330 +24734 mode @@ -11849,7 +12161,7 @@ 1 2 -15330 +24734 @@ -11868,8 +12180,8 @@ 1 -11522 -11523 +20926 +20927 1 @@ -11880,15 +12192,15 @@ namespaces -5457 +6505 id -5457 +6505 name -1491 +1717 @@ -11902,7 +12214,7 @@ 1 2 -5457 +6505 @@ -11918,37 +12230,37 @@ 1 2 -414 +407 2 3 -564 +730 3 4 -102 +103 4 -6 +5 132 -6 -8 -127 +5 +7 +86 -8 -17 -116 +7 +10 +137 -17 -66 -36 +10 +69 +122 @@ -11958,15 +12270,15 @@ namespace_declarations -14700 +22696 id -14700 +22696 namespace_id -1549 +1922 @@ -11980,7 +12292,7 @@ 1 2 -14700 +22696 @@ -11996,47 +12308,47 @@ 1 2 -481 +638 2 3 -281 +295 3 4 -130 +144 4 5 -91 +105 5 7 -136 +148 7 10 -125 +147 10 -16 -118 +17 +157 -16 -38 -118 +17 +35 +147 -38 +35 646 -69 +141 @@ -12046,15 +12358,15 @@ namespace_declaration_location -14700 +22696 id -14700 +22696 loc -12601 +19757 @@ -12068,7 +12380,7 @@ 1 2 -14700 +22696 @@ -12084,17 +12396,17 @@ 1 2 -10914 +17726 2 3 -1412 +1611 3 -11 -275 +128 +420 @@ -12104,15 +12416,15 @@ parent_namespace -454645 +360683 child_id -454645 +360683 namespace_id -3755 +4420 @@ -12126,7 +12438,7 @@ 1 2 -454645 +360683 @@ -12142,52 +12454,52 @@ 1 2 -1052 +1289 2 3 -443 +494 3 4 -265 +306 4 5 -201 +217 5 7 -326 +382 7 11 -343 +402 11 -18 -298 +17 +338 -18 -33 -300 +17 +30 +338 -33 -87 -283 +30 +66 +335 -87 -144013 -244 +66 +108885 +319 @@ -12197,15 +12509,15 @@ parent_namespace_declaration -17614 +34436 child_id -14102 +24003 namespace_id -14694 +22688 @@ -12219,17 +12531,22 @@ 1 2 -12053 +17774 2 3 -1555 +4375 3 -143 -494 +11 +1807 + + +11 +259 +47 @@ -12245,12 +12562,17 @@ 1 2 -13937 +20681 2 +10 +1727 + + +10 299 -757 +280 @@ -12260,15 +12582,15 @@ using_namespace_directives -85929 +106992 id -85929 +106992 namespace_id -1294 +1422 @@ -12282,7 +12604,7 @@ 1 2 -85929 +106992 @@ -12298,52 +12620,52 @@ 1 2 -322 +341 2 3 -193 +202 3 4 -109 +112 4 6 -112 +131 6 9 -98 +112 9 15 -110 +117 15 -29 -103 +28 +111 -29 -71 -99 +28 +55 +107 -71 -265 -98 +55 +180 +107 -266 -8577 -50 +180 +10946 +82 @@ -12353,15 +12675,15 @@ using_static_directives -253 +321 id -253 +321 type_id -74 +75 @@ -12375,7 +12697,7 @@ 1 2 -253 +321 @@ -12396,32 +12718,37 @@ 2 3 -28 +21 3 4 -7 +10 4 5 -8 +6 5 -7 -5 +8 +6 8 -12 -5 +11 +6 -12 -16 -4 +11 +15 +6 + + +15 +19 +3 @@ -12431,15 +12758,15 @@ using_directive_location -86182 +107313 id -86182 +107313 loc -73015 +91983 @@ -12453,7 +12780,7 @@ 1 2 -86182 +107313 @@ -12469,17 +12796,17 @@ 1 2 -61748 +79730 2 3 -9952 +10544 3 -12 -1315 +128 +1709 @@ -12489,19 +12816,19 @@ types -507522 +413820 id -507522 +413820 kind -28 +27 name -146855 +180164 @@ -12515,7 +12842,7 @@ 1 2 -507522 +413820 @@ -12531,7 +12858,7 @@ 1 2 -507522 +413820 @@ -12547,31 +12874,31 @@ 1 2 -18 +17 -272 -2028 +383 +1383 2 -2476 -7952 +1768 +7962 2 -8356 -37595 +8073 +31633 2 -49262 -80546 +40645 +58091 2 -142002 -176860 +126692 +137174 2 @@ -12588,31 +12915,31 @@ 1 2 -18 +17 -194 -562 +317 +580 2 -931 -995 +1014 +1043 2 -2768 -5106 +3386 +6731 2 -12169 -19871 +14006 +23824 2 -46794 -59834 +62903 +69095 2 @@ -12629,27 +12956,17 @@ 1 2 -99207 +158707 2 -3 -22271 - - -3 4 -10613 +15195 4 -8 -11224 - - -8 -10421 -3540 +8751 +6262 @@ -12665,12 +12982,12 @@ 1 2 -144518 +177472 2 5 -2337 +2692 @@ -12680,15 +12997,15 @@ typerefs -427553 +349451 id -427553 +349451 name -64947 +79294 @@ -12702,7 +13019,7 @@ 1 2 -427553 +349451 @@ -12718,22 +13035,17 @@ 1 2 -47720 +69433 2 3 -8138 +5934 3 -5 -5295 - - -5 -36269 -3794 +26887 +3927 @@ -12743,15 +13055,15 @@ typeref_type -415976 +343625 id -415976 +343625 typeId -415976 +343625 @@ -12765,7 +13077,7 @@ 1 2 -415976 +343625 @@ -12781,7 +13093,7 @@ 1 2 -415976 +343625 @@ -12791,11 +13103,11 @@ array_element_type -7951 +7961 array -7951 +7961 dimension @@ -12807,7 +13119,7 @@ element -7930 +7932 @@ -12821,7 +13133,7 @@ 1 2 -7951 +7961 @@ -12837,7 +13149,7 @@ 1 2 -7951 +7961 @@ -12853,7 +13165,7 @@ 1 2 -7951 +7961 @@ -12867,18 +13179,18 @@ 12 -1 -2 +2 +3 1 -28 -29 +49 +50 1 -7922 -7923 +7910 +7911 1 @@ -12919,18 +13231,18 @@ 12 -1 -2 +2 +3 1 -27 -28 +48 +49 1 -7902 -7903 +7882 +7883 1 @@ -12950,18 +13262,18 @@ 1 -6 -7 +10 +11 1 -22 -23 +24 +25 1 -7922 -7923 +7926 +7927 1 @@ -13007,18 +13319,18 @@ 1 -6 -7 +10 +11 1 -22 -23 +24 +25 1 -7922 -7923 +7926 +7927 1 @@ -13035,12 +13347,12 @@ 1 2 -7913 +7908 2 5 -17 +24 @@ -13056,7 +13368,7 @@ 1 2 -7930 +7932 @@ -13072,12 +13384,12 @@ 1 2 -7913 +7908 2 5 -17 +24 @@ -13087,15 +13399,15 @@ nullable_underlying_type -2027 +1382 nullable -2027 +1382 underlying -1490 +1382 @@ -13109,7 +13421,7 @@ 1 2 -2027 +1382 @@ -13125,22 +13437,7 @@ 1 2 -1132 - - -2 -3 -205 - - -3 -4 -138 - - -4 -7 -15 +1382 @@ -13150,15 +13447,15 @@ pointer_referent_type -272 +383 pointer -272 +383 referent -272 +383 @@ -13172,7 +13469,7 @@ 1 2 -272 +383 @@ -13188,7 +13485,7 @@ 1 2 -272 +383 @@ -13198,11 +13495,11 @@ enum_underlying_type -8356 +8079 enum_id -8356 +8079 underlying_type_id @@ -13220,7 +13517,7 @@ 1 2 -8356 +8079 @@ -13234,13 +13531,13 @@ 12 -6 -7 +5 +6 1 -8 -9 +6 +7 1 @@ -13249,28 +13546,28 @@ 1 -82 -83 +41 +42 1 -111 -112 +82 +83 1 -274 -275 +289 +290 1 -404 -405 +392 +393 1 -7455 -7456 +7248 +7249 1 @@ -13281,15 +13578,15 @@ delegate_return_type -49285 +40602 delegate_id -49285 +40602 return_type_id -21520 +17705 @@ -13303,7 +13600,7 @@ 1 2 -49285 +40602 @@ -13319,17 +13616,17 @@ 1 2 -19160 +16003 2 4 -1772 +1360 4 -7319 -588 +7208 +342 @@ -13339,15 +13636,15 @@ extend -507096 +206708 sub -507096 +206708 super -12966 +10856 @@ -13361,7 +13658,7 @@ 1 2 -507096 +206708 @@ -13377,32 +13674,32 @@ 1 2 -7018 +6157 2 3 -2596 +2069 3 4 -1035 +789 4 6 -1105 +902 6 -24 -974 +34 +815 -24 -176860 -238 +34 +52181 +124 @@ -13412,15 +13709,15 @@ implement -681583 +501419 sub -206287 +165927 super -152713 +111188 @@ -13434,32 +13731,37 @@ 1 2 -51447 +46744 2 3 -62642 +48255 3 4 -47212 +35908 4 -6 -18296 +5 +9804 -6 -11 -16904 +5 +8 +10322 -11 -44 -9786 +8 +14 +14877 + + +14 +31 +17 @@ -13475,32 +13777,32 @@ 1 2 -67731 +52605 2 3 -41030 +27664 3 4 -18277 +11959 4 6 -11342 +9609 6 -8 -11679 +10 +8459 -8 -151421 -2654 +10 +113783 +892 @@ -13510,15 +13812,15 @@ type_location -333640 +445714 id -215765 +185891 loc -26226 +52345 @@ -13532,27 +13834,27 @@ 1 2 -148580 +99018 2 3 -38656 +41333 3 4 -10826 +18115 4 -5 -16223 +7 +16473 -5 -104 -1480 +7 +717 +10952 @@ -13568,17 +13870,12 @@ 1 2 -24077 +49945 2 -252 -1968 - - -257 17019 -181 +2400 @@ -13588,15 +13885,15 @@ tuple_underlying_type -2894 +1768 tuple -2894 +1768 struct -1559 +699 @@ -13610,7 +13907,7 @@ 1 2 -2894 +1768 @@ -13626,22 +13923,27 @@ 1 2 -860 +228 2 3 -447 +259 3 4 -143 +123 4 -101 -109 +6 +64 + + +6 +153 +25 @@ -13651,11 +13953,11 @@ tuple_element -9220 +4528 tuple -2476 +1768 index @@ -13663,7 +13965,7 @@ field -9220 +4528 @@ -13677,32 +13979,27 @@ 1 2 -58 +10 2 3 -1593 +1395 3 4 -265 +221 4 -7 -226 - - -7 -13 -191 +18 +134 -13 +18 22 -143 +8 @@ -13718,32 +14015,27 @@ 1 2 -58 +10 2 3 -1593 +1395 3 4 -265 +221 4 -7 -226 - - -7 -13 -191 +18 +134 -13 +18 22 -143 +8 @@ -13757,108 +14049,108 @@ 12 -13 -14 +2 +3 1 -26 -27 +4 +5 1 -39 -40 +6 +7 1 -52 -53 +8 +9 1 -65 -66 +10 +11 1 -78 -79 +12 +13 1 -91 -92 +14 +15 1 -117 -118 +18 +19 1 -143 -144 +22 +23 1 -169 -170 +26 +27 1 -197 -198 +32 +33 1 -223 -224 +36 +37 1 -249 -250 +40 +41 1 -283 -284 +47 +48 1 -334 -335 +55 +56 1 -387 -388 +65 +66 1 -475 -476 +100 +101 1 -560 -561 +142 +143 1 -825 -826 +363 +364 1 -2418 -2419 +1758 +1759 1 -2476 -2477 +1768 +1769 1 @@ -13873,108 +14165,108 @@ 12 -13 -14 +2 +3 1 -26 -27 +4 +5 1 -39 -40 +6 +7 1 -52 -53 +8 +9 1 -65 -66 +10 +11 1 -78 -79 +12 +13 1 -91 -92 +14 +15 1 -117 -118 +18 +19 1 -143 -144 +22 +23 1 -169 -170 +26 +27 1 -197 -198 +32 +33 1 -223 -224 +36 +37 1 -249 -250 +40 +41 1 -283 -284 +47 +48 1 -334 -335 +55 +56 1 -387 -388 +65 +66 1 -475 -476 +100 +101 1 -560 -561 +142 +143 1 -825 -826 +363 +364 1 -2418 -2419 +1758 +1759 1 -2476 -2477 +1768 +1769 1 @@ -13991,7 +14283,7 @@ 1 2 -9220 +4528 @@ -14007,7 +14299,7 @@ 1 2 -9220 +4528 @@ -14017,19 +14309,19 @@ attributes -120784 +152979 id -120784 +152979 type_id -559 +468 target -67938 +78814 @@ -14043,7 +14335,7 @@ 1 2 -120784 +152979 @@ -14059,7 +14351,7 @@ 1 2 -120784 +152979 @@ -14075,62 +14367,62 @@ 1 2 -90 +71 2 3 -67 +52 3 4 -30 +28 4 6 -48 +42 6 -10 -50 +9 +36 -10 -15 -46 +9 +14 +36 -15 -21 -44 +14 +23 +36 -21 -40 -43 +23 +45 +36 -40 -67 -42 +45 +81 +37 -67 -114 -42 +86 +205 +37 -114 -488 -42 +217 +1059 +39 -509 +1079 49629 -15 +18 @@ -14146,62 +14438,57 @@ 1 2 -111 +93 2 3 -66 +51 3 4 -30 +32 4 6 -40 +35 6 9 -43 +39 9 -14 -42 - - -14 -20 -44 +16 +38 -20 -31 -42 +16 +28 +36 -31 -59 -42 +28 +56 +36 -59 -101 -42 +56 +121 +36 -103 -343 -42 +124 +417 +38 -365 -49629 -15 +421 +49626 +34 @@ -14217,22 +14504,22 @@ 1 2 -33353 +40545 2 3 -25919 +28536 3 4 -6776 +7103 4 -853 -1890 +2518 +2630 @@ -14248,22 +14535,22 @@ 1 2 -33726 +42542 2 3 -26581 +28029 3 4 -6618 +6770 4 -14 -1013 +16 +1473 @@ -14273,15 +14560,15 @@ attribute_location -231497 +295887 id -120784 +152979 loc -119045 +150274 @@ -14300,7 +14587,7 @@ 2 3 -110713 +142908 @@ -14316,12 +14603,12 @@ 1 2 -117698 +147783 2 33350 -1347 +2491 @@ -14331,19 +14618,19 @@ type_mention -1477122 +2269573 id -1477122 +2269573 type_id -40955 +62260 parent -1403992 +2098317 @@ -14357,7 +14644,7 @@ 1 2 -1477122 +2269573 @@ -14373,7 +14660,7 @@ 1 2 -1477122 +2269573 @@ -14389,47 +14676,47 @@ 1 2 -11444 +16389 2 3 -8616 +12921 3 4 -3498 +5673 4 5 -3051 +4952 5 7 -3038 +4946 7 -12 -3491 +11 +4873 -12 -24 -3193 +11 +21 +4739 -24 -80 -3077 +21 +62 +4682 -80 -112680 -1547 +62 +170762 +3085 @@ -14445,47 +14732,47 @@ 1 2 -12381 +19486 2 3 -8459 +12123 3 4 -3612 +5422 4 5 -2990 +4489 5 7 -2899 +4628 7 12 -3354 +5228 12 25 -3238 +4788 25 -125 -3073 +127 +4672 -125 -109603 -949 +127 +157226 +1424 @@ -14501,12 +14788,12 @@ 1 2 -1372976 +1990082 2 953 -31016 +108235 @@ -14522,12 +14809,12 @@ 1 2 -1384839 +2068929 2 29 -19153 +29388 @@ -14537,15 +14824,15 @@ type_mention_location -1477122 +2269573 id -1477122 +2269573 loc -1361596 +2163726 @@ -14559,7 +14846,7 @@ 1 2 -1477122 +2269573 @@ -14575,12 +14862,12 @@ 1 2 -1316306 +2129500 2 -198 -45290 +227 +34226 @@ -14590,15 +14877,15 @@ type_annotation -60856 +45915 id -60732 +45915 annotation -5 +3 @@ -14612,12 +14899,7 @@ 1 2 -60608 - - -2 -3 -124 +45915 @@ -14631,28 +14913,76 @@ 12 -105 -106 +1956 +1957 1 -1664 -1665 +13501 +13502 1 -13118 -13119 +30458 +30459 1 + + + + + + + +nullability +116 + + +nullability +116 + + +kind +3 + + + + +nullability +kind + + +12 + -14761 -14762 +1 +2 +116 + + + + + + +kind +nullability + + +12 + + +11 +12 1 -31208 -31209 +47 +48 +1 + + +58 +59 1 @@ -14662,26 +14992,26 @@ -type_argument_annotation -374019 +nullability_member +381 -constructedgeneric -279883 +nullability +113 -position -21 +index +17 -annotation -2 +child +25 -constructedgeneric -position +nullability +index 12 @@ -14689,25 +15019,45 @@ 1 2 -217898 +34 2 3 -50067 +33 3 -22 -11918 +4 +14 + + +4 +5 +10 + + +5 +8 +10 + + +8 +15 +9 + + +15 +18 +3 -constructedgeneric -annotation +nullability +child 12 @@ -14715,121 +15065,213 @@ 1 2 -279477 +50 2 3 -406 +54 + + +3 +4 +9 -position -constructedgeneric +index +nullability 12 +1 +2 +1 + + +2 +3 +1 + + +3 +4 +1 + + +4 +5 +1 + + 5 6 -4 +1 -95 -96 +6 +7 1 -234 -235 +7 +8 1 -373 -374 +8 +9 1 -512 -513 +9 +10 1 -651 -652 +12 +13 1 -791 -792 +14 +15 1 -932 -933 +18 +19 1 -1077 -1078 +22 +23 1 -1222 -1223 +32 +33 1 -2100 -2101 +46 +47 1 -2364 -2365 +79 +80 1 -2679 -2680 +113 +114 1 + + + + + +index +child + + +12 + -3197 -3198 +1 +2 1 -3986 -3987 +2 +3 +9 + + +3 +4 +2 + + +4 +5 1 -11918 -11919 +5 +6 +2 + + +9 +10 1 -62003 -62004 +25 +26 1 + + + + + +child +nullability + + +12 + + +1 +2 +14 + -279865 -279866 +3 +4 1 + +4 +5 +2 + + +5 +6 +2 + + +6 +7 +2 + + +23 +27 +2 + + +28 +62 +2 + -position -annotation +child +index 12 @@ -14837,54 +15279,135 @@ 1 2 -4 +16 2 3 -17 +3 + + +3 +4 +2 + + +5 +8 +2 + + +16 +18 +2 + + + +type_nullability +243176 + + +id +239388 + + +nullability +107 + + + -annotation -constructedgeneric +id +nullability 12 -939 -940 -1 +1 +2 +235606 -279350 -279351 -1 +2 +4 +3782 -annotation -position +nullability +id 12 -17 -18 -1 +1 +2 +23 -21 -22 -1 +2 +3 +7 + + +3 +4 +4 + + +4 +6 +9 + + +6 +7 +9 + + +7 +10 +5 + + +10 +15 +9 + + +19 +31 +9 + + +40 +106 +9 + + +119 +481 +9 + + +540 +3383 +9 + + +14434 +154277 +5 @@ -14894,33 +15417,33 @@ is_generic -71108 +60403 id -71108 +60403 is_constructed -301218 +237565 id -301218 +237565 type_parameters -80382 +58092 id -80382 +58092 index @@ -14928,7 +15451,7 @@ generic_id -48687 +37990 variance @@ -14946,7 +15469,7 @@ 1 2 -80382 +58092 @@ -14962,7 +15485,7 @@ 1 2 -80382 +58092 @@ -14978,7 +15501,7 @@ 1 2 -80382 +58092 @@ -14992,48 +15515,48 @@ 12 -4 -5 +1 +2 16 -6 -9 +2 +4 3 -31 -76 +7 +15 3 -99 -315 +18 +150 3 -498 -865 +270 +511 3 -1049 -1425 +632 +887 3 -1613 -2054 +1013 +1291 3 -2301 -2958 +1461 +1881 3 -3671 -48681 +2310 +37991 3 @@ -15048,48 +15571,48 @@ 12 -4 -5 +1 +2 16 -6 -9 +2 +4 3 -31 -76 +7 +15 3 -99 -315 +18 +150 3 -498 -865 +270 +511 3 -1049 -1425 +632 +887 3 -1613 -2054 +1013 +1291 3 -2301 -2958 +1461 +1881 3 -3671 -48688 +2310 +37991 3 @@ -15132,22 +15655,17 @@ 1 2 -40503 +32308 2 3 -4513 +3372 3 -22 -3663 - - -23 41 -8 +2310 @@ -15163,22 +15681,17 @@ 1 2 -40503 +32308 2 3 -4513 +3372 3 -22 -3663 - - -23 41 -8 +2310 @@ -15194,12 +15707,12 @@ 1 2 -48578 +37946 2 3 -109 +44 @@ -15213,18 +15726,18 @@ 12 -161 -162 +63 +64 1 -1243 -1244 +312 +313 1 -78971 -78972 +57717 +57718 1 @@ -15265,18 +15778,18 @@ 12 -160 -161 +61 +62 1 -226 -227 +71 +72 1 -48410 -48411 +37902 +37903 1 @@ -15287,11 +15800,11 @@ type_arguments -399681 +312757 id -109145 +87949 index @@ -15299,7 +15812,7 @@ constructed_id -301218 +237565 @@ -15313,17 +15826,17 @@ 1 2 -86914 +68801 2 3 -21432 +18339 3 18 -799 +809 @@ -15339,32 +15852,37 @@ 1 2 -52585 +44933 2 3 -24128 +16977 3 -4 -7419 +5 +7885 -4 +5 7 -9307 +4344 7 -10 -8716 +8 +6689 -10 -8571 -6990 +8 +28 +6603 + + +28 +7377 +518 @@ -15378,93 +15896,93 @@ 12 -5 -6 +2 +3 4 -38 -39 +32 +33 1 -176 -177 +146 +147 1 -314 -315 +259 +260 1 -452 -453 +372 +373 1 -590 -591 +485 +486 1 -729 -730 +600 +601 1 -868 -869 +716 +717 1 -1013 -1014 +836 +837 1 -1156 -1157 +953 +954 1 -1951 -1952 +1185 +1186 1 -2028 -2029 +1279 +1280 1 -2192 -2193 +1436 +1437 1 -2499 -2500 +1645 +1646 1 -2952 -2953 +1998 +1999 1 -9725 -9726 +7659 +7660 1 -25413 -25414 +21869 +21870 1 -80771 -80772 +67117 +67118 1 @@ -15479,93 +15997,93 @@ 12 -5 -6 +2 +3 4 -95 -96 +77 +78 1 -234 -235 +192 +193 1 -373 -374 +307 +308 1 -512 -513 +422 +423 1 -651 -652 +537 +538 1 -791 -792 +654 +655 1 -932 -933 +773 +774 1 -1077 -1078 +894 +895 1 -1222 -1223 +1014 +1015 1 -2100 -2101 +1253 +1254 1 -2364 -2365 +1404 +1405 1 -2683 -2684 +1616 +1617 1 -3208 -3209 +1958 +1959 1 -4032 -4033 +2634 +2635 1 -12237 -12238 +9388 +9389 1 -65932 -65933 +52061 +52062 1 -301218 -301219 +237565 +237566 1 @@ -15582,17 +16100,17 @@ 1 2 -236948 +186726 2 3 -53158 +42264 3 22 -11112 +8575 @@ -15608,17 +16126,17 @@ 1 2 -235286 +185504 2 3 -53695 +42673 3 22 -12237 +9388 @@ -15628,15 +16146,15 @@ constructed_generic -301218 +237565 constructed -301218 +237565 generic -5869 +5449 @@ -15650,7 +16168,7 @@ 1 2 -301218 +237565 @@ -15666,42 +16184,37 @@ 1 2 -2045 +2207 2 3 -1117 +1075 3 4 -526 +506 4 -5 -360 - - -5 -8 -460 +6 +479 -8 -15 -483 +6 +11 +442 -15 -46 -451 +11 +33 +409 -46 -31135 -427 +33 +21877 +331 @@ -15711,15 +16224,15 @@ type_parameter_constraints -330908 +389563 id -330908 +389563 param_id -80545 +58090 @@ -15733,7 +16246,7 @@ 1 2 -330908 +389563 @@ -15749,27 +16262,32 @@ 1 2 -55069 +32353 2 3 -12393 +9062 3 -5 -6822 +4 +5333 -5 -167 -6041 +4 +7 +4581 -171 -7522 -220 +7 +17 +4653 + + +17 +10899 +2108 @@ -15815,15 +16333,15 @@ general_type_parameter_constraints -46646 +49753 id -46610 +49483 kind -4 +5 @@ -15837,12 +16355,12 @@ 1 2 -46574 +49213 2 3 -36 +270 @@ -15856,23 +16374,28 @@ 12 -2 -3 +60 +61 1 -318 -319 +176 +177 +1 + + +372 +373 1 -3083 -3084 +4647 +4648 1 -43243 -43244 +44498 +44499 1 @@ -15883,15 +16406,15 @@ specific_type_parameter_constraints -39729 +41475 id -39242 +40987 base_id -2954 +2496 @@ -15905,12 +16428,12 @@ 1 2 -38792 +40536 2 5 -450 +451 @@ -15926,42 +16449,47 @@ 1 2 -1312 +951 2 3 -349 +329 3 4 -270 +224 4 -5 -223 +6 +231 -5 +6 8 -223 +172 8 -14 -237 +12 +204 -14 -38 -223 +12 +25 +191 -38 -5247 -117 +25 +671 +188 + + +947 +6057 +6 @@ -15970,20 +16498,20 @@ -specific_type_parameter_annotation -6 +specific_type_parameter_nullability +305 id -6 +305 base_id -3 +24 -annotation -1 +nullability +5 @@ -15997,7 +16525,7 @@ 1 2 -6 +305 @@ -16005,7 +16533,7 @@ id -annotation +nullability 12 @@ -16013,7 +16541,7 @@ 1 2 -6 +305 @@ -16029,20 +16557,55 @@ 1 2 +1 + + +2 +3 +7 + + +3 +4 2 4 5 +2 + + +5 +6 +5 + + +6 +8 +2 + + +8 +9 1 + +34 +35 +2 + + +60 +103 +2 + base_id -annotation +nullability 12 @@ -16050,6 +16613,11 @@ 1 2 +21 + + +2 +3 3 @@ -16057,31 +16625,61 @@ -annotation +nullability id 12 +2 +3 +1 + + +4 +5 +1 + + +5 +6 +1 + + 6 7 1 + +288 +289 +1 + -annotation +nullability base_id 12 -3 -4 +1 +2 +2 + + +2 +3 +2 + + +21 +22 1 @@ -16140,11 +16738,11 @@ has_modifiers -3869176 +3644548 id -2587027 +2423233 mod_id @@ -16162,17 +16760,17 @@ 1 2 -1372230 +1294970 2 3 -1147995 +1036528 3 -5 -66802 +6 +91735 @@ -16186,93 +16784,93 @@ 12 -71 -72 +474 +475 1 -150 -151 +595 +596 1 -453 -454 +858 +859 1 -568 -569 +1986 +1987 1 -1224 -1225 +3632 +3633 1 -3007 -3008 +9430 +9431 1 -21791 -21792 +22226 +22227 1 -40903 -40904 +29654 +29655 1 -52292 -52293 +53969 +53970 1 -85916 -85917 +70891 +70892 1 -122762 -122763 +106769 +106770 1 -166812 -166813 +143771 +143772 1 -168050 -168051 +147924 +147925 1 -201700 -201701 +199833 +199834 1 -226436 -226437 +247611 +247612 1 -342644 -342645 +373610 +373611 1 -435003 -435004 +443150 +443151 1 -1999394 -1999395 +1788165 +1788166 1 @@ -16283,26 +16881,26 @@ compiler_generated -54510 +78129 id -54510 +78129 exprorstmt_name -201 +1656 parent_id -201 +1656 name -44 +221 @@ -16316,7 +16914,7 @@ 1 2 -201 +1656 @@ -16337,31 +16935,41 @@ 2 3 -18 +75 3 4 -4 +36 4 +5 +31 + + +5 6 -4 +14 6 -7 -3 +8 +18 8 13 -4 +19 -14 -38 +13 +85 +17 + + +111 +176 3 @@ -16372,19 +16980,19 @@ nested_types -57997 +57581 id -57997 +57581 declaring_type_id -21939 +18925 unbound_id -37006 +36015 @@ -16398,7 +17006,7 @@ 1 2 -57997 +57581 @@ -16414,7 +17022,7 @@ 1 2 -57997 +57581 @@ -16430,27 +17038,32 @@ 1 2 -11856 +9127 2 3 -3440 +2917 3 4 -3479 +3625 4 -7 -1715 +6 +1378 -7 +6 +14 +1452 + + +14 592 -1449 +426 @@ -16466,27 +17079,32 @@ 1 2 -11883 +9216 2 3 -3455 +2893 3 4 -3471 +3605 4 -7 -1744 +6 +1380 -7 +6 +14 +1427 + + +14 592 -1386 +404 @@ -16502,12 +17120,12 @@ 1 2 -35043 +34018 2 -1139 -1963 +1347 +1997 @@ -16523,12 +17141,12 @@ 1 2 -35366 +34383 2 -1139 -1640 +1347 +1632 @@ -16538,27 +17156,27 @@ properties -277986 +268986 id -277986 +268986 name -43605 +58896 declaring_type_id -67202 +66590 type_id -29120 +27500 unbound_id -184077 +174793 @@ -16572,7 +17190,7 @@ 1 2 -277986 +268986 @@ -16588,7 +17206,7 @@ 1 2 -277986 +268986 @@ -16604,7 +17222,7 @@ 1 2 -277986 +268986 @@ -16620,7 +17238,7 @@ 1 2 -277986 +268986 @@ -16636,32 +17254,27 @@ 1 2 -27030 +37823 2 3 -6251 +11142 3 -4 -2804 - - -4 -7 -3533 +5 +4879 -7 -35 -3296 +5 +31 +4418 -35 -21502 -691 +31 +20332 +634 @@ -16677,32 +17290,27 @@ 1 2 -27030 +37823 2 3 -6279 +11174 3 -4 -2819 - - -4 -7 -3498 +5 +4870 -7 -35 -3295 +5 +32 +4435 -35 -18336 -684 +32 +18333 +594 @@ -16718,22 +17326,17 @@ 1 2 -36738 +53616 2 -3 -2855 - - -3 -8 -3321 +6 +4499 -8 -3061 -691 +6 +3187 +781 @@ -16749,32 +17352,27 @@ 1 2 -27278 +38193 2 3 -6314 +11213 3 -4 -2818 - - -4 -7 -3458 +5 +4821 -7 -44 -3282 +5 +55 +4419 -44 -5880 -455 +55 +5009 +250 @@ -16790,42 +17388,37 @@ 1 2 -21589 +21446 2 3 -20521 +21133 3 4 -6501 +5984 4 5 -4298 +4091 5 7 -4082 +3967 7 12 -5068 +5094 12 -59 -5045 - - -59 -3766 -98 +6356 +4875 @@ -16841,37 +17434,37 @@ 1 2 -24075 +23866 2 3 -18654 +18876 3 4 -5987 +5924 4 5 -4254 +4042 5 7 -5482 +5519 7 11 -5654 +5515 11 -3766 -3096 +6356 +2848 @@ -16887,32 +17480,32 @@ 1 2 -24811 +25457 2 3 -22293 +22110 3 4 -7975 +7831 4 5 -4735 +4467 5 -11 -5410 +12 +6097 -11 -54 -1978 +12 +51 +628 @@ -16928,42 +17521,37 @@ 1 2 -21589 +21446 2 3 -20521 +21133 3 4 -6501 +5984 4 5 -4298 +4091 5 7 -4082 +3967 7 12 -5068 +5094 12 -59 -5045 - - -59 -3766 -98 +6356 +4875 @@ -16979,32 +17567,27 @@ 1 2 -16756 +15184 2 3 -5933 +6965 3 4 -1876 +1444 4 7 -2274 +2106 7 -148 -2184 - - -148 -62273 -97 +55172 +1801 @@ -17020,22 +17603,17 @@ 1 2 -23964 +23189 2 3 -2857 +2495 3 -33 -2184 - - -33 -11367 -115 +19160 +1816 @@ -17051,27 +17629,27 @@ 1 2 -17446 +15664 2 3 -5749 +6934 3 4 -1941 +1415 4 8 -2243 +2095 8 -25633 -1741 +25360 +1392 @@ -17087,27 +17665,27 @@ 1 2 -16893 +15350 2 3 -6155 +7099 3 4 -2003 +1492 4 8 -2323 +2176 8 -32140 -1746 +37193 +1383 @@ -17123,12 +17701,12 @@ 1 2 -180296 +172012 2 -5587 -3781 +5604 +2781 @@ -17144,7 +17722,7 @@ 1 2 -184077 +174793 @@ -17160,12 +17738,12 @@ 1 2 -180296 +172012 2 -5587 -3781 +5604 +2781 @@ -17181,12 +17759,12 @@ 1 2 -180871 +173873 2 -1130 -3206 +1060 +920 @@ -17196,15 +17774,15 @@ property_location -412445 +621543 id -274983 +268771 loc -32996 +73027 @@ -17218,27 +17796,32 @@ 1 2 -199797 +137047 2 3 -39513 +73922 3 4 -10699 +19805 4 -5 -24258 +6 +13360 -5 -28 -716 +6 +15 +20275 + + +15 +257 +4362 @@ -17254,12 +17837,12 @@ 1 2 -31248 +70153 2 -29600 -1748 +29742 +2874 @@ -17269,11 +17852,11 @@ indexers -23786 +25314 id -23786 +25314 name @@ -17281,15 +17864,15 @@ declaring_type_id -17060 +18446 type_id -4609 +5634 unbound_id -2432 +2521 @@ -17303,7 +17886,7 @@ 1 2 -23786 +25314 @@ -17319,7 +17902,7 @@ 1 2 -23786 +25314 @@ -17335,7 +17918,7 @@ 1 2 -23786 +25314 @@ -17351,7 +17934,7 @@ 1 2 -23786 +25314 @@ -17372,21 +17955,16 @@ 2 3 -1 - - -7 -8 -1 +2 -14 -15 +6 +7 1 -23758 -23759 +25301 +25302 1 @@ -17408,21 +17986,16 @@ 2 3 -1 - - -7 -8 -1 +2 -8 -9 +4 +5 1 -17043 -17044 +18438 +18439 1 @@ -17442,13 +18015,13 @@ 5 -8 -9 +4 +5 1 -4599 -4600 +5631 +5632 1 @@ -17470,21 +18043,16 @@ 2 3 -1 - - -7 -8 -1 +2 -14 -15 +6 +7 1 -2406 -2407 +2508 +2509 1 @@ -17501,22 +18069,22 @@ 1 2 -12885 +14068 2 3 -2695 +2930 3 5 -1477 +1421 -6 +5 7 -3 +27 @@ -17532,7 +18100,7 @@ 1 2 -17057 +18443 2 @@ -17553,17 +18121,12 @@ 1 2 -13102 +14223 2 3 -3957 - - -4 -5 -1 +4223 @@ -17579,22 +18142,22 @@ 1 2 -12885 +14068 2 3 -2695 +2930 3 5 -1477 +1421 -6 +5 7 -3 +27 @@ -17610,42 +18173,37 @@ 1 2 -657 +739 2 3 -995 +1537 3 4 -1279 +1740 4 5 -262 +261 5 6 -547 +630 6 7 -386 +435 7 -13 -366 - - -13 -4907 -117 +5790 +292 @@ -17661,12 +18219,12 @@ 1 2 -4607 +5629 2 4 -2 +5 @@ -17682,32 +18240,32 @@ 1 2 -772 +786 2 3 -900 +1495 3 4 -1764 +2375 4 5 -478 +550 5 -7 -351 +32 +423 -7 -4785 -344 +44 +5703 +5 @@ -17723,37 +18281,37 @@ 1 2 -667 +739 2 3 -1151 +1537 3 4 -1329 +1776 4 5 -193 +265 5 6 -582 +643 6 7 -397 +425 7 -993 -290 +1531 +249 @@ -17769,17 +18327,12 @@ 1 2 -2187 +2371 2 -28 -183 - - -28 -3834 -62 +3967 +150 @@ -17795,7 +18348,7 @@ 1 2 -2432 +2521 @@ -17811,17 +18364,12 @@ 1 2 -2187 +2371 2 -28 -183 - - -28 -3834 -62 +3967 +150 @@ -17837,12 +18385,12 @@ 1 2 -2258 +2407 2 -3011 -174 +3967 +114 @@ -17852,15 +18400,15 @@ indexer_location -27388 +40309 id -23784 +25314 loc -427 +1604 @@ -17874,17 +18422,22 @@ 1 2 -21223 +19371 2 3 -1913 +3547 3 -11 -648 +10 +1912 + + +10 +19 +484 @@ -17900,47 +18453,37 @@ 1 2 -168 +1040 2 3 -47 +77 3 4 -32 +72 4 -5 -35 - - -5 -9 -34 - - -9 -15 -35 +6 +120 -15 -39 -33 +6 +14 +144 -44 -283 -33 +14 +127 +121 -283 -6385 -10 +127 +6138 +30 @@ -17950,11 +18493,11 @@ accessors -337094 +336633 id -337094 +336633 kind @@ -17962,15 +18505,15 @@ name -56178 +74791 declaring_member_id -291680 +286717 unbound_id -218777 +211967 @@ -17984,7 +18527,7 @@ 1 2 -337094 +336633 @@ -18000,7 +18543,7 @@ 1 2 -337094 +336633 @@ -18016,7 +18559,7 @@ 1 2 -337094 +336633 @@ -18032,7 +18575,7 @@ 1 2 -337094 +336633 @@ -18046,13 +18589,13 @@ 12 -45608 -45609 +50195 +50196 1 -291486 -291487 +286438 +286439 1 @@ -18067,13 +18610,13 @@ 12 -10798 -10799 +14093 +14094 1 -45380 -45381 +60698 +60699 1 @@ -18088,13 +18631,13 @@ 12 -45249 -45250 +50186 +50187 1 -291486 -291487 +286438 +286439 1 @@ -18109,13 +18652,13 @@ 12 -33261 -33262 +36119 +36120 1 -185516 -185517 +175848 +175849 1 @@ -18132,32 +18675,27 @@ 1 2 -34024 +46914 2 3 -8492 +15055 3 -4 -3907 - - -4 -7 -4784 +5 +6355 -7 -36 -4219 +5 +29 +5645 -36 -17260 -752 +29 +17446 +822 @@ -18173,7 +18711,7 @@ 1 2 -56178 +74791 @@ -18189,32 +18727,27 @@ 1 2 -34058 +46917 2 3 -8490 +15053 3 -4 -3887 - - -4 -7 -4784 +5 +6354 -7 -37 -4237 +5 +29 +5645 -37 -17260 -722 +29 +17446 +822 @@ -18230,32 +18763,27 @@ 1 2 -34365 +47440 2 3 -8582 +15185 3 -4 -3929 - - -4 -7 -4701 +5 +6280 -7 -58 -4217 +5 +55 +5613 -58 -3126 -384 +55 +2297 +273 @@ -18271,17 +18799,17 @@ 1 2 -246623 +236810 2 3 -44725 +49898 3 -5 -332 +4 +9 @@ -18297,12 +18825,12 @@ 1 2 -246625 +236810 2 3 -45055 +49907 @@ -18318,12 +18846,12 @@ 1 2 -246625 +236810 2 3 -45055 +49907 @@ -18339,17 +18867,17 @@ 1 2 -246623 +236810 2 3 -44725 +49898 3 -5 -332 +4 +9 @@ -18365,12 +18893,12 @@ 1 2 -214272 +208543 2 -5587 -4505 +5604 +3424 @@ -18386,7 +18914,7 @@ 1 2 -218777 +211967 @@ -18402,7 +18930,7 @@ 1 2 -218777 +211967 @@ -18418,12 +18946,12 @@ 1 2 -214272 +208543 2 -5587 -4505 +5604 +3424 @@ -18433,15 +18961,15 @@ accessor_location -493716 +760991 id -337094 +336633 loc -38581 +87557 @@ -18455,27 +18983,27 @@ 1 2 -250312 +178438 2 3 -46346 +91540 3 4 -12722 +22414 4 -5 -26975 +7 +27767 -5 -28 -739 +7 +257 +16474 @@ -18491,12 +19019,12 @@ 1 2 -36538 +84261 2 -39761 -2043 +38689 +3296 @@ -18506,27 +19034,27 @@ events -6046 +8976 id -6046 +8976 name -3240 +3901 declaring_type_id -1381 +2161 type_id -2048 +2621 unbound_id -5720 +8739 @@ -18540,7 +19068,7 @@ 1 2 -6046 +8976 @@ -18556,7 +19084,7 @@ 1 2 -6046 +8976 @@ -18572,7 +19100,7 @@ 1 2 -6046 +8976 @@ -18588,7 +19116,7 @@ 1 2 -6046 +8976 @@ -18604,22 +19132,27 @@ 1 2 -2526 +2559 2 3 -302 +356 3 -5 -248 +4 +557 -5 -163 -164 +4 +9 +293 + + +9 +148 +136 @@ -18635,22 +19168,22 @@ 1 2 -2526 +2559 2 3 -302 +824 3 -5 -249 +6 +315 -5 -119 -163 +6 +107 +203 @@ -18666,17 +19199,17 @@ 1 2 -2933 +3548 2 5 -261 +304 5 26 -46 +49 @@ -18692,22 +19225,27 @@ 1 2 -2544 +2577 2 3 -298 +351 3 -6 -271 +4 +554 -6 -93 -127 +4 +10 +311 + + +10 +76 +108 @@ -18723,32 +19261,37 @@ 1 2 -701 +877 2 3 -241 +532 3 4 -139 +187 4 5 -79 +172 5 -9 -121 +8 +181 -9 +8 +19 +163 + + +19 465 -100 +49 @@ -18764,32 +19307,32 @@ 1 2 -710 +1091 2 3 -272 +429 3 4 -108 +204 4 -6 -120 +5 +112 -6 -13 -108 +5 +8 +179 -13 +8 465 -63 +146 @@ -18805,27 +19348,27 @@ 1 2 -809 +1345 2 3 -276 +373 3 4 -106 +195 4 -6 -111 +7 +166 -6 +7 181 -79 +82 @@ -18841,32 +19384,37 @@ 1 2 -701 +877 2 3 -241 +532 3 4 -139 +187 4 5 -79 +172 5 -9 -121 +8 +181 -9 +8 +19 +163 + + +19 465 -100 +49 @@ -18882,27 +19430,27 @@ 1 2 -1222 +1063 2 3 -473 +456 3 -5 -181 +4 +764 -5 -29 -154 +4 +7 +204 -30 -1024 -18 +7 +1070 +134 @@ -18918,22 +19466,22 @@ 1 2 -1507 +2009 2 3 -343 +384 3 -7 -154 +9 +197 -7 -402 -44 +9 +435 +31 @@ -18949,22 +19497,17 @@ 1 2 -1640 +1456 2 3 -233 +987 3 -9 -156 - - -9 -346 -19 +363 +178 @@ -18980,27 +19523,27 @@ 1 2 -1224 +1065 2 3 -474 +457 3 -5 -181 +4 +763 -5 -31 -155 +4 +7 +206 -31 -1024 -14 +7 +1059 +130 @@ -19016,12 +19559,12 @@ 1 2 -5671 +8689 2 33 -49 +50 @@ -19037,7 +19580,7 @@ 1 2 -5720 +8739 @@ -19053,12 +19596,12 @@ 1 2 -5671 +8689 2 33 -49 +50 @@ -19074,12 +19617,12 @@ 1 2 -5621 +8725 2 26 -99 +14 @@ -19089,15 +19632,15 @@ event_location -7637 +13927 id -5957 +8976 loc -906 +1497 @@ -19111,22 +19654,17 @@ 1 2 -5050 +6948 2 3 -454 +1532 3 -5 -452 - - -8 -9 -1 +19 +496 @@ -19142,27 +19680,22 @@ 1 2 -668 +1123 2 4 -73 +136 4 -12 -68 - - -12 -32 -69 +13 +126 -36 -1532 -28 +13 +2320 +112 @@ -19172,11 +19705,11 @@ event_accessors -12026 +15714 id -12026 +15714 kind @@ -19184,15 +19717,15 @@ name -6534 +7856 declaring_event_id -5924 +7857 unbound_id -11552 +15240 @@ -19206,7 +19739,7 @@ 1 2 -12026 +15714 @@ -19222,7 +19755,7 @@ 1 2 -12026 +15714 @@ -19238,7 +19771,7 @@ 1 2 -12026 +15714 @@ -19254,7 +19787,7 @@ 1 2 -12026 +15714 @@ -19268,8 +19801,8 @@ 12 -6013 -6014 +7857 +7858 2 @@ -19284,8 +19817,8 @@ 12 -3267 -3268 +3928 +3929 2 @@ -19300,8 +19833,8 @@ 12 -5924 -5925 +7857 +7858 2 @@ -19316,8 +19849,8 @@ 12 -5776 -5777 +7620 +7621 2 @@ -19334,22 +19867,22 @@ 1 2 -5098 +5204 2 3 -606 +1630 3 -5 -502 +6 +616 -5 -110 -328 +6 +97 +406 @@ -19365,7 +19898,7 @@ 1 2 -6534 +7856 @@ -19381,22 +19914,22 @@ 1 2 -5106 +5204 2 3 -614 +1630 3 -5 -496 +6 +616 -5 -105 -318 +6 +97 +406 @@ -19412,22 +19945,22 @@ 1 2 -5134 +5240 2 3 -600 +1622 3 6 -542 +596 6 -72 -258 +58 +398 @@ -19443,12 +19976,7 @@ 2 3 -5836 - - -4 -7 -88 +7857 @@ -19464,7 +19992,7 @@ 2 3 -5924 +7857 @@ -19480,7 +20008,7 @@ 2 3 -5924 +7857 @@ -19496,12 +20024,7 @@ 2 3 -5836 - - -4 -7 -88 +7857 @@ -19517,12 +20040,12 @@ 1 2 -11454 +15140 2 33 -98 +100 @@ -19538,7 +20061,7 @@ 1 2 -11552 +15240 @@ -19554,7 +20077,7 @@ 1 2 -11552 +15240 @@ -19570,12 +20093,12 @@ 1 2 -11454 +15140 2 33 -98 +100 @@ -19585,15 +20108,15 @@ event_accessor_location -15212 +23116 id -12026 +15714 loc -951 +1813 @@ -19607,17 +20130,17 @@ 1 2 -10234 +14122 2 -3 -932 +8 +1180 -3 -5 -860 +8 +19 +412 @@ -19633,32 +20156,27 @@ 1 2 -92 +648 2 3 -624 +798 4 7 -74 +136 8 -27 -73 - - -28 -107 -72 +29 +137 -114 -3063 -16 +30 +4639 +94 @@ -19668,11 +20186,11 @@ operators -14355 +13320 id -14355 +13320 name @@ -19684,15 +20202,15 @@ declaring_type_id -4406 +5147 type_id -1784 +1724 unbound_id -7361 +7036 @@ -19706,7 +20224,7 @@ 1 2 -14355 +13320 @@ -19722,7 +20240,7 @@ 1 2 -14355 +13320 @@ -19738,7 +20256,7 @@ 1 2 -14355 +13320 @@ -19754,7 +20272,7 @@ 1 2 -14355 +13320 @@ -19770,7 +20288,7 @@ 1 2 -14355 +13320 @@ -19784,68 +20302,68 @@ 12 -6 -7 +4 +5 2 -8 -9 -3 +5 +6 +2 -11 -18 +6 +12 2 -23 -25 +12 +18 2 -30 -68 +20 +30 2 -73 -96 +31 +53 2 -151 -152 -1 +94 +127 +2 -152 -153 +128 +134 2 -153 -157 +142 +168 2 -169 -172 +205 +215 2 -189 -221 +332 +346 2 -1456 -2125 +723 +1751 2 -4406 -4478 +4233 +4530 2 @@ -19876,74 +20394,69 @@ 12 -6 -7 +4 +5 2 -8 -9 -3 - - -11 -18 +5 +6 2 -23 -25 +6 +12 2 -30 -31 -1 +12 +18 +2 -67 -68 +20 +30 2 -73 -82 +31 +36 2 -129 -130 -1 +47 +119 +2 -136 -137 +124 +127 2 -137 -141 +129 +142 2 -143 -188 +201 +211 2 -218 -678 +330 +344 2 -1335 -2996 +432 +1105 2 -3066 -3067 -1 +3261 +3558 +2 @@ -19962,59 +20475,59 @@ 2 -4 -5 +2 +3 6 -5 -6 +3 +4 1 -8 -9 +5 +6 2 11 -18 +13 2 -23 -25 +17 +21 2 -30 -31 -1 +29 +32 +2 -67 -68 +35 +48 2 -73 -82 +103 +127 2 -119 -144 +141 +330 2 -186 -218 +342 +435 2 -671 -970 -2 +882 +883 +1 @@ -20028,70 +20541,75 @@ 12 -6 -7 +4 +5 2 -8 -9 -3 +5 +6 +2 -11 -18 +6 +12 2 -23 -25 -2 +12 +13 +1 -30 -68 +17 +18 2 -73 -96 +28 +30 2 -151 -152 -1 +49 +86 +2 -152 -153 +123 +129 2 -153 -157 +133 +140 2 -169 -172 +164 +206 2 -189 -221 +214 +330 2 -977 -1079 +342 +380 2 -1673 -1745 +488 +1913 2 + +2208 +2209 +1 + @@ -20104,63 +20622,63 @@ 12 -6 -7 +4 +5 2 -8 -9 -3 +5 +6 +2 -11 -24 +6 +13 2 -24 -31 +17 +21 2 -73 -96 +29 +53 2 -151 -152 -1 +94 +127 +2 -152 -153 +128 +134 2 -153 -157 +173 +179 2 -188 -190 +205 +215 2 -220 -237 +332 +346 2 -1456 -2125 +723 +1751 2 -4406 -4478 +4233 +4530 2 @@ -20196,64 +20714,64 @@ 12 -6 -7 +4 +5 2 -8 -9 -3 +5 +6 +2 -11 -24 +6 +13 2 -24 -31 +17 +21 2 -67 -74 +29 +36 2 -81 -132 +47 +121 2 -136 -137 +124 +127 2 -137 -141 +129 +142 2 -143 -188 +201 +211 2 -218 -678 +330 +344 2 -1335 -2996 +432 +1105 2 -3066 -3067 -1 +3261 +3558 +2 @@ -20272,53 +20790,53 @@ 2 -4 -5 +2 +3 6 -5 -6 +3 +4 1 -8 -9 +5 +6 2 -11 -24 +12 +18 2 -24 -31 +20 +30 2 -67 -74 +35 +48 2 -81 -122 +105 +127 2 -143 -187 +141 +330 2 -217 -672 +342 +435 2 -969 -970 +882 +883 1 @@ -20333,63 +20851,63 @@ 12 -6 -7 +4 +5 2 -8 -9 -3 +5 +6 +2 -11 -24 +6 +13 2 -24 -31 +17 +18 2 -73 -96 +29 +50 2 -151 -152 -1 +85 +124 +2 -152 -153 +128 +134 2 -153 -157 +167 +176 2 -188 -190 +205 +215 2 -220 -237 +329 +343 2 -977 -1079 +379 +489 2 -1673 -1745 +1912 +2209 2 @@ -20406,32 +20924,27 @@ 1 2 -1105 +1742 2 3 -1458 +1542 3 4 -144 +257 4 5 -1061 +1272 5 -7 -383 - - -7 -114 -255 +77 +334 @@ -20447,27 +20960,27 @@ 1 2 -1241 +1880 2 3 -2380 +2392 3 4 -345 +476 4 -7 -338 +14 +387 -7 +14 24 -102 +12 @@ -20483,27 +20996,27 @@ 1 2 -1241 +1880 2 3 -2381 +2393 3 4 -344 +475 4 -7 -350 +13 +388 -7 +15 22 -90 +11 @@ -20519,22 +21032,17 @@ 1 2 -3187 +3956 2 3 -762 +890 3 -4 -285 - - -4 -60 -172 +41 +301 @@ -20550,32 +21058,27 @@ 1 2 -1105 +1742 2 3 -1458 +1542 3 4 -142 +255 4 5 -1062 +1273 5 -7 -384 - - -7 -114 -255 +77 +335 @@ -20591,27 +21094,22 @@ 1 2 -1112 +1083 2 3 -359 +364 3 4 -131 +154 4 -20 -135 - - -20 -9397 -47 +9483 +123 @@ -20627,22 +21125,22 @@ 1 2 -1451 +1305 2 3 -154 +240 3 -8 -150 +5 +139 -9 +5 18 -29 +40 @@ -20658,22 +21156,22 @@ 1 2 -1451 +1305 2 3 -156 +241 3 -7 -148 +5 +143 -8 +5 16 -29 +35 @@ -20689,17 +21187,17 @@ 1 2 -1520 +1553 2 -3 -134 +5 +135 -3 -3499 -130 +5 +4333 +36 @@ -20715,22 +21213,22 @@ 1 2 -1156 +1092 2 3 -344 +367 3 -5 -151 +4 +157 -5 -3838 -133 +4 +4753 +108 @@ -20746,12 +21244,12 @@ 1 2 -7237 +6925 2 -957 -124 +954 +111 @@ -20767,7 +21265,7 @@ 1 2 -7361 +7036 @@ -20783,7 +21281,7 @@ 1 2 -7361 +7036 @@ -20799,12 +21297,12 @@ 1 2 -7237 +6925 2 -957 -124 +954 +111 @@ -20820,12 +21318,12 @@ 1 2 -7329 +6996 2 -380 -32 +316 +40 @@ -20835,15 +21333,15 @@ operator_location -17972 +26888 id -12398 +8870 loc -645 +2942 @@ -20857,22 +21355,32 @@ 1 2 -9338 +5627 2 3 -1751 +1265 3 -4 -634 +5 +670 -4 -11 -675 +5 +15 +602 + + +15 +18 +699 + + +18 +21 +7 @@ -20888,37 +21396,22 @@ 1 2 -322 +2404 2 -3 -99 - - -3 -6 -47 - - -6 -11 -57 - - -11 -40 -50 +5 +270 -40 -229 -58 +5 +121 +221 -278 -4153 -12 +136 +3457 +47 @@ -20928,15 +21421,15 @@ constant_value -123998 +109873 id -123998 +108394 value -24364 +26585 @@ -20950,7 +21443,12 @@ 1 2 -123998 +107086 + + +2 +5 +1308 @@ -20966,27 +21464,22 @@ 1 2 -15909 +20463 2 3 -4035 +3137 3 -5 -1856 - - -5 -12 -1925 +8 +2119 -12 -8469 -639 +8 +8085 +866 @@ -20996,27 +21489,27 @@ methods -1076961 +990339 id -1076961 +990339 name -123752 +145323 declaring_type_id -122626 +115072 type_id -85751 +75864 unbound_id -485699 +416703 @@ -21030,7 +21523,7 @@ 1 2 -1076961 +990339 @@ -21046,7 +21539,7 @@ 1 2 -1076961 +990339 @@ -21062,7 +21555,7 @@ 1 2 -1076961 +990339 @@ -21078,7 +21571,7 @@ 1 2 -1076961 +990339 @@ -21094,27 +21587,27 @@ 1 2 -84817 +103232 2 3 -14120 +18945 3 5 -10260 +11241 5 -13 -9409 +60 +10906 -13 -34427 -5146 +60 +33554 +999 @@ -21130,27 +21623,22 @@ 1 2 -88126 +107949 2 3 -13684 +17436 3 -5 -9813 - - -5 -18 -9310 +6 +12134 -18 -17762 -2819 +6 +17745 +7804 @@ -21166,17 +21654,17 @@ 1 2 -109390 +134024 2 -5 -10284 +124 +10936 -5 -13972 -4078 +124 +13470 +363 @@ -21192,27 +21680,22 @@ 1 2 -85912 +105154 2 3 -14443 +19254 3 5 -10418 +11116 5 -15 -9328 - - -15 -9184 -3651 +8756 +9799 @@ -21228,42 +21711,47 @@ 1 2 -34188 +30339 2 3 -17314 +17979 3 4 -20964 +20209 4 5 -8816 +7063 5 6 -10575 +11230 6 10 -10963 +9248 10 -23 -10702 +21 +8656 -23 -2721 -9104 +21 +82 +9133 + + +82 +4659 +1215 @@ -21279,42 +21767,42 @@ 1 2 -36689 +31840 2 3 -19872 +18946 3 4 -21628 +20938 4 5 -9733 +10198 5 6 -9479 +9143 6 10 -9575 +8968 10 22 -9473 +8901 22 2630 -6177 +6138 @@ -21330,32 +21818,32 @@ 1 2 -50588 +46532 2 3 -38419 +36855 3 4 -8775 +8749 4 5 -8027 +8055 5 9 -9887 +8673 9 -1435 -6930 +2310 +6208 @@ -21371,42 +21859,47 @@ 1 2 -34249 +30464 2 3 -17356 +17990 3 4 -20967 +20224 4 5 -8827 +7078 5 6 -10584 +11238 6 10 -11009 +9259 10 -23 -10686 +22 +8857 -23 -2634 -8948 +22 +82 +8820 + + +82 +2631 +1142 @@ -21422,32 +21915,32 @@ 1 2 -53339 +45668 2 3 -12908 +13238 3 4 -5962 +5192 4 10 -6853 +5878 10 221 -6574 +5798 -222 -291373 -115 +224 +281834 +90 @@ -21463,22 +21956,22 @@ 1 2 -65576 +56967 2 3 -7734 +7755 3 7 -6549 +5788 7 -58312 -5892 +66425 +5354 @@ -21494,22 +21987,22 @@ 1 2 -61912 +53716 2 3 -14166 +13964 3 -6 -6543 +7 +6247 -6 -57678 -3130 +7 +56084 +1937 @@ -21525,32 +22018,32 @@ 1 2 -53406 +45760 2 3 -13007 +13288 3 4 -5965 +5214 4 10 -6831 +5845 10 -221 -6437 +252 +5691 -221 -160307 -105 +254 +149113 +66 @@ -21566,12 +22059,12 @@ 1 2 -465024 +401515 2 -8433 -20675 +8127 +15188 @@ -21587,7 +22080,7 @@ 1 2 -485699 +416703 @@ -21603,12 +22096,12 @@ 1 2 -467820 +404324 2 -8433 -17879 +8127 +12379 @@ -21624,12 +22117,12 @@ 1 2 -474343 +410109 2 -8438 -11356 +8127 +6594 @@ -21639,15 +22132,15 @@ method_location -1613197 +2069011 id -1073711 +989823 loc -136410 +225377 @@ -21661,22 +22154,27 @@ 1 2 -685284 +481413 2 3 -300207 +351054 3 -5 -86944 +4 +59147 -5 -13 -1276 +4 +9 +74877 + + +9 +24 +23332 @@ -21692,12 +22190,12 @@ 1 2 -127523 +213144 2 -122930 -8887 +117240 +12233 @@ -21707,23 +22205,23 @@ constructors -154830 +149144 id -154830 +149144 name -46607 +54143 declaring_type_id -104385 +101619 unbound_id -108271 +98805 @@ -21737,7 +22235,7 @@ 1 2 -154830 +149144 @@ -21753,7 +22251,7 @@ 1 2 -154830 +149144 @@ -21769,7 +22267,7 @@ 1 2 -154830 +149144 @@ -21785,27 +22283,22 @@ 1 2 -29993 +39528 2 3 -8076 +8842 3 -4 -2952 - - -4 7 -3570 +4536 7 -8393 -2016 +7428 +1237 @@ -21821,22 +22314,17 @@ 1 2 -34660 +47190 2 3 -6241 +4506 3 -5 -3617 - - -5 -5524 -2089 +5277 +2447 @@ -21852,27 +22340,22 @@ 1 2 -30316 +40238 2 3 -8174 +8855 3 -4 -2879 - - -4 -8 -3698 +7 +4181 -8 -4201 -1540 +7 +4418 +869 @@ -21888,22 +22371,22 @@ 1 2 -83056 +80662 2 3 -11296 +11743 3 8 -8546 +7758 8 -44 -1487 +42 +1456 @@ -21919,7 +22402,7 @@ 1 2 -104385 +101619 @@ -21935,22 +22418,22 @@ 1 2 -83056 +80662 2 3 -11296 +11743 3 8 -8546 +7758 8 -44 -1487 +42 +1456 @@ -21966,12 +22449,12 @@ 1 2 -106112 +96762 2 -1790 -2159 +3787 +2043 @@ -21987,7 +22470,7 @@ 1 2 -108271 +98805 @@ -22003,12 +22486,12 @@ 1 2 -106112 +96762 2 -1790 -2159 +3787 +2043 @@ -22018,15 +22501,15 @@ constructor_location -222090 +294390 id -154828 +149141 loc -19558 +44163 @@ -22040,22 +22523,27 @@ 1 2 -112277 +95933 2 3 -24589 +26780 3 4 -11838 +12519 4 -28 -6124 +13 +11784 + + +13 +591 +2125 @@ -22071,17 +22559,17 @@ 1 2 -17208 +39468 2 7 -1512 +3388 7 -17811 -838 +17601 +1307 @@ -22091,23 +22579,23 @@ destructors -461 +388 id -461 +388 name -288 +300 declaring_type_id -461 +388 unbound_id -413 +315 @@ -22121,7 +22609,7 @@ 1 2 -461 +388 @@ -22137,7 +22625,7 @@ 1 2 -461 +388 @@ -22153,7 +22641,7 @@ 1 2 -461 +388 @@ -22169,22 +22657,12 @@ 1 2 -220 +278 2 -3 -36 - - -3 -5 -23 - - -5 -25 -9 +23 +22 @@ -22200,22 +22678,12 @@ 1 2 -220 +278 2 -3 -36 - - -3 -5 -23 - - -5 -25 -9 +23 +22 @@ -22231,22 +22699,12 @@ 1 2 -224 +287 2 -3 -37 - - -3 -6 -22 - - -6 -11 -5 +4 +13 @@ -22262,7 +22720,7 @@ 1 2 -461 +388 @@ -22278,7 +22736,7 @@ 1 2 -461 +388 @@ -22294,7 +22752,7 @@ 1 2 -461 +388 @@ -22310,12 +22768,12 @@ 1 2 -403 +304 2 -22 -10 +23 +11 @@ -22331,7 +22789,7 @@ 1 2 -413 +315 @@ -22347,12 +22805,12 @@ 1 2 -403 +304 2 -22 -10 +23 +11 @@ -22362,15 +22820,15 @@ destructor_location -842 +1101 id -461 +388 loc -168 +381 @@ -22384,27 +22842,32 @@ 1 2 -268 +197 2 3 -80 +69 3 4 -44 +38 4 -5 -68 +7 +35 -10 -11 -1 +7 +12 +35 + + +12 +18 +14 @@ -22420,37 +22883,32 @@ 1 2 -84 +256 2 3 -20 +35 3 4 -13 +21 4 -5 -14 - - -5 -9 -14 +6 +33 -9 -20 -13 +6 +22 +29 -20 -75 -10 +22 +33 +7 @@ -22460,15 +22918,15 @@ overrides -156312 +117202 id -156312 +116553 base_id -44250 +31431 @@ -22482,7 +22940,12 @@ 1 2 -156312 +115904 + + +2 +3 +649 @@ -22498,27 +22961,27 @@ 1 2 -24930 +18013 2 3 -9202 +6343 3 4 -3081 +2243 4 7 -3911 +2620 7 -3299 -3126 +3939 +2212 @@ -22528,15 +22991,15 @@ explicitly_implements -173173 +181041 id -173173 +181041 interface_id -19919 +21520 @@ -22550,7 +23013,7 @@ 1 2 -173173 +181041 @@ -22566,42 +23029,42 @@ 1 2 -8589 +8591 2 3 -3727 +4158 3 4 -1718 +1973 4 5 -444 +666 5 6 -2452 +2548 6 -12 -1382 +10 +1626 -12 -58 -1496 +10 +19 +1621 -58 -10759 -111 +19 +24037 +337 @@ -22611,23 +23074,23 @@ local_functions -1174 +1201 id -1174 +1201 name -730 +755 return_type -166 +169 unbound_id -1172 +1199 @@ -22641,7 +23104,7 @@ 1 2 -1174 +1201 @@ -22657,7 +23120,7 @@ 1 2 -1174 +1201 @@ -22673,7 +23136,7 @@ 1 2 -1174 +1201 @@ -22689,12 +23152,12 @@ 1 2 -645 +668 2 4 -58 +60 4 @@ -22715,7 +23178,7 @@ 1 2 -722 +747 2 @@ -22736,12 +23199,12 @@ 1 2 -646 +669 2 4 -57 +59 4 @@ -22762,22 +23225,22 @@ 1 2 -121 +123 2 3 -20 +21 3 -6 -14 +5 +13 -6 -693 -11 +5 +697 +12 @@ -22793,7 +23256,7 @@ 1 2 -130 +133 2 @@ -22802,13 +23265,13 @@ 3 -7 -14 +8 +13 -13 -297 -5 +15 +301 +6 @@ -22824,22 +23287,22 @@ 1 2 -121 +123 2 3 -20 +21 3 -6 -14 +5 +13 -6 -693 -11 +5 +697 +12 @@ -22855,7 +23318,7 @@ 1 2 -1171 +1198 3 @@ -22876,7 +23339,7 @@ 1 2 -1172 +1199 @@ -22892,7 +23355,7 @@ 1 2 -1171 +1198 3 @@ -22907,15 +23370,15 @@ local_function_stmts -1305 +1199 fn -1305 +1199 stmt -1172 +1199 @@ -22929,7 +23392,7 @@ 1 2 -1305 +1199 @@ -22945,12 +23408,7 @@ 1 2 -1104 - - -2 -9 -68 +1199 @@ -22960,11 +23418,11 @@ fields -292454 +285648 id -292454 +285648 kind @@ -22972,19 +23430,19 @@ name -103398 +127772 declaring_type_id -55991 +58158 type_id -54021 +47955 unbound_id -272257 +267317 @@ -22998,7 +23456,7 @@ 1 2 -292454 +285648 @@ -23014,7 +23472,7 @@ 1 2 -292454 +285648 @@ -23030,7 +23488,7 @@ 1 2 -292454 +285648 @@ -23046,7 +23504,7 @@ 1 2 -292454 +285648 @@ -23062,7 +23520,7 @@ 1 2 -292454 +285648 @@ -23076,13 +23534,13 @@ 12 -122762 -122763 +106769 +106770 1 -160511 -160512 +178578 +178579 1 @@ -23097,13 +23555,13 @@ 12 -40098 -40099 +54214 +54215 1 -65413 -65414 +76116 +76117 1 @@ -23118,13 +23576,13 @@ 12 -10855 -10856 +10999 +11000 1 -46872 -46873 +49829 +49830 1 @@ -23139,13 +23597,13 @@ 12 -8748 -8749 +7955 +7956 1 -46848 -46849 +41759 +41760 1 @@ -23160,13 +23618,13 @@ 12 -122638 -122639 +106161 +106162 1 -149619 -149620 +161161 +161162 1 @@ -23183,27 +23641,22 @@ 1 2 -71846 +101759 2 3 -12945 +13893 3 -4 -7951 - - -4 -10 -8225 +9 +9606 -10 -6843 -2431 +9 +7502 +2514 @@ -23219,12 +23672,12 @@ 1 2 -101285 +125214 2 3 -2113 +2558 @@ -23240,27 +23693,22 @@ 1 2 -71846 +101759 2 3 -12945 +13893 3 -4 -7951 - - -4 -10 -8225 +9 +9606 -10 -6843 -2431 +9 +7502 +2514 @@ -23276,22 +23724,17 @@ 1 2 -79247 +111990 2 3 -10211 +9417 3 -5 -8781 - - -5 -4553 -5159 +4791 +6365 @@ -23307,27 +23750,22 @@ 1 2 -72207 +102538 2 3 -13022 +13899 3 -4 -7894 - - -4 -10 -7975 +11 +9600 -10 -6843 -2300 +11 +7502 +1735 @@ -23343,42 +23781,42 @@ 1 2 -13938 +13468 2 3 -13645 +13970 3 4 -8248 +9308 4 5 -5544 +5925 5 6 -3469 +3861 6 8 -4613 +4917 8 15 -4445 +4612 15 4792 -2089 +2097 @@ -23394,12 +23832,12 @@ 1 2 -54255 +55488 2 3 -1736 +2670 @@ -23415,42 +23853,42 @@ 1 2 -13938 +13468 2 3 -13645 +13970 3 4 -8248 +9308 4 5 -5544 +5925 5 6 -3469 +3861 6 8 -4613 +4917 8 15 -4445 +4612 15 4792 -2089 +2097 @@ -23466,32 +23904,32 @@ 1 2 -24596 +23657 2 3 -14427 +16254 3 4 -6072 +6661 4 5 -3106 +3854 5 -8 -5024 +7 +4345 -8 -184 -2766 +7 +569 +3387 @@ -23507,42 +23945,42 @@ 1 2 -13938 +13468 2 3 -13645 +13970 3 4 -8248 +9308 4 5 -5544 +5925 5 6 -3469 +3861 6 8 -4613 +4917 8 15 -4445 +4612 15 4792 -2089 +2097 @@ -23558,32 +23996,32 @@ 1 2 -32209 +28567 2 3 -7718 +6526 3 4 -4216 +3634 4 6 -3904 +3781 6 -16 -4181 +15 +3728 -16 -31639 -1793 +15 +38777 +1719 @@ -23599,12 +24037,12 @@ 1 2 -52446 +46196 2 3 -1575 +1759 @@ -23620,27 +24058,27 @@ 1 2 -35276 +31776 2 3 -7110 +5924 3 4 -3716 +3057 4 7 -4170 +3977 7 -16842 -3749 +22007 +3221 @@ -23656,22 +24094,22 @@ 1 2 -41289 +36247 2 3 -6855 +5872 3 -7 -4189 +6 +3680 -7 -11356 -1688 +6 +13299 +2156 @@ -23687,32 +24125,32 @@ 1 2 -32287 +28687 2 3 -7753 +6534 3 4 -4195 +3601 4 6 -3885 +3767 6 -16 -4140 +15 +3691 -16 -31127 -1761 +15 +36782 +1675 @@ -23728,12 +24166,12 @@ 1 2 -270801 +264767 2 -957 -1456 +954 +2550 @@ -23749,7 +24187,12 @@ 1 2 -272257 +267312 + + +2 +3 +5 @@ -23765,7 +24208,7 @@ 1 2 -272257 +267317 @@ -23781,12 +24224,12 @@ 1 2 -270801 +264767 2 -957 -1456 +954 +2550 @@ -23802,12 +24245,12 @@ 1 2 -262887 +265821 2 -957 -9370 +954 +1496 @@ -23817,15 +24260,15 @@ field_location -471966 +665606 id -275969 +283536 loc -38796 +100719 @@ -23839,27 +24282,27 @@ 1 2 -150431 +110804 2 3 -83301 +112944 3 4 -15612 +21535 4 -5 -25909 +7 +25436 -5 -14 -716 +7 +534 +12817 @@ -23875,17 +24318,12 @@ 1 2 -33152 +95087 2 -3 -3438 - - -3 9082 -2206 +5632 @@ -23895,11 +24333,11 @@ localvars -240033 +309450 id -240033 +309450 kind @@ -23907,7 +24345,7 @@ name -34551 +50758 implicitly_typed @@ -23915,11 +24353,11 @@ type_id -14128 +19087 parent_id -240033 +309450 @@ -23933,7 +24371,7 @@ 1 2 -240033 +309450 @@ -23949,7 +24387,7 @@ 1 2 -240033 +309450 @@ -23965,7 +24403,7 @@ 1 2 -240033 +309450 @@ -23981,7 +24419,7 @@ 1 2 -240033 +309450 @@ -23997,7 +24435,7 @@ 1 2 -240033 +309450 @@ -24011,18 +24449,18 @@ 12 -11 -12 +54 +55 1 -1223 -1224 +1627 +1628 1 -238799 -238800 +307769 +307770 1 @@ -24037,18 +24475,18 @@ 12 -5 -6 +31 +32 1 -413 -414 +783 +784 1 -34260 -34261 +50117 +50118 1 @@ -24084,18 +24522,18 @@ 12 -5 -6 +21 +22 1 -32 -33 +43 +44 1 -14120 -14121 +19072 +19073 1 @@ -24110,18 +24548,18 @@ 12 -11 -12 +54 +55 1 -1223 -1224 +1627 +1628 1 -238799 -238800 +307769 +307770 1 @@ -24138,32 +24576,27 @@ 1 2 -20908 +31599 2 3 -5546 +8221 3 4 -2435 +3292 4 -7 -2614 - - -7 -62 -2595 +8 +4188 -62 -14242 -453 +8 +14339 +3458 @@ -24179,12 +24612,12 @@ 1 2 -34424 +50585 2 3 -127 +173 @@ -24200,12 +24633,12 @@ 1 2 -30837 +45779 2 3 -3714 +4979 @@ -24221,17 +24654,17 @@ 1 2 -28724 +43415 2 3 -3287 +4121 3 -1256 -2540 +1514 +3222 @@ -24247,32 +24680,27 @@ 1 2 -20908 +31599 2 3 -5546 +8221 3 4 -2435 +3292 4 -7 -2614 - - -7 -62 -2595 +8 +4188 -62 -14242 -453 +8 +14339 +3458 @@ -24286,13 +24714,13 @@ 12 -49660 -49661 +119948 +119949 1 -190373 -190374 +189502 +189503 1 @@ -24328,13 +24756,13 @@ 12 -11178 -11179 +27809 +27810 1 -27087 -27088 +27928 +27929 1 @@ -24349,13 +24777,13 @@ 12 -4093 -4094 +9524 +9525 1 -12464 -12465 +12356 +12357 1 @@ -24370,13 +24798,13 @@ 12 -49660 -49661 +119948 +119949 1 -190373 -190374 +189502 +189503 1 @@ -24393,37 +24821,37 @@ 1 2 -6390 +8834 2 3 -2419 +3200 3 4 -1200 +1561 4 6 -1291 +1732 6 10 -1115 +1473 10 -30 -1068 +29 +1446 -30 -52306 -645 +29 +57038 +841 @@ -24439,12 +24867,12 @@ 1 2 -14100 +19041 2 4 -28 +46 @@ -24460,27 +24888,27 @@ 1 2 -8681 +11861 2 3 -2316 +3127 3 4 -982 +1302 4 7 -1150 +1505 7 -3654 -999 +5718 +1292 @@ -24496,12 +24924,12 @@ 1 2 -11699 +16294 2 3 -2429 +2793 @@ -24517,37 +24945,37 @@ 1 2 -6390 +8834 2 3 -2419 +3200 3 4 -1200 +1561 4 6 -1291 +1732 6 10 -1115 +1473 10 -30 -1068 +29 +1446 -30 -52306 -645 +29 +57038 +841 @@ -24563,7 +24991,7 @@ 1 2 -240033 +309450 @@ -24579,7 +25007,7 @@ 1 2 -240033 +309450 @@ -24595,7 +25023,7 @@ 1 2 -240033 +309450 @@ -24611,7 +25039,7 @@ 1 2 -240033 +309450 @@ -24627,7 +25055,7 @@ 1 2 -240033 +309450 @@ -24637,15 +25065,15 @@ localvar_location -240033 +309450 id -240033 +309450 loc -233676 +309085 @@ -24659,7 +25087,7 @@ 1 2 -240033 +309450 @@ -24675,12 +25103,12 @@ 1 2 -229323 +308720 2 -9 -4353 +3 +365 @@ -24690,19 +25118,19 @@ params -1873820 +1662795 id -1873820 +1662795 name -41364 +48172 type_id -161044 +127333 index @@ -24714,11 +25142,11 @@ parent_id -1116592 +1009707 unbound_id -877362 +709589 @@ -24732,7 +25160,7 @@ 1 2 -1873820 +1662795 @@ -24748,7 +25176,7 @@ 1 2 -1873820 +1662795 @@ -24764,7 +25192,7 @@ 1 2 -1873820 +1662795 @@ -24780,7 +25208,7 @@ 1 2 -1873820 +1662795 @@ -24796,7 +25224,7 @@ 1 2 -1873820 +1662795 @@ -24812,7 +25240,7 @@ 1 2 -1873820 +1662795 @@ -24828,47 +25256,42 @@ 1 2 -13621 +18527 2 3 -7047 +8846 3 4 -4026 +4277 4 5 -3188 +3465 5 -7 -3256 - - -7 -11 -3127 +8 +4374 -11 -21 -3167 +8 +15 +3854 -21 -123 -3106 +15 +65 +3617 -123 -129722 -826 +65 +115038 +1212 @@ -24884,22 +25307,22 @@ 1 2 -30165 +38960 2 3 -4715 +4760 3 -5 -3381 +12 +3615 -5 -14591 -3103 +12 +13741 +837 @@ -24915,22 +25338,22 @@ 1 2 -28293 +32920 2 3 -7375 +8631 3 4 -2787 +3251 4 28 -2909 +3370 @@ -24946,17 +25369,17 @@ 1 2 -38214 +44430 2 5 -3112 +3689 5 7 -38 +53 @@ -24972,47 +25395,42 @@ 1 2 -13621 +18527 2 3 -7047 +8846 3 4 -4026 +4277 4 5 -3188 +3465 5 -7 -3256 - - -7 -11 -3127 +8 +4374 -11 -21 -3167 +8 +15 +3854 -21 -123 -3106 +15 +65 +3617 -123 -129722 -826 +65 +115038 +1212 @@ -25028,47 +25446,42 @@ 1 2 -13968 +19226 2 3 -7266 +9088 3 4 -4092 +4287 4 5 -3223 +3445 5 -7 -3194 - - -7 -11 -3118 +8 +4279 -11 -23 -3207 +8 +15 +3620 -23 -539 -3103 +15 +107 +3613 -543 -67549 -193 +107 +59449 +614 @@ -25084,37 +25497,37 @@ 1 2 -91168 +66747 2 3 -17876 +14274 3 4 -8604 +7070 4 5 -10406 +10049 5 -9 -12941 +8 +10159 -9 -20 -12267 +8 +16 +10230 -20 -262274 -7782 +16 +250157 +8804 @@ -25130,22 +25543,22 @@ 1 2 -128753 +98326 2 3 -16870 +13720 3 -8 -12219 +6 +10307 -8 -6338 -3202 +6 +7254 +4980 @@ -25161,22 +25574,22 @@ 1 2 -126154 +95270 2 3 -22257 +20230 3 -8 -12236 +5 +10443 -8 +5 50 -397 +1390 @@ -25192,12 +25605,12 @@ 1 2 -152216 +119091 2 6 -8828 +8242 @@ -25213,37 +25626,37 @@ 1 2 -92367 +67557 2 3 -18720 +15267 3 4 -8759 +7257 4 -6 -13993 +5 +8928 -6 -13 -14744 +5 +8 +9845 -13 -283 -12079 +8 +16 +10012 -283 -211973 -382 +16 +203397 +8467 @@ -25259,37 +25672,37 @@ 1 2 -91920 +67273 2 3 -17586 +14078 3 4 -9255 +7143 4 5 -10966 +10798 5 -9 -13759 +8 +10706 -9 -26 -12406 +8 +17 +10208 -26 -94223 -5152 +17 +82653 +7127 @@ -25308,48 +25721,48 @@ 11 -5 -6 +2 +3 8 -9 -28 +6 +19 4 -30 -56 +20 +37 4 -64 -109 +42 +68 4 -124 -231 +74 +119 4 -463 -1329 +285 +932 4 -1755 -4383 +1269 +3439 4 -7196 -32601 +5388 +26515 4 -73082 -1116593 +60694 +1006637 4 @@ -25379,38 +25792,38 @@ 4 -10 -19 +11 +21 4 -19 -29 +21 +32 4 -33 -53 +36 +56 4 -76 -183 +80 +187 4 -255 -752 +270 +852 4 -1209 -4484 +1380 +5216 4 -7204 -19237 +8435 +22372 4 @@ -25430,54 +25843,54 @@ 11 -5 -6 +2 +3 8 -7 -13 +4 +9 4 -14 -23 -3 +10 +15 +2 -23 -46 +16 +20 4 -50 -80 -4 +25 +27 +3 -100 -643 +32 +176 4 -840 -1577 +297 +767 4 -1921 -4399 +936 +1850 4 -5863 -49674 +2277 +8796 4 -111424 -111425 -1 +17296 +92711 +3 @@ -25537,48 +25950,48 @@ 11 -5 -6 +2 +3 8 -9 -28 +6 +19 4 -30 -56 +20 +37 4 -64 -109 +42 +68 4 -124 -231 +74 +119 4 -463 -1329 +285 +932 4 -1755 -4383 +1269 +3439 4 -7196 -32601 +5388 +26515 4 -73082 -1116593 +60694 +1006637 4 @@ -25598,48 +26011,48 @@ 11 -5 -6 +2 +3 8 -9 -28 +6 +19 4 -30 -56 +20 +37 4 -64 -109 +42 +68 4 -124 -231 +74 +119 4 -328 -741 +174 +451 4 -1019 -3147 +664 +2379 4 -5508 -25827 +3992 +20329 4 -48569 -474892 +38390 +389589 4 @@ -25654,33 +26067,33 @@ 12 -511 -512 +733 +734 1 -8643 -8644 +6510 +6511 1 -13051 -13052 +13337 +13338 1 -29937 -29938 +20276 +20277 1 -31208 -31209 +30458 +30459 1 -1790319 -1790320 +1591179 +1591180 1 @@ -25695,33 +26108,33 @@ 12 -39 -40 +79 +80 1 -475 -476 +483 +484 1 -960 -961 +1013 +1014 1 -1769 -1770 +2257 +2258 1 -4676 -4677 +5499 +5500 1 -37382 -37383 +43559 +43560 1 @@ -25736,33 +26149,33 @@ 12 -125 -126 +147 +148 1 -1391 -1392 +1038 +1039 1 -1839 -1840 +2115 +2116 1 -5719 -5720 +4196 +4197 1 -10363 -10364 +5987 +5988 1 -151475 -151476 +123175 +123176 1 @@ -25818,33 +26231,33 @@ 12 -447 -448 +652 +653 1 -8643 -8644 +6510 +6511 1 -11110 -11111 +10961 +10962 1 -23417 -23418 +20276 +20277 1 -29937 -29938 +24590 +24591 1 -1093892 -1093893 +991551 +991552 1 @@ -25859,33 +26272,33 @@ 12 -264 -265 +353 +354 1 -5881 -5882 +3872 +3873 1 -11779 -11780 +10322 +10323 1 -18436 -18437 +10847 +10848 1 -23618 -23619 +21440 +21441 1 -817385 -817386 +662845 +662846 1 @@ -25902,22 +26315,22 @@ 1 2 -672190 +614133 2 3 -288892 +263888 3 4 -82428 +71715 4 52 -73082 +59971 @@ -25933,22 +26346,22 @@ 1 2 -672186 +614072 2 3 -288887 +263868 3 4 -82430 +71736 4 52 -73089 +60031 @@ -25964,22 +26377,22 @@ 1 2 -721470 +660352 2 3 -280220 +255417 3 5 -93921 +77910 5 41 -20981 +16028 @@ -25995,22 +26408,22 @@ 1 2 -672190 +614133 2 3 -288892 +263888 3 4 -82428 +71715 4 52 -73082 +59971 @@ -26026,12 +26439,12 @@ 1 2 -1067388 +966434 2 5 -49204 +43273 @@ -26047,22 +26460,22 @@ 1 2 -672185 +614125 2 3 -288897 +263896 3 4 -82428 +71715 4 52 -73082 +59971 @@ -26078,12 +26491,12 @@ 1 2 -839334 +681004 2 -9488 -38028 +15458 +28585 @@ -26099,12 +26512,12 @@ 1 2 -877341 +709322 2 -12 -21 +4 +267 @@ -26120,12 +26533,12 @@ 1 2 -861642 +698010 2 -4604 -15720 +5635 +11579 @@ -26141,7 +26554,7 @@ 1 2 -877362 +709589 @@ -26157,12 +26570,12 @@ 1 2 -877361 +709499 2 3 -1 +90 @@ -26178,12 +26591,12 @@ 1 2 -839334 +681004 2 -9488 -38028 +15458 +28585 @@ -26193,15 +26606,15 @@ param_location -2407035 +3009317 id -1867344 +1650966 loc -199269 +370027 @@ -26215,22 +26628,27 @@ 1 2 -1533663 +1174826 2 3 -175244 +203043 3 -5 -156584 +4 +134596 -5 -13 -1853 +4 +15 +131678 + + +15 +534 +6823 @@ -26246,17 +26664,12 @@ 1 2 -180467 +345724 2 -7 -15302 - - -7 -208250 -3500 +215283 +24303 @@ -26266,11 +26679,11 @@ statements -1072910 +1789979 id -1072910 +1789979 kind @@ -26288,7 +26701,7 @@ 1 2 -1072910 +1789979 @@ -26302,83 +26715,83 @@ 12 -8 -18 +18 +187 2 -22 -55 +234 +253 2 -69 -77 +301 +331 2 -95 -116 +349 +440 2 -148 -150 +783 +795 2 -179 -657 +1199 +1201 2 -1155 -1223 +1334 +1624 2 -1305 -1697 +1831 +3271 2 -1828 -2056 +4304 +4712 2 -2439 -3371 +6120 +6287 2 -5182 -5511 +8021 +8190 2 -7981 -9036 +11629 +17069 2 -10708 -34568 +53160 +62808 2 -71396 -107423 +158006 +172167 2 -213042 -262648 +269815 +483216 2 -328762 -328763 +510339 +510340 1 @@ -26389,11 +26802,11 @@ stmt_parent -915253 +1511647 stmt -915253 +1511647 index @@ -26401,7 +26814,7 @@ parent -362670 +672991 @@ -26415,7 +26828,7 @@ 1 2 -915253 +1511647 @@ -26431,7 +26844,7 @@ 1 2 -915253 +1511647 @@ -26451,17 +26864,17 @@ 2 -15 +16 162 -15 -66 +16 +98 160 -66 -269102 +99 +477408 115 @@ -26482,17 +26895,17 @@ 2 -15 +16 162 -15 -66 +16 +98 160 -66 -269102 +99 +477408 115 @@ -26509,32 +26922,27 @@ 1 2 -210247 +417292 2 3 -61136 +117594 3 4 -30007 +47441 4 -6 -30325 - - -6 -18 -27276 +7 +56561 -18 +7 2123 -3679 +34103 @@ -26550,32 +26958,27 @@ 1 2 -210247 +417292 2 3 -61136 +117594 3 4 -30007 +47441 4 -6 -30325 - - -6 -18 -27276 +7 +56561 -18 +7 2123 -3679 +34103 @@ -26585,11 +26988,11 @@ stmt_parent_top_level -157657 +278332 stmt -157657 +278332 index @@ -26597,7 +27000,7 @@ parent -157653 +250974 @@ -26611,7 +27014,7 @@ 1 2 -157657 +278332 @@ -26627,7 +27030,7 @@ 1 2 -157657 +278332 @@ -26641,8 +27044,8 @@ 12 -157657 -157658 +278332 +278333 1 @@ -26657,8 +27060,8 @@ 12 -157653 -157654 +250974 +250975 1 @@ -26675,12 +27078,17 @@ 1 2 -157649 +223812 2 3 -4 +26967 + + +3 +5 +195 @@ -26696,7 +27104,7 @@ 1 2 -157653 +250974 @@ -26706,15 +27114,15 @@ stmt_location -1072910 +1789979 id -1072910 +1789979 loc -1030702 +1784517 @@ -26728,7 +27136,7 @@ 1 2 -1072910 +1789979 @@ -26744,12 +27152,12 @@ 1 2 -1002522 +1781311 2 -12 -28180 +45 +3206 @@ -26759,15 +27167,15 @@ catch_type -2055 +4711 catch_id -2055 +4711 type_id -166 +163 kind @@ -26785,7 +27193,7 @@ 1 2 -2055 +4711 @@ -26801,7 +27209,7 @@ 1 2 -2055 +4711 @@ -26817,7 +27225,7 @@ 1 2 -60 +48 2 @@ -26827,7 +27235,7 @@ 3 4 -21 +14 4 @@ -26836,23 +27244,28 @@ 5 -7 +8 15 -7 -13 -14 +8 +11 +15 -14 -82 +11 +28 13 -107 -389 -5 +30 +91 +13 + + +114 +1687 +7 @@ -26868,7 +27281,7 @@ 1 2 -166 +163 @@ -26882,13 +27295,13 @@ 12 -317 -318 +758 +759 1 -1738 -1739 +3953 +3954 1 @@ -26903,13 +27316,13 @@ 12 -6 -7 +1 +2 1 -160 -161 +162 +163 1 @@ -26920,19 +27333,19 @@ expressions -4889105 +7417345 id -4889105 +7417345 kind -103 +106 type_id -48005 +63982 @@ -26946,7 +27359,7 @@ 1 2 -4889105 +7417345 @@ -26962,7 +27375,7 @@ 1 2 -4889105 +7417345 @@ -26976,69 +27389,74 @@ 12 -4 -32 -9 +8 +50 +8 -34 -55 +69 +143 8 -64 -153 +178 +409 8 -160 -256 +435 +657 8 -257 -382 +715 +1216 8 -444 -1842 +1258 +2153 8 -1845 -2921 +2309 +4322 8 -3359 -4761 +4350 +7103 8 -4871 -7590 +7270 +12714 8 -8632 -17337 +14417 +22533 8 -20850 -51126 +24042 +32766 8 -58357 -331896 +41161 +212777 8 -342808 -756876 -6 +268458 +724743 +8 + + +928336 +1050543 +2 @@ -27054,56 +27472,56 @@ 1 2 -28 +29 2 -3 -6 - - -3 -5 +6 8 -5 +6 8 8 8 -16 +12 8 -20 -64 +13 +55 8 -78 -186 +59 +114 +8 + + +115 +319 8 -215 -715 +327 +1055 8 -733 -1554 +1063 +2159 8 -1774 -11493 +2975 +17362 8 -12327 -14569 +18530 +20120 5 @@ -27120,57 +27538,57 @@ 1 2 -12254 +14334 2 3 -5177 +5964 3 4 -3053 +3755 4 5 -2703 +4381 5 7 -4432 +5869 7 10 -3752 +5162 10 15 -3781 +5056 15 -25 -3779 +24 +4964 -25 -51 -3670 +24 +44 +4940 -51 -183 -3607 +44 +108 +4809 -183 -740099 -1797 +108 +977236 +4748 @@ -27186,37 +27604,42 @@ 1 2 -21735 +26518 2 3 -6947 +8251 3 4 -6168 +9231 4 5 -4210 +5758 5 -7 -4274 +6 +3874 -7 -11 -3645 +6 +8 +4706 -11 -54 -1026 +8 +13 +4969 + + +13 +56 +675 @@ -27226,19 +27649,19 @@ expr_parent -4738577 +7178046 expr -4738577 +7178046 index -7172 +8196 parent -3074959 +4743008 @@ -27252,7 +27675,7 @@ 1 2 -4738577 +7178046 @@ -27268,7 +27691,7 @@ 1 2 -4738577 +7178046 @@ -27284,27 +27707,27 @@ 1 2 -1 +1024 2 3 -3434 +3435 3 4 -2717 +2522 4 -7 -601 +9 +699 -7 -2212725 -419 +9 +3426742 +516 @@ -27320,27 +27743,27 @@ 1 2 -1 +1024 2 3 -3434 +3435 3 4 -2717 +2522 4 -7 -601 +9 +699 -7 -2212725 -419 +9 +3426742 +516 @@ -27356,22 +27779,22 @@ 1 2 -1908468 +2972682 2 3 -878461 +1395233 3 -5 -250958 +7 +359960 -5 -7169 -37072 +7 +8193 +15133 @@ -27387,22 +27810,22 @@ 1 2 -1908468 +2972682 2 3 -878461 +1395233 3 -5 -250958 +7 +359960 -5 -7169 -37072 +7 +8193 +15133 @@ -27412,11 +27835,11 @@ expr_parent_top_level -150528 +239299 expr -150528 +239299 index @@ -27424,7 +27847,7 @@ parent -106198 +179958 @@ -27438,7 +27861,7 @@ 1 2 -150528 +239299 @@ -27454,7 +27877,7 @@ 1 2 -150528 +239299 @@ -27478,38 +27901,38 @@ 1 -90 -91 +135 +136 1 -227 -228 +383 +384 1 -776 -777 +1297 +1298 1 -1641 -1642 +3062 +3063 1 -5737 -5738 +9978 +9979 1 -41969 -41970 +46561 +46562 1 -100036 -100037 +177831 +177832 1 @@ -27534,38 +27957,38 @@ 1 -90 -91 +135 +136 1 -227 -228 +383 +384 1 -776 -777 +1297 +1298 1 -1641 -1642 +3062 +3063 1 -5737 -5738 +9593 +9594 1 -41969 -41970 +46561 +46562 1 -100027 -100028 +169840 +169841 1 @@ -27582,17 +28005,17 @@ 1 2 -64654 +126296 2 3 -39903 +50329 3 -9 -1641 +129 +3333 @@ -27608,17 +28031,17 @@ 1 2 -64663 +133922 2 3 -39894 +42974 3 9 -1641 +3062 @@ -27628,22 +28051,22 @@ implicitly_typed_array_creation -11922 +12576 id -11922 +12576 explicitly_sized_array_creation -1067 +4077 id -1067 +4077 @@ -27692,26 +28115,26 @@ expr_compiler_generated -333735 +593552 id -333735 +593552 expr_value -975810 +1399433 id -975810 +1399433 value -148629 +185734 @@ -27725,7 +28148,7 @@ 1 2 -975810 +1399433 @@ -27741,22 +28164,22 @@ 1 2 -110088 +135437 2 3 -18409 +25714 3 7 -12465 +15324 7 -62610 -7667 +144837 +9259 @@ -27766,15 +28189,15 @@ expr_call -926537 +1347739 caller_id -926537 +1347739 target_id -106839 +157393 @@ -27788,7 +28211,7 @@ 1 2 -926537 +1347739 @@ -27804,32 +28227,32 @@ 1 2 -59013 +85183 2 3 -19203 +29466 3 4 -8209 +12338 4 7 -9384 +14239 7 25 -8038 +11905 25 -32692 -2992 +35631 +4262 @@ -27839,15 +28262,15 @@ expr_access -1851048 +2855307 accesser_id -1851048 +2855307 target_id -493998 +725838 @@ -27861,7 +28284,7 @@ 1 2 -1851048 +2855307 @@ -27877,32 +28300,37 @@ 1 2 -148659 +216414 2 3 -161012 +211536 3 4 -78460 +116569 4 5 -39494 +63157 5 -8 -38236 +7 +55255 -8 -20124 -28137 +7 +24 +54454 + + +24 +20125 +8453 @@ -27912,15 +28340,15 @@ expr_location -4889105 +7417345 id -4889105 +7417345 loc -4391516 +6768067 @@ -27934,7 +28362,7 @@ 1 2 -4889105 +7417345 @@ -27950,17 +28378,17 @@ 1 2 -3970377 +6140047 2 3 -376052 +613291 3 143 -45087 +14729 @@ -27970,11 +28398,11 @@ dynamic_member_name -976 +977 id -976 +977 name @@ -27992,7 +28420,7 @@ 1 2 -976 +977 @@ -28013,12 +28441,12 @@ 2 3 -51 +50 3 4 -30 +31 4 @@ -28043,22 +28471,22 @@ conditional_access -2576 +3445 id -2576 +3445 expr_argument -1169007 +1536561 id -1169007 +1536561 mode @@ -28076,7 +28504,7 @@ 1 2 -1169007 +1536561 @@ -28090,23 +28518,23 @@ 12 -97 -98 +123 +124 1 -5611 -5612 +10881 +10882 1 -10517 -10518 +16880 +16881 1 -1152782 -1152783 +1508677 +1508678 1 @@ -28117,15 +28545,15 @@ expr_argument_name -70217 +75690 id -70217 +75690 name -3869 +4374 @@ -28139,7 +28567,7 @@ 1 2 -70217 +75690 @@ -28155,47 +28583,47 @@ 1 2 -1148 +1356 2 3 -740 +859 3 4 -372 +424 4 5 -300 +327 5 7 -300 +331 7 12 -325 +375 12 -23 -302 +25 +340 -23 -88 -291 +25 +259 +329 -88 -10911 -91 +262 +10879 +33 @@ -32449,11 +32877,11 @@ commentline -348293 +618446 id -348293 +618446 kind @@ -32461,11 +32889,11 @@ text -178314 +304702 rawtext -180589 +309171 @@ -32479,7 +32907,7 @@ 1 2 -348293 +618446 @@ -32495,7 +32923,7 @@ 1 2 -348293 +618446 @@ -32511,7 +32939,7 @@ 1 2 -348293 +618446 @@ -32525,18 +32953,18 @@ 12 -2025 -2026 +12000 +12001 1 -155568 -155569 +276055 +276056 1 -190700 -190701 +330391 +330392 1 @@ -32551,18 +32979,18 @@ 12 -925 -926 +5817 +5818 1 -53848 -53849 +98398 +98399 1 -123958 -123959 +201704 +201705 1 @@ -32577,18 +33005,18 @@ 12 -1024 -1025 +6340 +6341 1 -54132 -54133 +99142 +99143 1 -125433 -125434 +203689 +203690 1 @@ -32605,17 +33033,17 @@ 1 2 -148797 +252156 2 3 -19726 +34923 3 -31960 -9791 +49511 +17623 @@ -32631,12 +33059,12 @@ 1 2 -177910 +303526 2 4 -404 +1176 @@ -32652,12 +33080,12 @@ 1 2 -176699 +301509 2 -52 -1615 +86 +3193 @@ -32673,17 +33101,17 @@ 1 2 -151083 +256975 2 3 -19835 +34845 3 -31893 -9671 +49420 +17351 @@ -32699,7 +33127,7 @@ 1 2 -180589 +309171 @@ -32715,7 +33143,7 @@ 1 2 -180589 +309171 @@ -32725,15 +33153,15 @@ commentline_location -348293 +618446 id -348293 +618446 loc -348293 +618446 @@ -32747,7 +33175,7 @@ 1 2 -348293 +618446 @@ -32763,7 +33191,7 @@ 1 2 -348293 +618446 @@ -32773,26 +33201,26 @@ commentblock -142586 +247138 id -142586 +247138 commentblock_location -142586 +247138 id -142586 +247138 loc -142586 +247138 @@ -32806,7 +33234,7 @@ 1 2 -142586 +247138 @@ -32822,7 +33250,7 @@ 1 2 -142586 +247138 @@ -32832,15 +33260,15 @@ commentblock_binding -447717 +794277 id -142583 +247103 entity -190431 +339770 bindtype @@ -32858,22 +33286,22 @@ 1 2 -51033 +64059 2 3 -24776 +47892 3 4 -63952 +134744 4 -25 -2822 +7 +408 @@ -32889,22 +33317,22 @@ 1 2 -10757 +19446 2 3 -40830 +44772 3 4 -25115 +47839 4 5 -65881 +135046 @@ -32920,22 +33348,17 @@ 1 2 -140143 +247642 2 3 -35948 +67118 3 -68 -14284 - - -69 -1882 -56 +8449 +25010 @@ -32951,22 +33374,22 @@ 1 2 -82511 +146681 2 3 -81857 +146587 3 4 -25421 +45202 4 5 -642 +1300 @@ -32980,23 +33403,23 @@ 12 -70390 -70391 +143047 +143048 1 -101775 -101776 +202047 +202048 1 -127314 -127315 +220046 +220047 1 -131807 -131808 +227551 +227552 1 @@ -33011,23 +33434,23 @@ 12 -52557 -52558 +85120 +85121 1 -70536 -70537 +134653 +134654 1 -100163 -100164 +175047 +175048 1 -101800 -101801 +185841 +185842 1 @@ -33038,19 +33461,19 @@ commentblock_child -347934 +618012 id -142586 +247138 commentline -347934 +618012 index -297 +1135 @@ -33064,63 +33487,73 @@ 1 2 -60572 +119292 + + +2 +3 +47018 + + +3 +4 +42534 + + +4 +6 +19386 + + +6 +32 +18550 + + +32 +1136 +358 + + + + + + +id +index + + +12 + + +1 +2 +119292 2 3 -39466 +47018 3 4 -20594 +42534 4 6 -11412 +19386 6 -298 -10542 - - - - - - -id -index - - -12 - - -1 -2 -60572 - - -2 -3 -39466 - - -3 -4 -20594 - - -4 -6 -11412 +32 +18550 -6 -298 -10542 +32 +1136 +358 @@ -33136,7 +33569,7 @@ 1 2 -347934 +618012 @@ -33152,7 +33585,7 @@ 1 2 -347934 +618012 @@ -33168,42 +33601,37 @@ 1 2 -53 +623 2 3 -115 +73 3 4 -9 +142 4 -6 -26 - - -6 -10 -25 +9 +56 -10 -40 -23 +9 +12 +101 -42 -216 -23 +12 +95 +86 -237 -142587 -23 +96 +247139 +54 @@ -33219,42 +33647,37 @@ 1 2 -53 +623 2 3 -115 +73 3 4 -9 +142 4 -6 -26 - - -6 -10 -25 +9 +56 -10 -40 -23 +9 +12 +101 -42 -216 -23 +12 +95 +86 -237 -142587 -23 +96 +247139 +54 @@ -34804,11 +35227,11 @@ cil_instruction -11738854 +17762677 id -11738854 +17762677 opcode @@ -34820,7 +35243,7 @@ impl -764571 +1075745 @@ -34834,7 +35257,7 @@ 1 2 -11738854 +17762677 @@ -34850,7 +35273,7 @@ 1 2 -11738854 +17762677 @@ -34866,7 +35289,7 @@ 1 2 -11738854 +17762677 @@ -34881,67 +35304,67 @@ 1 -14 +31 16 -16 -50 +34 +103 16 -52 -113 +107 +272 16 -127 -392 +291 +761 16 -402 -805 +786 +1799 16 -882 -1781 +1819 +3232 16 -1840 -3594 +3540 +6280 16 -3656 -7680 +6599 +13336 16 -7691 -15395 +13561 +25517 16 -15628 -41250 +26360 +58843 16 -41579 -101314 +60259 +150959 16 -108039 -267456 +153187 +397705 16 -269151 -1219506 +421486 +1761436 13 @@ -34957,68 +35380,68 @@ 1 -9 -16 +17 +17 -9 -28 +19 +53 16 -30 -61 +53 +103 16 -65 -116 +115 +193 16 -123 -202 +202 +296 16 -203 -304 +299 +415 16 -304 -401 +416 +524 16 -406 -524 +551 +705 16 -526 -686 +708 +857 16 -687 -853 +867 +1037 16 -886 -1103 +1044 +1359 16 -1135 -1907 +1384 +2339 16 -1974 -3722 -13 +2493 +4004 +12 @@ -35033,68 +35456,68 @@ 1 -7 +16 16 -7 -21 -17 +16 +49 +16 -25 -69 +54 +133 16 -72 -190 +148 +476 16 -214 -466 +485 +819 16 -489 -963 +849 +1544 16 -964 -1633 +1656 +2600 16 -1646 -4521 +2888 +7581 16 -4775 -9554 +7638 +16576 16 -10805 -22012 +16749 +28630 16 -23094 -44749 +29955 +66775 16 -48809 -119795 +72210 +156029 16 -131667 -534809 -12 +176525 +758788 +13 @@ -35134,48 +35557,48 @@ 6 -8 +9 248 -8 -9 -336 +9 +13 +472 -9 -11 -376 +13 +23 +493 -11 -16 -461 +23 +39 +435 -17 -26 -467 +40 +80 +424 -26 -72 -420 +80 +317 +422 -72 -315 +317 +1566 419 -315 -4330 +1569 +92206 419 -4367 -764572 -229 +94672 +1075746 +43 @@ -35206,52 +35629,52 @@ 4 5 -282 +281 5 6 -473 +449 6 -8 -473 - - -8 9 -329 +482 9 -11 -389 +12 +435 -11 -14 -423 +12 +17 +474 -14 -22 -452 +17 +26 +453 -22 -49 -420 +26 +45 +428 -49 -93 -421 +45 +79 +424 -93 -169 -358 +79 +136 +422 + + +136 +175 +172 @@ -35291,48 +35714,48 @@ 6 -8 +9 248 -8 -9 -336 +9 +13 +472 -9 -11 -376 +13 +23 +493 -11 -16 -461 +23 +39 +435 -17 -26 -467 +40 +80 +424 -26 -72 -420 +80 +317 +422 -72 -315 +317 +1566 419 -315 -4330 +1569 +92206 419 -4367 -764572 -229 +94672 +1075746 +43 @@ -35348,52 +35771,52 @@ 1 2 -20708 +27075 2 3 -239575 +283722 3 4 -95590 +178628 4 5 -54260 +76302 5 7 -62698 +91491 7 10 -62426 +93902 10 15 -62313 +83468 15 26 -60287 +84044 26 53 -58090 +82354 53 5580 -48624 +74759 @@ -35409,57 +35832,57 @@ 1 2 -20708 +27075 2 3 -239654 +284008 3 4 -98321 +190914 4 5 -64878 +92479 5 6 -49135 +60711 6 7 -34933 +48353 7 9 -63779 +90930 9 -12 -58221 +13 +98471 -12 -18 -60506 +13 +20 +84244 -18 -32 -58247 +20 +35 +80775 -32 +35 77 -16189 +17785 @@ -35475,52 +35898,52 @@ 1 2 -20708 +27075 2 3 -239575 +283722 3 4 -95590 +178628 4 5 -54260 +76302 5 7 -62698 +91491 7 10 -62426 +93902 10 15 -62313 +83468 15 26 -60287 +84044 26 53 -58090 +82354 53 5580 -48624 +74759 @@ -35530,15 +35953,15 @@ cil_jump -959958 +1461276 instruction -959958 +1461276 target -753795 +1171285 @@ -35552,7 +35975,7 @@ 1 2 -959958 +1461276 @@ -35568,17 +35991,17 @@ 1 2 -646657 +1023904 2 3 -69975 +95406 3 256 -37163 +51975 @@ -35588,15 +36011,15 @@ cil_access -4229231 +6097501 instruction -4229231 +6097501 target -1029648 +1342773 @@ -35610,7 +36033,7 @@ 1 2 -4229231 +6097501 @@ -35626,37 +36049,37 @@ 1 2 -376838 +400905 2 3 -298666 +452358 3 4 -118675 +149466 4 5 -72560 +105242 5 8 -84020 +116951 8 -125 -77235 +30 +100903 -125 -34817 -1654 +30 +47893 +16948 @@ -35666,15 +36089,15 @@ cil_value -368821 +556329 instruction -368821 +556329 value -61708 +86381 @@ -35688,7 +36111,7 @@ 1 2 -368821 +556329 @@ -35704,32 +36127,32 @@ 1 2 -27735 +37537 2 3 -19017 +26864 3 4 -4145 +6509 4 -7 -5590 +6 +6181 -7 -57 -4629 +6 +18 +6520 -57 -93559 -592 +18 +153323 +2770 @@ -35739,11 +36162,11 @@ cil_switch -128085 +154637 instruction -8423 +11344 index @@ -35751,7 +36174,7 @@ target -46102 +65029 @@ -35770,52 +36193,47 @@ 3 4 -2198 +2846 4 5 -1324 +1845 5 6 -1027 +1459 6 7 -534 +727 7 -8 -473 - - -8 -11 -749 +9 +1045 -11 -15 -656 +9 +12 +879 -15 -27 -684 +12 +18 +952 -27 -154 -722 +18 +32 +885 -154 +32 412 -34 +684 @@ -35831,47 +36249,47 @@ 1 2 -89 +58 2 3 -948 +1036 3 4 -2671 +3463 4 5 -1769 +2605 5 6 -773 +1040 6 7 -509 +700 7 10 -691 +996 10 -17 -670 +16 +862 -17 +16 256 -303 +584 @@ -35916,37 +36334,37 @@ 27 -32 +34 35 -33 -353 +35 +355 32 -354 -370 +356 +376 31 -370 -418 +376 +434 31 -418 -547 +434 +626 31 -554 -6204 +640 +8477 31 -8401 -8424 +11322 +11345 3 @@ -35992,37 +36410,37 @@ 27 -32 +34 35 -33 -353 +35 +355 32 -354 -370 +356 +376 31 -370 -418 +376 +434 31 -418 -538 +434 +617 31 -546 -6052 +632 +8262 31 -8212 -8304 +11061 +11172 3 @@ -36039,12 +36457,12 @@ 1 2 -45517 +64116 2 12 -585 +913 @@ -36060,17 +36478,17 @@ 1 2 -39139 +56028 2 4 -3821 +5079 4 247 -3142 +3922 @@ -36122,15 +36540,15 @@ cil_type_location -152210 +212852 id -89583 +118809 loc -1126 +1701 @@ -36144,22 +36562,27 @@ 1 2 -44965 +52292 2 3 -32740 +50361 3 4 -5869 +6744 4 -10 -6009 +6 +9035 + + +6 +16 +377 @@ -36175,47 +36598,57 @@ 1 2 -432 +464 2 -5 -88 +3 +27 -5 -11 -98 +3 +4 +170 -11 -19 -86 +4 +9 +150 -19 -33 -85 +9 +14 +130 -33 -71 -86 +14 +23 +144 -72 -144 -85 +23 +37 +133 -144 -447 -85 +37 +66 +128 -447 -3291 -81 +66 +137 +129 + + +138 +416 +128 + + +434 +11741 +98 @@ -36225,15 +36658,15 @@ cil_method_location -1165492 +1622420 id -726017 +939512 loc -691 +1234 @@ -36247,22 +36680,27 @@ 1 2 -418176 +474427 2 3 -221887 +340605 3 4 -41809 +49527 4 -10 -44145 +6 +71871 + + +6 +16 +3082 @@ -36277,73 +36715,73 @@ 1 -14 -53 +2 +7 -14 -32 -55 +2 +3 +130 -32 -61 -52 +3 +17 +94 -61 -100 -53 +17 +44 +95 -100 -154 -53 +44 +78 +95 -155 -213 -52 +78 +121 +96 -217 -292 -54 +122 +179 +93 -295 -415 -52 +180 +247 +94 -424 -615 -52 +248 +360 +93 -619 -1106 -52 +362 +520 +94 -1127 -2065 -52 +520 +887 +93 -2113 -4064 -52 +887 +1666 +93 -4078 -25628 -52 +1683 +5309 +93 -28337 -33613 -7 +5436 +59205 +64 @@ -36353,15 +36791,15 @@ cil_type -343192 +310744 id -343192 +310744 name -53588 +69903 kind @@ -36369,11 +36807,11 @@ parent -91545 +54196 sourceDecl -197636 +189847 @@ -36387,7 +36825,7 @@ 1 2 -343192 +310744 @@ -36403,7 +36841,7 @@ 1 2 -343192 +310744 @@ -36419,7 +36857,7 @@ 1 2 -343192 +310744 @@ -36435,7 +36873,7 @@ 1 2 -343192 +310744 @@ -36451,27 +36889,22 @@ 1 2 -37936 +41024 2 3 -7739 +18965 3 -4 -2848 - - -4 -9 -4115 +5 +5619 -9 -73139 -950 +5 +33435 +4295 @@ -36487,7 +36920,7 @@ 1 2 -53588 +69903 @@ -36503,17 +36936,17 @@ 1 2 -46572 +60864 2 3 -4953 +6391 3 -73139 -2063 +33435 +2648 @@ -36529,22 +36962,22 @@ 1 2 -39647 +42608 2 3 -7512 +19051 3 -5 -4604 +6 +6151 -5 -73139 -1825 +6 +33435 +2093 @@ -36558,23 +36991,23 @@ 12 -440 -441 +638 +639 1 -8222 -8223 +6961 +6962 1 -98272 -98273 +53658 +53659 1 -236158 -236159 +249378 +249379 1 @@ -36594,18 +37027,18 @@ 1 -350 -351 +447 +448 1 -1788 -1789 +2112 +2113 1 -51410 -51411 +67304 +67305 1 @@ -36625,18 +37058,18 @@ 1 -139 -140 +200 +201 1 -19206 -19207 +21759 +21760 1 -73138 -73139 +33434 +33435 1 @@ -36651,23 +37084,23 @@ 12 -440 -441 +638 +639 1 -7605 -7606 +6112 +6113 1 -91319 -91320 +53658 +53659 1 -98272 -98273 +129439 +129440 1 @@ -36684,22 +37117,22 @@ 1 2 -69148 +36999 2 3 -15292 +8838 3 -70 -6868 +6 +4361 -70 -54255 -237 +6 +39242 +3998 @@ -36715,17 +37148,22 @@ 1 2 -69364 +37293 2 3 -15415 +8985 3 -2161 -6766 +6 +4275 + + +6 +2536 +3643 @@ -36741,12 +37179,12 @@ 1 2 -90607 +52999 2 4 -938 +1197 @@ -36762,17 +37200,22 @@ 1 2 -69323 +37238 2 3 -15415 +8978 3 -9130 -6807 +6 +4253 + + +6 +8395 +3727 @@ -36788,12 +37231,12 @@ 1 2 -191008 +181709 2 -11648 -6628 +5085 +8138 @@ -36809,7 +37252,7 @@ 1 2 -197636 +189847 @@ -36825,7 +37268,7 @@ 1 2 -197636 +189847 @@ -36841,12 +37284,12 @@ 1 2 -195187 +186967 2 491 -2449 +2880 @@ -36856,15 +37299,15 @@ cil_pointer_type -440 +638 id -440 +638 pointee -440 +638 @@ -36878,7 +37321,7 @@ 1 2 -440 +638 @@ -36894,7 +37337,7 @@ 1 2 -440 +638 @@ -36904,15 +37347,15 @@ cil_array_type -8222 +6961 id -8222 +6961 element_type -8198 +6928 rank @@ -36930,7 +37373,7 @@ 1 2 -8222 +6961 @@ -36946,7 +37389,7 @@ 1 2 -8222 +6961 @@ -36962,12 +37405,12 @@ 1 2 -8176 +6898 2 4 -22 +30 @@ -36983,12 +37426,12 @@ 1 2 -8176 +6898 2 4 -22 +30 @@ -37002,18 +37445,18 @@ 12 -4 -5 +8 +9 1 -26 -27 +31 +32 1 -8192 -8193 +6922 +6923 1 @@ -37028,18 +37471,18 @@ 12 -4 -5 +8 +9 1 -26 -27 +31 +32 1 -8192 -8193 +6922 +6923 1 @@ -37050,23 +37493,23 @@ cil_method -982868 +1164170 id -982868 +1164170 name -161199 +196164 parent -136179 +166238 return_type -109834 +90658 @@ -37080,7 +37523,7 @@ 1 2 -982868 +1164170 @@ -37096,7 +37539,7 @@ 1 2 -982868 +1164170 @@ -37112,7 +37555,7 @@ 1 2 -982868 +1164170 @@ -37128,32 +37571,32 @@ 1 2 -84543 +91448 2 3 -36569 +46810 3 4 -10379 +18752 4 6 -12506 +15548 6 -16 -12221 +13 +15554 -16 -109404 -4981 +13 +131916 +8052 @@ -37169,32 +37612,32 @@ 1 2 -89508 +96428 2 3 -35748 +46661 3 4 -9567 +17952 4 6 -11701 +14538 6 -23 -12183 +15 +14970 -23 -87224 -2492 +15 +103427 +5615 @@ -37210,22 +37653,17 @@ 1 2 -133751 +162790 2 3 -15357 +19275 3 -6995 -12090 - - -7095 -7096 -1 +7390 +14099 @@ -37241,42 +37679,47 @@ 1 2 -40455 +46618 2 3 -26404 +31338 3 4 -16912 +20193 4 5 -10810 +14379 5 7 -11129 +14505 7 10 -10666 +13582 10 -18 -10760 +17 +12893 -18 -13475 -9043 +17 +197 +12468 + + +197 +6088 +262 @@ -37292,42 +37735,47 @@ 1 2 -42239 +48881 2 3 -27319 +32472 3 4 -17627 +20980 4 5 -11309 +14854 5 -7 -12205 +6 +8121 -7 -11 -11242 +6 +8 +12842 -11 -26 -10224 +8 +13 +13194 -26 +13 +43 +12517 + + +43 3766 -4014 +2377 @@ -37343,37 +37791,37 @@ 1 2 -54109 +63599 2 3 -33724 +40692 3 4 -17338 +22116 4 5 -8609 +11345 5 7 -11498 +14610 7 -27 -10243 +20 +12473 -27 -7169 -658 +20 +3066 +1403 @@ -37389,27 +37837,32 @@ 1 2 -75434 +49584 2 3 -15073 +17237 3 -5 -8716 +4 +7858 -5 -20 -8307 +4 +7 +7467 -20 -322198 -2304 +7 +31 +6851 + + +31 +402822 +1661 @@ -37425,22 +37878,27 @@ 1 2 -83942 +61071 2 3 -13387 +15140 3 -7 -8631 +5 +7349 -7 -43617 -3874 +5 +60 +6802 + + +60 +53362 +296 @@ -37456,22 +37914,27 @@ 1 2 -81013 +55043 2 3 -14595 +16656 3 -6 -9185 +4 +7537 -6 -101084 -5041 +4 +8 +7186 + + +8 +123711 +4236 @@ -37481,15 +37944,15 @@ cil_method_source_declaration -891568 +1075007 method -891568 +1075007 source -785482 +976101 @@ -37503,7 +37966,7 @@ 1 2 -891568 +1075007 @@ -37519,17 +37982,12 @@ 1 2 -709384 +933517 2 -3 -65448 - - -3 -306 -10650 +565 +42584 @@ -37539,19 +37997,19 @@ cil_method_implementation -1040241 +1351436 id -1040241 +1351436 method -647453 +788230 location -659 +1200 @@ -37565,7 +38023,7 @@ 1 2 -1040241 +1351436 @@ -37581,7 +38039,7 @@ 1 2 -1040241 +1351436 @@ -37597,22 +38055,27 @@ 1 2 -369448 +419065 2 3 -203313 +258887 3 4 -36064 +43514 4 -10 -38628 +6 +63854 + + +6 +16 +2910 @@ -37628,22 +38091,27 @@ 1 2 -369448 +419085 2 3 -203313 +258867 3 4 -36064 +43514 4 -10 -38628 +6 +63854 + + +6 +16 +2910 @@ -37658,73 +38126,73 @@ 1 -12 -50 +2 +13 -12 -31 -52 +2 +3 +131 -31 -54 -51 +3 +17 +93 -54 -87 -50 +18 +42 +90 -89 -143 -50 +42 +73 +91 -143 -204 -51 +73 +109 +90 -208 -270 -51 +109 +172 +90 -270 -371 -50 +174 +225 +91 -376 -540 -51 +225 +328 +90 -550 -1119 -51 +329 +450 +90 -1120 -2075 -50 +451 +834 +90 -2100 -4503 -50 +840 +1640 +90 -4651 -32572 -50 +1642 +4858 +90 -32984 +5076 33031 -2 +61 @@ -37739,73 +38207,73 @@ 1 -12 -50 +2 +13 -12 -31 -52 +2 +3 +131 -31 -54 -51 +3 +17 +93 -54 -87 -50 +18 +42 +90 -89 -143 -50 +42 +73 +91 -143 -204 -51 +73 +109 +90 -208 -270 -51 +109 +172 +90 -270 -371 -50 +174 +225 +91 -376 -540 -51 +225 +328 +90 -550 -1119 -51 +329 +450 +90 -1120 -2075 -50 +451 +834 +90 -2100 -4503 -50 +840 +1640 +90 -4651 -32572 -50 +1642 +4858 +90 -32984 +5076 33031 -2 +61 @@ -37815,15 +38283,15 @@ cil_implements -46066 +77303 id -43911 +74672 decl -11125 +32636 @@ -37837,12 +38305,12 @@ 1 2 -42414 +72729 2 5 -1497 +1943 @@ -37858,22 +38326,22 @@ 1 2 -7900 +27601 2 3 -1673 +2530 3 -6 -904 +85 +2450 -6 +86 2300 -648 +55 @@ -37883,23 +38351,23 @@ cil_field -373454 +459117 id -373454 +459117 parent -63864 +78097 name -141811 +163874 field_type -55057 +66956 @@ -37913,7 +38381,7 @@ 1 2 -373454 +459117 @@ -37929,7 +38397,7 @@ 1 2 -373454 +459117 @@ -37945,7 +38413,7 @@ 1 2 -373454 +459117 @@ -37961,47 +38429,47 @@ 1 2 -16008 +18670 2 3 -13743 +16155 3 4 -7634 +9581 4 5 -6078 +7771 5 6 -4068 +5300 6 8 -5334 +6837 8 12 -5499 +6885 12 -34 -4814 +33 +5931 -34 +33 4792 -686 +967 @@ -38017,47 +38485,47 @@ 1 2 -16008 +18670 2 3 -13743 +16155 3 4 -7634 +9581 4 5 -6078 +7771 5 6 -4068 +5300 6 8 -5334 +6837 8 12 -5499 +6885 12 -34 -4814 +33 +5931 -34 +33 4792 -686 +967 @@ -38073,37 +38541,37 @@ 1 2 -19045 +22569 2 3 -22202 +28213 3 4 -7167 +8776 4 5 -4134 +5004 5 7 -4819 +5963 7 13 -4989 +5897 13 -172 -1508 +569 +1675 @@ -38119,22 +38587,22 @@ 1 2 -96617 +105589 2 3 -24916 +32731 3 5 -11640 +13968 5 -7385 -8638 +10637 +11586 @@ -38150,22 +38618,22 @@ 1 2 -96617 +105589 2 3 -24916 +32731 3 5 -11640 +13968 5 -7385 -8638 +10637 +11586 @@ -38181,22 +38649,22 @@ 1 2 -111626 +125364 2 3 -18303 +23735 3 -12 -10801 +10 +12597 -12 -4061 -1081 +10 +4427 +2178 @@ -38212,32 +38680,37 @@ 1 2 -27378 +32076 2 3 -12337 +15156 3 4 -3618 +4604 4 -6 -4812 +5 +4144 -6 -13 -4248 +5 +9 +5779 -13 -49751 -2664 +9 +160 +5023 + + +161 +63270 +174 @@ -38253,22 +38726,22 @@ 1 2 -34264 +41592 2 3 -12721 +15722 3 5 -4135 +5025 5 -21009 -3937 +27862 +4617 @@ -38284,27 +38757,32 @@ 1 2 -36493 +43052 2 3 -6728 +8271 3 4 -3371 +4356 4 7 -4516 +6059 7 -23165 -3949 +89 +5022 + + +90 +25354 +196 @@ -38314,15 +38792,15 @@ cil_parameter -1904597 +2241273 id -1904597 +2241273 method -921545 +1091090 index @@ -38330,7 +38808,7 @@ param_type -233580 +227413 @@ -38344,7 +38822,7 @@ 1 2 -1904597 +2241273 @@ -38360,7 +38838,7 @@ 1 2 -1904597 +2241273 @@ -38376,7 +38854,7 @@ 1 2 -1904597 +2241273 @@ -38392,27 +38870,27 @@ 1 2 -373799 +457241 2 3 -323581 +371753 3 4 -133559 +150895 4 7 -74604 +92314 7 53 -16002 +18887 @@ -38428,27 +38906,27 @@ 1 2 -373799 +457241 2 3 -323581 +371753 3 4 -133559 +150895 4 7 -74604 +92314 7 53 -16002 +18887 @@ -38464,27 +38942,27 @@ 1 2 -397141 +478810 2 3 -328789 +381799 3 4 -125672 +146612 4 -11 -69153 +10 +82574 -11 +10 41 -790 +1295 @@ -38508,58 +38986,58 @@ 11 -12 -13 +10 +11 3 -15 -16 +13 +14 3 -16 -28 +14 +30 4 -36 -58 +38 +62 4 -64 -98 +68 +105 4 -114 -197 +123 +217 4 -241 -572 +265 +641 4 -786 -2257 +877 +2572 4 -3431 -16003 +3932 +18888 4 -27777 -224166 +33136 +262097 4 -547746 -921546 +633849 +1091091 2 @@ -38584,58 +39062,58 @@ 11 -12 -13 +10 +11 3 -15 -16 +13 +14 3 -16 -28 +14 +30 4 -36 -58 +38 +62 4 -64 -98 +68 +105 4 -114 -197 +123 +217 4 -241 -572 +265 +641 4 -786 -2257 +877 +2572 4 -3431 -16003 +3932 +18888 4 -27777 -224166 +33136 +262097 4 -547746 -921546 +633849 +1091091 2 @@ -38660,53 +39138,53 @@ 2 -9 -10 +7 +8 5 -13 -21 +11 +19 4 -21 -31 +19 +30 4 -31 -39 +30 +38 4 -51 -67 +50 +71 4 -83 -176 +90 +194 4 -233 -501 +256 +552 4 -666 -1923 +744 +2266 4 -2805 -10797 +3354 +12987 4 -36393 -175126 +35950 +179765 3 @@ -38723,37 +39201,42 @@ 1 2 -98696 +67477 2 3 -47541 +53744 3 4 -20497 +22720 4 -6 -21504 +5 +15429 -6 -10 -19815 +5 +7 +20114 -10 -27 -17540 +7 +11 +19073 -27 -99475 -7987 +11 +24 +17383 + + +24 +127666 +11473 @@ -38769,37 +39252,42 @@ 1 2 -103646 +68945 2 3 -45853 +53403 3 4 -18465 +22604 4 -6 -21100 +5 +15196 -6 -10 -19543 +5 +7 +20025 -10 -28 -17569 +7 +11 +18906 -28 -80024 -7404 +11 +24 +17145 + + +24 +101271 +11189 @@ -38815,22 +39303,22 @@ 1 2 -170930 +161358 2 3 -42071 +44633 3 -6 -18729 +5 +17710 -6 +5 51 -1850 +3712 @@ -38840,37 +39328,37 @@ cil_parameter_in -23105 +55741 id -23105 +55741 cil_parameter_out -31233 +39090 id -31233 +39090 cil_setter -30179 +44695 prop -30179 +44695 method -30179 +44695 @@ -38884,7 +39372,7 @@ 1 2 -30179 +44695 @@ -38900,7 +39388,7 @@ 1 2 -30179 +44695 @@ -38910,15 +39398,15 @@ cil_getter -165951 +232515 prop -165951 +232515 method -165951 +232515 @@ -38932,7 +39420,7 @@ 1 2 -165951 +232515 @@ -38948,7 +39436,7 @@ 1 2 -165951 +232515 @@ -38958,15 +39446,15 @@ cil_adder -3719 +6369 event -3719 +6369 method -3719 +6369 @@ -38980,7 +39468,7 @@ 1 2 -3719 +6369 @@ -38996,7 +39484,7 @@ 1 2 -3719 +6369 @@ -39006,15 +39494,15 @@ cil_remover -3719 +6369 event -3719 +6369 method -3719 +6369 @@ -39028,7 +39516,7 @@ 1 2 -3719 +6369 @@ -39044,7 +39532,7 @@ 1 2 -3719 +6369 @@ -39102,23 +39590,23 @@ cil_property -166215 +232995 id -166215 +232995 parent -32452 +45688 name -46487 +60870 property_type -17696 +23848 @@ -39132,7 +39620,7 @@ 1 2 -166215 +232995 @@ -39148,7 +39636,7 @@ 1 2 -166215 +232995 @@ -39164,7 +39652,7 @@ 1 2 -166215 +232995 @@ -39180,42 +39668,42 @@ 1 2 -10930 +13054 2 3 -6385 +11267 3 4 -4050 +5670 4 5 -2722 +3802 5 -7 -2979 +6 +2462 -7 -11 -2655 +6 +8 +3199 -11 -39 -2439 +8 +14 +3555 -39 +14 3766 -292 +2679 @@ -39231,42 +39719,42 @@ 1 2 -10954 +15338 2 3 -6401 +9095 3 4 -4029 +5624 4 5 -2725 +3819 5 -7 -2999 +6 +2437 -7 -11 -2625 +6 +8 +3322 -11 -40 -2447 +8 +14 +3455 -40 +14 3766 -272 +2598 @@ -39282,32 +39770,32 @@ 1 2 -13163 +16716 2 3 -7694 +12911 3 4 -4314 +5999 4 5 -2403 +3365 5 8 -2921 +4175 8 50 -1957 +2522 @@ -39323,27 +39811,27 @@ 1 2 -27082 +31483 2 3 -10143 +16819 3 4 -2363 +2816 4 7 -3703 +5360 7 -2519 -3196 +5089 +4392 @@ -39359,27 +39847,27 @@ 1 2 -27082 +31483 2 3 -10143 +16827 3 4 -2363 +2821 4 7 -3704 +5354 7 -2519 -3195 +3124 +4385 @@ -39395,22 +39883,17 @@ 1 2 -39411 +51983 2 3 -3424 +4636 3 -17 -3493 - - -17 -1131 -159 +1437 +4251 @@ -39426,32 +39909,32 @@ 1 2 -10530 +12810 2 3 -2911 +5226 3 4 -1198 +1491 4 7 -1425 +2148 7 -40 -1336 +39 +1797 -40 -32241 -296 +39 +49263 +376 @@ -39467,27 +39950,32 @@ 1 2 -11216 +13648 2 3 -2687 +5033 3 4 -1142 +1436 4 -8 -1460 +7 +1894 -8 -10207 -1191 +7 +149 +1789 + + +152 +13924 +48 @@ -39503,22 +39991,22 @@ 1 2 -13415 +18376 2 3 -2299 +2969 3 -7 -1412 +8 +1886 -7 -13568 -570 +8 +21084 +617 @@ -39528,23 +40016,23 @@ cil_event -3719 +6340 id -3719 +6340 parent -1117 +2205 name -1471 +2130 event_type -1015 +1978 @@ -39558,7 +40046,7 @@ 1 2 -3719 +6340 @@ -39574,7 +40062,7 @@ 1 2 -3719 +6340 @@ -39590,7 +40078,7 @@ 1 2 -3719 +6340 @@ -39606,32 +40094,32 @@ 1 2 -565 +1143 2 3 -227 +438 3 4 -100 +212 4 -6 -97 +5 +115 -6 -14 -85 +5 +8 +168 -14 +8 127 -43 +129 @@ -39647,32 +40135,32 @@ 1 2 -565 +1143 2 3 -227 +438 3 4 -100 +212 4 -6 -97 +5 +115 -6 -14 -85 +5 +8 +168 -14 +8 127 -43 +129 @@ -39688,27 +40176,27 @@ 1 2 -702 +1402 2 3 -194 +372 3 4 -87 +198 4 -7 -90 +8 +176 -7 +8 39 -44 +57 @@ -39724,32 +40212,32 @@ 1 2 -816 +749 2 3 -268 +792 3 4 -130 +112 4 5 -117 +209 5 -15 -114 +9 +173 -15 -77 -26 +9 +88 +95 @@ -39765,32 +40253,32 @@ 1 2 -816 +749 2 3 -268 +792 3 4 -130 +112 4 5 -117 +209 5 -15 -114 +9 +173 -15 -77 -26 +9 +88 +95 @@ -39806,22 +40294,22 @@ 1 2 -1198 +1642 2 3 -103 +224 3 -4 -126 +5 +181 -4 -18 -44 +5 +25 +83 @@ -39837,27 +40325,27 @@ 1 2 -543 +647 2 3 -263 +984 3 4 -52 +58 4 6 -80 +148 6 1055 -77 +141 @@ -39873,27 +40361,22 @@ 1 2 -659 +784 2 3 -203 +999 3 -4 -53 - - -4 7 -78 +165 7 349 -22 +30 @@ -39909,17 +40392,17 @@ 1 2 -800 +1626 2 3 -139 +220 3 433 -76 +132 @@ -39929,15 +40412,15 @@ cil_local_variable -624672 +989635 id -624672 +989635 impl -195943 +292891 index @@ -39945,7 +40428,7 @@ var_type -55931 +69258 @@ -39959,7 +40442,7 @@ 1 2 -624672 +989635 @@ -39975,7 +40458,7 @@ 1 2 -624672 +989635 @@ -39991,7 +40474,7 @@ 1 2 -624672 +989635 @@ -40007,37 +40490,37 @@ 1 2 -90782 +132499 2 3 -33013 +49612 3 4 -20310 +30061 4 5 -12895 +19183 5 7 -16152 +24373 7 12 -15274 +23871 12 286 -7517 +13292 @@ -40053,37 +40536,37 @@ 1 2 -90782 +132499 2 3 -33013 +49612 3 4 -20310 +30061 4 5 -12895 +19183 5 7 -16152 +24373 7 12 -15274 +23871 12 286 -7517 +13292 @@ -40099,32 +40582,32 @@ 1 2 -98633 +147882 2 3 -40155 +63289 3 4 -20365 +30966 4 5 -12225 +17823 5 8 -16632 +23050 8 62 -7933 +9881 @@ -40145,37 +40628,52 @@ 2 3 -144 +26 -3 +4 5 +88 + + +6 +7 +4 + + +8 +9 26 -5 -12 -22 +10 +16 +24 -14 -46 +17 +33 +23 + + +34 +97 22 -48 -173 +100 +415 22 -181 -1532 +435 +2748 22 -1743 -195944 -21 +3102 +292892 +22 @@ -40196,37 +40694,52 @@ 2 3 -144 +26 -3 +4 5 +88 + + +6 +7 +4 + + +8 +9 26 -5 -12 -22 +10 +16 +24 -14 -46 +17 +33 +23 + + +34 +97 22 -48 -173 +100 +415 22 -181 -1532 +435 +2748 22 -1743 -195944 -21 +3102 +292892 +22 @@ -40242,47 +40755,52 @@ 1 2 -85 +12 2 3 -66 +85 3 4 -15 +49 4 -6 +7 25 -6 -17 +7 +10 23 -17 -38 +10 +28 22 -41 -293 +28 +79 22 -305 -6526 +81 +459 22 -8789 -32764 -5 +503 +13334 +22 + + +16802 +40620 +3 @@ -40298,37 +40816,37 @@ 1 2 -25298 +28957 2 3 -13407 +17276 3 4 -3534 +4168 4 6 -4383 +6351 6 -11 -4499 +10 +5195 -11 -72 -4201 +10 +33 +5228 -72 -121017 -609 +33 +279245 +2083 @@ -40344,32 +40862,37 @@ 1 2 -27445 +31734 2 3 -12868 +16810 3 4 -3534 +4152 4 6 -3993 +5775 6 12 -4215 +5561 12 -55100 -3876 +1221 +5195 + + +1227 +109010 +31 @@ -40385,27 +40908,27 @@ 1 2 -33173 +40009 2 3 -10821 +13804 3 4 -4081 +5323 4 7 -4716 +6061 7 -277 -3140 +279 +4061 @@ -40415,19 +40938,19 @@ cil_handler -38721 +54069 id -38721 +54069 impl -27322 +38434 index -19 +26 kind @@ -40435,15 +40958,15 @@ try_start -37216 +51487 try_end -37715 +52378 handler_start -38721 +54069 @@ -40457,7 +40980,7 @@ 1 2 -38721 +54069 @@ -40473,7 +40996,7 @@ 1 2 -38721 +54069 @@ -40489,7 +41012,7 @@ 1 2 -38721 +54069 @@ -40505,7 +41028,7 @@ 1 2 -38721 +54069 @@ -40521,7 +41044,7 @@ 1 2 -38721 +54069 @@ -40537,7 +41060,7 @@ 1 2 -38721 +54069 @@ -40553,22 +41076,22 @@ 1 2 -20370 +28919 2 3 -4581 +6239 3 6 -2137 +2953 6 -20 -234 +27 +323 @@ -40584,22 +41107,22 @@ 1 2 -20370 +28919 2 3 -4581 +6239 3 6 -2137 +2953 6 -20 -234 +27 +323 @@ -40615,17 +41138,17 @@ 1 2 -24183 +34351 2 3 -2974 +3890 3 4 -165 +193 @@ -40641,17 +41164,17 @@ 1 2 -20998 +30073 2 3 -4347 +5801 3 20 -1977 +2560 @@ -40667,22 +41190,17 @@ 1 2 -20729 +29584 2 3 -4509 +6080 3 -9 -2050 - - -9 20 -34 +2770 @@ -40698,22 +41216,22 @@ 1 2 -20370 +28919 2 3 -4581 +6239 3 6 -2137 +2953 6 -20 -234 +27 +323 @@ -40727,88 +41245,58 @@ 12 -1 -2 -2 - - 2 3 -2 - - -3 -4 -1 +7 4 5 -1 - - -10 -11 -1 +2 -20 -21 -1 +5 +6 +2 -27 -28 -1 +6 +8 +2 -30 -31 -1 +13 +25 +2 -42 +31 43 -1 - - -81 -82 -1 - - -135 -136 -1 - - -234 -235 -1 +2 -467 -468 -1 +60 +112 +2 -1017 -1018 -1 +184 +324 +2 -2371 -2372 -1 +620 +1392 +2 -6952 -6953 -1 +3276 +9516 +2 -27322 -27323 +38434 +38435 1 @@ -40823,88 +41311,58 @@ 12 -1 -2 -2 - - 2 3 -2 - - -3 -4 -1 +7 4 5 -1 - - -10 -11 -1 +2 -20 -21 -1 +5 +6 +2 -27 -28 -1 +6 +8 +2 -30 -31 -1 +13 +25 +2 -42 +31 43 -1 - - -81 -82 -1 - - -135 -136 -1 - - -234 -235 -1 +2 -467 -468 -1 +60 +112 +2 -1017 -1018 -1 +184 +324 +2 -2371 -2372 -1 +620 +1392 +2 -6952 -6953 -1 +3276 +9516 +2 -27322 -27323 +38434 +38435 1 @@ -40921,12 +41379,12 @@ 1 2 -2 +7 2 3 -7 +9 3 @@ -40950,88 +41408,58 @@ 12 -1 -2 -2 - - 2 3 -2 - - -3 -4 -1 +7 4 5 -1 - - -10 -11 -1 +2 -20 -21 -1 +5 +6 +2 -27 -28 -1 +6 +8 +2 -30 -31 -1 +13 +25 +2 -42 +31 43 -1 - - -81 -82 -1 - - -135 -136 -1 - - -234 -235 -1 +2 -467 -468 -1 +60 +112 +2 -1017 -1018 -1 +184 +324 +2 -2371 -2372 -1 +620 +1392 +2 -6952 -6953 -1 +3276 +9516 +2 -27322 -27323 +38434 +38435 1 @@ -41046,88 +41474,58 @@ 12 -1 -2 -2 - - 2 3 -2 - - -3 -4 -1 +7 4 5 -1 - - -10 -11 -1 +2 -20 -21 -1 +5 +6 +2 -27 -28 -1 +6 +8 +2 -30 -31 -1 +13 +25 +2 -42 +31 43 -1 - - -81 -82 -1 - - -135 -136 -1 - - -234 -235 -1 +2 -467 -468 -1 +60 +112 +2 -1017 -1018 -1 +184 +324 +2 -2371 -2372 -1 +620 +1392 +2 -6952 -6953 -1 +3276 +9516 +2 -27322 -27323 +38434 +38435 1 @@ -41142,88 +41540,58 @@ 12 -1 -2 -2 - - 2 3 -2 - - -3 -4 -1 +7 4 5 -1 - - -10 -11 -1 +2 -20 -21 -1 +5 +6 +2 -27 -28 -1 +6 +8 +2 -30 -31 -1 +13 +25 +2 -42 +31 43 -1 - - -81 -82 -1 - - -135 -136 -1 - - -234 -235 -1 +2 -467 -468 -1 +60 +112 +2 -1017 -1018 -1 +184 +324 +2 -2371 -2372 -1 +620 +1392 +2 -6952 -6953 -1 +3276 +9516 +2 -27322 -27323 +38434 +38435 1 @@ -41238,23 +41606,23 @@ 12 -742 -743 +901 +902 1 -799 -800 +931 +932 1 -10888 -10889 +16252 +16253 1 -26292 -26293 +35985 +35986 1 @@ -41269,23 +41637,23 @@ 12 -698 -699 +849 +850 1 -799 -800 +931 +932 1 -9008 -9009 +13194 +13195 1 -20121 -20122 +27736 +27737 1 @@ -41310,13 +41678,13 @@ 1 -17 -18 +19 +20 1 -19 -20 +26 +27 1 @@ -41331,23 +41699,23 @@ 12 -730 -731 +888 +889 1 -799 -800 +931 +932 1 -9963 -9964 +14647 +14648 1 -26282 -26283 +35975 +35976 1 @@ -41362,23 +41730,23 @@ 12 -730 -731 +888 +889 1 -799 -800 +931 +932 1 -9978 -9979 +14662 +14663 1 -26292 -26293 +35985 +35986 1 @@ -41393,23 +41761,23 @@ 12 -742 -743 +901 +902 1 -799 -800 +931 +932 1 -10888 -10889 +16252 +16253 1 -26292 -26293 +35985 +35986 1 @@ -41426,12 +41794,12 @@ 1 2 -36056 +49479 2 10 -1160 +2008 @@ -41447,7 +41815,7 @@ 1 2 -37216 +51487 @@ -41463,12 +41831,12 @@ 1 2 -36056 +49479 2 10 -1160 +2008 @@ -41484,12 +41852,12 @@ 1 2 -36674 +50549 2 4 -542 +938 @@ -41505,12 +41873,12 @@ 1 2 -36727 +50606 2 4 -489 +881 @@ -41526,12 +41894,12 @@ 1 2 -36056 +49479 2 10 -1160 +2008 @@ -41547,12 +41915,12 @@ 1 2 -36999 +51177 2 9 -716 +1201 @@ -41568,7 +41936,7 @@ 1 2 -37715 +52378 @@ -41584,12 +41952,12 @@ 1 2 -36999 +51177 2 9 -716 +1201 @@ -41605,12 +41973,12 @@ 1 2 -37631 +52290 2 3 -84 +88 @@ -41626,7 +41994,7 @@ 1 2 -37715 +52378 @@ -41642,12 +42010,12 @@ 1 2 -36999 +51177 2 9 -716 +1201 @@ -41663,7 +42031,7 @@ 1 2 -38721 +54069 @@ -41679,7 +42047,7 @@ 1 2 -38721 +54069 @@ -41695,7 +42063,7 @@ 1 2 -38721 +54069 @@ -41711,7 +42079,7 @@ 1 2 -38721 +54069 @@ -41727,7 +42095,7 @@ 1 2 -38721 +54069 @@ -41743,7 +42111,7 @@ 1 2 -38721 +54069 @@ -41753,15 +42121,15 @@ cil_handler_filter -742 +901 id -742 +901 filter_start -742 +901 @@ -41775,7 +42143,7 @@ 1 2 -742 +901 @@ -41791,7 +42159,7 @@ 1 2 -742 +901 @@ -41801,15 +42169,15 @@ cil_handler_type -10888 +16252 id -10888 +16252 catch_type -300 +441 @@ -41823,7 +42191,7 @@ 1 2 -10888 +16252 @@ -41839,47 +42207,52 @@ 1 2 -80 +102 2 3 -55 +78 3 4 -23 +32 4 5 -28 +43 5 8 -24 +36 8 12 -23 +40 12 -22 -25 +20 +34 -22 -56 -23 +20 +40 +35 -58 -3349 -19 +42 +268 +34 + + +299 +3353 +7 @@ -41889,11 +42262,11 @@ cil_method_stack_size -1040241 +1351436 method -1040241 +1351436 size @@ -41911,7 +42284,7 @@ 1 2 -1040241 +1351436 @@ -41942,38 +42315,43 @@ 10 12 -4 +2 12 -18 -4 +13 +3 -33 -78 +15 +38 4 -134 -816 +58 +146 4 -831 -3809 +166 +910 4 -6693 -22107 +1406 +8644 4 -25517 -830206 +16282 +39542 4 + +74163 +1041565 +3 + @@ -41982,169 +42360,169 @@ cil_public -681979 +883904 id -681979 +883904 cil_private -405970 +508798 id -405970 +508798 cil_protected -663333 +856296 id -663333 +856296 cil_internal -42022 +51633 id -42022 +51633 cil_static -422704 +459535 id -422704 +459535 cil_sealed -131092 +184038 id -131092 +184038 cil_virtual -276040 +375107 id -276040 +375107 cil_abstract -76553 +118976 id -76553 +118976 cil_class -89583 +103798 id -89583 +103798 cil_interface -8115 +15011 id -8115 +15011 cil_security -3903 +3935 id -3903 +3935 cil_requiresecobject -48 +72 id -48 +72 cil_specialname -310527 +415805 id -310527 +415805 cil_newslot -166898 +243445 id -166898 +243445 cil_base_class -85560 +108602 id -85560 +108602 base -7154 +8840 @@ -42158,7 +42536,7 @@ 1 2 -85560 +108602 @@ -42174,32 +42552,32 @@ 1 2 -3312 +4177 2 3 -1950 +2267 3 4 -634 +795 4 6 -564 +714 6 -24 -539 +20 +668 -24 -36427 -155 +20 +45957 +219 @@ -42209,15 +42587,15 @@ cil_base_interface -40265 +52126 id -19132 +25869 base -10540 +16465 @@ -42231,32 +42609,32 @@ 1 2 -11711 +16163 2 3 -2772 +3920 3 4 -1643 +2150 4 5 -466 +687 5 -6 -1645 +7 +2240 -6 -47 -895 +7 +49 +709 @@ -42272,22 +42650,22 @@ 1 2 -7652 +12889 2 3 -1307 +1648 3 -5 -835 +7 +1293 -5 +7 2300 -746 +635 @@ -42297,11 +42675,11 @@ cil_type_parameter -98272 +53658 unbound -73138 +33434 index @@ -42309,7 +42687,7 @@ param -98272 +53658 @@ -42323,17 +42701,17 @@ 1 2 -57933 +24838 2 3 -12999 +6183 3 41 -2206 +2413 @@ -42349,17 +42727,17 @@ 1 2 -57933 +24838 2 3 -12999 +6183 3 41 -2206 +2413 @@ -42373,48 +42751,48 @@ 12 -6 -7 +4 +5 16 -8 -11 +6 +9 3 -30 -71 +34 +87 3 -92 -169 +113 +205 3 -219 -322 +263 +382 3 -373 -489 +441 +579 3 -547 -737 +650 +887 3 -847 -1242 +1023 +1514 3 -2206 -73139 +2413 +33435 3 @@ -42429,48 +42807,48 @@ 12 -6 -7 +4 +5 16 -8 -11 +6 +9 3 -30 -71 +34 +87 3 -92 -169 +113 +205 3 -219 -322 +263 +382 3 -373 -489 +441 +579 3 -547 -737 +650 +887 3 -847 -1242 +1023 +1514 3 -2206 -73139 +2413 +33435 3 @@ -42487,7 +42865,7 @@ 1 2 -98272 +53658 @@ -42503,7 +42881,7 @@ 1 2 -98272 +53658 @@ -42513,11 +42891,11 @@ cil_type_argument -285765 +242722 bound -212638 +171457 index @@ -42525,7 +42903,7 @@ t -94872 +75242 @@ -42539,17 +42917,17 @@ 1 2 -156670 +120678 2 3 -49401 +43115 3 41 -6567 +7664 @@ -42565,17 +42943,17 @@ 1 2 -158825 +122717 2 3 -48373 +42236 3 41 -5440 +6504 @@ -42604,33 +42982,33 @@ 3 -16 -61 +15 +60 3 -91 -154 +90 +153 3 187 -268 +272 3 -308 -1324 +314 +1646 3 -1585 -2884 +1986 +3608 3 -6567 -212639 +7664 +171458 3 @@ -42675,23 +43053,23 @@ 3 -134 -195 +135 +200 3 -226 -914 +233 +1139 3 -921 -1510 +1143 +1878 3 -3492 -80006 +4004 +58848 3 @@ -42708,27 +43086,32 @@ 1 2 -44926 +32891 2 3 -30329 +20500 3 4 -8671 +9967 4 -8 -7431 +6 +5945 -8 -9142 -3515 +6 +43 +5650 + + +43 +7168 +289 @@ -42744,17 +43127,17 @@ 1 2 -78890 +60909 2 3 -14957 +13109 3 18 -1025 +1224 @@ -42855,19 +43238,19 @@ cil_attribute -140634 +248346 attributeid -140634 +248346 element -71402 +94117 constructor -750 +1217 @@ -42881,7 +43264,7 @@ 1 2 -140634 +248346 @@ -42897,7 +43280,7 @@ 1 2 -140634 +248346 @@ -42913,27 +43296,32 @@ 1 2 -33119 +35112 2 3 -26720 +33216 3 4 -3637 +3905 4 -6 -5549 +5 +8237 -6 -41 -2377 +5 +7 +7190 + + +7 +49 +6457 @@ -42949,22 +43337,22 @@ 1 2 -51190 +58737 2 3 -14687 +19785 3 -7 -5397 +4 +9074 -7 -11 -128 +4 +18 +6521 @@ -42980,67 +43368,67 @@ 1 2 -82 +97 2 3 -94 +130 3 4 -28 +38 4 5 -44 +143 5 +6 +47 + + +6 7 -69 +100 7 -11 -65 +10 +95 -11 -19 -59 +10 +15 +99 -19 -35 -60 +15 +29 +97 -35 -61 -59 +29 +57 +96 -61 +57 129 -58 +93 129 -307 -57 - - -312 -1450 -57 +399 +92 -1518 -19521 -18 +404 +23319 +90 @@ -43056,57 +43444,57 @@ 1 2 -120 +152 2 3 -116 +308 3 +4 +56 + + +4 5 -61 +72 5 7 -61 +94 7 -11 -66 - - -11 -20 -58 +12 +102 -20 -35 -66 +12 +25 +102 -35 -69 -57 +25 +48 +94 -69 -153 -57 +48 +116 +93 -165 -539 -57 +117 +489 +92 -586 -15827 -31 +491 +15830 +52 @@ -43116,19 +43504,19 @@ cil_attribute_named_argument -2830 +5911 attribute_id -2462 +5474 param -46 +49 value -459 +543 @@ -43142,17 +43530,12 @@ 1 2 -2142 +5093 2 -3 -276 - - -3 5 -44 +381 @@ -43168,17 +43551,12 @@ 1 2 -2185 +5137 2 -3 -250 - - -3 4 -27 +337 @@ -43194,7 +43572,7 @@ 1 2 -4 +5 2 @@ -43209,52 +43587,52 @@ 4 5 -5 +4 5 -6 -2 +7 +4 -6 -7 -5 +7 +10 +4 -9 +10 12 -4 +3 -15 -20 +16 +27 4 -25 +27 35 4 36 -58 +91 4 -77 -230 +98 +169 4 -237 -476 +171 +285 4 -482 -483 -1 +286 +2537 +4 @@ -43275,20 +43653,25 @@ 2 3 -7 +8 3 5 -4 +2 5 -7 +8 4 -11 +9 +12 +4 + + +13 26 4 @@ -43298,8 +43681,8 @@ 4 -198 -199 +248 +249 1 @@ -43316,37 +43699,37 @@ 1 2 -126 +152 2 3 -167 +196 3 4 -18 +15 4 5 -62 +60 5 -10 -35 +7 +44 -10 -35 -35 +7 +17 +42 -38 -264 -16 +18 +1137 +34 @@ -43362,12 +43745,12 @@ 1 2 -403 +482 2 3 -33 +38 3 @@ -43382,19 +43765,19 @@ cil_attribute_positional_argument -49501 +206816 attribute_id -46841 +73198 index -6 +11 value -7954 +23645 @@ -43408,12 +43791,17 @@ 1 2 -44365 +55372 2 7 -2476 +4994 + + +11 +12 +12832 @@ -43429,12 +43817,17 @@ 1 2 -44378 +55391 2 -7 -2463 +11 +6295 + + +11 +12 +11512 @@ -43448,33 +43841,38 @@ 12 -4 -5 +12832 +12833 +5 + + +12836 +12837 1 -52 -53 +12914 +12915 1 -55 -56 +12917 +12918 1 -73 -74 +12965 +12966 1 -2476 -2477 +17826 +17827 1 -46841 -46842 +73198 +73199 1 @@ -43489,33 +43887,38 @@ 12 -3 -4 +115 +116 1 -5 -6 +256 +257 +5 + + +257 +258 1 -8 -9 +259 +260 1 -15 -16 +3306 +3307 1 -124 -125 +6197 +6198 1 -7849 -7850 +14427 +14428 1 @@ -43532,32 +43935,32 @@ 1 2 -3974 +4049 2 3 -1480 +14560 3 4 -1101 +1037 4 5 -628 +1972 5 -18 -598 +321 +1774 -18 -7750 -173 +322 +8073 +253 @@ -43573,12 +43976,12 @@ 1 2 -7914 +23039 2 -6 -40 +12 +606 @@ -43588,19 +43991,19 @@ metadata_handle -3939398 +5245589 entity -2510549 +2712144 location -1229 +1806 handle -62737 +117188 @@ -43614,22 +44017,27 @@ 1 2 -1505031 +1333886 2 3 -730243 +920872 3 4 -134024 +171626 4 -104 -141251 +6 +221369 + + +6 +591 +64391 @@ -43645,22 +44053,27 @@ 1 2 -1698902 +1843036 2 3 -598520 +491566 3 -5 -211853 +4 +162465 -5 -20 -1274 +4 +10 +206601 + + +10 +39 +8476 @@ -43681,52 +44094,57 @@ 2 3 -432 +464 3 -75 -93 +13 +146 -75 -192 -93 +14 +88 +136 -192 -424 -93 +88 +208 +136 -424 -706 -93 +208 +409 +137 -718 -1306 -93 +410 +658 +137 -1309 -2401 -93 +663 +1103 +136 -2445 -6196 -93 +1105 +1792 +136 -6271 -34416 -93 +1795 +3903 +136 -35288 -94585 -31 +3999 +13105 +137 + + +13241 +110459 +83 @@ -43742,52 +44160,57 @@ 1 2 -454 +486 2 -40 -93 +7 +142 -40 -108 -94 +7 +46 +136 -110 -226 -94 +46 +113 +137 -229 -417 -93 +113 +222 +136 -417 -729 -94 +223 +355 +136 -735 -1474 -93 +359 +579 +137 -1477 -3811 -93 +583 +1038 +137 -3943 -22304 -93 +1039 +2262 +136 -22464 -55159 -28 +2268 +7743 +136 + + +7800 +110459 +87 @@ -43802,68 +44225,53 @@ 1 -5 -5311 - - -5 -8 -5381 - - -8 -12 -5363 - - -12 -17 -5497 +2 +355 -17 -24 -5744 +2 +3 +53204 -24 -29 -4967 +3 +7 +9098 -29 -41 -4790 +7 +15 +8859 -41 -53 -4973 +15 +26 +9051 -53 -71 -4708 +26 +39 +8919 -71 -83 -4805 +39 +63 +9148 -83 -127 -4725 +63 +104 +8882 -127 -295 -4715 +104 +539 +8794 -295 -1334 -1758 +539 +1544 +878 @@ -43878,73 +44286,48 @@ 1 -3 -3109 - - -3 4 -5069 +4254 4 -7 -4563 - - -7 -8 -4073 - - -8 -11 -5180 - - -11 -14 -4626 +5 +55971 -14 -17 -4785 +5 +12 +9795 -17 -24 -4978 +12 +20 +8862 -24 -32 -5382 +20 +28 +9240 -32 +28 43 -4868 +8804 43 -52 -4881 - - -52 -81 -4785 +63 +8904 -81 -195 -4719 +63 +200 +8803 -195 -1230 -1719 +200 +1807 +2555 From e7f5fd6b4b3d8c8a09e0c452a8aa244e98a9ee10 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 1 Oct 2019 17:33:29 +0100 Subject: [PATCH 0345/2538] C#: DB upgrade script --- .../old.dbscheme | 1872 ++++++++++++++++ .../semmlecode.csharp.dbscheme | 1883 +++++++++++++++++ .../upgrade.properties | 2 + 3 files changed, 3757 insertions(+) create mode 100644 csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/old.dbscheme create mode 100644 csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme create mode 100644 csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/upgrade.properties diff --git a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/old.dbscheme b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/old.dbscheme new file mode 100644 index 000000000000..f93793ee5f6b --- /dev/null +++ b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/old.dbscheme @@ -0,0 +1,1872 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + varchar(900) queryPath: string ref, + int location: @location ref, + varchar(900) message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + varchar(900) queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + varchar(900) path: string ref, + int column: int ref, + varchar(900) value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + varchar(900) prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + varchar(900) relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + varchar(900) relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + unique int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + varchar(900) fullname: string ref, + varchar(900) name: string ref, + varchar(900) version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + varchar(900) name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + varchar(900) name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + varchar(900) name: string ref); + +typeref_type( + unique int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @struct_type ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @array_type | @expr | @delegate_type; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +/** The annotation of type arguments of a constructed type or method. */ +type_argument_annotation(int constructedgeneric: @generic ref, int position: int ref, int annotation: int ref); + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +is_generic(unique int id: @generic ref); + +is_constructed(unique int id: @generic ref); + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_annotation( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int annotation: int ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function; + +modifiers( + unique int id: @modifier, + varchar(900) name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + varchar(900) name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + varchar(900) name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + varchar(900) name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + varchar(900) name: string ref, + varchar(900) symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + unique int id: @variable ref, + varchar(900) value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + unique int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + unique int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + varchar(900) name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + varchar(900) name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + varchar(900) name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + varchar(900) value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + varchar(900) name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + varchar(900) name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + varchar(900) encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + varchar(800) text: string ref, + varchar(800) rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + varchar(1000) name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + varchar(1000) name: string ref); +asp_element_body( + unique int element: @asp_element ref, + varchar(1000) body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + varchar(1000) name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + varchar(1000) name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + varchar(900) value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + varchar(900) name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + varchar(900) name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + varchar(900) name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + varchar(900) name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + varchar(900) name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + varchar(100) param: string ref, + varchar(900) value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + varchar(900) value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme new file mode 100644 index 000000000000..e4ab77432e6d --- /dev/null +++ b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme @@ -0,0 +1,1883 @@ + +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * csc f1.cs f2.cs f3.cs + * + * The `id` simply identifies the invocation, while `cwd` is the working + * directory from which the compiler was invoked. + */ +compilations( + unique int id : @compilation, + string cwd : string ref +); + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | --compiler + * 1 | *path to compiler* + * 2 | --cil + * 3 | f1.cs + * 4 | f2.cs + * 5 | f3.cs + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The source files that are compiled by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | f1.cs + * 1 | f2.cs + * 2 | f3.cs + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The references used by a compiler invocation. + * If `id` is for the compiler invocation + * + * csc f1.cs f2.cs f3.cs /r:ref1.dll /r:ref2.dll /r:ref3.dll + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | ref1.dll + * 1 | ref2.dll + * 2 | ref3.dll + */ +#keyset[id, num] +compilation_referencing_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * The time taken by the extractor for a compiler invocation. + * + * For each file `num`, there will be rows for + * + * kind | seconds + * ---- | --- + * 1 | CPU seconds used by the extractor frontend + * 2 | Elapsed seconds during the extractor frontend + * 3 | CPU seconds used by the extractor backend + * 4 | Elapsed seconds during the extractor backend + */ +#keyset[id, num, kind] +compilation_time( + int id : @compilation ref, + int num : int ref, + /* kind: + 1 = frontend_cpu_seconds + 2 = frontend_elapsed_seconds + 3 = extractor_cpu_seconds + 4 = extractor_elapsed_seconds + */ + int kind : int ref, + float seconds : float ref +); + +/** + * An error or warning generated by the extractor. + * The diagnostic message `diagnostic` was generated during compiler + * invocation `compilation`, and is the `file_number_diagnostic_number`th + * message generated while extracting the `file_number`th file of that + * invocation. + */ +#keyset[compilation, file_number, file_number_diagnostic_number] +diagnostic_for( + unique int diagnostic : @diagnostic ref, + int compilation : @compilation ref, + int file_number : int ref, + int file_number_diagnostic_number : int ref +); + +diagnostics( + unique int id: @diagnostic, + int severity: int ref, + string error_tag: string ref, + string error_message: string ref, + string full_error_message: string ref, + int location: @location_default ref +); + +extractor_messages( + unique int id: @extractor_message, + int severity: int ref, + string origin : string ref, + string text : string ref, + string entity : string ref, + int location: @location_default ref, + string stack_trace : string ref +); + +/** + * If extraction was successful, then `cpu_seconds` and + * `elapsed_seconds` are the CPU time and elapsed time (respectively) + * that extraction took for compiler invocation `id`. + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref +); + +/* + * External artifacts + */ + +externalDefects( + unique int id: @externalDefect, + varchar(900) queryPath: string ref, + int location: @location ref, + varchar(900) message: string ref, + float severity: float ref); + +externalMetrics( + unique int id: @externalMetric, + varchar(900) queryPath: string ref, + int location: @location ref, + float value: float ref); + +externalData( + int id: @externalDataElement, + varchar(900) path: string ref, + int column: int ref, + varchar(900) value: string ref); + +snapshotDate( + unique date snapshotDate: date ref); + +sourceLocationPrefix( + varchar(900) prefix: string ref); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id: @duplication, + varchar(900) relativePath: string ref, + int equivClass: int ref); + +similarCode( + unique int id: @similarity, + varchar(900) relativePath: string ref, + int equivClass: int ref); + +@duplication_or_similarity = @duplication | @similarity + +tokens( + int id: @duplication_or_similarity ref, + int offset: int ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +/* + * C# dbscheme + */ + +/** ELEMENTS **/ + +@element = @declaration | @stmt | @expr | @modifier | @attribute | @namespace_declaration + | @using_directive | @type_parameter_constraints | @external_element + | @xmllocatable | @asp_element | @namespace; + +@declaration = @callable | @generic | @assignable | @namespace; + +@named_element = @namespace | @declaration; + +@declaration_with_accessors = @property | @indexer | @event; + +@assignable = @variable | @assignable_with_accessors | @event; + +@assignable_with_accessors = @property | @indexer; + +@external_element = @externalMetric | @externalDefect | @externalDataElement; + +@attributable = @assembly | @field | @parameter | @operator | @method | @constructor + | @destructor | @callable_accessor | @value_or_ref_type | @declaration_with_accessors; + +/** LOCATIONS, ASEMMBLIES, MODULES, FILES and FOLDERS **/ + +@location = @location_default | @assembly; + +locations_default( + unique int id: @location_default, + int file: @file ref, + int beginLine: int ref, + int beginColumn: int ref, + int endLine: int ref, + int endColumn: int ref); + +@sourceline = @file | @callable | @xmllocatable; + +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref); + +assemblies( + unique int id: @assembly, + int file: @file ref, + varchar(900) fullname: string ref, + varchar(900) name: string ref, + varchar(900) version: string ref); + +/* + fromSource(0) = unknown, + fromSource(1) = from source, + fromSource(2) = from library +*/ +files( + unique int id: @file, + varchar(900) name: string ref, + varchar(900) simple: string ref, + varchar(900) ext: string ref, + int fromSource: int ref); + +folders( + unique int id: @folder, + varchar(900) name: string ref, + varchar(900) simple: string ref); + +@container = @folder | @file ; + +containerparent( + int parent: @container ref, + unique int child: @container ref); + +file_extraction_mode( + unique int file: @file ref, + int mode: int ref + /* 0 = normal, 1 = standalone extractor */ + ); + +/** NAMESPACES **/ + +@type_container = @namespace | @type; + +namespaces( + unique int id: @namespace, + varchar(900) name: string ref); + +namespace_declarations( + unique int id: @namespace_declaration, + int namespace_id: @namespace ref); + +namespace_declaration_location( + unique int id: @namespace_declaration ref, + int loc: @location ref); + +parent_namespace( + unique int child_id: @type_container ref, + int namespace_id: @namespace ref); + +@declaration_or_directive = @namespace_declaration | @type | @using_directive; + +parent_namespace_declaration( + int child_id: @declaration_or_directive ref, // cannot be unique because of partial classes + int namespace_id: @namespace_declaration ref); + +@using_directive = @using_namespace_directive | @using_static_directive; + +using_namespace_directives( + unique int id: @using_namespace_directive, + int namespace_id: @namespace ref); + +using_static_directives( + unique int id: @using_static_directive, + int type_id: @type_or_ref ref); + +using_directive_location( + unique int id: @using_directive ref, + int loc: @location ref); + +/** TYPES **/ + +types( + unique int id: @type, + int kind: int ref, + varchar(900) name: string ref); + +case @type.kind of + 1 = @bool_type +| 2 = @char_type +| 3 = @decimal_type +| 4 = @sbyte_type +| 5 = @short_type +| 6 = @int_type +| 7 = @long_type +| 8 = @byte_type +| 9 = @ushort_type +| 10 = @uint_type +| 11 = @ulong_type +| 12 = @float_type +| 13 = @double_type +| 14 = @enum_type +| 15 = @struct_type +| 17 = @class_type +| 19 = @interface_type +| 20 = @delegate_type +| 21 = @null_type +| 22 = @type_parameter +| 23 = @pointer_type +| 24 = @nullable_type +| 25 = @array_type +| 26 = @void_type +| 27 = @int_ptr_type +| 28 = @uint_ptr_type +| 29 = @dynamic_type +| 30 = @arglist_type +| 31 = @unknown_type +| 32 = @tuple_type + ; + +@simple_type = @bool_type | @char_type | @integral_type | @floating_point_type | @decimal_type; +@integral_type = @signed_integral_type | @unsigned_integral_type; +@signed_integral_type = @sbyte_type | @short_type | @int_type | @long_type; +@unsigned_integral_type = @byte_type | @ushort_type | @uint_type | @ulong_type; +@floating_point_type = @float_type | @double_type; +@value_type = @simple_type | @enum_type | @struct_type | @nullable_type | @int_ptr_type + | @uint_ptr_type | @tuple_type; +@ref_type = @class_type | @interface_type | @array_type | @delegate_type | @null_type + | @dynamic_type; +@value_or_ref_type = @value_type | @ref_type; + +typerefs( + unique int id: @typeref, + varchar(900) name: string ref); + +typeref_type( + int id: @typeref ref, + unique int typeId: @type ref); + +@type_or_ref = @type | @typeref; + +array_element_type( + unique int array: @array_type ref, + int dimension: int ref, + int rank: int ref, + int element: @type_or_ref ref); + +nullable_underlying_type( + unique int nullable: @nullable_type ref, + int underlying: @type_or_ref ref); + +pointer_referent_type( + unique int pointer: @pointer_type ref, + int referent: @type_or_ref ref); + +enum_underlying_type( + unique int enum_id: @enum_type ref, + int underlying_type_id: @type_or_ref ref); + +delegate_return_type( + unique int delegate_id: @delegate_type ref, + int return_type_id: @type_or_ref ref); + +extend( + unique int sub: @type ref, + int super: @type_or_ref ref); + +@interface_or_ref = @interface_type | @typeref; + +implement( + int sub: @type ref, + int super: @type_or_ref ref); + +type_location( + int id: @type ref, + int loc: @location ref); + +tuple_underlying_type( + unique int tuple: @tuple_type ref, + int struct: @type_or_ref ref); + +#keyset[tuple, index] +tuple_element( + int tuple: @tuple_type ref, + int index: int ref, + unique int field: @field ref); + +attributes( + unique int id: @attribute, + int type_id: @type_or_ref ref, + int target: @attributable ref); + +attribute_location( + int id: @attribute ref, + int loc: @location ref); + +@type_mention_parent = @element | @type_mention; + +type_mention( + unique int id: @type_mention, + int type_id: @type_or_ref ref, + int parent: @type_mention_parent ref); + +type_mention_location( + unique int id: @type_mention ref, + int loc: @location ref); + +@has_type_annotation = @assignable | @type_parameter | @callable | @expr | @delegate_type | @generic; + +/** + * A direct annotation on an entity, for example `string? x;`. + * + * Annotations: + * 2 = reftype is not annotated "!" + * 3 = reftype is annotated "?" + * 4 = readonly ref type / in parameter + * 5 = ref type parameter, return or local variable + * 6 = out parameter + * + * Note that the annotation depends on the element it annotates. + * @assignable: The annotation is on the type of the assignable, for example the variable type. + * @type_parameter: The annotation is on the reftype constraint + * @callable: The annotation is on the return type + * @array_type: The annotation is on the element type + */ +type_annotation(int id: @has_type_annotation ref, int annotation: int ref); + +nullability(unique int nullability: @nullability, int kind: int ref); + +case @nullability.kind of + 0 = @oblivious +| 1 = @not_annotated +| 2 = @annotated +; + +#keyset[nullability, index] +nullability_member(int nullability: @nullability ref, int index: int ref, int child: @nullability ref) + +type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref) + +/** GENERICS **/ + +@generic = @type | @method | @local_function; + +is_generic(unique int id: @generic ref); + +is_constructed(unique int id: @generic ref); + +type_parameters( + unique int id: @type_parameter ref, + int index: int ref, + int generic_id: @generic ref, + int variance: int ref /* none = 0, out = 1, in = 2 */); + +#keyset[constructed_id, index] +type_arguments( + int id: @type_or_ref ref, + int index: int ref, + int constructed_id: @generic_or_ref ref); + +@generic_or_ref = @generic | @typeref; + +constructed_generic( + unique int constructed: @generic ref, + int generic: @generic_or_ref ref); + +type_parameter_constraints( + unique int id: @type_parameter_constraints, + int param_id: @type_parameter ref); + +type_parameter_constraints_location( + int id: @type_parameter_constraints ref, + int loc: @location ref); + +general_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int kind: int ref /* class = 1, struct = 2, new = 3 */); + +specific_type_parameter_constraints( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref); + +specific_type_parameter_nullability( + int id: @type_parameter_constraints ref, + int base_id: @type_or_ref ref, + int nullability: @nullability ref); + +/** MODIFIERS */ + +@modifiable = @modifiable_direct | @event_accessor; + +@modifiable_direct = @member | @accessor | @local_function; + +modifiers( + unique int id: @modifier, + varchar(900) name: string ref); + +has_modifiers( + int id: @modifiable_direct ref, + int mod_id: @modifier ref); + +compiler_generated(unique int id: @modifiable_direct ref); + +/** MEMBERS **/ + +@member = @method | @constructor | @destructor | @field | @property | @event | @operator | @indexer | @type; + +@named_exprorstmt = @goto_stmt | @labeled_stmt | @expr; + +@virtualizable = @method | @property | @indexer | @event; + +exprorstmt_name( + unique int parent_id: @named_exprorstmt ref, + varchar(900) name: string ref); + +nested_types( + unique int id: @type ref, + int declaring_type_id: @type ref, + int unbound_id: @type ref); + +properties( + unique int id: @property, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @property ref); + +property_location( + int id: @property ref, + int loc: @location ref); + +indexers( + unique int id: @indexer, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @indexer ref); + +indexer_location( + int id: @indexer ref, + int loc: @location ref); + +accessors( + unique int id: @accessor, + int kind: int ref, + varchar(900) name: string ref, + int declaring_member_id: @member ref, + int unbound_id: @accessor ref); + +case @accessor.kind of + 1 = @getter +| 2 = @setter + ; + +accessor_location( + int id: @accessor ref, + int loc: @location ref); + +events( + unique int id: @event, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @event ref); + +event_location( + int id: @event ref, + int loc: @location ref); + +event_accessors( + unique int id: @event_accessor, + int kind: int ref, + varchar(900) name: string ref, + int declaring_event_id: @event ref, + int unbound_id: @event_accessor ref); + +case @event_accessor.kind of + 1 = @add_event_accessor +| 2 = @remove_event_accessor + ; + +event_accessor_location( + int id: @event_accessor ref, + int loc: @location ref); + +operators( + unique int id: @operator, + varchar(900) name: string ref, + varchar(900) symbol: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @operator ref); + +operator_location( + int id: @operator ref, + int loc: @location ref); + +constant_value( + int id: @variable ref, + string value: string ref); + +/** CALLABLES **/ + +@callable = @method | @constructor | @destructor | @operator | @callable_accessor | @anonymous_function_expr | @local_function; + +@callable_accessor = @accessor | @event_accessor; + +methods( + unique int id: @method, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @method ref); + +method_location( + int id: @method ref, + int loc: @location ref); + +constructors( + unique int id: @constructor, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @constructor ref); + +constructor_location( + int id: @constructor ref, + int loc: @location ref); + +destructors( + unique int id: @destructor, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int unbound_id: @destructor ref); + +destructor_location( + int id: @destructor ref, + int loc: @location ref); + +overrides( + int id: @callable ref, + int base_id: @callable ref); + +explicitly_implements( + unique int id: @member ref, + int interface_id: @interface_or_ref ref); + +local_functions( + unique int id: @local_function, + varchar(900) name: string ref, + int return_type: @type ref, + int unbound_id: @local_function ref); + +local_function_stmts( + unique int fn: @local_function_stmt ref, + int stmt: @local_function ref); + +/** VARIABLES **/ + +@variable = @local_scope_variable | @field; + +@local_scope_variable = @local_variable | @parameter; + +fields( + unique int id: @field, + int kind: int ref, + varchar(900) name: string ref, + int declaring_type_id: @type ref, + int type_id: @type_or_ref ref, + int unbound_id: @field ref); + +case @field.kind of + 1 = @addressable_field +| 2 = @constant + ; + +field_location( + int id: @field ref, + int loc: @location ref); + +localvars( + unique int id: @local_variable, + int kind: int ref, + varchar(900) name: string ref, + int implicitly_typed: int ref /* 0 = no, 1 = yes */, + int type_id: @type_or_ref ref, + int parent_id: @local_var_decl_expr ref); + +case @local_variable.kind of + 1 = @addressable_local_variable +| 2 = @local_constant +| 3 = @local_variable_ref + ; + +localvar_location( + unique int id: @local_variable ref, + int loc: @location ref); + +@parameterizable = @callable | @delegate_type | @indexer; + +#keyset[name, parent_id] +#keyset[index, parent_id] +params( + unique int id: @parameter, + varchar(900) name: string ref, + int type_id: @type_or_ref ref, + int index: int ref, + int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ + int parent_id: @parameterizable ref, + int unbound_id: @parameter ref); + +param_location( + int id: @parameter ref, + int loc: @location ref); + +/** STATEMENTS **/ + +@exprorstmt_parent = @control_flow_element | @top_level_exprorstmt_parent; + +statements( + unique int id: @stmt, + int kind: int ref); + +#keyset[index, parent] +stmt_parent( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_stmt_parent = @callable; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +stmt_parent_top_level( + unique int stmt: @stmt ref, + int index: int ref, + int parent: @top_level_stmt_parent ref); + +case @stmt.kind of + 1 = @block_stmt +| 2 = @expr_stmt +| 3 = @if_stmt +| 4 = @switch_stmt +| 5 = @while_stmt +| 6 = @do_stmt +| 7 = @for_stmt +| 8 = @foreach_stmt +| 9 = @break_stmt +| 10 = @continue_stmt +| 11 = @goto_stmt +| 12 = @goto_case_stmt +| 13 = @goto_default_stmt +| 14 = @throw_stmt +| 15 = @return_stmt +| 16 = @yield_stmt +| 17 = @try_stmt +| 18 = @checked_stmt +| 19 = @unchecked_stmt +| 20 = @lock_stmt +| 21 = @using_block_stmt +| 22 = @var_decl_stmt +| 23 = @const_decl_stmt +| 24 = @empty_stmt +| 25 = @unsafe_stmt +| 26 = @fixed_stmt +| 27 = @label_stmt +| 28 = @catch +| 29 = @case_stmt +| 30 = @local_function_stmt +| 31 = @using_decl_stmt + ; + +@using_stmt = @using_block_stmt | @using_decl_stmt; + +@labeled_stmt = @label_stmt | @case; + +@decl_stmt = @var_decl_stmt | @const_decl_stmt | @using_decl_stmt; + +@cond_stmt = @if_stmt | @switch_stmt; + +@loop_stmt = @while_stmt | @do_stmt | @for_stmt | @foreach_stmt; + +@jump_stmt = @break_stmt | @goto_any_stmt | @continue_stmt | @throw_stmt | @return_stmt + | @yield_stmt; + +@goto_any_stmt = @goto_default_stmt | @goto_case_stmt | @goto_stmt; + + +stmt_location( + unique int id: @stmt ref, + int loc: @location ref); + +catch_type( + unique int catch_id: @catch ref, + int type_id: @type_or_ref ref, + int kind: int ref /* explicit = 1, implicit = 2 */); + +/** EXPRESSIONS **/ + +expressions( + unique int id: @expr, + int kind: int ref, + int type_id: @type_or_ref ref); + +#keyset[index, parent] +expr_parent( + unique int expr: @expr ref, + int index: int ref, + int parent: @control_flow_element ref); + +@top_level_expr_parent = @attribute | @field | @property | @indexer | @parameter; + +@top_level_exprorstmt_parent = @top_level_expr_parent | @top_level_stmt_parent; + +// [index, parent] is not a keyset because the same parent may be compiled multiple times +expr_parent_top_level( + unique int expr: @expr ref, + int index: int ref, + int parent: @top_level_exprorstmt_parent ref); + +case @expr.kind of +/* literal */ + 1 = @bool_literal_expr +| 2 = @char_literal_expr +| 3 = @decimal_literal_expr +| 4 = @int_literal_expr +| 5 = @long_literal_expr +| 6 = @uint_literal_expr +| 7 = @ulong_literal_expr +| 8 = @float_literal_expr +| 9 = @double_literal_expr +| 10 = @string_literal_expr +| 11 = @null_literal_expr +/* primary & unary */ +| 12 = @this_access_expr +| 13 = @base_access_expr +| 14 = @local_variable_access_expr +| 15 = @parameter_access_expr +| 16 = @field_access_expr +| 17 = @property_access_expr +| 18 = @method_access_expr +| 19 = @event_access_expr +| 20 = @indexer_access_expr +| 21 = @array_access_expr +| 22 = @type_access_expr +| 23 = @typeof_expr +| 24 = @method_invocation_expr +| 25 = @delegate_invocation_expr +| 26 = @operator_invocation_expr +| 27 = @cast_expr +| 28 = @object_creation_expr +| 29 = @explicit_delegate_creation_expr +| 30 = @implicit_delegate_creation_expr +| 31 = @array_creation_expr +| 32 = @default_expr +| 33 = @plus_expr +| 34 = @minus_expr +| 35 = @bit_not_expr +| 36 = @log_not_expr +| 37 = @post_incr_expr +| 38 = @post_decr_expr +| 39 = @pre_incr_expr +| 40 = @pre_decr_expr +/* multiplicative */ +| 41 = @mul_expr +| 42 = @div_expr +| 43 = @rem_expr +/* additive */ +| 44 = @add_expr +| 45 = @sub_expr +/* shift */ +| 46 = @lshift_expr +| 47 = @rshift_expr +/* relational */ +| 48 = @lt_expr +| 49 = @gt_expr +| 50 = @le_expr +| 51 = @ge_expr +/* equality */ +| 52 = @eq_expr +| 53 = @ne_expr +/* logical */ +| 54 = @bit_and_expr +| 55 = @bit_xor_expr +| 56 = @bit_or_expr +| 57 = @log_and_expr +| 58 = @log_or_expr +/* type testing */ +| 59 = @is_expr +| 60 = @as_expr +/* null coalescing */ +| 61 = @null_coalescing_expr +/* conditional */ +| 62 = @conditional_expr +/* assignment */ +| 63 = @simple_assign_expr +| 64 = @assign_add_expr +| 65 = @assign_sub_expr +| 66 = @assign_mul_expr +| 67 = @assign_div_expr +| 68 = @assign_rem_expr +| 69 = @assign_and_expr +| 70 = @assign_xor_expr +| 71 = @assign_or_expr +| 72 = @assign_lshift_expr +| 73 = @assign_rshift_expr +/* more */ +| 74 = @object_init_expr +| 75 = @collection_init_expr +| 76 = @array_init_expr +| 77 = @checked_expr +| 78 = @unchecked_expr +| 79 = @constructor_init_expr +| 80 = @add_event_expr +| 81 = @remove_event_expr +| 82 = @par_expr +| 83 = @local_var_decl_expr +| 84 = @lambda_expr +| 85 = @anonymous_method_expr +| 86 = @namespace_expr +/* dynamic */ +| 92 = @dynamic_element_access_expr +| 93 = @dynamic_member_access_expr +/* unsafe */ +| 100 = @pointer_indirection_expr +| 101 = @address_of_expr +| 102 = @sizeof_expr +/* async */ +| 103 = @await_expr +/* C# 6.0 */ +| 104 = @nameof_expr +| 105 = @interpolated_string_expr +| 106 = @unknown_expr +/* C# 7.0 */ +| 107 = @throw_expr +| 108 = @tuple_expr +| 109 = @local_function_invocation_expr +| 110 = @ref_expr +| 111 = @discard_expr +/* C# 8.0 */ +| 112 = @range_expr +| 113 = @index_expr +| 114 = @switch_expr +| 115 = @recursive_pattern_expr +| 116 = @property_pattern_expr +| 117 = @positional_pattern_expr +| 118 = @switch_case_expr +| 119 = @assign_coalesce_expr +| 120 = @suppress_nullable_warning_expr +| 121 = @namespace_access_expr +; + +@switch = @switch_stmt | @switch_expr; +@case = @case_stmt | @switch_case_expr; +@pattern_match = @case | @is_expr; + +@integer_literal_expr = @int_literal_expr | @long_literal_expr | @uint_literal_expr | @ulong_literal_expr; +@real_literal_expr = @float_literal_expr | @double_literal_expr | @decimal_literal_expr; +@literal_expr = @bool_literal_expr | @char_literal_expr | @integer_literal_expr | @real_literal_expr + | @string_literal_expr | @null_literal_expr; + +@assign_expr = @simple_assign_expr | @assign_op_expr | @local_var_decl_expr; +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr | @assign_event_expr | @assign_coalesce_expr; +@assign_event_expr = @add_event_expr | @remove_event_expr; + +@assign_arith_expr = @assign_add_expr | @assign_sub_expr | @assign_mul_expr | @assign_div_expr + | @assign_rem_expr +@assign_bitwise_expr = @assign_and_expr | @assign_or_expr | @assign_xor_expr + | @assign_lshift_expr | @assign_rshift_expr; + +@member_access_expr = @field_access_expr | @property_access_expr | @indexer_access_expr | @event_access_expr + | @method_access_expr | @type_access_expr | @dynamic_member_access_expr; +@access_expr = @member_access_expr | @this_access_expr | @base_access_expr | @assignable_access_expr | @namespace_access_expr; +@element_access_expr = @indexer_access_expr | @array_access_expr | @dynamic_element_access_expr; + +@local_variable_access = @local_variable_access_expr | @local_var_decl_expr; +@local_scope_variable_access_expr = @parameter_access_expr | @local_variable_access; +@variable_access_expr = @local_scope_variable_access_expr | @field_access_expr; + +@assignable_access_expr = @variable_access_expr | @property_access_expr | @element_access_expr + | @event_access_expr | @dynamic_member_access_expr; + +@objectorcollection_init_expr = @object_init_expr | @collection_init_expr; + +@delegate_creation_expr = @explicit_delegate_creation_expr | @implicit_delegate_creation_expr; + +@bin_arith_op_expr = @mul_expr | @div_expr | @rem_expr | @add_expr | @sub_expr; +@incr_op_expr = @pre_incr_expr | @post_incr_expr; +@decr_op_expr = @pre_decr_expr | @post_decr_expr; +@mut_op_expr = @incr_op_expr | @decr_op_expr; +@un_arith_op_expr = @plus_expr | @minus_expr | @mut_op_expr; +@arith_op_expr = @bin_arith_op_expr | @un_arith_op_expr; + +@ternary_log_op_expr = @conditional_expr; +@bin_log_op_expr = @log_and_expr | @log_or_expr | @null_coalescing_expr; +@un_log_op_expr = @log_not_expr; +@log_expr = @un_log_op_expr | @bin_log_op_expr | @ternary_log_op_expr; + +@bin_bit_op_expr = @bit_and_expr | @bit_or_expr | @bit_xor_expr | @lshift_expr + | @rshift_expr; +@un_bit_op_expr = @bit_not_expr; +@bit_expr = @un_bit_op_expr | @bin_bit_op_expr; + +@equality_op_expr = @eq_expr | @ne_expr; +@rel_op_expr = @gt_expr | @lt_expr| @ge_expr | @le_expr; +@comp_expr = @equality_op_expr | @rel_op_expr; + +@op_expr = @assign_expr | @un_op | @bin_op | @ternary_op; + +@ternary_op = @ternary_log_op_expr; +@bin_op = @bin_arith_op_expr | @bin_log_op_expr | @bin_bit_op_expr | @comp_expr; +@un_op = @un_arith_op_expr | @un_log_op_expr | @un_bit_op_expr | @sizeof_expr + | @pointer_indirection_expr | @address_of_expr; + +@anonymous_function_expr = @lambda_expr | @anonymous_method_expr; + +@call = @method_invocation_expr | @constructor_init_expr | @operator_invocation_expr + | @delegate_invocation_expr | @object_creation_expr | @call_access_expr + | @local_function_invocation_expr; + +@call_access_expr = @property_access_expr | @event_access_expr | @indexer_access_expr; + +@late_bindable_expr = @dynamic_element_access_expr | @dynamic_member_access_expr + | @object_creation_expr | @method_invocation_expr | @operator_invocation_expr; + +@throw_element = @throw_expr | @throw_stmt; + +implicitly_typed_array_creation( + unique int id: @array_creation_expr ref); + +explicitly_sized_array_creation( + unique int id: @array_creation_expr ref); + +mutator_invocation_mode( + unique int id: @operator_invocation_expr ref, + int mode: int ref /* prefix = 1, postfix = 2*/); + +expr_compiler_generated( + unique int id: @expr ref); + +expr_value( + unique int id: @expr ref, + varchar(900) value: string ref); + +expr_call( + unique int caller_id: @expr ref, + int target_id: @callable ref); + +expr_access( + unique int accesser_id: @access_expr ref, + int target_id: @accessible ref); + +@accessible = @method | @assignable | @local_function | @namespace; + +expr_location( + unique int id: @expr ref, + int loc: @location ref); + +dynamic_member_name( + unique int id: @late_bindable_expr ref, + varchar(900) name: string ref); + +@qualifiable_expr = @member_access_expr + | @method_invocation_expr + | @element_access_expr + | @delegate_invocation_expr; + +conditional_access( + unique int id: @qualifiable_expr ref); + +expr_argument( + unique int id: @expr ref, + int mode: int ref); + /* mode is the same as params: value = 0, ref = 1, out = 2 */ + +expr_argument_name( + unique int id: @expr ref, + varchar(900) name: string ref); + +/** CONTROL/DATA FLOW **/ + +@control_flow_element = @stmt | @expr; + +/* XML Files */ + +xmlEncoding ( + unique int id: @file ref, + varchar(900) encoding: string ref); + +xmlDTDs( + unique int id: @xmldtd, + varchar(900) root: string ref, + varchar(900) publicId: string ref, + varchar(900) systemId: string ref, + int fileid: @file ref); + +xmlElements( + unique int id: @xmlelement, + varchar(900) name: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int fileid: @file ref); + +xmlAttrs( + unique int id: @xmlattribute, + int elementid: @xmlelement ref, + varchar(900) name: string ref, + varchar(3600) value: string ref, + int idx: int ref, + int fileid: @file ref); + +xmlNs( + int id: @xmlnamespace, + varchar(900) prefixName: string ref, + varchar(900) URI: string ref, + int fileid: @file ref); + +xmlHasNs( + int elementId: @xmlnamespaceable ref, + int nsId: @xmlnamespace ref, + int fileid: @file ref); + +xmlComments( + unique int id: @xmlcomment, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int fileid: @file ref); + +xmlChars( + unique int id: @xmlcharacters, + varchar(3600) text: string ref, + int parentid: @xmlparent ref, + int idx: int ref, + int isCDATA: int ref, + int fileid: @file ref); + +@xmlparent = @file | @xmlelement; +@xmlnamespaceable = @xmlelement | @xmlattribute; + +xmllocations( + int xmlElement: @xmllocatable ref, + int location: @location_default ref); + +@xmllocatable = @xmlcharacters | @xmlelement | @xmlcomment | @xmlattribute | @xmldtd | @file | @xmlnamespace; + +/* Comments */ + +commentline( + unique int id: @commentline, + int kind: int ref, + varchar(800) text: string ref, + varchar(800) rawtext: string ref); + +case @commentline.kind of + 0 = @singlelinecomment +| 1 = @xmldoccomment +| 2 = @multilinecomment; + +commentline_location( + unique int id: @commentline ref, + int loc: @location ref); + +commentblock( + unique int id : @commentblock); + +commentblock_location( + unique int id: @commentblock ref, + int loc: @location ref); + +commentblock_binding( + int id: @commentblock ref, + int entity: @element ref, + int bindtype: int ref); /* 0: Parent, 1: Best, 2: Before, 3: After */ + +commentblock_child( + int id: @commentblock ref, + int commentline: @commentline ref, + int index: int ref); + +/* ASP.NET */ + +case @asp_element.kind of + 0=@asp_close_tag +| 1=@asp_code +| 2=@asp_comment +| 3=@asp_data_binding +| 4=@asp_directive +| 5=@asp_open_tag +| 6=@asp_quoted_string +| 7=@asp_text +| 8=@asp_xml_directive; + +@asp_attribute = @asp_code | @asp_data_binding | @asp_quoted_string; + +asp_elements( + unique int id: @asp_element, + int kind: int ref, + int loc: @location ref); + +asp_comment_server(unique int comment: @asp_comment ref); +asp_code_inline(unique int code: @asp_code ref); +asp_directive_attribute( + int directive: @asp_directive ref, + int index: int ref, + varchar(1000) name: string ref, + int value: @asp_quoted_string ref); +asp_directive_name( + unique int directive: @asp_directive ref, + varchar(1000) name: string ref); +asp_element_body( + unique int element: @asp_element ref, + varchar(1000) body: string ref); +asp_tag_attribute( + int tag: @asp_open_tag ref, + int index: int ref, + varchar(1000) name: string ref, + int attribute: @asp_attribute ref); +asp_tag_name( + unique int tag: @asp_open_tag ref, + varchar(1000) name: string ref); +asp_tag_isempty(int tag: @asp_open_tag ref); + +/* Common Intermediate Language - CIL */ + +case @cil_instruction.opcode of + 0 = @cil_nop +| 1 = @cil_break +| 2 = @cil_ldarg_0 +| 3 = @cil_ldarg_1 +| 4 = @cil_ldarg_2 +| 5 = @cil_ldarg_3 +| 6 = @cil_ldloc_0 +| 7 = @cil_ldloc_1 +| 8 = @cil_ldloc_2 +| 9 = @cil_ldloc_3 +| 10 = @cil_stloc_0 +| 11 = @cil_stloc_1 +| 12 = @cil_stloc_2 +| 13 = @cil_stloc_3 +| 14 = @cil_ldarg_s +| 15 = @cil_ldarga_s +| 16 = @cil_starg_s +| 17 = @cil_ldloc_s +| 18 = @cil_ldloca_s +| 19 = @cil_stloc_s +| 20 = @cil_ldnull +| 21 = @cil_ldc_i4_m1 +| 22 = @cil_ldc_i4_0 +| 23 = @cil_ldc_i4_1 +| 24 = @cil_ldc_i4_2 +| 25 = @cil_ldc_i4_3 +| 26 = @cil_ldc_i4_4 +| 27 = @cil_ldc_i4_5 +| 28 = @cil_ldc_i4_6 +| 29 = @cil_ldc_i4_7 +| 30 = @cil_ldc_i4_8 +| 31 = @cil_ldc_i4_s +| 32 = @cil_ldc_i4 +| 33 = @cil_ldc_i8 +| 34 = @cil_ldc_r4 +| 35 = @cil_ldc_r8 +| 37 = @cil_dup +| 38 = @cil_pop +| 39 = @cil_jmp +| 40 = @cil_call +| 41 = @cil_calli +| 42 = @cil_ret +| 43 = @cil_br_s +| 44 = @cil_brfalse_s +| 45 = @cil_brtrue_s +| 46 = @cil_beq_s +| 47 = @cil_bge_s +| 48 = @cil_bgt_s +| 49 = @cil_ble_s +| 50 = @cil_blt_s +| 51 = @cil_bne_un_s +| 52 = @cil_bge_un_s +| 53 = @cil_bgt_un_s +| 54 = @cil_ble_un_s +| 55 = @cil_blt_un_s +| 56 = @cil_br +| 57 = @cil_brfalse +| 58 = @cil_brtrue +| 59 = @cil_beq +| 60 = @cil_bge +| 61 = @cil_bgt +| 62 = @cil_ble +| 63 = @cil_blt +| 64 = @cil_bne_un +| 65 = @cil_bge_un +| 66 = @cil_bgt_un +| 67 = @cil_ble_un +| 68 = @cil_blt_un +| 69 = @cil_switch +| 70 = @cil_ldind_i1 +| 71 = @cil_ldind_u1 +| 72 = @cil_ldind_i2 +| 73 = @cil_ldind_u2 +| 74 = @cil_ldind_i4 +| 75 = @cil_ldind_u4 +| 76 = @cil_ldind_i8 +| 77 = @cil_ldind_i +| 78 = @cil_ldind_r4 +| 79 = @cil_ldind_r8 +| 80 = @cil_ldind_ref +| 81 = @cil_stind_ref +| 82 = @cil_stind_i1 +| 83 = @cil_stind_i2 +| 84 = @cil_stind_i4 +| 85 = @cil_stind_i8 +| 86 = @cil_stind_r4 +| 87 = @cil_stind_r8 +| 88 = @cil_add +| 89 = @cil_sub +| 90 = @cil_mul +| 91 = @cil_div +| 92 = @cil_div_un +| 93 = @cil_rem +| 94 = @cil_rem_un +| 95 = @cil_and +| 96 = @cil_or +| 97 = @cil_xor +| 98 = @cil_shl +| 99 = @cil_shr +| 100 = @cil_shr_un +| 101 = @cil_neg +| 102 = @cil_not +| 103 = @cil_conv_i1 +| 104 = @cil_conv_i2 +| 105 = @cil_conv_i4 +| 106 = @cil_conv_i8 +| 107 = @cil_conv_r4 +| 108 = @cil_conv_r8 +| 109 = @cil_conv_u4 +| 110 = @cil_conv_u8 +| 111 = @cil_callvirt +| 112 = @cil_cpobj +| 113 = @cil_ldobj +| 114 = @cil_ldstr +| 115 = @cil_newobj +| 116 = @cil_castclass +| 117 = @cil_isinst +| 118 = @cil_conv_r_un +| 121 = @cil_unbox +| 122 = @cil_throw +| 123 = @cil_ldfld +| 124 = @cil_ldflda +| 125 = @cil_stfld +| 126 = @cil_ldsfld +| 127 = @cil_ldsflda +| 128 = @cil_stsfld +| 129 = @cil_stobj +| 130 = @cil_conv_ovf_i1_un +| 131 = @cil_conv_ovf_i2_un +| 132 = @cil_conv_ovf_i4_un +| 133 = @cil_conv_ovf_i8_un +| 134 = @cil_conv_ovf_u1_un +| 135 = @cil_conv_ovf_u2_un +| 136 = @cil_conv_ovf_u4_un +| 137 = @cil_conv_ovf_u8_un +| 138 = @cil_conv_ovf_i_un +| 139 = @cil_conv_ovf_u_un +| 140 = @cil_box +| 141 = @cil_newarr +| 142 = @cil_ldlen +| 143 = @cil_ldelema +| 144 = @cil_ldelem_i1 +| 145 = @cil_ldelem_u1 +| 146 = @cil_ldelem_i2 +| 147 = @cil_ldelem_u2 +| 148 = @cil_ldelem_i4 +| 149 = @cil_ldelem_u4 +| 150 = @cil_ldelem_i8 +| 151 = @cil_ldelem_i +| 152 = @cil_ldelem_r4 +| 153 = @cil_ldelem_r8 +| 154 = @cil_ldelem_ref +| 155 = @cil_stelem_i +| 156 = @cil_stelem_i1 +| 157 = @cil_stelem_i2 +| 158 = @cil_stelem_i4 +| 159 = @cil_stelem_i8 +| 160 = @cil_stelem_r4 +| 161 = @cil_stelem_r8 +| 162 = @cil_stelem_ref +| 163 = @cil_ldelem +| 164 = @cil_stelem +| 165 = @cil_unbox_any +| 179 = @cil_conv_ovf_i1 +| 180 = @cil_conv_ovf_u1 +| 181 = @cil_conv_ovf_i2 +| 182 = @cil_conv_ovf_u2 +| 183 = @cil_conv_ovf_i4 +| 184 = @cil_conv_ovf_u4 +| 185 = @cil_conv_ovf_i8 +| 186 = @cil_conv_ovf_u8 +| 194 = @cil_refanyval +| 195 = @cil_ckinfinite +| 198 = @cil_mkrefany +| 208 = @cil_ldtoken +| 209 = @cil_conv_u2 +| 210 = @cil_conv_u1 +| 211 = @cil_conv_i +| 212 = @cil_conv_ovf_i +| 213 = @cil_conv_ovf_u +| 214 = @cil_add_ovf +| 215 = @cil_add_ovf_un +| 216 = @cil_mul_ovf +| 217 = @cil_mul_ovf_un +| 218 = @cil_sub_ovf +| 219 = @cil_sub_ovf_un +| 220 = @cil_endfinally +| 221 = @cil_leave +| 222 = @cil_leave_s +| 223 = @cil_stind_i +| 224 = @cil_conv_u +| 65024 = @cil_arglist +| 65025 = @cil_ceq +| 65026 = @cil_cgt +| 65027 = @cil_cgt_un +| 65028 = @cil_clt +| 65029 = @cil_clt_un +| 65030 = @cil_ldftn +| 65031 = @cil_ldvirtftn +| 65033 = @cil_ldarg +| 65034 = @cil_ldarga +| 65035 = @cil_starg +| 65036 = @cil_ldloc +| 65037 = @cil_ldloca +| 65038 = @cil_stloc +| 65039 = @cil_localloc +| 65041 = @cil_endfilter +| 65042 = @cil_unaligned +| 65043 = @cil_volatile +| 65044 = @cil_tail +| 65045 = @cil_initobj +| 65046 = @cil_constrained +| 65047 = @cil_cpblk +| 65048 = @cil_initblk +| 65050 = @cil_rethrow +| 65052 = @cil_sizeof +| 65053 = @cil_refanytype +| 65054 = @cil_readonly +; + +// CIL ignored instructions + +@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned; + +// CIL local/parameter/field access + +@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga; +@cil_starg_any = @cil_starg | @cil_starg_s; + +@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca; +@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc; + +@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda; +@cil_stfld_any = @cil_stfld | @cil_stsfld; + +@cil_local_access = @cil_stloc_any | @cil_ldloc_any; +@cil_arg_access = @cil_starg_any | @cil_ldarg_any; +@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any; +@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any; + +@cil_stack_access = @cil_local_access | @cil_arg_access; +@cil_field_access = @cil_ldfld_any | @cil_stfld_any; + +@cil_access = @cil_read_access | @cil_write_access; + +// CIL constant/literal instructions + +@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8; + +@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 | + @cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4; + +@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8; + +@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr; + +// Control flow + +@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump; +@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s | + @cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s | + @cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt | + @cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un; +@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch; +@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any; +@cil_leave_any = @cil_leave | @cil_leave_s; +@cil_jump = @cil_unconditional_jump | @cil_conditional_jump; + +// CIL call instructions + +@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj; + +// CIL expression instructions + +@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access | + @cil_newarr | @cil_ldtoken | @cil_sizeof | + @cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup; + +@cil_unary_expr = + @cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation| + @cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any | + @cil_ldind | @cil_unbox; + +@cil_conversion_operation = + @cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 | + @cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 | + @cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un | + @cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un | + @cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un | + @cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un | + @cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un | + @cil_conv_i | @cil_conv_u | @cil_conv_r_un; + +@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 | + @cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4; + +@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 | + @cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref; + +@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation; + +@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl; + +@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un | + @cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un | + @cil_sub_ovf | @cil_sub_ovf_un; + +@cil_unary_bitwise_operation = @cil_not; + +@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation; + +@cil_unary_arithmetic_operation = @cil_neg; + +@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un; + +// Elements that retrieve an address of something +@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema; + +// CIL array instructions + +@cil_read_array = + @cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i | + @cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 | + @cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4; + +@cil_write_array = @cil_stelem | @cil_stelem_ref | + @cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 | + @cil_stelem_r4 | @cil_stelem_r8; + +@cil_throw_any = @cil_throw | @cil_rethrow; + +#keyset[impl, index] +cil_instruction( + unique int id: @cil_instruction, + int opcode: int ref, + int index: int ref, + int impl: @cil_method_implementation ref); + +cil_jump( + unique int instruction: @cil_jump ref, + int target: @cil_instruction ref); + +cil_access( + unique int instruction: @cil_instruction ref, + int target: @cil_accessible ref); + +cil_value( + unique int instruction: @cil_literal ref, + varchar(900) value: string ref); + +#keyset[instruction, index] +cil_switch( + int instruction: @cil_switch ref, + int index: int ref, + int target: @cil_instruction ref); + +cil_instruction_location( + unique int id: @cil_instruction ref, + int loc: @location ref); + +cil_type_location( + int id: @cil_type ref, + int loc: @location ref); + +cil_method_location( + int id: @cil_method ref, + int loc: @location ref); + +@cil_namespace = @namespace; + +@cil_type_container = @cil_type | @cil_namespace | @cil_method; + +case @cil_type.kind of + 0 = @cil_valueorreftype +| 1 = @cil_typeparameter +| 2 = @cil_array_type +| 3 = @cil_pointer_type +; + +cil_type( + unique int id: @cil_type, + varchar(900) name: string ref, + int kind: int ref, + int parent: @cil_type_container ref, + int sourceDecl: @cil_type ref); + +cil_pointer_type( + unique int id: @cil_pointer_type ref, + int pointee: @cil_type ref); + +cil_array_type( + unique int id: @cil_array_type ref, + int element_type: @cil_type ref, + int rank: int ref); + +cil_method( + unique int id: @cil_method, + varchar(900) name: string ref, + int parent: @cil_type ref, + int return_type: @cil_type ref); + +cil_method_source_declaration( + unique int method: @cil_method ref, + int source: @cil_method ref); + +cil_method_implementation( + unique int id: @cil_method_implementation, + int method: @cil_method ref, + int location: @assembly ref); + +cil_implements( + int id: @cil_method ref, + int decl: @cil_method ref); + +#keyset[parent, name] +cil_field( + unique int id: @cil_field, + int parent: @cil_type ref, + varchar(900) name: string ref, + int field_type: @cil_type ref); + +@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; +@cil_named_element = @cil_declaration | @cil_namespace; +@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member; +@cil_accessible = @cil_declaration; +@cil_variable = @cil_field | @cil_stack_variable; +@cil_stack_variable = @cil_local_variable | @cil_parameter; +@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event; + +#keyset[method, index] +cil_parameter( + unique int id: @cil_parameter, + int method: @cil_method ref, + int index: int ref, + int param_type: @cil_type ref); + +cil_parameter_in(unique int id: @cil_parameter ref); +cil_parameter_out(unique int id: @cil_parameter ref); + +cil_setter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_getter(unique int prop: @cil_property ref, + int method: @cil_method ref); + +cil_adder(unique int event: @cil_event ref, + int method: @cil_method ref); + +cil_remover(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); + +cil_property( + unique int id: @cil_property, + int parent: @cil_type ref, + varchar(900) name: string ref, + int property_type: @cil_type ref); + +#keyset[parent, name] +cil_event(unique int id: @cil_event, + int parent: @cil_type ref, + varchar(900) name: string ref, + int event_type: @cil_type ref); + +#keyset[impl, index] +cil_local_variable( + unique int id: @cil_local_variable, + int impl: @cil_method_implementation ref, + int index: int ref, + int var_type: @cil_type ref); + +// CIL handlers (exception handlers etc). + +case @cil_handler.kind of + 0 = @cil_catch_handler +| 1 = @cil_filter_handler +| 2 = @cil_finally_handler +| 4 = @cil_fault_handler +; + +#keyset[impl, index] +cil_handler( + unique int id: @cil_handler, + int impl: @cil_method_implementation ref, + int index: int ref, + int kind: int ref, + int try_start: @cil_instruction ref, + int try_end: @cil_instruction ref, + int handler_start: @cil_instruction ref); + +cil_handler_filter( + unique int id: @cil_handler ref, + int filter_start: @cil_instruction ref); + +cil_handler_type( + unique int id: @cil_handler ref, + int catch_type: @cil_type ref); + +@cil_controlflow_node = @cil_entry_point | @cil_instruction; + +@cil_entry_point = @cil_method_implementation | @cil_handler; + +@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method; + +cil_method_stack_size( + unique int method: @cil_method_implementation ref, + int size: int ref); + +// CIL modifiers + +cil_public(int id: @cil_member ref); +cil_private(int id: @cil_member ref); +cil_protected(int id: @cil_member ref); +cil_internal(int id: @cil_member ref); +cil_static(int id: @cil_member ref); +cil_sealed(int id: @cil_member ref); +cil_virtual(int id: @cil_method ref); +cil_abstract(int id: @cil_member ref); +cil_class(int id: @cil_type ref); +cil_interface(int id: @cil_type ref); +cil_security(int id: @cil_member ref); +cil_requiresecobject(int id: @cil_method ref); +cil_specialname(int id: @cil_method ref); +cil_newslot(int id: @cil_method ref); + +cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref); +cil_base_interface(int id: @cil_type ref, int base: @cil_type ref); + +#keyset[unbound, index] +cil_type_parameter( + int unbound: @cil_member ref, + int index: int ref, + int param: @cil_typeparameter ref); + +#keyset[bound, index] +cil_type_argument( + int bound: @cil_member ref, + int index: int ref, + int t: @cil_type ref); + +// CIL type parameter constraints + +cil_typeparam_covariant(int tp: @cil_typeparameter ref); +cil_typeparam_contravariant(int tp: @cil_typeparameter ref); +cil_typeparam_class(int tp: @cil_typeparameter ref); +cil_typeparam_struct(int tp: @cil_typeparameter ref); +cil_typeparam_new(int tp: @cil_typeparameter ref); +cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref); + +// CIL attributes + +cil_attribute( + unique int attributeid: @cil_attribute, + int element: @cil_declaration ref, + int constructor: @cil_method ref); + +#keyset[attribute_id, param] +cil_attribute_named_argument( + int attribute_id: @cil_attribute ref, + varchar(100) param: string ref, + varchar(900) value: string ref); + +#keyset[attribute_id, index] +cil_attribute_positional_argument( + int attribute_id: @cil_attribute ref, + int index: int ref, + varchar(900) value: string ref); + + +// Common .Net data model covering both C# and CIL + +// Common elements +@dotnet_element = @element | @cil_element; +@dotnet_named_element = @named_element | @cil_named_element; +@dotnet_callable = @callable | @cil_method; +@dotnet_variable = @variable | @cil_variable; +@dotnet_field = @field | @cil_field; +@dotnet_parameter = @parameter | @cil_parameter; +@dotnet_declaration = @declaration | @cil_declaration; +@dotnet_member = @member | @cil_member; +@dotnet_event = @event | @cil_event; +@dotnet_property = @property | @cil_property | @indexer; + +// Common types +@dotnet_type = @type | @cil_type; +@dotnet_call = @call | @cil_call_any; +@dotnet_throw = @throw_element | @cil_throw_any; +@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type; +@dotnet_typeparameter = @type_parameter | @cil_typeparameter; +@dotnet_array_type = @array_type | @cil_array_type; +@dotnet_pointer_type = @pointer_type | @cil_pointer_type; +@dotnet_type_parameter = @type_parameter | @cil_typeparameter; +@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable; + +// Attributes +@dotnet_attribute = @attribute | @cil_attribute; + +// Expressions +@dotnet_expr = @expr | @cil_expr; + +// Literals +@dotnet_literal = @literal_expr | @cil_literal; +@dotnet_string_literal = @string_literal_expr | @cil_ldstr; +@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i; +@dotnet_float_literal = @float_literal_expr | @cil_ldc_r; +@dotnet_null_literal = @null_literal_expr | @cil_ldnull; + +@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property | + @callable | @value_or_ref_type | @void_type; + +#keyset[entity, location] +metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref) diff --git a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/upgrade.properties b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/upgrade.properties new file mode 100644 index 000000000000..a8ba5643bcb6 --- /dev/null +++ b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/upgrade.properties @@ -0,0 +1,2 @@ +description: Implement structured nullability +compatibility: backwards From c8225adf1b2b82c78570ad367c939cafeb6c764a Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Wed, 2 Oct 2019 10:43:56 +0100 Subject: [PATCH 0346/2538] C#: Add missing file & minor fixes. --- .../Entities/Symbol.cs | 1 - .../Entities/Types/Nullability.cs | 272 ++++++++++++++++++ 2 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs index 6d0f5dd80c8f..4f239083d24f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Symbol.cs @@ -30,7 +30,6 @@ protected void PopulateAttributes() protected void PopulateNullability(TextWriter trapFile, AnnotatedTypeSymbol type) { - var ta = type.Nullability.GetTypeAnnotation(); var n = NullabilityEntity.Create(Context, Nullability.Create(type)); if (!type.HasObliviousNullability()) { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs new file mode 100644 index 000000000000..cef905d343c3 --- /dev/null +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs @@ -0,0 +1,272 @@ +using Microsoft.CodeAnalysis; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +namespace Semmle.Extraction.CSharp.Entities +{ + public sealed class Nullability + { + public int Annotation { get; private set; } + + static readonly Nullability[] EmptyArray = new Nullability[0]; + public readonly Nullability[] NullableParameters; + + public static Nullability Create(AnnotatedTypeSymbol ts) + { + if(ts.HasConsistentNullability()) + { + switch (ts.Nullability) + { + case NullableAnnotation.Annotated: + return annotated; + case NullableAnnotation.NotAnnotated: + return notannotated; + default: + return oblivious; + } + } + + return new Nullability(ts); + } + + static readonly Nullability oblivious = new Nullability(NullableAnnotation.Disabled); + static readonly Nullability annotated = new Nullability(NullableAnnotation.Annotated); + static readonly Nullability notannotated = new Nullability(NullableAnnotation.NotAnnotated); + + private Nullability(NullableAnnotation n) + { + SetNullability(n); + NullableParameters = new Nullability[0]; + } + + private void SetNullability(NullableAnnotation n) + { + switch (n) + { + case NullableAnnotation.NotAnnotated: + Annotation = 1; + break; + case NullableAnnotation.Annotated: + Annotation = 2; + break; + default: + Annotation = 0; + break; + } + } + + private Nullability(AnnotatedTypeSymbol ts) : this(ts.Nullability) + { + NullableParameters = ts.HasConsistentNullability() ? EmptyArray : ts.GetAnnotatedTypeArguments().Select(Create).ToArray(); + } + + public Nullability(IMethodSymbol method) + { + Annotation = 0; + NullableParameters = method.GetAnnotatedTypeArguments().Select(a => new Nullability(a)).ToArray(); + } + + public override bool Equals(object other) + { + return other is Nullability n && Annotation == n.Annotation && NullableParameters.SequenceEqual(n.NullableParameters); + } + + public override int GetHashCode() + { + int h = Annotation; + + foreach (var t in NullableParameters) + h = h * 5 + t.GetHashCode(); + + return h; + } + + public void WriteId(TextWriter trapFile) + { + trapFile.Write(Annotation); + trapFile.Write('('); + foreach (var s in NullableParameters) + s.WriteId(trapFile); + trapFile.Write(')'); + } + + public override string ToString() + { + using (var w = new StringWriter()) + { + WriteId(w); + return w.ToString(); + } + } + } + + public class NullabilityEntity : CachedEntity + { + public NullabilityEntity(Context cx, Nullability init) : base(cx, init) + { + } + + public override Location ReportingLocation => throw new System.NotImplementedException(); + + public override bool NeedsPopulation => true; + + public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel; + + public override void Populate(TextWriter trapFile) + { + trapFile.nullability(this, symbol.Annotation); + + int i = 0; + foreach(var s in symbol.NullableParameters) + { + trapFile.nullability_member(this, i, Create(Context, s)); + i++; + } + } + + public override void WriteId(TextWriter trapFile) + { + symbol.WriteId(trapFile); + } + + public static NullabilityEntity Create(Context cx, Nullability init) => NullabilityFactory.Instance.CreateEntity(cx, init); + + class NullabilityFactory : ICachedEntityFactory + { + public static readonly NullabilityFactory Instance = new NullabilityFactory(); + + public NullabilityEntity Create(Context cx, Nullability init) => new NullabilityEntity(cx, init); + } + } + + public static class NullabilityExtensions + { + /// + /// Gets the annotated type of an ILocalSymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedType(this ILocalSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); + + /// + /// Gets the annotated type of an IParameterSymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedType(this IParameterSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); + + /// + /// Gets the annotated type of an IPropertySymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedType(this IPropertySymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); + + /// + /// Gets the annotated type of an IEventSymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedType(this IEventSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); + + /// + /// Gets the annotated type of an IFieldSymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedType(this IFieldSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); + + /// + /// Gets the annotated return type of an IMethodSymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedReturnType(this IMethodSymbol symbol) => new AnnotatedTypeSymbol(symbol.ReturnType, symbol.ReturnNullableAnnotation); + + /// + /// Gets the type annotation for a NullableAnnotation. + /// + public static Kinds.TypeAnnotation GetTypeAnnotation(this NullableAnnotation na) + { + switch (na) + { + case NullableAnnotation.Annotated: + return Kinds.TypeAnnotation.Annotated; + case NullableAnnotation.NotAnnotated: + return Kinds.TypeAnnotation.NotAnnotated; + default: + return Kinds.TypeAnnotation.None; + } + } + + public static IEnumerable GetAnnotatedTypeArguments(this AnnotatedTypeSymbol at) + { + switch (at.Symbol) + { + case IArrayTypeSymbol array: + yield return array.GetAnnotatedElementType(); + break; + case INamedTypeSymbol named: + foreach (var n in named.GetAnnotatedTypeArguments()) + yield return n; + break; + } + } + + /// + /// Checks if this type has consistent nullability, which is the most common case. + /// Either the code is oblivious to nullability, or is non-nullable. + /// This is so that we can avoid populating nullability in most cases. + /// For example, + /// + /// IEnumerable<string?> // false + /// IEnumerable<string?>? // true + /// string? // true + /// string[] // true + /// string?[] // false + /// string?[]? // true + /// + /// + /// The annotated type. + /// If the nullability is consistent in the type. + public static bool HasConsistentNullability(this AnnotatedTypeSymbol at) => + at.GetAnnotatedTypeArguments().All(a => a.Nullability == at.Nullability && a.HasConsistentNullability()); + + /// + /// Holds if the type symbol is completely oblivious to nullability. + /// + /// The annotated type symbol. + /// If at is oblivious. + public static bool HasObliviousNullability(this AnnotatedTypeSymbol at) => + at.Nullability.GetTypeAnnotation() == Kinds.TypeAnnotation.None && at.HasConsistentNullability(); + + /// + /// Gets the annotated element type of an IArrayTypeSymbol. + /// This has not yet been exposed on the public API. + /// + public static AnnotatedTypeSymbol GetAnnotatedElementType(this IArrayTypeSymbol symbol) => + new AnnotatedTypeSymbol(symbol.ElementType, symbol.ElementNullableAnnotation); + + /// + /// Gets the annotated type arguments of an INamedTypeSymbol. + /// This has not yet been exposed on the public API. + /// + public static IEnumerable GetAnnotatedTypeArguments(this INamedTypeSymbol symbol) => + symbol.TypeArguments.Zip(symbol.TypeArgumentsNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a)); + + /// + /// Gets the annotated type arguments of an IMethodSymbol. + /// This has not yet been exposed on the public API. + /// + public static IEnumerable GetAnnotatedTypeArguments(this IMethodSymbol symbol) => + symbol.TypeArguments.Zip(symbol.TypeArgumentsNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a)); + + /// + /// Gets the annotated type constraints of an ITypeParameterSymbol. + /// This has not yet been exposed on the public API. + /// + public static IEnumerable GetAnnotatedTypeConstraints(this ITypeParameterSymbol symbol) => + symbol.ConstraintTypes.Zip(symbol.ConstraintNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a)); + + /// + /// Creates an AnnotatedTypeSymbol from an ITypeSymbol. + /// + public static AnnotatedTypeSymbol WithAnnotation(this ITypeSymbol symbol, NullableAnnotation annotation) => + new AnnotatedTypeSymbol(symbol, annotation); + } +} From a0fa7dad79370ed50ef2f6604412ba7c13fce437 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Wed, 2 Oct 2019 11:01:25 +0100 Subject: [PATCH 0347/2538] C#: Autoformat --- csharp/ql/src/semmle/code/csharp/AnnotatedType.qll | 2 +- csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql | 4 +--- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index afa80c43ae6b..a6e2417796a4 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -164,7 +164,7 @@ private module Annotations { /** * Gets the `i`th member of this annotation. - * Returns `this` if the nullability is not explicitly + * Returns `this` if the nullability is not explicitly * stored in the database, since many type annotations will have consistent * nullability. */ diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql index cf5d320ca915..de55dd7b2721 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql @@ -45,9 +45,7 @@ query predicate methodTypeArguments(ConstructedGeneric generic, int arg, string argument = generic.getAnnotatedTypeArgument(arg).toString() } -query predicate constructedTypes( - AnnotatedConstructedType at, int i, string arg, string nullability -) { +query predicate constructedTypes(AnnotatedConstructedType at, int i, string arg, string nullability) { arg = at.getTypeArgument(i).toString() and at.getLocation() instanceof SourceLocation and nullability = at.getAnnotations().getNullability().toString() From f00276a82c140dea2cd43e64bdf8999776648489 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Thu, 24 Oct 2019 18:53:29 +0100 Subject: [PATCH 0348/2538] C#: Remove non-essential changes --- .../Entities/LocalFunction.cs | 2 +- .../Entities/Method.cs | 10 +-- .../Entities/Types/NamedType.cs | 8 +-- .../Entities/Types/TupleType.cs | 2 +- .../Entities/Types/Type.cs | 3 - .../Entities/UserOperator.cs | 2 +- .../SymbolExtensions.cs | 66 +++++++------------ .../csharp8/NullableRefTypes.expected | 3 - .../library-tests/csharp8/NullableRefTypes.ql | 3 +- 9 files changed, 37 insertions(+), 62 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs index 7199b6945076..f58c027eca54 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/LocalFunction.cs @@ -19,7 +19,7 @@ public override void WriteId(TextWriter trapFile) if (symbol.IsGenericMethod && !IsSourceDeclaration) { trapFile.Write('<'); - trapFile.BuildList(",", symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(Context, tb0, symbol, ta, TypeIdentifierContext.MethodName)); + trapFile.BuildList(",", symbol.TypeArguments, (ta, tb0) => AddSignatureTypeToId(Context, tb0, symbol, ta)); trapFile.Write('>'); } trapFile.Write(";localfunction"); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index 18aec3b05ecc..f3aba9744be3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -129,7 +129,7 @@ protected static void BuildMethodId(Method m, TextWriter trapFile) // Type arguments with different nullability can result in // a constructed method with different nullability of its parameters and return type, // so we need to create a distinct database entity for it. - trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol, TypeIdentifierContext.MethodName); trapFile.Write((int)ta.Nullability); }); + trapFile.BuildList(",", m.symbol.GetAnnotatedTypeArguments(), (ta, tb0) => { AddSignatureTypeToId(m.Context, tb0, m.symbol, ta.Symbol); trapFile.Write((int)ta.Nullability); }); trapFile.Write('>'); } } @@ -199,10 +199,10 @@ public override void WriteId(TextWriter trapFile) /// to make the reference to #3 in the label definition #4 for /// T valid. /// - protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type, TypeIdentifierContext tic) + protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMethodSymbol method, ITypeSymbol type) { if (type.ContainsTypeParameters(cx, method)) - type.BuildTypeId(cx, trapFile, (cx0, tb0, type0, _) => AddSignatureTypeToId(cx, tb0, method, type0, tic), tic, method); + type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); else trapFile.WriteSubId(Type.Create(cx, type).TypeRef); } @@ -215,13 +215,13 @@ protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethod if (method.MethodKind == MethodKind.ReducedExtension) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType, TypeIdentifierContext.MethodParam); + AddSignatureTypeToId(cx, trapFile, method, method.ReceiverType); } foreach (var param in method.Parameters) { trapFile.WriteSeparator(",", ref index); - AddSignatureTypeToId(cx, trapFile, method, param.Type, TypeIdentifierContext.MethodParam); + AddSignatureTypeToId(cx, trapFile, method, param.Type); switch (param.RefKind) { case RefKind.Out: diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index 28b1e37514ae..fa5f6a4bdf9e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -111,7 +111,7 @@ public override IEnumerable Locations public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeIdentifierContext.TypeName, symbol); + symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";type"); } @@ -177,12 +177,12 @@ class NamedTypeRefFactory : ICachedEntityFactory<(Type, ITypeSymbol), TypeRef> public override void WriteId(TextWriter trapFile) { - void ExpandType(Context cx0, TextWriter tb0, ITypeSymbol sub, ISymbol gc) + void ExpandType(Context cx0, TextWriter tb0, ITypeSymbol sub) { - sub.BuildTypeId(cx0, tb0, ExpandType, TypeIdentifierContext.TypeRef, gc); + sub.BuildTypeId(cx0, tb0, ExpandType); } - symbol.BuildTypeId(Context, trapFile, ExpandType, TypeIdentifierContext.TypeRef, symbol); + symbol.BuildTypeId(Context, trapFile, ExpandType); trapFile.Write(";typeref"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index 8da87ba318df..d486506408b7 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -32,7 +32,7 @@ class TupleTypeFactory : ICachedEntityFactory public override void WriteId(TextWriter trapFile) { - symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub, _) => tb0.WriteSubId(Create(cx0, sub)), TypeIdentifierContext.TypeName, symbol); + symbol.BuildTypeId(Context, trapFile, (cx0, tb0, sub) => tb0.WriteSubId(Create(cx0, sub))); trapFile.Write(";tuple"); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index d541febee6db..276cf6758e2c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -270,9 +270,6 @@ public static Type Create(Context cx, ITypeSymbol type) { type = type.DisambiguateType(); - if (type is INamedTypeSymbol nt && nt.IsEvilTwin()) - type = nt.ConstructedFrom; - const bool errorTypeIsNull = false; return type == null || (errorTypeIsNull && type.TypeKind == TypeKind.Error) ? NullType.Create(cx).Type : (Type)cx.CreateEntity(type); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs index 5ac9c3015e0c..2a64a29fa0d2 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/UserOperator.cs @@ -51,7 +51,7 @@ public override Type ContainingType public override void WriteId(TextWriter trapFile) { - AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType, TypeIdentifierContext.MethodParam); // Needed for op_explicit(), which differs only by return type. + AddSignatureTypeToId(Context, trapFile, symbol, symbol.ReturnType); // Needed for op_explicit(), which differs only by return type. trapFile.Write(' '); BuildMethodId(this, trapFile); } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index a5a5dc3aa839..6e2b52f3086d 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -27,19 +27,6 @@ public AnnotatedTypeSymbol(ITypeSymbol symbol, NullableAnnotation nullability) } } - /// - /// Marks where a type identifier is being generated, which could change - /// the way that the identifier is generated. - /// - public enum TypeIdentifierContext - { - TypeName, - TypeRef, - AnonymousType, - MethodName, - MethodParam - } - static class SymbolExtensions { /// @@ -146,7 +133,7 @@ public static bool ContainsTypeParameters(this ITypeSymbol type, Context cx, ISy /// The extraction context. /// The trap builder used to store the result. /// The action to apply to syntactic sub terms of this type. - public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, TypeIdentifierContext tic, ISymbol genericContext) + public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction) { switch(type.SpecialType) { @@ -184,7 +171,7 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra { case TypeKind.Array: var array = (IArrayTypeSymbol)type; - subTermAction(cx, trapFile, array.ElementType, genericContext); + subTermAction(cx, trapFile, array.ElementType); array.BuildArraySuffix(trapFile); return; case TypeKind.Class: @@ -194,29 +181,16 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra case TypeKind.Delegate: case TypeKind.Error: var named = (INamedTypeSymbol)type; - named.BuildNamedTypeId(cx, trapFile, subTermAction, tic, genericContext); + named.BuildNamedTypeId(cx, trapFile, subTermAction); return; case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; - subTermAction(cx, trapFile, ptr.PointedAtType, genericContext); + subTermAction(cx, trapFile, ptr.PointedAtType); trapFile.Write("*"); return; case TypeKind.TypeParameter: var tp = (ITypeParameterSymbol)type; - switch(tp.TypeParameterKind) - { - case TypeParameterKind.Method: - if (!Equals(genericContext, tp.DeclaringMethod)) - trapFile.WriteSubId(Method.Create(cx, tp.DeclaringMethod)); - trapFile.Write("!!"); - break; - case TypeParameterKind.Type: - if (!Equals(genericContext,tp.DeclaringType)) - subTermAction(cx, trapFile, tp.DeclaringType, genericContext); - trapFile.Write("!"); - break; - } - trapFile.Write(tp.Ordinal); + trapFile.Write(tp.Name); return; case TypeKind.Dynamic: trapFile.Write("dynamic"); @@ -258,11 +232,10 @@ private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool trapFile.Write("::"); } - public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction, TypeIdentifierContext tic, ISymbol genericContext) + public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) { bool prefixAssembly = false; if (named.IsAnonymous()) prefixAssembly = true; - else if(tic == TypeIdentifierContext.TypeName && cx.Extractor.TrapIdentifiers != TrapIdenfierMode.Imprecise) prefixAssembly = true; if (named.ContainingAssembly is null) prefixAssembly = false; if (prefixAssembly) @@ -276,7 +249,7 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex { trapFile.Write(f.Name); trapFile.Write(":"); - subTermAction(cx, tb0, f.Type, genericContext); + subTermAction(cx, tb0, f.Type); } ); trapFile.Write(")"); @@ -285,16 +258,16 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex if (named.ContainingType != null) { - subTermAction(cx, trapFile, named.ContainingType, genericContext); + subTermAction(cx, trapFile, named.ContainingType); trapFile.Write('.'); } - else if (named.ContainingNamespace != null && !named.IsConstructedGeneric()) + else if (named.ContainingNamespace != null) { named.ContainingNamespace.BuildNamespace(cx, trapFile); } if (named.IsAnonymousType) - named.BuildAnonymousName(cx, trapFile, subTermAction, true, genericContext); + named.BuildAnonymousName(cx, trapFile, subTermAction, true); else if (named.TypeParameters.IsEmpty) trapFile.Write(named.Name); else if (IsReallyUnbound(named)) @@ -305,14 +278,14 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex } else { - subTermAction(cx, trapFile, named.ConstructedFrom, genericContext); + subTermAction(cx, trapFile, named.ConstructedFrom); trapFile.Write('<'); // Encode the nullability of the type arguments in the label. // Type arguments with different nullability can result in // a constructed type with different nullability of its members and methods, // so we need to create a distinct database entity for it. trapFile.BuildList(",", named.GetAnnotatedTypeArguments(), - (ta, tb0) => subTermAction(cx, tb0, ta.Symbol, genericContext) + (ta, tb0) => subTermAction(cx, tb0, ta.Symbol) ); trapFile.Write('>'); } @@ -324,16 +297,16 @@ static void BuildNamespace(this INamespaceSymbol ns, Context cx, TextWriter trap trapFile.Write('.'); } - static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName, ISymbol genericContext) + static void BuildAnonymousName(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction, bool includeParamName) { var buildParam = includeParamName ? (prop, tb0) => { tb0.Write(prop.Name); tb0.Write(' '); - subTermAction(cx, tb0, prop.Type, genericContext); + subTermAction(cx, tb0, prop.Type); } - : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type, genericContext)); + : (Action)((prop, tb0) => subTermAction(cx, tb0, prop.Type)); int memberCount = type.GetMembers().OfType().Count(); int hackTypeNumber = memberCount == 1 ? 1 : 0; trapFile.Write("<>__AnonType"); @@ -405,7 +378,7 @@ public static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Co if (namedType.IsAnonymousType) { - namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub, _) => sub.BuildDisplayName(cx0, tb0), false, namedType); + namedType.BuildAnonymousName(cx, trapFile, (cx0, tb0, sub) => sub.BuildDisplayName(cx0, tb0), false); } trapFile.Write(namedType.Name); @@ -617,5 +590,12 @@ public static IEnumerable GetAnnotatedTypeConstraints(this /// public static AnnotatedTypeSymbol WithAnnotation(this ITypeSymbol symbol, NullableAnnotation annotation) => new AnnotatedTypeSymbol(symbol, annotation); + + /// + /// Holds if this type looks like an "anonymous" type. Names of anonymous types + /// sometimes collide so they need to be handled separately. + /// + public static bool IsAnonymous(this INamedTypeSymbol type) => + type.IsAnonymousType || type.Name.StartsWith("<>"); } } diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected index 4ea99349aa83..915992329e37 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.expected @@ -201,9 +201,6 @@ methodTypeArguments | NullableRefTypes.cs:67:10:67:21 | GenericFn | 0 | MyClass | | NullableRefTypes.cs:67:10:67:21 | GenericFn | 0 | MyClass! | constructedTypes -| AsyncStreams.cs:34:15:34:37 | IAsyncEnumerable | 0 | int | _ | -| AsyncStreams.cs:39:15:39:37 | IAsyncEnumerator | 0 | T | _ | -| AsyncStreams.cs:39:15:39:37 | IAsyncEnumerator | 0 | int | _ | | NullableRefTypes.cs:54:11:54:33 | Generic | 0 | MyClass | _ | | NullableRefTypes.cs:54:11:54:33 | Generic | 1 | MyClass | _ | | NullableRefTypes.cs:54:11:54:33 | Generic | 2 | IDisposable | _ | diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql index de55dd7b2721..416929afb92a 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql @@ -47,12 +47,13 @@ query predicate methodTypeArguments(ConstructedGeneric generic, int arg, string query predicate constructedTypes(AnnotatedConstructedType at, int i, string arg, string nullability) { arg = at.getTypeArgument(i).toString() and - at.getLocation() instanceof SourceLocation and + at.getLocation().getFile().getBaseName() = "NullableRefTypes.cs" and nullability = at.getAnnotations().getNullability().toString() } query predicate nullableTypeParameters(TypeParameter p) { p.getConstraints().hasNullableRefTypeConstraint() + and p.getLocation().getFile().getBaseName() = "NullableRefTypes.cs" } query predicate annotatedTypeConstraints(TypeParameter p, AnnotatedType t) { From 58e14af9cd3920e6a1ad6db96856648206936090 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Sun, 3 Nov 2019 15:26:29 +0000 Subject: [PATCH 0349/2538] C#: Address review comments. Create a TNullability type annotation and restructure TAnnotation. --- .../Entities/Types/Nullability.cs | 11 +- .../src/semmle/code/csharp/AnnotatedType.qll | 229 +++++++++--------- 2 files changed, 121 insertions(+), 119 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs index cef905d343c3..4dc0a9046aa6 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs @@ -7,14 +7,14 @@ namespace Semmle.Extraction.CSharp.Entities { public sealed class Nullability { - public int Annotation { get; private set; } + public int Annotation { get; } static readonly Nullability[] EmptyArray = new Nullability[0]; public readonly Nullability[] NullableParameters; public static Nullability Create(AnnotatedTypeSymbol ts) { - if(ts.HasConsistentNullability()) + if (ts.HasConsistentNullability()) { switch (ts.Nullability) { @@ -35,12 +35,6 @@ public static Nullability Create(AnnotatedTypeSymbol ts) static readonly Nullability notannotated = new Nullability(NullableAnnotation.NotAnnotated); private Nullability(NullableAnnotation n) - { - SetNullability(n); - NullableParameters = new Nullability[0]; - } - - private void SetNullability(NullableAnnotation n) { switch (n) { @@ -54,6 +48,7 @@ private void SetNullability(NullableAnnotation n) Annotation = 0; break; } + NullableParameters = EmptyArray; } private Nullability(AnnotatedTypeSymbol ts) : this(ts.Nullability) diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index a6e2417796a4..96300abdcd81 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -8,173 +8,163 @@ import csharp -private module Annotations { +module Annotations { newtype TAnnotation = - TNotNullableRefType() or - TNullableRefType() or TReadonlyRefType() or TRefType() or - TOutType() + TOutType() or + TNullability(@nullability n) /** An annotation on a type. */ class TypeAnnotation extends TAnnotation { - /** Holds if this string should prefix the type string. */ - predicate isPrefix() { none() } - - /** Holds if this string should suffix the type string. */ - predicate isSuffix() { none() } - - /** Gets the bit position in the bit-field. */ + /** Gets the bit position in the bit-field, also used to order the annotations in the text format. */ abstract int getBit(); - /** Gets a string representation of this type annotation. */ - abstract string toString(); - } + /** Gets the string prefixing the type, if any. */ + string getPrefix() { none() } - /** An annotation indicating that the type is not nullable. */ - class NonNullableRefType extends TypeAnnotation, TNotNullableRefType { - override predicate isSuffix() { any() } + /** Gets the string suffixing the type, if any. */ + string getSuffix() { none() } - override string toString() { result = "!" } - - override int getBit() { result = 2 } - } - - /** An annotation indicating that the type is a nullable reference type. */ - class NullableRefType extends TypeAnnotation, TNullableRefType { - override predicate isSuffix() { any() } - - override string toString() { result = "?" } - - override int getBit() { result = 3 } + /** Gets a string representation of this type annotation. */ + string toString() { none() } } /** An annotation indicating that the type is a readonly reference. */ class ReadonlyRefType extends TypeAnnotation, TReadonlyRefType { - override predicate isPrefix() { any() } + override string getPrefix() { result = "readonly " } - override string toString() { result = "readonly " } + override string toString() { result = "readonly ref" } override int getBit() { result = 4 } } /** An annotation indicating that the variable or return is by `ref`. */ class RefTypeAnnotation extends TypeAnnotation, TRefType { - override predicate isPrefix() { any() } + override string getPrefix() { result = "ref " } - override string toString() { result = "ref " } + override string toString() { result = "ref" } override int getBit() { result = 5 } } /** An annotation indicating that the parameter is `out`. */ class OutType extends TypeAnnotation, TOutType { - override predicate isPrefix() { any() } + override string getPrefix() { result = "out " } - override string toString() { result = "out " } + override string toString() { result = "out" } override int getBit() { result = 6 } } - newtype TAnnotations = + private newtype TAnnotations = TAnnotationFlags(int flags, Nullability n) { - exists(Element e | flags = getElementTypeFlags(e) and n = getElementNullability(e)) - or - flags = 0 // n is unbound - } + exists(Element e | + flags = getElementTypeFlags(e) and + n = getElementNullability(e) + ) + } or + TAnnotationsNoFlags(Nullability n) + /** A collection of type annotations. */ class TypeAnnotations extends TAnnotations { - int flags; - - Nullability nullability; - - TypeAnnotations() { this = TAnnotationFlags(flags, nullability) } - - /** Gets the flags (as a bitset) of this type annotation. */ - int getFlags() { result = flags } - /** Gets the nullability of this type annotation. */ - Nullability getNullability() { result = nullability } - - /** - * Gets the `i`th "child" of this type annotation. - * This is used to represent structured datatypes, where the structure - * of the type annotation mirrors the structure of the annotated type. - */ - bindingset[i] - TypeAnnotations getChild(int i) { - result.getFlags() = 0 and result.getNullability() = this.getNullability().getMember(i) + Nullability getNullability() { + this = TAnnotationFlags(_, result) + or + this = TAnnotationsNoFlags(result) } + /** Gets the nullability with no additional flags. */ + Nullability getNoFlagsNullability() { this = TAnnotationsNoFlags(result) } + /** Gets text to be displayed before the type. */ string getTypePrefix() { result = concat(TypeAnnotation a | - a = this.getAnAnnotation() and a.isPrefix() + a = this.getAnAnnotation() | - a.toString(), "" order by a.getBit() + a.getPrefix(), "" order by a.getBit() ) } /** Gets text to be displayed after the type. */ string getTypeSuffix() { result = concat(TypeAnnotation a | - a = this.getAnAnnotation() and a.isSuffix() + a = this.getAnAnnotation() | - a.toString(), "" order by a.getBit() + a.getSuffix(), "" order by a.getBit() ) } /** Gets a textual representation of this type annotation. */ - string toString() { result = getTypePrefix() + getTypeSuffix() } + string toString() { result = getTypePrefix() + getNullability() + getTypeSuffix() } + + private int getFlags() { this = TAnnotationFlags(result, _) } private predicate isSet(int bit) { isBit(bit) and - exists(int mask | mask = getBitMask(bit) | flags.bitAnd(mask) = mask) + exists(int mask | mask = getBitMask(bit) | this.getFlags().bitAnd(mask) = mask) } /** Gets an annotation in this set of annotations. */ TypeAnnotation getAnAnnotation() { isSet(result.getBit()) or - nullability instanceof AnnotatedNullability and result instanceof NullableRefType - or - nullability instanceof NotAnnotatedNullability and result instanceof NonNullableRefType + result = this.getNullability() } } + /** + * Gets the `i`th child of type annotations `annotations`. + * This is used to represent structured datatypes, where the structure + * of the type annotation mirrors the structure of the annotated type. + */ + bindingset[i] + TypeAnnotations getChild(TypeAnnotations annotations, int i) { + result.getNoFlagsNullability() = getChildNullability(annotations.getNullability(), i) + } + /** * A structured type annotation representing type nullability. * For example, `IDictionary?` has nullability `?`. */ - class Nullability extends @nullability { - string toString() { result = getMemberString() + getSelfNullability() } + abstract class Nullability extends TypeAnnotation, TNullability { + @nullability nullability; + + Nullability() { this = TNullability(nullability) } + + @nullability getNullability() { result = nullability } + + override string toString() { result = getMemberString() + getSelfNullability() } language[monotonicAggregates] private string getMemberString() { - if nullability_member(this, _, _) + if nullability_member(nullability, _, _) then result = "<" + concat(int i, Nullability child | - nullability_member(this, i, child) + nullability_member(nullability, i, child.getNullability()) | child.toString(), "," order by i ) + ">" else result = "" } - /** - * Gets the `i`th member of this annotation. - * Returns `this` if the nullability is not explicitly - * stored in the database, since many type annotations will have consistent - * nullability. - */ - bindingset[i] - Nullability getMember(int i) { - if nullability_member(this, i, _) then nullability_member(this, i, result) else result = this - } + /** Gets a string representing the nullability, disregarding child nullability. */ + string getSelfNullability() { none() } + } - /** Gets a string representing the nullability. */ - abstract string getSelfNullability(); + /** + * Gets the `i`th child of nullability `n`. + * Returns `n` if the nullability is not explicitly + * stored in the database, since many type annotations will have consistent + * nullability. + */ + bindingset[i] + Nullability getChildNullability(Nullability n, int i) { + if nullability_member(n.getNullability(), i, _) + then nullability_member(n.getNullability(), i, result.getNullability()) + else result = n } /** @@ -182,8 +172,12 @@ private module Annotations { * applicable, because the code was not compiled in a nullable context, or * because the C# language version is less than 8. */ - class ObliviousNullability extends Nullability, @oblivious { + class ObliviousNullability extends Nullability { + ObliviousNullability() { nullability instanceof @oblivious } + override string getSelfNullability() { result = "_" } + + override int getBit() { none() } } /** @@ -191,26 +185,43 @@ private module Annotations { * and all type arguments are oblivious. */ class NoNullability extends ObliviousNullability { - NoNullability() { not nullability_member(this, _, _) } + NoNullability() { not nullability_member(nullability, _, _) } } /** A type with annotated nullablity, `?`. */ - class AnnotatedNullability extends Nullability, @annotated { + class AnnotatedNullability extends Nullability { + AnnotatedNullability() { nullability instanceof @annotated } + override string getSelfNullability() { result = "?" } + + override int getBit() { result = 3 } + + override string getSuffix() { result = "?" } } /** * A ref type not annotated with `?` in a nullable context. */ - class NotAnnotatedNullability extends Nullability, @not_annotated { + class NotAnnotatedNullability extends Nullability { + NotAnnotatedNullability() { nullability instanceof @not_annotated } + override string getSelfNullability() { result = "!" } + + override int getBit() { result = 2 } + + override string getSuffix() { result = "!" } } /** Holds if the type annotations `annotations` apply to type `type` on element `element`. */ predicate elementTypeAnnotations( @has_type_annotation element, Type type, TypeAnnotations annotations ) { - annotations = TAnnotationFlags(getElementTypeFlags(element), getElementNullability(element)) and + ( + annotations = TAnnotationFlags(getElementTypeFlags(element), getElementNullability(element)) + or + not exists(getElementTypeFlags(element)) and + annotations.getNoFlagsNullability() = getElementNullability(element) + ) and ( type = element.(Assignable).getType() or @@ -232,14 +243,14 @@ private int getBitMask(int bit) { } private int getElementTypeFlags(@has_type_annotation element) { - result = sum(int b | type_annotation(element, b) | b) + result = strictsum(int b | type_annotation(element, b) | b) } private Annotations::Nullability getTypeParameterNullability( TypeParameterConstraints constraints, Type type ) { if specific_type_parameter_nullability(constraints, getTypeRef(type), _) - then specific_type_parameter_nullability(constraints, getTypeRef(type), result) + then specific_type_parameter_nullability(constraints, getTypeRef(type), result.getNullability()) else ( specific_type_parameter_constraints(constraints, type) and result instanceof Annotations::NoNullability @@ -248,7 +259,7 @@ private Annotations::Nullability getTypeParameterNullability( private Annotations::Nullability getElementNullability(@has_type_annotation element) { if type_nullability(element, _) - then type_nullability(element, result) + then type_nullability(element, result.getNullability()) else result instanceof Annotations::NoNullability } @@ -258,26 +269,23 @@ private newtype TAnnotatedType = or exists(AnnotatedConstructedType c, int i | type = c.getType().(ConstructedType).getTypeArgument(i) and - annotations = c.getAnnotations().getChild(i) + annotations = Annotations::getChild(c.getAnnotations(), i) ) or - annotations.getFlags() = 0 and - annotations.getNullability() = getTypeParameterNullability(_, type) + annotations.getNoFlagsNullability() = getTypeParameterNullability(_, type) or - // All types exist as AnnotatedTypes with NoNullability. - annotations.getFlags() = 0 and - annotations.getNullability() instanceof Annotations::NoNullability + // All types have at least one annotated type + annotations.getNoFlagsNullability() instanceof Annotations::NoNullability or exists(AnnotatedArrayType at | type = at.getType().(ArrayType).getElementType() and - annotations = at.getAnnotations().getChild(0) + annotations = Annotations::getChild(at.getAnnotations(), 0) ) } /** A type with additional type information. */ class AnnotatedType extends TAnnotatedType { Type type; - Annotations::TypeAnnotations annotations; AnnotatedType() { this = TAnnotatedTypeNullability(type, annotations) } @@ -317,12 +325,12 @@ class AnnotatedType extends TAnnotatedType { } /** Holds if the type is a non-nullable reference, for example, `string` in a nullable-enabled context. */ - predicate isNonNullableRefType() { - this.getAnAnnotation() instanceof Annotations::NonNullableRefType - } + predicate isNonNullableRefType() { this.getAnAnnotation() instanceof Annotations::NoNullability } /** Holds if the type is a nullable reference, for example `string?`. */ - predicate isNullableRefType() { this.getAnAnnotation() instanceof Annotations::NullableRefType } + predicate isNullableRefType() { + this.getAnAnnotation() instanceof Annotations::AnnotatedNullability + } /** Holds if the type is a `ref`, for example the return type of `ref int F()`. */ predicate isRef() { this.getAnAnnotation() instanceof Annotations::RefTypeAnnotation } @@ -336,17 +344,16 @@ class AnnotatedType extends TAnnotatedType { /** Holds if this annotated type applies to element `e`. */ predicate appliesTo(Element e) { Annotations::elementTypeAnnotations(e, type, annotations) } - /** Holds if this annotated type is the type argument 'i' of constructed generic 'g'. */ + /** Holds if this annotated type is the `ith` type argument of constructed generic 'g'. */ predicate appliesToTypeArgument(ConstructedGeneric g, int i) { - this.getAnnotations().getFlags() = 0 and - this.getAnnotations().getNullability() = getElementNullability(g).getMember(i) and + this.getAnnotations().getNoFlagsNullability() = Annotations::getChildNullability(getElementNullability(g), + i) and this.getType() = g.getTypeArgument(i) } /** Holds if this annotated type applies to type parameter constraints `constraints`. */ predicate appliesToTypeConstraint(TypeParameterConstraints constraints) { - this.getAnnotations().getFlags() = 0 and - this.getAnnotations().getNullability() = getTypeParameterNullability(constraints, type) + this.getAnnotations().getNoFlagsNullability() = getTypeParameterNullability(constraints, type) } } @@ -357,7 +364,7 @@ class AnnotatedArrayType extends AnnotatedType { /** Gets the annotated element type of this array, for example `int?` in `int?[]`. */ final AnnotatedType getElementType() { result.getType() = type.getElementType() and - result.getAnnotations() = this.getAnnotations().getChild(0) + result.getAnnotations() = Annotations::getChild(this.getAnnotations(), 0) } private string getDimensionString(AnnotatedType elementType) { @@ -387,7 +394,7 @@ class AnnotatedConstructedType extends AnnotatedType { /** Gets the `i`th type argument of this constructed type. */ AnnotatedType getTypeArgument(int i) { result.getType() = type.getTypeArgument(i) and - result.getAnnotations() = this.getAnnotations().getChild(i) + result.getAnnotations() = Annotations::getChild(this.getAnnotations(), i) } override string toString() { From 61630118fef5a0aad35215a9dbb86993ccfce810 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Sun, 3 Nov 2019 18:37:38 +0000 Subject: [PATCH 0350/2538] C#: Fix ql tests. --- csharp/ql/test/library-tests/aliases/aliases1.expected | 2 -- csharp/ql/test/library-tests/aliases/aliases2.expected | 4 ++-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/csharp/ql/test/library-tests/aliases/aliases1.expected b/csharp/ql/test/library-tests/aliases/aliases1.expected index f6289f38f51c..9417df43012e 100644 --- a/csharp/ql/test/library-tests/aliases/aliases1.expected +++ b/csharp/ql/test/library-tests/aliases/aliases1.expected @@ -1,3 +1 @@ -| Assembly1.dll:0:0:0:0 | Class | -| Assembly2.dll:0:0:0:0 | Class | | Program.cs:10:7:10:11 | Class | diff --git a/csharp/ql/test/library-tests/aliases/aliases2.expected b/csharp/ql/test/library-tests/aliases/aliases2.expected index 45870c5dda24..50cfbf37f1ed 100644 --- a/csharp/ql/test/library-tests/aliases/aliases2.expected +++ b/csharp/ql/test/library-tests/aliases/aliases2.expected @@ -1,3 +1,3 @@ -| Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class | -| Program.cs:19:21:19:22 | c2 | Assembly2.dll:0:0:0:0 | Class | +| Program.cs:18:21:18:22 | c1 | Program.cs:10:7:10:11 | Class | +| Program.cs:19:21:19:22 | c2 | Program.cs:10:7:10:11 | Class | | Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class | From 657c839e2bfc1a14d2768d9c2f0244da590e9802 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Sun, 3 Nov 2019 18:56:14 +0000 Subject: [PATCH 0351/2538] C#: Change varchar to string in the dbscheme. --- csharp/ql/src/semmlecode.csharp.dbscheme | 130 +++++++++++------------ 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index a26548ca2427..e55d8c990309 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -157,28 +157,28 @@ compilation_finished( externalDefects( unique int id: @externalDefect, - varchar(900) queryPath: string ref, + string queryPath: string ref, int location: @location ref, - varchar(900) message: string ref, + string message: string ref, float severity: float ref); externalMetrics( unique int id: @externalMetric, - varchar(900) queryPath: string ref, + string queryPath: string ref, int location: @location ref, float value: float ref); externalData( int id: @externalDataElement, - varchar(900) path: string ref, + string path: string ref, int column: int ref, - varchar(900) value: string ref); + string value: string ref); snapshotDate( unique date snapshotDate: date ref); sourceLocationPrefix( - varchar(900) prefix: string ref); + string prefix: string ref); /* * Duplicate code @@ -186,12 +186,12 @@ sourceLocationPrefix( duplicateCode( unique int id: @duplication, - varchar(900) relativePath: string ref, + string relativePath: string ref, int equivClass: int ref); similarCode( unique int id: @similarity, - varchar(900) relativePath: string ref, + string relativePath: string ref, int equivClass: int ref); @duplication_or_similarity = @duplication | @similarity @@ -252,9 +252,9 @@ numlines( assemblies( unique int id: @assembly, int file: @file ref, - varchar(900) fullname: string ref, - varchar(900) name: string ref, - varchar(900) version: string ref); + string fullname: string ref, + string name: string ref, + string version: string ref); /* fromSource(0) = unknown, @@ -263,15 +263,15 @@ assemblies( */ files( unique int id: @file, - varchar(900) name: string ref, - varchar(900) simple: string ref, - varchar(900) ext: string ref, + string name: string ref, + string simple: string ref, + string ext: string ref, int fromSource: int ref); folders( unique int id: @folder, - varchar(900) name: string ref, - varchar(900) simple: string ref); + string name: string ref, + string simple: string ref); @container = @folder | @file ; @@ -291,7 +291,7 @@ file_extraction_mode( namespaces( unique int id: @namespace, - varchar(900) name: string ref); + string name: string ref); namespace_declarations( unique int id: @namespace_declaration, @@ -330,7 +330,7 @@ using_directive_location( types( unique int id: @type, int kind: int ref, - varchar(900) name: string ref); + string name: string ref); case @type.kind of 1 = @bool_type @@ -378,7 +378,7 @@ case @type.kind of typerefs( unique int id: @typeref, - varchar(900) name: string ref); + string name: string ref); typeref_type( int id: @typeref ref, @@ -540,7 +540,7 @@ specific_type_parameter_nullability( modifiers( unique int id: @modifier, - varchar(900) name: string ref); + string name: string ref); has_modifiers( int id: @modifiable_direct ref, @@ -558,7 +558,7 @@ compiler_generated(unique int id: @modifiable_direct ref); exprorstmt_name( unique int parent_id: @named_exprorstmt ref, - varchar(900) name: string ref); + string name: string ref); nested_types( unique int id: @type ref, @@ -567,7 +567,7 @@ nested_types( properties( unique int id: @property, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @property ref); @@ -578,7 +578,7 @@ property_location( indexers( unique int id: @indexer, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @indexer ref); @@ -590,7 +590,7 @@ indexer_location( accessors( unique int id: @accessor, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int declaring_member_id: @member ref, int unbound_id: @accessor ref); @@ -605,7 +605,7 @@ accessor_location( events( unique int id: @event, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @event ref); @@ -617,7 +617,7 @@ event_location( event_accessors( unique int id: @event_accessor, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int declaring_event_id: @event ref, int unbound_id: @event_accessor ref); @@ -632,8 +632,8 @@ event_accessor_location( operators( unique int id: @operator, - varchar(900) name: string ref, - varchar(900) symbol: string ref, + string name: string ref, + string symbol: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @operator ref); @@ -654,7 +654,7 @@ constant_value( methods( unique int id: @method, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @method ref); @@ -665,7 +665,7 @@ method_location( constructors( unique int id: @constructor, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int unbound_id: @constructor ref); @@ -675,7 +675,7 @@ constructor_location( destructors( unique int id: @destructor, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int unbound_id: @destructor ref); @@ -693,7 +693,7 @@ explicitly_implements( local_functions( unique int id: @local_function, - varchar(900) name: string ref, + string name: string ref, int return_type: @type ref, int unbound_id: @local_function ref); @@ -710,7 +710,7 @@ local_function_stmts( fields( unique int id: @field, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @field ref); @@ -727,7 +727,7 @@ field_location( localvars( unique int id: @local_variable, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int implicitly_typed: int ref /* 0 = no, 1 = yes */, int type_id: @type_or_ref ref, int parent_id: @local_var_decl_expr ref); @@ -748,7 +748,7 @@ localvar_location( #keyset[index, parent_id] params( unique int id: @parameter, - varchar(900) name: string ref, + string name: string ref, int type_id: @type_or_ref ref, int index: int ref, int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ @@ -1085,7 +1085,7 @@ expr_compiler_generated( expr_value( unique int id: @expr ref, - varchar(900) value: string ref); + string value: string ref); expr_call( unique int caller_id: @expr ref, @@ -1103,7 +1103,7 @@ expr_location( dynamic_member_name( unique int id: @late_bindable_expr ref, - varchar(900) name: string ref); + string name: string ref); @qualifiable_expr = @member_access_expr | @method_invocation_expr @@ -1119,7 +1119,7 @@ expr_argument( expr_argument_name( unique int id: @expr ref, - varchar(900) name: string ref); + string name: string ref); /** CONTROL/DATA FLOW **/ @@ -1129,18 +1129,18 @@ expr_argument_name( xmlEncoding ( unique int id: @file ref, - varchar(900) encoding: string ref); + string encoding: string ref); xmlDTDs( unique int id: @xmldtd, - varchar(900) root: string ref, - varchar(900) publicId: string ref, - varchar(900) systemId: string ref, + string root: string ref, + string publicId: string ref, + string systemId: string ref, int fileid: @file ref); xmlElements( unique int id: @xmlelement, - varchar(900) name: string ref, + string name: string ref, int parentid: @xmlparent ref, int idx: int ref, int fileid: @file ref); @@ -1148,15 +1148,15 @@ xmlElements( xmlAttrs( unique int id: @xmlattribute, int elementid: @xmlelement ref, - varchar(900) name: string ref, - varchar(3600) value: string ref, + string name: string ref, + string value: string ref, int idx: int ref, int fileid: @file ref); xmlNs( int id: @xmlnamespace, - varchar(900) prefixName: string ref, - varchar(900) URI: string ref, + string prefixName: string ref, + string URI: string ref, int fileid: @file ref); xmlHasNs( @@ -1166,13 +1166,13 @@ xmlHasNs( xmlComments( unique int id: @xmlcomment, - varchar(3600) text: string ref, + string text: string ref, int parentid: @xmlparent ref, int fileid: @file ref); xmlChars( unique int id: @xmlcharacters, - varchar(3600) text: string ref, + string text: string ref, int parentid: @xmlparent ref, int idx: int ref, int isCDATA: int ref, @@ -1192,8 +1192,8 @@ xmllocations( commentline( unique int id: @commentline, int kind: int ref, - varchar(800) text: string ref, - varchar(800) rawtext: string ref); + string text: string ref, + string rawtext: string ref); case @commentline.kind of 0 = @singlelinecomment @@ -1246,22 +1246,22 @@ asp_code_inline(unique int code: @asp_code ref); asp_directive_attribute( int directive: @asp_directive ref, int index: int ref, - varchar(1000) name: string ref, + string name: string ref, int value: @asp_quoted_string ref); asp_directive_name( unique int directive: @asp_directive ref, - varchar(1000) name: string ref); + string name: string ref); asp_element_body( unique int element: @asp_element ref, - varchar(1000) body: string ref); + string body: string ref); asp_tag_attribute( int tag: @asp_open_tag ref, int index: int ref, - varchar(1000) name: string ref, + string name: string ref, int attribute: @asp_attribute ref); asp_tag_name( unique int tag: @asp_open_tag ref, - varchar(1000) name: string ref); + string name: string ref); asp_tag_isempty(int tag: @asp_open_tag ref); /* Common Intermediate Language - CIL */ @@ -1616,7 +1616,7 @@ cil_access( cil_value( unique int instruction: @cil_literal ref, - varchar(900) value: string ref); + string value: string ref); #keyset[instruction, index] cil_switch( @@ -1649,7 +1649,7 @@ case @cil_type.kind of cil_type( unique int id: @cil_type, - varchar(900) name: string ref, + string name: string ref, int kind: int ref, int parent: @cil_type_container ref, int sourceDecl: @cil_type ref); @@ -1665,7 +1665,7 @@ cil_array_type( cil_method( unique int id: @cil_method, - varchar(900) name: string ref, + string name: string ref, int parent: @cil_type ref, int return_type: @cil_type ref); @@ -1686,7 +1686,7 @@ cil_implements( cil_field( unique int id: @cil_field, int parent: @cil_type ref, - varchar(900) name: string ref, + string name: string ref, int field_type: @cil_type ref); @cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; @@ -1723,13 +1723,13 @@ cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); cil_property( unique int id: @cil_property, int parent: @cil_type ref, - varchar(900) name: string ref, + string name: string ref, int property_type: @cil_type ref); #keyset[parent, name] cil_event(unique int id: @cil_event, int parent: @cil_type ref, - varchar(900) name: string ref, + string name: string ref, int event_type: @cil_type ref); #keyset[impl, index] @@ -1827,14 +1827,14 @@ cil_attribute( #keyset[attribute_id, param] cil_attribute_named_argument( int attribute_id: @cil_attribute ref, - varchar(100) param: string ref, - varchar(900) value: string ref); + string param: string ref, + string value: string ref); #keyset[attribute_id, index] cil_attribute_positional_argument( int attribute_id: @cil_attribute ref, int index: int ref, - varchar(900) value: string ref); + string value: string ref); // Common .Net data model covering both C# and CIL From 4d13957eedd8b34125c5aeb1cbd826483be36e48 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Sun, 3 Nov 2019 19:41:50 +0000 Subject: [PATCH 0352/2538] C#: Modify db upgrade script --- .../semmlecode.csharp.dbscheme | 133 +++++++++--------- 1 file changed, 66 insertions(+), 67 deletions(-) diff --git a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme index e4ab77432e6d..e55d8c990309 100644 --- a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme +++ b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme @@ -157,28 +157,28 @@ compilation_finished( externalDefects( unique int id: @externalDefect, - varchar(900) queryPath: string ref, + string queryPath: string ref, int location: @location ref, - varchar(900) message: string ref, + string message: string ref, float severity: float ref); externalMetrics( unique int id: @externalMetric, - varchar(900) queryPath: string ref, + string queryPath: string ref, int location: @location ref, float value: float ref); externalData( int id: @externalDataElement, - varchar(900) path: string ref, + string path: string ref, int column: int ref, - varchar(900) value: string ref); + string value: string ref); snapshotDate( unique date snapshotDate: date ref); sourceLocationPrefix( - varchar(900) prefix: string ref); + string prefix: string ref); /* * Duplicate code @@ -186,12 +186,12 @@ sourceLocationPrefix( duplicateCode( unique int id: @duplication, - varchar(900) relativePath: string ref, + string relativePath: string ref, int equivClass: int ref); similarCode( unique int id: @similarity, - varchar(900) relativePath: string ref, + string relativePath: string ref, int equivClass: int ref); @duplication_or_similarity = @duplication | @similarity @@ -252,9 +252,9 @@ numlines( assemblies( unique int id: @assembly, int file: @file ref, - varchar(900) fullname: string ref, - varchar(900) name: string ref, - varchar(900) version: string ref); + string fullname: string ref, + string name: string ref, + string version: string ref); /* fromSource(0) = unknown, @@ -263,15 +263,15 @@ assemblies( */ files( unique int id: @file, - varchar(900) name: string ref, - varchar(900) simple: string ref, - varchar(900) ext: string ref, + string name: string ref, + string simple: string ref, + string ext: string ref, int fromSource: int ref); folders( unique int id: @folder, - varchar(900) name: string ref, - varchar(900) simple: string ref); + string name: string ref, + string simple: string ref); @container = @folder | @file ; @@ -291,7 +291,7 @@ file_extraction_mode( namespaces( unique int id: @namespace, - varchar(900) name: string ref); + string name: string ref); namespace_declarations( unique int id: @namespace_declaration, @@ -330,7 +330,7 @@ using_directive_location( types( unique int id: @type, int kind: int ref, - varchar(900) name: string ref); + string name: string ref); case @type.kind of 1 = @bool_type @@ -378,7 +378,7 @@ case @type.kind of typerefs( unique int id: @typeref, - varchar(900) name: string ref); + string name: string ref); typeref_type( int id: @typeref ref, @@ -540,7 +540,7 @@ specific_type_parameter_nullability( modifiers( unique int id: @modifier, - varchar(900) name: string ref); + string name: string ref); has_modifiers( int id: @modifiable_direct ref, @@ -558,7 +558,7 @@ compiler_generated(unique int id: @modifiable_direct ref); exprorstmt_name( unique int parent_id: @named_exprorstmt ref, - varchar(900) name: string ref); + string name: string ref); nested_types( unique int id: @type ref, @@ -567,7 +567,7 @@ nested_types( properties( unique int id: @property, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @property ref); @@ -578,7 +578,7 @@ property_location( indexers( unique int id: @indexer, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @indexer ref); @@ -590,7 +590,7 @@ indexer_location( accessors( unique int id: @accessor, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int declaring_member_id: @member ref, int unbound_id: @accessor ref); @@ -605,7 +605,7 @@ accessor_location( events( unique int id: @event, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @event ref); @@ -617,7 +617,7 @@ event_location( event_accessors( unique int id: @event_accessor, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int declaring_event_id: @event ref, int unbound_id: @event_accessor ref); @@ -632,8 +632,8 @@ event_accessor_location( operators( unique int id: @operator, - varchar(900) name: string ref, - varchar(900) symbol: string ref, + string name: string ref, + string symbol: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @operator ref); @@ -654,7 +654,7 @@ constant_value( methods( unique int id: @method, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @method ref); @@ -665,7 +665,7 @@ method_location( constructors( unique int id: @constructor, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int unbound_id: @constructor ref); @@ -675,7 +675,7 @@ constructor_location( destructors( unique int id: @destructor, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int unbound_id: @destructor ref); @@ -693,7 +693,7 @@ explicitly_implements( local_functions( unique int id: @local_function, - varchar(900) name: string ref, + string name: string ref, int return_type: @type ref, int unbound_id: @local_function ref); @@ -710,7 +710,7 @@ local_function_stmts( fields( unique int id: @field, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int declaring_type_id: @type ref, int type_id: @type_or_ref ref, int unbound_id: @field ref); @@ -727,7 +727,7 @@ field_location( localvars( unique int id: @local_variable, int kind: int ref, - varchar(900) name: string ref, + string name: string ref, int implicitly_typed: int ref /* 0 = no, 1 = yes */, int type_id: @type_or_ref ref, int parent_id: @local_var_decl_expr ref); @@ -748,7 +748,7 @@ localvar_location( #keyset[index, parent_id] params( unique int id: @parameter, - varchar(900) name: string ref, + string name: string ref, int type_id: @type_or_ref ref, int index: int ref, int mode: int ref, /* value = 0, ref = 1, out = 2, array = 3, this = 4 */ @@ -1085,7 +1085,7 @@ expr_compiler_generated( expr_value( unique int id: @expr ref, - varchar(900) value: string ref); + string value: string ref); expr_call( unique int caller_id: @expr ref, @@ -1103,12 +1103,11 @@ expr_location( dynamic_member_name( unique int id: @late_bindable_expr ref, - varchar(900) name: string ref); + string name: string ref); @qualifiable_expr = @member_access_expr | @method_invocation_expr - | @element_access_expr - | @delegate_invocation_expr; + | @element_access_expr; conditional_access( unique int id: @qualifiable_expr ref); @@ -1120,7 +1119,7 @@ expr_argument( expr_argument_name( unique int id: @expr ref, - varchar(900) name: string ref); + string name: string ref); /** CONTROL/DATA FLOW **/ @@ -1130,18 +1129,18 @@ expr_argument_name( xmlEncoding ( unique int id: @file ref, - varchar(900) encoding: string ref); + string encoding: string ref); xmlDTDs( unique int id: @xmldtd, - varchar(900) root: string ref, - varchar(900) publicId: string ref, - varchar(900) systemId: string ref, + string root: string ref, + string publicId: string ref, + string systemId: string ref, int fileid: @file ref); xmlElements( unique int id: @xmlelement, - varchar(900) name: string ref, + string name: string ref, int parentid: @xmlparent ref, int idx: int ref, int fileid: @file ref); @@ -1149,15 +1148,15 @@ xmlElements( xmlAttrs( unique int id: @xmlattribute, int elementid: @xmlelement ref, - varchar(900) name: string ref, - varchar(3600) value: string ref, + string name: string ref, + string value: string ref, int idx: int ref, int fileid: @file ref); xmlNs( int id: @xmlnamespace, - varchar(900) prefixName: string ref, - varchar(900) URI: string ref, + string prefixName: string ref, + string URI: string ref, int fileid: @file ref); xmlHasNs( @@ -1167,13 +1166,13 @@ xmlHasNs( xmlComments( unique int id: @xmlcomment, - varchar(3600) text: string ref, + string text: string ref, int parentid: @xmlparent ref, int fileid: @file ref); xmlChars( unique int id: @xmlcharacters, - varchar(3600) text: string ref, + string text: string ref, int parentid: @xmlparent ref, int idx: int ref, int isCDATA: int ref, @@ -1193,8 +1192,8 @@ xmllocations( commentline( unique int id: @commentline, int kind: int ref, - varchar(800) text: string ref, - varchar(800) rawtext: string ref); + string text: string ref, + string rawtext: string ref); case @commentline.kind of 0 = @singlelinecomment @@ -1247,22 +1246,22 @@ asp_code_inline(unique int code: @asp_code ref); asp_directive_attribute( int directive: @asp_directive ref, int index: int ref, - varchar(1000) name: string ref, + string name: string ref, int value: @asp_quoted_string ref); asp_directive_name( unique int directive: @asp_directive ref, - varchar(1000) name: string ref); + string name: string ref); asp_element_body( unique int element: @asp_element ref, - varchar(1000) body: string ref); + string body: string ref); asp_tag_attribute( int tag: @asp_open_tag ref, int index: int ref, - varchar(1000) name: string ref, + string name: string ref, int attribute: @asp_attribute ref); asp_tag_name( unique int tag: @asp_open_tag ref, - varchar(1000) name: string ref); + string name: string ref); asp_tag_isempty(int tag: @asp_open_tag ref); /* Common Intermediate Language - CIL */ @@ -1617,7 +1616,7 @@ cil_access( cil_value( unique int instruction: @cil_literal ref, - varchar(900) value: string ref); + string value: string ref); #keyset[instruction, index] cil_switch( @@ -1650,7 +1649,7 @@ case @cil_type.kind of cil_type( unique int id: @cil_type, - varchar(900) name: string ref, + string name: string ref, int kind: int ref, int parent: @cil_type_container ref, int sourceDecl: @cil_type ref); @@ -1666,7 +1665,7 @@ cil_array_type( cil_method( unique int id: @cil_method, - varchar(900) name: string ref, + string name: string ref, int parent: @cil_type ref, int return_type: @cil_type ref); @@ -1687,7 +1686,7 @@ cil_implements( cil_field( unique int id: @cil_field, int parent: @cil_type ref, - varchar(900) name: string ref, + string name: string ref, int field_type: @cil_type ref); @cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace; @@ -1724,13 +1723,13 @@ cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref); cil_property( unique int id: @cil_property, int parent: @cil_type ref, - varchar(900) name: string ref, + string name: string ref, int property_type: @cil_type ref); #keyset[parent, name] cil_event(unique int id: @cil_event, int parent: @cil_type ref, - varchar(900) name: string ref, + string name: string ref, int event_type: @cil_type ref); #keyset[impl, index] @@ -1828,14 +1827,14 @@ cil_attribute( #keyset[attribute_id, param] cil_attribute_named_argument( int attribute_id: @cil_attribute ref, - varchar(100) param: string ref, - varchar(900) value: string ref); + string param: string ref, + string value: string ref); #keyset[attribute_id, index] cil_attribute_positional_argument( int attribute_id: @cil_attribute ref, int index: int ref, - varchar(900) value: string ref); + string value: string ref); // Common .Net data model covering both C# and CIL From ce188c0c22f703ef93b29cff48791e15145b0169 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Mon, 4 Nov 2019 09:39:43 +0000 Subject: [PATCH 0353/2538] C#: Autoformat --- csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql index 416929afb92a..c37e180d1ec6 100644 --- a/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql +++ b/csharp/ql/test/library-tests/csharp8/NullableRefTypes.ql @@ -52,8 +52,8 @@ query predicate constructedTypes(AnnotatedConstructedType at, int i, string arg, } query predicate nullableTypeParameters(TypeParameter p) { - p.getConstraints().hasNullableRefTypeConstraint() - and p.getLocation().getFile().getBaseName() = "NullableRefTypes.cs" + p.getConstraints().hasNullableRefTypeConstraint() and + p.getLocation().getFile().getBaseName() = "NullableRefTypes.cs" } query predicate annotatedTypeConstraints(TypeParameter p, AnnotatedType t) { From a261cbaeef409075107477709deca27566ae28f1 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Wed, 6 Nov 2019 12:43:12 +0000 Subject: [PATCH 0354/2538] C#: Fix type ID generation from merge --- .../Semmle.Extraction.CSharp/SymbolExtensions.cs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 6e2b52f3086d..9f7f36ce662c 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -234,12 +234,7 @@ private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) { - bool prefixAssembly = false; - if (named.IsAnonymous()) prefixAssembly = true; - if (named.ContainingAssembly is null) prefixAssembly = false; - - if (prefixAssembly) - BuildAssembly(named.ContainingAssembly, trapFile); + bool prefixAssembly = !(named.ContainingAssembly is null); if (named.IsTupleType) { @@ -263,6 +258,8 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex } else if (named.ContainingNamespace != null) { + if (prefixAssembly) + BuildAssembly(named.ContainingAssembly, trapFile); named.ContainingNamespace.BuildNamespace(cx, trapFile); } From fe83bac0fb368f061edf827e11bc9fe6a4947564 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Wed, 6 Nov 2019 18:22:26 +0000 Subject: [PATCH 0355/2538] C#: Fix up test output C#: Fix a qltest whereby a tuple type having multiple underlying types was causing an issue with the IR sanity checks. C#: Revert more changes. C#: Fix tests and remove dead code. --- .../Entities/Method.cs | 2 +- .../Entities/Parameter.cs | 3 +- .../Entities/Types/NamedType.cs | 27 +- .../Entities/Types/TupleType.cs | 2 +- .../Entities/Types/Type.cs | 2 - .../Semmle.Extraction.CSharp/Extractor.cs | 3 +- .../SymbolExtensions.cs | 182 +-- .../Semmle.Extraction.CSharp/Tuples.cs | 8 +- .../extractor/Semmle.Extraction/Extractor.cs | 19 - .../src/semmle/code/csharp/AnnotatedType.qll | 2 +- .../library-tests/aliases/aliases1.expected | 2 + .../library-tests/aliases/aliases2.expected | 4 +- .../Disposal/DisposedParameter.expected | 2 +- .../csharp7/LocalVariables.expected | 10 +- .../library-tests/csharp7/TupleTypes.expected | 98 +- .../library/LibraryTypeDataFlow.expected | 1054 ++++++++--------- .../dispatch/GetADynamicTarget.expected | 232 ++-- .../format/StringFormatItemParameter.expected | 24 +- .../methods/Parameters9.expected | 4 +- .../overrides/Overrides22.expected | 6 +- .../toStringWithTypes.expected | 9 +- 21 files changed, 774 insertions(+), 921 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index f3aba9744be3..f3a9a9f0d084 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -204,7 +204,7 @@ protected static void AddSignatureTypeToId(Context cx, TextWriter trapFile, IMet if (type.ContainsTypeParameters(cx, method)) type.BuildTypeId(cx, trapFile, (cx0, tb0, type0) => AddSignatureTypeToId(cx, tb0, method, type0)); else - trapFile.WriteSubId(Type.Create(cx, type).TypeRef); + trapFile.WriteSubId(Type.Create(cx, type)); } protected static void AddParametersToId(Context cx, TextWriter trapFile, IMethodSymbol method) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs index c353ea34c163..f05bab3f366f 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Parameter.cs @@ -86,8 +86,7 @@ public override void WriteId(TextWriter trapFile) trapFile.Write(";parameter"); } - // If we don't have the type of the parameter, do not populate it. - public override bool NeedsPopulation => symbol.Type.TypeKind != TypeKind.Error; + public override bool NeedsPopulation => true; string Name { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs index fa5f6a4bdf9e..e22d32c0d019 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/NamedType.cs @@ -29,7 +29,7 @@ public override void Populate(TextWriter trapFile) return; } - trapFile.typeref_type((TypeRef)TypeRef, this); + trapFile.typeref_type((NamedTypeRef)TypeRef, this); if (symbol.IsGenericType) { @@ -151,39 +151,34 @@ class NamedTypeFactory : ICachedEntityFactory public NamedType Create(Context cx, INamedTypeSymbol init) => new NamedType(cx, init); } - public override Type TypeRef => Entities.TypeRef.Create(Context, this, symbol); + public override Type TypeRef => NamedTypeRef.Create(Context, symbol); } - class TypeRef : Type + class NamedTypeRef : Type { readonly Type referencedType; - public TypeRef(Context cx, Type type, ITypeSymbol symbol) : base(cx, symbol) + public NamedTypeRef(Context cx, INamedTypeSymbol symbol) : base(cx, symbol) { - referencedType = type; + referencedType = Type.Create(cx, symbol); } - public static TypeRef Create(Context cx, Type referencedType, ITypeSymbol type) => - NamedTypeRefFactory.Instance.CreateEntity2(cx, (referencedType, type)); + public static NamedTypeRef Create(Context cx, INamedTypeSymbol type) => + NamedTypeRefFactory.Instance.CreateEntity2(cx, type); - class NamedTypeRefFactory : ICachedEntityFactory<(Type, ITypeSymbol), TypeRef> + class NamedTypeRefFactory : ICachedEntityFactory { public static readonly NamedTypeRefFactory Instance = new NamedTypeRefFactory(); - public TypeRef Create(Context cx, (Type, ITypeSymbol) init) => new TypeRef(cx, init.Item1, init.Item2); + public NamedTypeRef Create(Context cx, INamedTypeSymbol init) => new NamedTypeRef(cx, init); } public override bool NeedsPopulation => true; public override void WriteId(TextWriter trapFile) { - void ExpandType(Context cx0, TextWriter tb0, ITypeSymbol sub) - { - sub.BuildTypeId(cx0, tb0, ExpandType); - } - - symbol.BuildTypeId(Context, trapFile, ExpandType); - trapFile.Write(";typeref"); + trapFile.WriteSubId(referencedType); + trapFile.Write(";typeRef"); } public override void Populate(TextWriter trapFile) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs index d486506408b7..de6ea2170849 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/TupleType.cs @@ -42,7 +42,7 @@ public override void Populate(TextWriter trapFile) PopulateGenerics(); var underlyingType = NamedType.Create(Context, symbol.TupleUnderlyingType); - trapFile.tuple_underlying_type(this, underlyingType.TypeRef); + trapFile.tuple_underlying_type(this, underlyingType); int index = 0; foreach (var element in TupleElements) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs index 276cf6758e2c..4b4a8f919ec3 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Type.cs @@ -95,7 +95,6 @@ protected void PopulateType(TextWriter trapFile) var baseTypes = new List(); if (symbol.BaseType != null) { - // !! Do not extend "object" if the base type is missing :-( Type baseKey = Create(Context, symbol.BaseType); trapFile.extend(this, baseKey.TypeRef); if (symbol.TypeKind != TypeKind.Struct) @@ -269,7 +268,6 @@ public void ExtractRecursive(TextWriter trapFile, IEntity parent) public static Type Create(Context cx, ITypeSymbol type) { type = type.DisambiguateType(); - const bool errorTypeIsNull = false; return type == null || (errorTypeIsNull && type.TypeKind == TypeKind.Error) ? NullType.Create(cx).Type : (Type)cx.CreateEntity(type); diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs b/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs index fadcbd8127b9..7ca12e00f26b 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Extractor.cs @@ -120,8 +120,7 @@ public static ExitCode Run(string[] args) var syntaxTrees = new List(); var syntaxTreeTasks = ReadSyntaxTrees( compilerArguments.SourceFiles. - Select(src => canonicalPathCache.GetCanonicalPath(src.Path)). - Where(f => !f.EndsWith(".dll")), + Select(src => canonicalPathCache.GetCanonicalPath(src.Path)), analyser, compilerArguments.ParseOptions, compilerArguments.Encoding, diff --git a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs index 9f7f36ce662c..e42eb56ddbce 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/SymbolExtensions.cs @@ -4,8 +4,6 @@ using System.Collections.Generic; using System.IO; using System.Linq; -using System.Security.Cryptography; -using System.Text; namespace Semmle.Extraction.CSharp { @@ -135,34 +133,15 @@ public static bool ContainsTypeParameters(this ITypeSymbol type, Context cx, ISy /// The action to apply to syntactic sub terms of this type. public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter trapFile, Action subTermAction) { - switch(type.SpecialType) + if (type.SpecialType != SpecialType.None) { - case SpecialType.System_Object: - case SpecialType.System_Void: - case SpecialType.System_Boolean: - case SpecialType.System_Char: - case SpecialType.System_SByte: - case SpecialType.System_Byte: - case SpecialType.System_Int16: - case SpecialType.System_UInt16: - case SpecialType.System_Int32: - case SpecialType.System_UInt32: - case SpecialType.System_Int64: - case SpecialType.System_UInt64: - case SpecialType.System_Decimal: - case SpecialType.System_Single: - case SpecialType.System_Double: - case SpecialType.System_String: - case SpecialType.System_IntPtr: - case SpecialType.System_UIntPtr: - - /* - * Use the keyword ("int" etc) for the built-in types. - * This makes the IDs shorter and means that all built-in types map to - * the same entities (even when using multiple versions of mscorlib). - */ - trapFile.Write(type.ToDisplayString()); - return; + /* + * Use the keyword ("int" etc) for the built-in types. + * This makes the IDs shorter and means that all built-in types map to + * the same entities (even when using multiple versions of mscorlib). + */ + trapFile.Write(type.ToDisplayString()); + return; } using (cx.StackGuard) @@ -186,7 +165,7 @@ public static void BuildTypeId(this ITypeSymbol type, Context cx, TextWriter tra case TypeKind.Pointer: var ptr = (IPointerTypeSymbol)type; subTermAction(cx, trapFile, ptr.PointedAtType); - trapFile.Write("*"); + trapFile.Write('*'); return; case TypeKind.TypeParameter: var tp = (ITypeParameterSymbol)type; @@ -214,28 +193,8 @@ public static void BuildArraySuffix(this IArrayTypeSymbol array, TextWriter trap trapFile.Write(']'); } - private static void BuildAssembly(IAssemblySymbol asm, TextWriter trapFile, bool extraPrecise = false) + static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) { - var assembly = asm.Identity; - trapFile.Write(assembly.Name); - trapFile.Write('_'); - trapFile.Write(assembly.Version.Major); - trapFile.Write('.'); - trapFile.Write(assembly.Version.Minor); - trapFile.Write('.'); - trapFile.Write(assembly.Version.Build); - if (extraPrecise) - { - trapFile.Write('.'); - trapFile.Write(assembly.Version.Revision); - } - trapFile.Write("::"); - } - - public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, TextWriter trapFile, Action subTermAction) - { - bool prefixAssembly = !(named.ContainingAssembly is null); - if (named.IsTupleType) { trapFile.Write('('); @@ -258,8 +217,6 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex } else if (named.ContainingNamespace != null) { - if (prefixAssembly) - BuildAssembly(named.ContainingAssembly, trapFile); named.ContainingNamespace.BuildNamespace(cx, trapFile); } @@ -290,6 +247,26 @@ public static void BuildNamedTypeId(this INamedTypeSymbol named, Context cx, Tex static void BuildNamespace(this INamespaceSymbol ns, Context cx, TextWriter trapFile) { + // Only include the assembly information in each type ID + // for normal extractions. This is because standalone extractions + // lack assembly information or may be ambiguous. + bool prependAssemblyToTypeId = !cx.Extractor.Standalone && ns.ContainingAssembly != null; + + if (prependAssemblyToTypeId) + { + // Note that we exclude the revision number as this has + // been observed to be unstable. + var assembly = ns.ContainingAssembly.Identity; + trapFile.Write(assembly.Name); + trapFile.Write('_'); + trapFile.Write(assembly.Version.Major); + trapFile.Write('.'); + trapFile.Write(assembly.Version.Minor); + trapFile.Write('.'); + trapFile.Write(assembly.Version.Build); + trapFile.Write("::"); + } + trapFile.WriteSubId(Namespace.Create(cx, ns)); trapFile.Write('.'); } @@ -379,7 +356,7 @@ public static void BuildNamedTypeDisplayName(this INamedTypeSymbol namedType, Co } trapFile.Write(namedType.Name); - if (namedType.IsGenericType && namedType.TypeArguments.Any()) + if (namedType.IsGenericType && namedType.TypeKind != TypeKind.Error && namedType.TypeArguments.Any()) { trapFile.Write('<'); trapFile.BuildList(",", namedType.TypeArguments, (p, tb0) => @@ -478,30 +455,6 @@ public static TypeInfo GetTypeInfo(this Context cx, Microsoft.CodeAnalysis.CShar public static SymbolInfo GetSymbolInfo(this Context cx, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode node) => cx.GetModel(node).GetSymbolInfo(node); - /// - /// Gets the symbol for a particular syntax node. - /// Throws an exception if the symbol is not found. - /// - /// - /// - /// This gives a nicer message than a "null pointer exception", - /// and should be used where we require a symbol to be resolved. - /// - /// - /// The extraction context. - /// The syntax node. - /// The resolved symbol. - public static ISymbol GetSymbol(this Context cx, Microsoft.CodeAnalysis.CSharp.CSharpSyntaxNode node) - { - var info = GetSymbolInfo(cx, node); - if (info.Symbol == null) - { - throw new InternalError(node, "Could not resolve symbol"); - } - - return info.Symbol; - } - /// /// Determines the type of a node, or default /// if the type could not be determined. @@ -515,84 +468,11 @@ public static AnnotatedTypeSymbol GetType(this Context cx, Microsoft.CodeAnalysi return new AnnotatedTypeSymbol(info.Type.DisambiguateType(), info.Nullability.Annotation); } - /// - /// Gets the annotated type of an IPropertySymbol. - /// This has not yet been exposed on the public API. - /// - public static AnnotatedTypeSymbol GetAnnotatedType(this IPropertySymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); - - /// - /// Gets the annotated type of an IFieldSymbol. - /// This has not yet been exposed on the public API. - /// - public static AnnotatedTypeSymbol GetAnnotatedType(this IFieldSymbol symbol) => new AnnotatedTypeSymbol(symbol.Type, symbol.NullableAnnotation); - private static bool IsSpecialized(this IMethodSymbol method) => - method.IsGenericMethod && - !ReferenceEquals(method, method.OriginalDefinition) && - method.TypeParameters.Zip(method.TypeArguments, (a, b) => !ReferenceEquals(a, b)).Any(b => b); - - /// - /// Gets the annotated return type of an IMethodSymbol. - /// This has not yet been exposed on the public API. - /// - public static AnnotatedTypeSymbol GetAnnotatedReturnType(this IMethodSymbol symbol) => new AnnotatedTypeSymbol(symbol.ReturnType, symbol.ReturnNullableAnnotation); - - /// - /// Gets the type annotation for a NullableAnnotation. - /// - public static Kinds.TypeAnnotation GetTypeAnnotation(this NullableAnnotation na) - { - switch(na) - { - case NullableAnnotation.Annotated: - return Kinds.TypeAnnotation.Annotated; - case NullableAnnotation.NotAnnotated: - return Kinds.TypeAnnotation.NotAnnotated; - default: - return Kinds.TypeAnnotation.None; - } - } - - /// - /// Gets the annotated element type of an IArrayTypeSymbol. - /// This has not yet been exposed on the public API. - /// - public static AnnotatedTypeSymbol GetAnnotatedElementType(this IArrayTypeSymbol symbol) => - new AnnotatedTypeSymbol(symbol.ElementType, symbol.ElementNullableAnnotation); - /// /// Gets the annotated type arguments of an INamedTypeSymbol. /// This has not yet been exposed on the public API. /// public static IEnumerable GetAnnotatedTypeArguments(this INamedTypeSymbol symbol) => symbol.TypeArguments.Zip(symbol.TypeArgumentsNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a)); - - /// - /// Gets the annotated type arguments of an IMethodSymbol. - /// This has not yet been exposed on the public API. - /// - public static IEnumerable GetAnnotatedTypeArguments(this IMethodSymbol symbol) => - symbol.TypeArguments.Zip(symbol.TypeArgumentsNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a)); - - /// - /// Gets the annotated type constraints of an ITypeParameterSymbol. - /// This has not yet been exposed on the public API. - /// - public static IEnumerable GetAnnotatedTypeConstraints(this ITypeParameterSymbol symbol) => - symbol.ConstraintTypes.Zip(symbol.ConstraintNullableAnnotations, (t, a) => new AnnotatedTypeSymbol(t, a)); - - /// - /// Creates an AnnotatedTypeSymbol from an ITypeSymbol. - /// Note: not currently used but might be useful. - /// - public static AnnotatedTypeSymbol WithAnnotation(this ITypeSymbol symbol, NullableAnnotation annotation) => - new AnnotatedTypeSymbol(symbol, annotation); - - /// - /// Holds if this type looks like an "anonymous" type. Names of anonymous types - /// sometimes collide so they need to be handled separately. - /// - public static bool IsAnonymous(this INamedTypeSymbol type) => - type.IsAnonymousType || type.Name.StartsWith("<>"); } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index c239d4f0bb20..f6de00452d0e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -388,7 +388,7 @@ internal static void nullability(this TextWriter trapFile, NullabilityEntity nul internal static void nullability_member(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity child) { - trapFile.WriteTuple(nameof(nullability_member), nullability, index, child); + trapFile.WriteTuple("nullability_member", nullability, index, child); } internal static void numlines(this TextWriter trapFile, IEntity label, LineCounts lineCounts) @@ -481,7 +481,7 @@ internal static void tuple_element(this TextWriter trapFile, TupleType type, int trapFile.WriteTuple("tuple_element", type, index, field); } - internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, Type underlying) + internal static void tuple_underlying_type(this TextWriter trapFile, TupleType type, NamedType underlying) { trapFile.WriteTuple("tuple_underlying_type", type, underlying); } @@ -526,12 +526,12 @@ internal static void type_parameters(this TextWriter trapFile, TypeParameter par trapFile.WriteTuple("type_parameters", param, child, typeOrMethod, (int)param.Variance); } - internal static void typeref_type(this TextWriter trapFile, TypeRef typeref, Type type) + internal static void typeref_type(this TextWriter trapFile, NamedTypeRef typeref, Type type) { trapFile.WriteTuple("typeref_type", typeref, type); } - internal static void typerefs(this TextWriter trapFile, TypeRef type, string name) + internal static void typerefs(this TextWriter trapFile, NamedTypeRef type, string name) { trapFile.WriteTuple("typerefs", type, name); } diff --git a/csharp/extractor/Semmle.Extraction/Extractor.cs b/csharp/extractor/Semmle.Extraction/Extractor.cs index fd8aee723e30..e470d3258ece 100644 --- a/csharp/extractor/Semmle.Extraction/Extractor.cs +++ b/csharp/extractor/Semmle.Extraction/Extractor.cs @@ -87,22 +87,6 @@ public interface IExtractor /// The extraction scope (what to include in this trap file). /// Context CreateContext(Compilation c, TrapWriter trapWriter, IExtractionScope scope); - - /// - /// Adjusts the algorithm used to generate identifiers in trap files. - /// - TrapIdenfierMode TrapIdentifiers { get; } - } - - /// - /// Configures how to generate identifiers in trap files. - /// - public enum TrapIdenfierMode - { - Imprecise, // Names are not qualified by assembly version - Flexible, // Some names are qualified by assembly versions - typerefs are not however. - Precise, // All names are qualified by their partial assembly version (excludes build number) - ExtraPrecise // All names are qualified by their full assembly version. } /// @@ -128,7 +112,6 @@ public bool Standalone public Extractor(bool standalone, string outputPath, ILogger logger) { Standalone = standalone; - if (Standalone) TrapIdentifiers = TrapIdenfierMode.Imprecise; OutputPath = outputPath; Logger = logger; } @@ -214,7 +197,5 @@ public string OutputPath public ILogger Logger { get; private set; } public static string Version => $"{ThisAssembly.Git.BaseTag} ({ThisAssembly.Git.Sha})"; - - public TrapIdenfierMode TrapIdentifiers { get; } = TrapIdenfierMode.Imprecise; } } diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index 96300abdcd81..98e25aa7524b 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -8,7 +8,7 @@ import csharp -module Annotations { +private module Annotations { newtype TAnnotation = TReadonlyRefType() or TRefType() or diff --git a/csharp/ql/test/library-tests/aliases/aliases1.expected b/csharp/ql/test/library-tests/aliases/aliases1.expected index 9417df43012e..f6289f38f51c 100644 --- a/csharp/ql/test/library-tests/aliases/aliases1.expected +++ b/csharp/ql/test/library-tests/aliases/aliases1.expected @@ -1 +1,3 @@ +| Assembly1.dll:0:0:0:0 | Class | +| Assembly2.dll:0:0:0:0 | Class | | Program.cs:10:7:10:11 | Class | diff --git a/csharp/ql/test/library-tests/aliases/aliases2.expected b/csharp/ql/test/library-tests/aliases/aliases2.expected index 50cfbf37f1ed..45870c5dda24 100644 --- a/csharp/ql/test/library-tests/aliases/aliases2.expected +++ b/csharp/ql/test/library-tests/aliases/aliases2.expected @@ -1,3 +1,3 @@ -| Program.cs:18:21:18:22 | c1 | Program.cs:10:7:10:11 | Class | -| Program.cs:19:21:19:22 | c2 | Program.cs:10:7:10:11 | Class | +| Program.cs:18:21:18:22 | c1 | Assembly1.dll:0:0:0:0 | Class | +| Program.cs:19:21:19:22 | c2 | Assembly2.dll:0:0:0:0 | Class | | Program.cs:20:15:20:16 | c3 | Program.cs:10:7:10:11 | Class | diff --git a/csharp/ql/test/library-tests/commons/Disposal/DisposedParameter.expected b/csharp/ql/test/library-tests/commons/Disposal/DisposedParameter.expected index 917ea971094a..88f27e32bbc5 100644 --- a/csharp/ql/test/library-tests/commons/Disposal/DisposedParameter.expected +++ b/csharp/ql/test/library-tests/commons/Disposal/DisposedParameter.expected @@ -332,7 +332,7 @@ | XmlEncodedRawTextWriterIndent(Stream, XmlWriterSettings) | 0 | | XmlEncodedRawTextWriterIndent(TextWriter, XmlWriterSettings) | 0 | | XmlRawWriterWrapper(XmlWriter) | 0 | -| XmlSqlBinaryReader(Stream, byte[], int, string, bool, XmlReaderSettings) | 0 | +| XmlSqlBinaryReader(Stream, Byte[], int, string, bool, XmlReaderSettings) | 0 | | XmlTextReader(Stream) | 0 | | XmlTextReader(Stream, XmlNameTable) | 0 | | XmlTextReader(Stream, XmlNodeType, XmlParserContext) | 0 | diff --git a/csharp/ql/test/library-tests/csharp7/LocalVariables.expected b/csharp/ql/test/library-tests/csharp7/LocalVariables.expected index 33514e8f6a30..06f61a52f91e 100644 --- a/csharp/ql/test/library-tests/csharp7/LocalVariables.expected +++ b/csharp/ql/test/library-tests/csharp7/LocalVariables.expected @@ -33,8 +33,8 @@ | CSharp7.cs:119:13:119:15 | m11 | int | | CSharp7.cs:122:16:122:18 | m12 | string | | CSharp7.cs:123:16:123:18 | m13 | string | -| CSharp7.cs:135:19:135:20 | f4 | Func | -| CSharp7.cs:139:24:139:25 | f5 | Func | +| CSharp7.cs:135:19:135:20 | f4 | Func | +| CSharp7.cs:139:24:139:25 | f5 | Func | | CSharp7.cs:151:16:151:16 | a | Action | | CSharp7.cs:176:16:176:18 | src | string | | CSharp7.cs:181:13:181:17 | sink1 | string | @@ -42,7 +42,7 @@ | CSharp7.cs:183:13:183:17 | sink3 | string | | CSharp7.cs:191:13:191:14 | v1 | int | | CSharp7.cs:192:17:192:18 | r1 | int | -| CSharp7.cs:193:13:193:17 | array | int[] | +| CSharp7.cs:193:13:193:17 | array | Int32[] | | CSharp7.cs:196:17:196:18 | r2 | int | | CSharp7.cs:197:17:197:18 | r3 | int | | CSharp7.cs:199:17:199:18 | r4 | int | @@ -58,8 +58,8 @@ | CSharp7.cs:261:22:261:23 | i3 | int | | CSharp7.cs:264:25:264:26 | s2 | string | | CSharp7.cs:270:22:270:23 | v2 | object | -| CSharp7.cs:283:13:283:16 | dict | Dictionary | -| CSharp7.cs:284:13:284:16 | list | IEnumerable<(int, string)> | +| CSharp7.cs:283:13:283:16 | dict | Dictionary | +| CSharp7.cs:284:13:284:16 | list | IEnumerable<(Int32,String)> | | CSharp7.cs:286:23:286:23 | a | int | | CSharp7.cs:286:33:286:33 | b | string | | CSharp7.cs:288:23:288:23 | a | int | diff --git a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected index 8c50282dd038..7168e2b833f7 100644 --- a/csharp/ql/test/library-tests/csharp7/TupleTypes.expected +++ b/csharp/ql/test/library-tests/csharp7/TupleTypes.expected @@ -1,49 +1,49 @@ -| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:77:10:77:14 | a | -| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:77:36:77:36 | Item1 | -| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:78:24:78:24 | b | -| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:77:17:77:30 | Item2 | -| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:77:39:77:39 | z | -| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:78:27:78:32 | Item2 | -| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 0 | CSharp7.cs:98:19:98:19 | Item1 | -| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 1 | CSharp7.cs:98:22:98:42 | Item2 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:214:6:214:8 | Item1 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:224:10:224:14 | x | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:225:10:225:10 | Item1 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:214:11:214:16 | Item2 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:224:17:224:17 | Item2 | -| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:225:13:225:17 | y | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:64:6:64:8 | Item1 | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:71:10:71:14 | x | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:77:18:77:22 | b | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:78:28:78:28 | c | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:112:15:112:16 | m4 | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:114:19:114:24 | m8 | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:64:11:64:13 | Item2 | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:71:17:71:21 | y | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:77:25:77:29 | c | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:78:31:78:31 | a | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:112:19:112:20 | m5 | -| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:114:27:114:32 | m9 | -| (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 0 | CSharp7.cs:75:10:75:10 | x | -| (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 1 | CSharp7.cs:75:13:75:13 | y | -| (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 2 | CSharp7.cs:75:16:75:22 | Item3 | -| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:284:41:284:48 | Key | -| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:286:19:286:23 | a | -| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:284:51:284:60 | Value | -| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:286:26:286:33 | b | -| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:109:10:109:15 | m1 | -| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:112:10:112:11 | m3 | -| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:114:10:114:15 | m7 | -| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:109:18:109:23 | m2 | -| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:112:14:112:21 | Item2 | -| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:114:18:114:33 | Item2 | -| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:79:14:79:14 | i | -| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:79:23:79:24 | Item1 | -| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:84:17:84:17 | a | -| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:79:17:79:17 | j | -| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:79:27:79:27 | x | -| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:84:23:84:23 | Item2 | -| (String,String) | (string, string) | ValueTuple | 2 | 0 | CSharp7.cs:89:19:89:27 | Item1 | -| (String,String) | (string, string) | ValueTuple | 2 | 0 | CSharp7.cs:90:10:90:15 | t2 | -| (String,String) | (string, string) | ValueTuple | 2 | 1 | CSharp7.cs:89:30:89:33 | Item2 | -| (String,String) | (string, string) | ValueTuple | 2 | 1 | CSharp7.cs:90:18:90:23 | t3 | +| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:77:10:77:14 | a | +| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:77:36:77:36 | Item1 | +| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:78:24:78:24 | b | +| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:77:17:77:30 | Item2 | +| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:77:39:77:39 | z | +| (Int32,(Int32,Int32)) | (int, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:78:27:78:32 | Item2 | +| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 0 | CSharp7.cs:98:19:98:19 | Item1 | +| (Int32,(String,Int32)) | (int, (string, int)) | ValueTuple | 2 | 1 | CSharp7.cs:98:22:98:42 | Item2 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:214:6:214:8 | Item1 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:224:10:224:14 | x | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 0 | CSharp7.cs:225:10:225:10 | Item1 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:214:11:214:16 | Item2 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:224:17:224:17 | Item2 | +| (Int32,Double) | (int, double) | ValueTuple | 2 | 1 | CSharp7.cs:225:13:225:17 | y | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:64:6:64:8 | Item1 | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:71:10:71:14 | x | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:77:18:77:22 | b | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:78:28:78:28 | c | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:112:15:112:16 | m4 | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 0 | CSharp7.cs:114:19:114:24 | m8 | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:64:11:64:13 | Item2 | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:71:17:71:21 | y | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:77:25:77:29 | c | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:78:31:78:31 | a | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:112:19:112:20 | m5 | +| (Int32,Int32) | (int, int) | ValueTuple | 2 | 1 | CSharp7.cs:114:27:114:32 | m9 | +| (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 0 | CSharp7.cs:75:10:75:10 | x | +| (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 1 | CSharp7.cs:75:13:75:13 | y | +| (Int32,Int32,Int32) | (int, int, int) | ValueTuple | 3 | 2 | CSharp7.cs:75:16:75:22 | Item3 | +| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:284:41:284:48 | Key | +| (Int32,String) | (int, string) | ValueTuple | 2 | 0 | CSharp7.cs:286:19:286:23 | a | +| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:284:51:284:60 | Value | +| (Int32,String) | (int, string) | ValueTuple | 2 | 1 | CSharp7.cs:286:26:286:33 | b | +| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:109:10:109:15 | m1 | +| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:112:10:112:11 | m3 | +| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 0 | CSharp7.cs:114:10:114:15 | m7 | +| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:109:18:109:23 | m2 | +| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:112:14:112:21 | Item2 | +| (String,(Int32,Int32)) | (string, (int, int)) | ValueTuple | 2 | 1 | CSharp7.cs:114:18:114:33 | Item2 | +| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:79:14:79:14 | i | +| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:79:23:79:24 | Item1 | +| (String,Int32) | (string, int) | ValueTuple | 2 | 0 | CSharp7.cs:84:17:84:17 | a | +| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:79:17:79:17 | j | +| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:79:27:79:27 | x | +| (String,Int32) | (string, int) | ValueTuple | 2 | 1 | CSharp7.cs:84:23:84:23 | Item2 | +| (String,String) | (string, string) | ValueTuple | 2 | 0 | CSharp7.cs:89:19:89:27 | Item1 | +| (String,String) | (string, string) | ValueTuple | 2 | 0 | CSharp7.cs:90:10:90:15 | t2 | +| (String,String) | (string, string) | ValueTuple | 2 | 1 | CSharp7.cs:89:30:89:33 | Item2 | +| (String,String) | (string, string) | ValueTuple | 2 | 1 | CSharp7.cs:90:18:90:23 | t3 | diff --git a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected index 12ae9dff58a7..be9d872af1f1 100644 --- a/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/library/LibraryTypeDataFlow.expected @@ -178,7 +178,7 @@ | System.Collections.Specialized.OrderedDictionary.get_Values() | qualifier -> return | false | | System.Collections.Specialized.StringCollection.Add(object) | argument 0 -> qualifier | false | | System.Collections.Specialized.StringCollection.Add(string) | argument 0 -> qualifier | false | -| System.Collections.Specialized.StringCollection.AddRange(string[]) | argument 0 -> qualifier | false | +| System.Collections.Specialized.StringCollection.AddRange(String[]) | argument 0 -> qualifier | false | | System.Collections.Specialized.StringCollection.GetEnumerator() | qualifier -> return | false | | System.Collections.Specialized.StringCollection.Insert(int, object) | argument 1 -> qualifier | false | | System.Collections.Specialized.StringCollection.Insert(int, string) | argument 1 -> qualifier | false | @@ -221,17 +221,17 @@ | System.Convert.ChangeType(object, Type, IFormatProvider) | argument 0 -> return | false | | System.Convert.ChangeType(object, TypeCode) | argument 0 -> return | false | | System.Convert.ChangeType(object, TypeCode, IFormatProvider) | argument 0 -> return | false | -| System.Convert.FromBase64CharArray(char[], int, int) | argument 0 -> return | false | +| System.Convert.FromBase64CharArray(Char[], int, int) | argument 0 -> return | false | | System.Convert.FromBase64String(string) | argument 0 -> return | false | | System.Convert.GetTypeCode(object) | argument 0 -> return | false | | System.Convert.IsDBNull(object) | argument 0 -> return | false | -| System.Convert.ToBase64CharArray(byte[], int, int, char[], int) | argument 0 -> return | false | -| System.Convert.ToBase64CharArray(byte[], int, int, char[], int, Base64FormattingOptions) | argument 0 -> return | false | -| System.Convert.ToBase64String(ReadOnlySpan, Base64FormattingOptions) | argument 0 -> return | false | -| System.Convert.ToBase64String(byte[]) | argument 0 -> return | false | -| System.Convert.ToBase64String(byte[], Base64FormattingOptions) | argument 0 -> return | false | -| System.Convert.ToBase64String(byte[], int, int) | argument 0 -> return | false | -| System.Convert.ToBase64String(byte[], int, int, Base64FormattingOptions) | argument 0 -> return | false | +| System.Convert.ToBase64CharArray(Byte[], int, int, Char[], int) | argument 0 -> return | false | +| System.Convert.ToBase64CharArray(Byte[], int, int, Char[], int, Base64FormattingOptions) | argument 0 -> return | false | +| System.Convert.ToBase64String(Byte[]) | argument 0 -> return | false | +| System.Convert.ToBase64String(Byte[], Base64FormattingOptions) | argument 0 -> return | false | +| System.Convert.ToBase64String(Byte[], int, int) | argument 0 -> return | false | +| System.Convert.ToBase64String(Byte[], int, int, Base64FormattingOptions) | argument 0 -> return | false | +| System.Convert.ToBase64String(ReadOnlySpan, Base64FormattingOptions) | argument 0 -> return | false | | System.Convert.ToBoolean(DateTime) | argument 0 -> return | false | | System.Convert.ToBoolean(bool) | argument 0 -> return | false | | System.Convert.ToBoolean(byte) | argument 0 -> return | false | @@ -528,58 +528,58 @@ | System.Convert.ToUInt64(uint) | argument 0 -> return | false | | System.Convert.ToUInt64(ulong) | argument 0 -> return | false | | System.Convert.ToUInt64(ushort) | argument 0 -> return | false | -| System.Convert.TryFromBase64Chars(ReadOnlySpan, Span, out int) | argument 0 -> return | false | -| System.Convert.TryFromBase64String(string, Span, out int) | argument 0 -> return | false | -| System.Convert.TryToBase64Chars(ReadOnlySpan, Span, out int, Base64FormattingOptions) | argument 0 -> return | false | -| System.Dynamic.ExpandoObject.Add(KeyValuePair) | argument 0 -> qualifier | false | +| System.Convert.TryFromBase64Chars(ReadOnlySpan, Span, out int) | argument 0 -> return | false | +| System.Convert.TryFromBase64String(string, Span, out int) | argument 0 -> return | false | +| System.Convert.TryToBase64Chars(ReadOnlySpan, Span, out int, Base64FormattingOptions) | argument 0 -> return | false | +| System.Dynamic.ExpandoObject.Add(KeyValuePair) | argument 0 -> qualifier | false | | System.Dynamic.ExpandoObject.Add(string, object) | argument 1 -> qualifier | false | | System.Dynamic.ExpandoObject.GetEnumerator() | qualifier -> return | false | | System.ICloneable.Clone() | qualifier -> return | false | -| System.IO.BufferedStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.IO.BufferedStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.IO.BufferedStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.IO.BufferedStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | | System.IO.BufferedStream.CopyTo(Stream, int) | qualifier -> argument 0 | false | | System.IO.BufferedStream.CopyToAsync(Stream, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.BufferedStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.BufferedStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.BufferedStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.BufferedStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | -| System.IO.Compression.DeflateStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.IO.Compression.DeflateStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.IO.BufferedStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.BufferedStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.BufferedStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.BufferedStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.Compression.DeflateStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.IO.Compression.DeflateStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | | System.IO.Compression.DeflateStream.CopyToAsync(Stream, int, CancellationToken) | qualifier -> argument 0 | false | | System.IO.Compression.DeflateStream.DeflateStream(Stream, CompressionLevel) | argument 0 -> return | false | | System.IO.Compression.DeflateStream.DeflateStream(Stream, CompressionLevel, bool) | argument 0 -> return | false | | System.IO.Compression.DeflateStream.DeflateStream(Stream, CompressionMode) | argument 0 -> return | false | | System.IO.Compression.DeflateStream.DeflateStream(Stream, CompressionMode, bool) | argument 0 -> return | false | -| System.IO.Compression.DeflateStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.Compression.DeflateStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.Compression.DeflateStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.Compression.DeflateStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | -| System.IO.Compression.GZipStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.IO.Compression.GZipStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.IO.Compression.DeflateStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.Compression.DeflateStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.Compression.DeflateStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.Compression.DeflateStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.Compression.GZipStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.IO.Compression.GZipStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | | System.IO.Compression.GZipStream.CopyTo(Stream, int) | qualifier -> argument 0 | false | | System.IO.Compression.GZipStream.CopyToAsync(Stream, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.Compression.GZipStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.Compression.GZipStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.Compression.GZipStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.Compression.GZipStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | -| System.IO.FileStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.IO.FileStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | -| System.IO.FileStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.FileStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.FileStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.FileStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.Compression.GZipStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.Compression.GZipStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.Compression.GZipStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.Compression.GZipStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.FileStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.IO.FileStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.IO.FileStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.FileStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.FileStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.FileStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | | System.IO.MemoryStream.CopyTo(Stream, int) | qualifier -> argument 0 | false | | System.IO.MemoryStream.CopyToAsync(Stream, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.MemoryStream.MemoryStream(byte[]) | argument 0 -> return | false | -| System.IO.MemoryStream.MemoryStream(byte[], bool) | argument 0 -> return | false | -| System.IO.MemoryStream.MemoryStream(byte[], int, int) | argument 0 -> return | false | -| System.IO.MemoryStream.MemoryStream(byte[], int, int, bool) | argument 0 -> return | false | -| System.IO.MemoryStream.MemoryStream(byte[], int, int, bool, bool) | argument 0 -> return | false | -| System.IO.MemoryStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.MemoryStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.MemoryStream.MemoryStream(Byte[]) | argument 0 -> return | false | +| System.IO.MemoryStream.MemoryStream(Byte[], bool) | argument 0 -> return | false | +| System.IO.MemoryStream.MemoryStream(Byte[], int, int) | argument 0 -> return | false | +| System.IO.MemoryStream.MemoryStream(Byte[], int, int, bool) | argument 0 -> return | false | +| System.IO.MemoryStream.MemoryStream(Byte[], int, int, bool, bool) | argument 0 -> return | false | +| System.IO.MemoryStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.MemoryStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | | System.IO.MemoryStream.ToArray() | qualifier -> return | false | -| System.IO.MemoryStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.MemoryStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.MemoryStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.MemoryStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | | System.IO.Path.Combine(string, string) | argument 0 -> return | false | | System.IO.Path.Combine(string, string) | argument 1 -> return | false | | System.IO.Path.Combine(string, string, string) | argument 0 -> return | false | @@ -589,69 +589,69 @@ | System.IO.Path.Combine(string, string, string, string) | argument 1 -> return | false | | System.IO.Path.Combine(string, string, string, string) | argument 2 -> return | false | | System.IO.Path.Combine(string, string, string, string) | argument 3 -> return | false | -| System.IO.Path.GetDirectoryName(ReadOnlySpan) | argument 0 -> return | false | +| System.IO.Path.GetDirectoryName(ReadOnlySpan) | argument 0 -> return | false | | System.IO.Path.GetDirectoryName(string) | argument 0 -> return | false | -| System.IO.Path.GetExtension(ReadOnlySpan) | argument 0 -> return | false | +| System.IO.Path.GetExtension(ReadOnlySpan) | argument 0 -> return | false | | System.IO.Path.GetExtension(string) | argument 0 -> return | false | -| System.IO.Path.GetFileName(ReadOnlySpan) | argument 0 -> return | false | +| System.IO.Path.GetFileName(ReadOnlySpan) | argument 0 -> return | false | | System.IO.Path.GetFileName(string) | argument 0 -> return | false | -| System.IO.Path.GetFileNameWithoutExtension(ReadOnlySpan) | argument 0 -> return | false | +| System.IO.Path.GetFileNameWithoutExtension(ReadOnlySpan) | argument 0 -> return | false | | System.IO.Path.GetFileNameWithoutExtension(string) | argument 0 -> return | false | | System.IO.Path.GetFullPath(string) | argument 0 -> return | false | | System.IO.Path.GetFullPath(string, string) | argument 0 -> return | false | -| System.IO.Path.GetPathRoot(ReadOnlySpan) | argument 0 -> return | false | +| System.IO.Path.GetPathRoot(ReadOnlySpan) | argument 0 -> return | false | | System.IO.Path.GetPathRoot(string) | argument 0 -> return | false | | System.IO.Path.GetRelativePath(string, string) | argument 1 -> return | false | -| System.IO.Pipes.PipeStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.IO.Pipes.PipeStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | -| System.IO.Pipes.PipeStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.Pipes.PipeStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.Pipes.PipeStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.Pipes.PipeStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | -| System.IO.Stream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.IO.Stream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.IO.Pipes.PipeStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.IO.Pipes.PipeStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.IO.Pipes.PipeStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.Pipes.PipeStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.Pipes.PipeStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.Pipes.PipeStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.Stream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.IO.Stream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | | System.IO.Stream.CopyTo(Stream) | qualifier -> argument 0 | false | | System.IO.Stream.CopyTo(Stream, int) | qualifier -> argument 0 | false | | System.IO.Stream.CopyToAsync(Stream) | qualifier -> argument 0 | false | | System.IO.Stream.CopyToAsync(Stream, CancellationToken) | qualifier -> argument 0 | false | | System.IO.Stream.CopyToAsync(Stream, int) | qualifier -> argument 0 | false | | System.IO.Stream.CopyToAsync(Stream, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.Stream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.Stream.ReadAsync(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.Stream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.Stream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.Stream.WriteAsync(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.Stream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.Stream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.Stream.ReadAsync(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.Stream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.Stream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.Stream.WriteAsync(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.Stream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | | System.IO.StringReader.Read() | qualifier -> return | false | -| System.IO.StringReader.Read(Span) | qualifier -> return | false | -| System.IO.StringReader.Read(char[], int, int) | qualifier -> return | false | -| System.IO.StringReader.ReadAsync(Memory, CancellationToken) | qualifier -> return | false | -| System.IO.StringReader.ReadAsync(char[], int, int) | qualifier -> return | false | -| System.IO.StringReader.ReadBlock(Span) | qualifier -> return | false | -| System.IO.StringReader.ReadBlockAsync(Memory, CancellationToken) | qualifier -> return | false | -| System.IO.StringReader.ReadBlockAsync(char[], int, int) | qualifier -> return | false | +| System.IO.StringReader.Read(Char[], int, int) | qualifier -> return | false | +| System.IO.StringReader.Read(Span) | qualifier -> return | false | +| System.IO.StringReader.ReadAsync(Char[], int, int) | qualifier -> return | false | +| System.IO.StringReader.ReadAsync(Memory, CancellationToken) | qualifier -> return | false | +| System.IO.StringReader.ReadBlock(Span) | qualifier -> return | false | +| System.IO.StringReader.ReadBlockAsync(Char[], int, int) | qualifier -> return | false | +| System.IO.StringReader.ReadBlockAsync(Memory, CancellationToken) | qualifier -> return | false | | System.IO.StringReader.ReadLine() | qualifier -> return | false | | System.IO.StringReader.ReadLineAsync() | qualifier -> return | false | | System.IO.StringReader.ReadToEnd() | qualifier -> return | false | | System.IO.StringReader.ReadToEndAsync() | qualifier -> return | false | | System.IO.StringReader.StringReader(string) | argument 0 -> return | false | | System.IO.TextReader.Read() | qualifier -> return | false | -| System.IO.TextReader.Read(Span) | qualifier -> return | false | -| System.IO.TextReader.Read(char[], int, int) | qualifier -> return | false | -| System.IO.TextReader.ReadAsync(Memory, CancellationToken) | qualifier -> return | false | -| System.IO.TextReader.ReadAsync(char[], int, int) | qualifier -> return | false | -| System.IO.TextReader.ReadBlock(Span) | qualifier -> return | false | -| System.IO.TextReader.ReadBlock(char[], int, int) | qualifier -> return | false | -| System.IO.TextReader.ReadBlockAsync(Memory, CancellationToken) | qualifier -> return | false | -| System.IO.TextReader.ReadBlockAsync(char[], int, int) | qualifier -> return | false | +| System.IO.TextReader.Read(Char[], int, int) | qualifier -> return | false | +| System.IO.TextReader.Read(Span) | qualifier -> return | false | +| System.IO.TextReader.ReadAsync(Char[], int, int) | qualifier -> return | false | +| System.IO.TextReader.ReadAsync(Memory, CancellationToken) | qualifier -> return | false | +| System.IO.TextReader.ReadBlock(Char[], int, int) | qualifier -> return | false | +| System.IO.TextReader.ReadBlock(Span) | qualifier -> return | false | +| System.IO.TextReader.ReadBlockAsync(Char[], int, int) | qualifier -> return | false | +| System.IO.TextReader.ReadBlockAsync(Memory, CancellationToken) | qualifier -> return | false | | System.IO.TextReader.ReadLine() | qualifier -> return | false | | System.IO.TextReader.ReadLineAsync() | qualifier -> return | false | | System.IO.TextReader.ReadToEnd() | qualifier -> return | false | | System.IO.TextReader.ReadToEndAsync() | qualifier -> return | false | -| System.IO.UnmanagedMemoryStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.IO.UnmanagedMemoryStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.IO.UnmanagedMemoryStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.IO.UnmanagedMemoryStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.IO.UnmanagedMemoryStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.IO.UnmanagedMemoryStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.IO.UnmanagedMemoryStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.IO.UnmanagedMemoryStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | | System.Int32.Parse(string) | argument 0 -> return | false | | System.Int32.Parse(string, IFormatProvider) | argument 0 -> return | false | | System.Int32.Parse(string, NumberStyles) | argument 0 -> return | false | @@ -673,23 +673,23 @@ | System.Linq.Enumerable.Aggregate(IEnumerable, TAccumulate, Func) | output from argument 2 -> return | false | | System.Linq.Enumerable.Aggregate(IEnumerable, Func) | argument 0 -> parameter 1 of argument 1 | false | | System.Linq.Enumerable.Aggregate(IEnumerable, Func) | output from argument 1 -> return | false | -| System.Linq.Enumerable.All(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Any(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.All(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Any(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.AsEnumerable(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Average(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.Cast(IEnumerable) | argument 0 -> return | false | | System.Linq.Enumerable.Concat(IEnumerable, IEnumerable) | argument 0 -> return | false | | System.Linq.Enumerable.Concat(IEnumerable, IEnumerable) | argument 1 -> return | false | -| System.Linq.Enumerable.Count(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Count(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.DefaultIfEmpty(IEnumerable) | argument 0 -> return | false | | System.Linq.Enumerable.DefaultIfEmpty(IEnumerable, TSource) | argument 0 -> return | false | | System.Linq.Enumerable.DefaultIfEmpty(IEnumerable, TSource) | argument 1 -> return | false | @@ -700,11 +700,11 @@ | System.Linq.Enumerable.Except(IEnumerable, IEnumerable) | argument 0 -> return | false | | System.Linq.Enumerable.Except(IEnumerable, IEnumerable, IEqualityComparer) | argument 0 -> return | false | | System.Linq.Enumerable.First(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.First(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.First(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.First(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.First(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.FirstOrDefault(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.FirstOrDefault(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.FirstOrDefault(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.FirstOrDefault(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.FirstOrDefault(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.GroupBy(IEnumerable, Func, Func, Func, TResult>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.GroupBy(IEnumerable, Func, Func, Func, TResult>) | argument 0 -> parameter 0 of argument 2 | false | | System.Linq.Enumerable.GroupBy(IEnumerable, Func, Func, Func, TResult>) | output from argument 1 -> parameter 0 of argument 3 | false | @@ -753,34 +753,34 @@ | System.Linq.Enumerable.Join(IEnumerable, IEnumerable, Func, Func, Func, IEqualityComparer) | argument 1 -> parameter 1 of argument 4 | false | | System.Linq.Enumerable.Join(IEnumerable, IEnumerable, Func, Func, Func, IEqualityComparer) | output from argument 4 -> return | false | | System.Linq.Enumerable.Last(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.Last(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Last(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.Last(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Last(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.LastOrDefault(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.LastOrDefault(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.LastOrDefault(IEnumerable, Func) | argument 0 -> return | false | -| System.Linq.Enumerable.LongCount(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.LastOrDefault(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.LastOrDefault(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.LongCount(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Max(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Min(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.OfType(IEnumerable) | argument 0 -> return | false | | System.Linq.Enumerable.OrderBy(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.OrderBy(IEnumerable, Func) | argument 0 -> return | false | @@ -791,48 +791,48 @@ | System.Linq.Enumerable.OrderByDescending(IEnumerable, Func, IComparer) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.OrderByDescending(IEnumerable, Func, IComparer) | argument 0 -> return | false | | System.Linq.Enumerable.Reverse(IEnumerable) | argument 0 -> return | false | +| System.Linq.Enumerable.Select(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Select(IEnumerable, Func) | output from argument 1 -> return | false | | System.Linq.Enumerable.Select(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.Select(IEnumerable, Func) | output from argument 1 -> return | false | -| System.Linq.Enumerable.Select(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Select(IEnumerable, Func) | output from argument 1 -> return | false | | System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | argument 0 -> parameter 0 of argument 2 | false | | System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | output from argument 1 -> parameter 1 of argument 2 | false | | System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | output from argument 2 -> return | false | -| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | output from argument 1 -> parameter 1 of argument 2 | false | -| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | output from argument 2 -> return | false | +| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | output from argument 1 -> parameter 1 of argument 2 | false | +| System.Linq.Enumerable.SelectMany(IEnumerable, Func>, Func) | output from argument 2 -> return | false | | System.Linq.Enumerable.SelectMany(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.SelectMany(IEnumerable, Func>) | output from argument 1 -> return | false | -| System.Linq.Enumerable.SelectMany(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.SelectMany(IEnumerable, Func>) | output from argument 1 -> return | false | +| System.Linq.Enumerable.SelectMany(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.SelectMany(IEnumerable, Func>) | output from argument 1 -> return | false | | System.Linq.Enumerable.Single(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.Single(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Single(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.Single(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Single(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.SingleOrDefault(IEnumerable) | argument 0 -> return | false | -| System.Linq.Enumerable.SingleOrDefault(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.SingleOrDefault(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.SingleOrDefault(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.SingleOrDefault(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.Skip(IEnumerable, int) | argument 0 -> return | false | -| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> return | false | -| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> return | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.SkipWhile(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Sum(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.Take(IEnumerable, int) | argument 0 -> return | false | -| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> return | false | -| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.TakeWhile(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.ThenBy(IOrderedEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Enumerable.ThenBy(IOrderedEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.ThenBy(IOrderedEnumerable, Func, IComparer) | argument 0 -> parameter 0 of argument 1 | false | @@ -867,10 +867,10 @@ | System.Linq.Enumerable.Union(IEnumerable, IEnumerable) | argument 1 -> return | false | | System.Linq.Enumerable.Union(IEnumerable, IEnumerable, IEqualityComparer) | argument 0 -> return | false | | System.Linq.Enumerable.Union(IEnumerable, IEnumerable, IEqualityComparer) | argument 1 -> return | false | -| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> return | false | -| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> return | false | +| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Enumerable.Where(IEnumerable, Func) | argument 0 -> return | false | | System.Linq.Enumerable.Zip(IEnumerable, IEnumerable, Func) | argument 0 -> parameter 0 of argument 2 | false | | System.Linq.Enumerable.Zip(IEnumerable, IEnumerable, Func) | argument 1 -> parameter 1 of argument 2 | false | | System.Linq.Enumerable.Zip(IEnumerable, IEnumerable, Func) | output from argument 2 -> return | false | @@ -889,25 +889,25 @@ | System.Linq.ParallelEnumerable.Aggregate(ParallelQuery, TAccumulate, Func) | output from argument 2 -> return | false | | System.Linq.ParallelEnumerable.Aggregate(ParallelQuery, Func) | argument 0 -> parameter 1 of argument 1 | false | | System.Linq.ParallelEnumerable.Aggregate(ParallelQuery, Func) | output from argument 1 -> return | false | -| System.Linq.ParallelEnumerable.All(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Any(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.All(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Any(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.AsEnumerable(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Average(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.Cast(ParallelQuery) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Concat(ParallelQuery, IEnumerable) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Concat(ParallelQuery, IEnumerable) | argument 1 -> return | false | | System.Linq.ParallelEnumerable.Concat(ParallelQuery, ParallelQuery) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Concat(ParallelQuery, ParallelQuery) | argument 1 -> return | false | -| System.Linq.ParallelEnumerable.Count(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Count(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.DefaultIfEmpty(ParallelQuery) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.DefaultIfEmpty(ParallelQuery, TSource) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.DefaultIfEmpty(ParallelQuery, TSource) | argument 1 -> return | false | @@ -920,11 +920,11 @@ | System.Linq.ParallelEnumerable.Except(ParallelQuery, ParallelQuery) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Except(ParallelQuery, ParallelQuery, IEqualityComparer) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.First(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.First(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.First(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.First(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.First(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.FirstOrDefault(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.FirstOrDefault(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.FirstOrDefault(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.FirstOrDefault(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.FirstOrDefault(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.GroupBy(ParallelQuery, Func, Func, Func, TResult>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.GroupBy(ParallelQuery, Func, Func, Func, TResult>) | argument 0 -> parameter 0 of argument 2 | false | | System.Linq.ParallelEnumerable.GroupBy(ParallelQuery, Func, Func, Func, TResult>) | output from argument 1 -> parameter 0 of argument 3 | false | @@ -997,34 +997,34 @@ | System.Linq.ParallelEnumerable.Join(ParallelQuery, ParallelQuery, Func, Func, Func, IEqualityComparer) | argument 1 -> parameter 1 of argument 4 | false | | System.Linq.ParallelEnumerable.Join(ParallelQuery, ParallelQuery, Func, Func, Func, IEqualityComparer) | output from argument 4 -> return | false | | System.Linq.ParallelEnumerable.Last(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.Last(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Last(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.Last(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Last(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.LastOrDefault(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.LastOrDefault(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.LastOrDefault(ParallelQuery, Func) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.LongCount(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.LastOrDefault(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.LastOrDefault(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.LongCount(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Max(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Min(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.OfType(ParallelQuery) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.OrderBy(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.OrderBy(ParallelQuery, Func) | argument 0 -> return | false | @@ -1035,48 +1035,48 @@ | System.Linq.ParallelEnumerable.OrderByDescending(ParallelQuery, Func, IComparer) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.OrderByDescending(ParallelQuery, Func, IComparer) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Reverse(ParallelQuery) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.Select(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Select(ParallelQuery, Func) | output from argument 1 -> return | false | | System.Linq.ParallelEnumerable.Select(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.Select(ParallelQuery, Func) | output from argument 1 -> return | false | -| System.Linq.ParallelEnumerable.Select(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Select(ParallelQuery, Func) | output from argument 1 -> return | false | | System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | argument 0 -> parameter 0 of argument 2 | false | | System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | output from argument 1 -> parameter 1 of argument 2 | false | | System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | output from argument 2 -> return | false | -| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | output from argument 1 -> parameter 1 of argument 2 | false | -| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | output from argument 2 -> return | false | +| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | output from argument 1 -> parameter 1 of argument 2 | false | +| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>, Func) | output from argument 2 -> return | false | | System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>) | output from argument 1 -> return | false | -| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>) | output from argument 1 -> return | false | +| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.SelectMany(ParallelQuery, Func>) | output from argument 1 -> return | false | | System.Linq.ParallelEnumerable.Single(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.Single(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Single(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.Single(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Single(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.SingleOrDefault(ParallelQuery) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.SingleOrDefault(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.SingleOrDefault(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.SingleOrDefault(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.SingleOrDefault(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Skip(ParallelQuery, int) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.SkipWhile(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Sum(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.Take(ParallelQuery, int) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.TakeWhile(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.ThenBy(OrderedParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.ParallelEnumerable.ThenBy(OrderedParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.ThenBy(OrderedParallelQuery, Func, IComparer) | argument 0 -> parameter 0 of argument 1 | false | @@ -1115,10 +1115,10 @@ | System.Linq.ParallelEnumerable.Union(ParallelQuery, ParallelQuery) | argument 1 -> return | false | | System.Linq.ParallelEnumerable.Union(ParallelQuery, ParallelQuery, IEqualityComparer) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Union(ParallelQuery, ParallelQuery, IEqualityComparer) | argument 1 -> return | false | -| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> return | false | -| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> return | false | +| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.ParallelEnumerable.Where(ParallelQuery, Func) | argument 0 -> return | false | | System.Linq.ParallelEnumerable.Zip(ParallelQuery, IEnumerable, Func) | argument 0 -> parameter 0 of argument 2 | false | | System.Linq.ParallelEnumerable.Zip(ParallelQuery, IEnumerable, Func) | argument 1 -> parameter 1 of argument 2 | false | | System.Linq.ParallelEnumerable.Zip(ParallelQuery, IEnumerable, Func) | output from argument 2 -> return | false | @@ -1127,31 +1127,31 @@ | System.Linq.ParallelEnumerable.Zip(ParallelQuery, ParallelQuery, Func) | output from argument 2 -> return | false | | System.Linq.ParallelQuery.GetEnumerator() | qualifier -> return | false | | System.Linq.ParallelQuery<>.GetEnumerator() | qualifier -> return | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | argument 0 -> parameter 1 of argument 2 | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | argument 1 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | output from argument 2 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | output from argument 3 -> return | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>) | argument 0 -> parameter 1 of argument 2 | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>) | argument 1 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>) | output from argument 2 -> return | false | -| System.Linq.Queryable.Aggregate(IQueryable, Expression>) | argument 0 -> parameter 1 of argument 1 | false | -| System.Linq.Queryable.Aggregate(IQueryable, Expression>) | output from argument 1 -> return | false | -| System.Linq.Queryable.All(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Any(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | argument 0 -> parameter 1 of argument 2 | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | argument 1 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | output from argument 2 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>, Expression>) | output from argument 3 -> return | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>) | argument 0 -> parameter 1 of argument 2 | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>) | argument 1 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.Aggregate(IQueryable, TAccumulate, Expression>) | output from argument 2 -> return | false | +| System.Linq.Queryable.Aggregate(IQueryable, Expression>) | argument 0 -> parameter 1 of argument 1 | false | +| System.Linq.Queryable.Aggregate(IQueryable, Expression>) | output from argument 1 -> return | false | +| System.Linq.Queryable.All(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Any(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Average(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Cast(IQueryable) | argument 0 -> return | false | | System.Linq.Queryable.Concat(IQueryable, IEnumerable) | argument 0 -> return | false | | System.Linq.Queryable.Concat(IQueryable, IEnumerable) | argument 1 -> return | false | -| System.Linq.Queryable.Count(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Count(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.DefaultIfEmpty(IQueryable) | argument 0 -> return | false | | System.Linq.Queryable.DefaultIfEmpty(IQueryable, TSource) | argument 0 -> return | false | | System.Linq.Queryable.DefaultIfEmpty(IQueryable, TSource) | argument 1 -> return | false | @@ -1162,135 +1162,135 @@ | System.Linq.Queryable.Except(IQueryable, IEnumerable) | argument 0 -> return | false | | System.Linq.Queryable.Except(IQueryable, IEnumerable, IEqualityComparer) | argument 0 -> return | false | | System.Linq.Queryable.First(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.First(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.First(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.First(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.First(IQueryable, Expression>) | argument 0 -> return | false | | System.Linq.Queryable.FirstOrDefault(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.FirstOrDefault(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.FirstOrDefault(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>) | output from argument 1 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>) | output from argument 2 -> parameter 1 of argument 3 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>) | output from argument 3 -> return | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | output from argument 1 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | output from argument 2 -> parameter 1 of argument 3 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | output from argument 3 -> return | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>) | output from argument 2 -> return | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression, TResult>>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression, TResult>>) | output from argument 2 -> return | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression, TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression, TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.GroupBy(IQueryable, Expression>, IEqualityComparer) | argument 0 -> return | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>) | argument 0 -> parameter 0 of argument 4 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>) | argument 1 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>) | argument 1 -> parameter 1 of argument 4 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>) | output from argument 4 -> return | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 4 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | argument 1 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | argument 1 -> parameter 1 of argument 4 | false | -| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression, TResult>>, IEqualityComparer) | output from argument 4 -> return | false | +| System.Linq.Queryable.FirstOrDefault(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.FirstOrDefault(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>) | output from argument 1 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>) | output from argument 2 -> parameter 1 of argument 3 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>) | output from argument 3 -> return | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | output from argument 1 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | output from argument 2 -> parameter 1 of argument 3 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | output from argument 3 -> return | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>) | output from argument 2 -> return | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression,TResult>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression,TResult>>) | output from argument 2 -> return | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression,TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, Expression,TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.GroupBy(IQueryable, Expression>, IEqualityComparer) | argument 0 -> return | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>) | argument 0 -> parameter 0 of argument 4 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>) | argument 1 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>) | argument 1 -> parameter 1 of argument 4 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>) | output from argument 4 -> return | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | argument 0 -> parameter 0 of argument 4 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | argument 1 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | argument 1 -> parameter 1 of argument 4 | false | +| System.Linq.Queryable.GroupJoin(IQueryable, IEnumerable, Expression>, Expression>, Expression,TResult>>, IEqualityComparer) | output from argument 4 -> return | false | | System.Linq.Queryable.Intersect(IQueryable, IEnumerable) | argument 0 -> return | false | | System.Linq.Queryable.Intersect(IQueryable, IEnumerable) | argument 1 -> return | false | | System.Linq.Queryable.Intersect(IQueryable, IEnumerable, IEqualityComparer) | argument 0 -> return | false | | System.Linq.Queryable.Intersect(IQueryable, IEnumerable, IEqualityComparer) | argument 1 -> return | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 0 -> parameter 0 of argument 4 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 1 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 1 -> parameter 1 of argument 4 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | output from argument 4 -> return | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 4 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 1 -> parameter 0 of argument 3 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 1 -> parameter 1 of argument 4 | false | -| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | output from argument 4 -> return | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 0 -> parameter 0 of argument 4 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 1 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | argument 1 -> parameter 1 of argument 4 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>) | output from argument 4 -> return | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 0 -> parameter 0 of argument 4 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 1 -> parameter 0 of argument 3 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | argument 1 -> parameter 1 of argument 4 | false | +| System.Linq.Queryable.Join(IQueryable, IEnumerable, Expression>, Expression>, Expression>, IEqualityComparer) | output from argument 4 -> return | false | | System.Linq.Queryable.Last(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.Last(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Last(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.Last(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Last(IQueryable, Expression>) | argument 0 -> return | false | | System.Linq.Queryable.LastOrDefault(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.LastOrDefault(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.LastOrDefault(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.LongCount(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Max(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Min(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.LastOrDefault(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.LastOrDefault(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.LongCount(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Max(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Min(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.OfType(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.OrderBy(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.OrderBy(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.OrderBy(IQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.OrderBy(IQueryable, Expression>, IComparer) | argument 0 -> return | false | -| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>, IComparer) | argument 0 -> return | false | +| System.Linq.Queryable.OrderBy(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.OrderBy(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.OrderBy(IQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.OrderBy(IQueryable, Expression>, IComparer) | argument 0 -> return | false | +| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.OrderByDescending(IQueryable, Expression>, IComparer) | argument 0 -> return | false | | System.Linq.Queryable.Reverse(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.Select(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Select(IQueryable, Expression>) | output from argument 1 -> return | false | -| System.Linq.Queryable.Select(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Select(IQueryable, Expression>) | output from argument 1 -> return | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 1 -> parameter 1 of argument 2 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 2 -> return | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 1 -> parameter 1 of argument 2 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 2 -> return | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | output from argument 1 -> return | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | output from argument 1 -> return | false | +| System.Linq.Queryable.Select(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Select(IQueryable, Expression>) | output from argument 1 -> return | false | +| System.Linq.Queryable.Select(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Select(IQueryable, Expression>) | output from argument 1 -> return | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 1 -> parameter 1 of argument 2 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 2 -> return | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 1 -> parameter 1 of argument 2 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>, Expression>) | output from argument 2 -> return | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | output from argument 1 -> return | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SelectMany(IQueryable, Expression>>) | output from argument 1 -> return | false | | System.Linq.Queryable.Single(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.Single(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Single(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.Single(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Single(IQueryable, Expression>) | argument 0 -> return | false | | System.Linq.Queryable.SingleOrDefault(IQueryable) | argument 0 -> return | false | -| System.Linq.Queryable.SingleOrDefault(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SingleOrDefault(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.SingleOrDefault(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SingleOrDefault(IQueryable, Expression>) | argument 0 -> return | false | | System.Linq.Queryable.Skip(IQueryable, int) | argument 0 -> return | false | -| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.SkipWhile(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Sum(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | | System.Linq.Queryable.Take(IQueryable, int) | argument 0 -> return | false | -| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>, IComparer) | argument 0 -> return | false | -| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>, IComparer) | argument 0 -> return | false | +| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.TakeWhile(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.ThenBy(IOrderedQueryable, Expression>, IComparer) | argument 0 -> return | false | +| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>, IComparer) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.ThenByDescending(IOrderedQueryable, Expression>, IComparer) | argument 0 -> return | false | | System.Linq.Queryable.Union(IQueryable, IEnumerable) | argument 0 -> return | false | | System.Linq.Queryable.Union(IQueryable, IEnumerable) | argument 1 -> return | false | | System.Linq.Queryable.Union(IQueryable, IEnumerable, IEqualityComparer) | argument 0 -> return | false | | System.Linq.Queryable.Union(IQueryable, IEnumerable, IEqualityComparer) | argument 1 -> return | false | -| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | -| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> return | false | -| System.Linq.Queryable.Zip(IQueryable, IEnumerable, Expression>) | argument 0 -> parameter 0 of argument 2 | false | -| System.Linq.Queryable.Zip(IQueryable, IEnumerable, Expression>) | argument 1 -> parameter 1 of argument 2 | false | -| System.Linq.Queryable.Zip(IQueryable, IEnumerable, Expression>) | output from argument 2 -> return | false | +| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> parameter 0 of argument 1 | false | +| System.Linq.Queryable.Where(IQueryable, Expression>) | argument 0 -> return | false | +| System.Linq.Queryable.Zip(IQueryable, IEnumerable, Expression>) | argument 0 -> parameter 0 of argument 2 | false | +| System.Linq.Queryable.Zip(IQueryable, IEnumerable, Expression>) | argument 1 -> parameter 1 of argument 2 | false | +| System.Linq.Queryable.Zip(IQueryable, IEnumerable, Expression>) | output from argument 2 -> return | false | | System.Net.Cookie.get_Value() | qualifier -> return | false | | System.Net.CookieCollection.Add(Cookie) | argument 0 -> qualifier | false | | System.Net.CookieCollection.Add(CookieCollection) | argument 0 -> qualifier | false | @@ -1300,16 +1300,16 @@ | System.Net.HttpListenerPrefixCollection.GetEnumerator() | qualifier -> return | false | | System.Net.NetworkInformation.IPAddressCollection.Add(IPAddress) | argument 0 -> qualifier | false | | System.Net.NetworkInformation.IPAddressCollection.GetEnumerator() | qualifier -> return | false | -| System.Net.Security.NegotiateStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.Net.Security.NegotiateStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | -| System.Net.Security.NegotiateStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.Net.Security.NegotiateStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.Net.Security.SslStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.Net.Security.SslStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | -| System.Net.Security.SslStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.Net.Security.SslStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.Net.Security.SslStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.Net.Security.SslStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.Net.Security.NegotiateStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.Net.Security.NegotiateStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.Net.Security.NegotiateStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.Net.Security.NegotiateStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.Net.Security.SslStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.Net.Security.SslStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.Net.Security.SslStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.Net.Security.SslStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.Net.Security.SslStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.Net.Security.SslStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | | System.Net.WebUtility.HtmlEncode(string) | argument 0 -> return | false | | System.Net.WebUtility.HtmlEncode(string, TextWriter) | argument 0 -> return | false | | System.Net.WebUtility.UrlEncode(string) | argument 0 -> return | false | @@ -1326,15 +1326,15 @@ | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.Insert(int, object) | argument 1 -> qualifier | false | | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.Reverse() | qualifier -> return | false | | System.Runtime.CompilerServices.ReadOnlyCollectionBuilder<>.Reverse(int, int) | qualifier -> return | false | -| System.Security.Cryptography.CryptoStream.BeginRead(byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | -| System.Security.Cryptography.CryptoStream.BeginWrite(byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | -| System.Security.Cryptography.CryptoStream.Read(byte[], int, int) | qualifier -> argument 0 | false | -| System.Security.Cryptography.CryptoStream.ReadAsync(byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | -| System.Security.Cryptography.CryptoStream.Write(byte[], int, int) | argument 0 -> qualifier | false | -| System.Security.Cryptography.CryptoStream.WriteAsync(byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | +| System.Security.Cryptography.CryptoStream.BeginRead(Byte[], int, int, AsyncCallback, object) | qualifier -> argument 0 | false | +| System.Security.Cryptography.CryptoStream.BeginWrite(Byte[], int, int, AsyncCallback, object) | argument 0 -> qualifier | false | +| System.Security.Cryptography.CryptoStream.Read(Byte[], int, int) | qualifier -> argument 0 | false | +| System.Security.Cryptography.CryptoStream.ReadAsync(Byte[], int, int, CancellationToken) | qualifier -> argument 0 | false | +| System.Security.Cryptography.CryptoStream.Write(Byte[], int, int) | argument 0 -> qualifier | false | +| System.Security.Cryptography.CryptoStream.WriteAsync(Byte[], int, int, CancellationToken) | argument 0 -> qualifier | false | | System.String.Clone() | qualifier -> return | false | | System.String.Clone() | qualifier -> return | true | -| System.String.Concat(IEnumerable) | argument 0 -> return | false | +| System.String.Concat(IEnumerable) | argument 0 -> return | false | | System.String.Concat(object) | argument 0 -> return | false | | System.String.Concat(object, object) | argument 0 -> return | false | | System.String.Concat(object, object) | argument 1 -> return | false | @@ -1373,16 +1373,16 @@ | System.String.GetEnumerator() | qualifier -> return | false | | System.String.Insert(int, string) | argument 1 -> return | false | | System.String.Insert(int, string) | qualifier -> return | false | -| System.String.Join(string, IEnumerable) | argument 0 -> return | false | -| System.String.Join(string, IEnumerable) | argument 1 -> return | false | -| System.String.Join(string, params string[]) | argument 0 -> return | false | -| System.String.Join(string, params string[]) | argument 1 -> return | false | -| System.String.Join(string, params string[]) | argument 2 -> return | false | -| System.String.Join(string, params string[]) | argument 3 -> return | false | -| System.String.Join(string, string[], int, int) | argument 0 -> return | false | -| System.String.Join(string, string[], int, int) | argument 1 -> return | false | -| System.String.Join(string, string[], int, int) | argument 2 -> return | false | -| System.String.Join(string, string[], int, int) | argument 3 -> return | false | +| System.String.Join(string, IEnumerable) | argument 0 -> return | false | +| System.String.Join(string, IEnumerable) | argument 1 -> return | false | +| System.String.Join(string, String[], int, int) | argument 0 -> return | false | +| System.String.Join(string, String[], int, int) | argument 1 -> return | false | +| System.String.Join(string, String[], int, int) | argument 2 -> return | false | +| System.String.Join(string, String[], int, int) | argument 3 -> return | false | +| System.String.Join(string, params String[]) | argument 0 -> return | false | +| System.String.Join(string, params String[]) | argument 1 -> return | false | +| System.String.Join(string, params String[]) | argument 2 -> return | false | +| System.String.Join(string, params String[]) | argument 3 -> return | false | | System.String.Join(string, IEnumerable) | argument 0 -> return | false | | System.String.Join(string, IEnumerable) | argument 1 -> return | false | | System.String.Normalize() | qualifier -> return | false | @@ -1397,18 +1397,18 @@ | System.String.Replace(char, char) | qualifier -> return | false | | System.String.Replace(string, string) | argument 1 -> return | false | | System.String.Replace(string, string) | qualifier -> return | false | +| System.String.Split(Char[], StringSplitOptions) | qualifier -> return | false | +| System.String.Split(Char[], int) | qualifier -> return | false | +| System.String.Split(Char[], int, StringSplitOptions) | qualifier -> return | false | +| System.String.Split(String[], StringSplitOptions) | qualifier -> return | false | +| System.String.Split(String[], int, StringSplitOptions) | qualifier -> return | false | | System.String.Split(char, StringSplitOptions) | qualifier -> return | false | | System.String.Split(char, int, StringSplitOptions) | qualifier -> return | false | -| System.String.Split(char[], StringSplitOptions) | qualifier -> return | false | -| System.String.Split(char[], int) | qualifier -> return | false | -| System.String.Split(char[], int, StringSplitOptions) | qualifier -> return | false | -| System.String.Split(params char[]) | qualifier -> return | false | +| System.String.Split(params Char[]) | qualifier -> return | false | | System.String.Split(string, StringSplitOptions) | qualifier -> return | false | | System.String.Split(string, int, StringSplitOptions) | qualifier -> return | false | -| System.String.Split(string[], StringSplitOptions) | qualifier -> return | false | -| System.String.Split(string[], int, StringSplitOptions) | qualifier -> return | false | -| System.String.String(char[]) | argument 0 -> return | false | -| System.String.String(char[], int, int) | argument 0 -> return | false | +| System.String.String(Char[]) | argument 0 -> return | false | +| System.String.String(Char[], int, int) | argument 0 -> return | false | | System.String.Substring(int) | qualifier -> return | false | | System.String.Substring(int, int) | qualifier -> return | false | | System.String.ToLower() | qualifier -> return | false | @@ -1420,30 +1420,30 @@ | System.String.ToUpperInvariant() | qualifier -> return | false | | System.String.Trim() | qualifier -> return | false | | System.String.Trim(char) | qualifier -> return | false | -| System.String.Trim(params char[]) | qualifier -> return | false | +| System.String.Trim(params Char[]) | qualifier -> return | false | | System.String.TrimEnd() | qualifier -> return | false | | System.String.TrimEnd(char) | qualifier -> return | false | -| System.String.TrimEnd(params char[]) | qualifier -> return | false | +| System.String.TrimEnd(params Char[]) | qualifier -> return | false | | System.String.TrimStart() | qualifier -> return | false | | System.String.TrimStart(char) | qualifier -> return | false | -| System.String.TrimStart(params char[]) | qualifier -> return | false | -| System.Text.Encoding.GetBytes(ReadOnlySpan, Span) | argument 0 -> return | false | +| System.String.TrimStart(params Char[]) | qualifier -> return | false | +| System.Text.Encoding.GetBytes(Char[]) | argument 0 -> return | false | +| System.Text.Encoding.GetBytes(Char[], int, int) | argument 0 -> return | false | +| System.Text.Encoding.GetBytes(Char[], int, int, Byte[], int) | argument 0 -> return | false | +| System.Text.Encoding.GetBytes(ReadOnlySpan, Span) | argument 0 -> return | false | | System.Text.Encoding.GetBytes(char*, int, byte*, int) | argument 0 -> return | false | -| System.Text.Encoding.GetBytes(char[]) | argument 0 -> return | false | -| System.Text.Encoding.GetBytes(char[], int, int) | argument 0 -> return | false | -| System.Text.Encoding.GetBytes(char[], int, int, byte[], int) | argument 0 -> return | false | | System.Text.Encoding.GetBytes(string) | argument 0 -> return | false | | System.Text.Encoding.GetBytes(string, int, int) | argument 0 -> return | false | -| System.Text.Encoding.GetBytes(string, int, int, byte[], int) | argument 0 -> return | false | -| System.Text.Encoding.GetChars(ReadOnlySpan, Span) | argument 0 -> return | false | +| System.Text.Encoding.GetBytes(string, int, int, Byte[], int) | argument 0 -> return | false | +| System.Text.Encoding.GetChars(Byte[]) | argument 0 -> return | false | +| System.Text.Encoding.GetChars(Byte[], int, int) | argument 0 -> return | false | +| System.Text.Encoding.GetChars(Byte[], int, int, Char[], int) | argument 0 -> return | false | +| System.Text.Encoding.GetChars(ReadOnlySpan, Span) | argument 0 -> return | false | | System.Text.Encoding.GetChars(byte*, int, char*, int) | argument 0 -> return | false | -| System.Text.Encoding.GetChars(byte[]) | argument 0 -> return | false | -| System.Text.Encoding.GetChars(byte[], int, int) | argument 0 -> return | false | -| System.Text.Encoding.GetChars(byte[], int, int, char[], int) | argument 0 -> return | false | -| System.Text.Encoding.GetString(ReadOnlySpan) | argument 0 -> return | false | +| System.Text.Encoding.GetString(Byte[]) | argument 0 -> return | false | +| System.Text.Encoding.GetString(Byte[], int, int) | argument 0 -> return | false | +| System.Text.Encoding.GetString(ReadOnlySpan) | argument 0 -> return | false | | System.Text.Encoding.GetString(byte*, int) | argument 0 -> return | false | -| System.Text.Encoding.GetString(byte[]) | argument 0 -> return | false | -| System.Text.Encoding.GetString(byte[], int, int) | argument 0 -> return | false | | System.Text.RegularExpressions.CaptureCollection.Add(Capture) | argument 0 -> qualifier | false | | System.Text.RegularExpressions.CaptureCollection.Add(object) | argument 0 -> qualifier | false | | System.Text.RegularExpressions.CaptureCollection.GetEnumerator() | qualifier -> return | false | @@ -1485,106 +1485,106 @@ | System.Text.StringBuilder.StringBuilder(string, int) | argument 0 -> return | false | | System.Text.StringBuilder.StringBuilder(string, int, int, int) | argument 0 -> return | false | | System.Text.StringBuilder.ToString() | qualifier -> return | false | -| System.Threading.Tasks.Task.ContinueWith(Action, object) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Action, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Action, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Action, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Action, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Action, object) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Action, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Action, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Action, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Action, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, TaskContinuationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.ContinueWith(Func, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskContinuationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task.ContinueWith(Func, object, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.FromResult(TResult) | argument 0 -> return | true | | System.Threading.Tasks.Task.Run(Func) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.Run(Func, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.Run(Func>) | output from argument 0 -> return | true | | System.Threading.Tasks.Task.Run(Func>, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task.Task(Action, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task.Task(Action, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task.Task(Action, object, CancellationToken, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task.Task(Action, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task.Task(Action, object) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task.Task(Action, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task.Task(Action, object, CancellationToken, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task.Task(Action, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | | System.Threading.Tasks.Task.WhenAll(IEnumerable>) | argument 0 -> return | true | | System.Threading.Tasks.Task.WhenAll(params Task[]) | argument 0 -> return | true | | System.Threading.Tasks.Task.WhenAll(params Task[]) | argument 1 -> return | true | | System.Threading.Tasks.Task.WhenAny(IEnumerable>) | argument 0 -> return | true | | System.Threading.Tasks.Task.WhenAny(params Task[]) | argument 0 -> return | true | | System.Threading.Tasks.Task.WhenAny(params Task[]) | argument 1 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action, object>, object, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action>) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action>, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action>, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action>, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Action>, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, TaskContinuationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.ContinueWith(Func, object, TNewResult>, object, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action, Object>, object, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action>) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action>, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action>, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action>, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Action>, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | argument 1 -> parameter 1 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, Object, TNewResult>, object, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskContinuationOptions) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.ContinueWith(Func, TNewResult>, TaskScheduler) | qualifier -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.Task(Func, object) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.Task(Func, object) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | output from argument 0 -> return | true | +| System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func, CancellationToken, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.Task(Func, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object, CancellationToken, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.Task<>.Task(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.Task<>.get_Result() | qualifier -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func[], TResult>, TaskContinuationOptions) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action[]>) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action[]>, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action[]>, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action[]>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Action, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | @@ -1605,34 +1605,34 @@ | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory.ContinueWhenAny(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Action, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Action, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Action, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Action, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Action, object) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Action, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Action, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Action, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object) | output from argument 0 -> return | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | output from argument 0 -> return | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory.StartNew(Func, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory.StartNew(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | -| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func[], TResult>, TaskContinuationOptions) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | +| System.Threading.Tasks.TaskFactory<>.ContinueWhenAll(Task[], Func, TaskContinuationOptions) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, CancellationToken) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | @@ -1645,18 +1645,18 @@ | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, CancellationToken, TaskContinuationOptions, TaskScheduler) | output from argument 1 -> return | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | argument 0 -> parameter 0 of argument 1 | true | | System.Threading.Tasks.TaskFactory<>.ContinueWhenAny(Task[], Func, TResult>, TaskContinuationOptions) | output from argument 1 -> return | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | output from argument 0 -> return | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | output from argument 0 -> return | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | +| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | | System.Threading.Tasks.TaskFactory<>.StartNew(Func, TaskCreationOptions) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, CancellationToken, TaskCreationOptions, TaskScheduler) | output from argument 0 -> return | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | argument 1 -> parameter 0 of argument 0 | true | -| System.Threading.Tasks.TaskFactory<>.StartNew(Func, object, TaskCreationOptions) | output from argument 0 -> return | true | | System.Uri.ToString() | qualifier -> return | false | | System.Uri.Uri(string) | argument 0 -> return | false | | System.Uri.Uri(string, UriKind) | argument 0 -> return | false | diff --git a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected index fb766901ed5f..93f291abd5b0 100644 --- a/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected +++ b/csharp/ql/test/library-tests/dispatch/GetADynamicTarget.expected @@ -70,10 +70,10 @@ | ViableCallable.cs:12:9:12:28 | call to method M | C2.M(string, T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C2.M(string, T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C3.M(string, T3) | -| ViableCallable.cs:12:9:12:28 | call to method M | C4.M(int[], T3) | +| ViableCallable.cs:12:9:12:28 | call to method M | C4.M(Int32[], T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C5.M(string, T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C6.M(bool, T3) | -| ViableCallable.cs:12:9:12:28 | call to method M | C6.M(int[], T3) | +| ViableCallable.cs:12:9:12:28 | call to method M | C6.M(Int32[], T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C6.M(string, T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C6.M(string, T3) | | ViableCallable.cs:12:9:12:28 | call to method M | C6.M(string, T3) | @@ -82,10 +82,10 @@ | ViableCallable.cs:14:9:14:15 | access to property Prop | C2.set_Prop(string) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C2.set_Prop(string) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C3.set_Prop(string) | -| ViableCallable.cs:14:9:14:15 | access to property Prop | C4.set_Prop(int[]) | +| ViableCallable.cs:14:9:14:15 | access to property Prop | C4.set_Prop(Int32[]) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C5.set_Prop(string) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C6.set_Prop(bool) | -| ViableCallable.cs:14:9:14:15 | access to property Prop | C6.set_Prop(int[]) | +| ViableCallable.cs:14:9:14:15 | access to property Prop | C6.set_Prop(Int32[]) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C6.set_Prop(string) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C6.set_Prop(string) | | ViableCallable.cs:14:9:14:15 | access to property Prop | C6.set_Prop(string) | @@ -106,10 +106,10 @@ | ViableCallable.cs:16:9:16:23 | access to indexer | C2.set_Item(decimal, string) | | ViableCallable.cs:16:9:16:23 | access to indexer | C2.set_Item(int, string) | | ViableCallable.cs:16:9:16:23 | access to indexer | C3.set_Item(decimal, string) | -| ViableCallable.cs:16:9:16:23 | access to indexer | C4.set_Item(bool, int[]) | +| ViableCallable.cs:16:9:16:23 | access to indexer | C4.set_Item(bool, Int32[]) | | ViableCallable.cs:16:9:16:23 | access to indexer | C5.set_Item(bool, string) | | ViableCallable.cs:16:9:16:23 | access to indexer | C6.set_Item(byte, bool) | -| ViableCallable.cs:16:9:16:23 | access to indexer | C6.set_Item(bool, int[]) | +| ViableCallable.cs:16:9:16:23 | access to indexer | C6.set_Item(bool, Int32[]) | | ViableCallable.cs:16:9:16:23 | access to indexer | C6.set_Item(bool, string) | | ViableCallable.cs:16:9:16:23 | access to indexer | C6.set_Item(decimal, string) | | ViableCallable.cs:16:9:16:23 | access to indexer | C6.set_Item(int, string) | @@ -126,45 +126,45 @@ | ViableCallable.cs:16:27:16:41 | access to indexer | C6.get_Item(decimal) | | ViableCallable.cs:16:27:16:41 | access to indexer | C6.get_Item(int) | | ViableCallable.cs:16:27:16:41 | access to indexer | C7.get_Item(byte) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C2.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C2.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C2.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C3.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C4.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C5.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:18:9:18:16 | access to event Event | C7.add_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C2.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C2.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C2.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C3.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C4.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C5.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:19:9:19:16 | access to event Event | C7.remove_Event(EventHandler) | -| ViableCallable.cs:22:9:22:30 | call to method M | C4.M(int[], T3) | -| ViableCallable.cs:22:9:22:30 | call to method M | C6.M(int[], T3) | -| ViableCallable.cs:24:9:24:15 | access to property Prop | C4.set_Prop(int[]) | -| ViableCallable.cs:24:9:24:15 | access to property Prop | C6.set_Prop(int[]) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C2.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C2.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C2.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C3.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C4.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C5.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:18:9:18:16 | access to event Event | C7.add_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C2.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C2.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C2.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C3.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C4.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C5.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:19:9:19:16 | access to event Event | C7.remove_Event(EventHandler) | +| ViableCallable.cs:22:9:22:30 | call to method M | C4.M(Int32[], T3) | +| ViableCallable.cs:22:9:22:30 | call to method M | C6.M(Int32[], T3) | +| ViableCallable.cs:24:9:24:15 | access to property Prop | C4.set_Prop(Int32[]) | +| ViableCallable.cs:24:9:24:15 | access to property Prop | C6.set_Prop(Int32[]) | | ViableCallable.cs:24:19:24:25 | access to property Prop | C4.get_Prop() | | ViableCallable.cs:24:19:24:25 | access to property Prop | C6.get_Prop() | -| ViableCallable.cs:26:9:26:23 | access to indexer | C4.set_Item(bool, int[]) | -| ViableCallable.cs:26:9:26:23 | access to indexer | C6.set_Item(bool, int[]) | +| ViableCallable.cs:26:9:26:23 | access to indexer | C4.set_Item(bool, Int32[]) | +| ViableCallable.cs:26:9:26:23 | access to indexer | C6.set_Item(bool, Int32[]) | | ViableCallable.cs:26:27:26:41 | access to indexer | C4.get_Item(bool) | | ViableCallable.cs:26:27:26:41 | access to indexer | C6.get_Item(bool) | -| ViableCallable.cs:28:9:28:16 | access to event Event | C4.add_Event(EventHandler) | -| ViableCallable.cs:28:9:28:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:29:9:29:16 | access to event Event | C4.remove_Event(EventHandler) | -| ViableCallable.cs:29:9:29:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:32:30:32:52 | call to method Mock | ViableCallable.Mock>() | +| ViableCallable.cs:28:9:28:16 | access to event Event | C4.add_Event(EventHandler) | +| ViableCallable.cs:28:9:28:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:29:9:29:16 | access to event Event | C4.remove_Event(EventHandler) | +| ViableCallable.cs:29:9:29:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:32:30:32:52 | call to method Mock | ViableCallable.Mock>() | | ViableCallable.cs:33:9:33:23 | call to method M | C2.M(string, T3) | | ViableCallable.cs:33:9:33:23 | call to method M | C6.M(string, T3) | | ViableCallable.cs:35:9:35:15 | access to property Prop | C2.set_Prop(string) | @@ -175,11 +175,11 @@ | ViableCallable.cs:37:9:37:13 | access to indexer | C6.set_Item(int, string) | | ViableCallable.cs:37:17:37:21 | access to indexer | C2.get_Item(int) | | ViableCallable.cs:37:17:37:21 | access to indexer | C6.get_Item(int) | -| ViableCallable.cs:39:9:39:16 | access to event Event | C2.add_Event(EventHandler) | -| ViableCallable.cs:39:9:39:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:40:9:40:16 | access to event Event | C2.remove_Event(EventHandler) | -| ViableCallable.cs:40:9:40:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:43:34:43:60 | call to method Mock | ViableCallable.Mock>() | +| ViableCallable.cs:39:9:39:16 | access to event Event | C2.add_Event(EventHandler) | +| ViableCallable.cs:39:9:39:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:40:9:40:16 | access to event Event | C2.remove_Event(EventHandler) | +| ViableCallable.cs:40:9:40:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:43:34:43:60 | call to method Mock | ViableCallable.Mock>() | | ViableCallable.cs:44:9:44:24 | call to method M | C2.M(string, T3) | | ViableCallable.cs:44:9:44:24 | call to method M | C3.M(string, T3) | | ViableCallable.cs:44:9:44:24 | call to method M | C6.M(string, T3) | @@ -195,28 +195,28 @@ | ViableCallable.cs:48:18:48:23 | access to indexer | C2.get_Item(decimal) | | ViableCallable.cs:48:18:48:23 | access to indexer | C3.get_Item(decimal) | | ViableCallable.cs:48:18:48:23 | access to indexer | C6.get_Item(decimal) | -| ViableCallable.cs:50:9:50:16 | access to event Event | C2.add_Event(EventHandler) | -| ViableCallable.cs:50:9:50:16 | access to event Event | C3.add_Event(EventHandler) | -| ViableCallable.cs:50:9:50:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:51:9:51:16 | access to event Event | C2.remove_Event(EventHandler) | -| ViableCallable.cs:51:9:51:16 | access to event Event | C3.remove_Event(EventHandler) | -| ViableCallable.cs:51:9:51:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:54:30:54:52 | call to method Mock | ViableCallable.Mock>() | -| ViableCallable.cs:55:9:55:44 | call to method M | C4.M(int[], T3) | -| ViableCallable.cs:55:9:55:44 | call to method M | C6.M(int[], T3) | -| ViableCallable.cs:57:9:57:15 | access to property Prop | C4.set_Prop(int[]) | -| ViableCallable.cs:57:9:57:15 | access to property Prop | C6.set_Prop(int[]) | +| ViableCallable.cs:50:9:50:16 | access to event Event | C2.add_Event(EventHandler) | +| ViableCallable.cs:50:9:50:16 | access to event Event | C3.add_Event(EventHandler) | +| ViableCallable.cs:50:9:50:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:51:9:51:16 | access to event Event | C2.remove_Event(EventHandler) | +| ViableCallable.cs:51:9:51:16 | access to event Event | C3.remove_Event(EventHandler) | +| ViableCallable.cs:51:9:51:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:54:30:54:52 | call to method Mock | ViableCallable.Mock>() | +| ViableCallable.cs:55:9:55:44 | call to method M | C4.M(Int32[], T3) | +| ViableCallable.cs:55:9:55:44 | call to method M | C6.M(Int32[], T3) | +| ViableCallable.cs:57:9:57:15 | access to property Prop | C4.set_Prop(Int32[]) | +| ViableCallable.cs:57:9:57:15 | access to property Prop | C6.set_Prop(Int32[]) | | ViableCallable.cs:57:19:57:25 | access to property Prop | C4.get_Prop() | | ViableCallable.cs:57:19:57:25 | access to property Prop | C6.get_Prop() | -| ViableCallable.cs:59:9:59:17 | access to indexer | C4.set_Item(bool, int[]) | -| ViableCallable.cs:59:9:59:17 | access to indexer | C6.set_Item(bool, int[]) | +| ViableCallable.cs:59:9:59:17 | access to indexer | C4.set_Item(bool, Int32[]) | +| ViableCallable.cs:59:9:59:17 | access to indexer | C6.set_Item(bool, Int32[]) | | ViableCallable.cs:59:21:59:29 | access to indexer | C4.get_Item(bool) | | ViableCallable.cs:59:21:59:29 | access to indexer | C6.get_Item(bool) | -| ViableCallable.cs:61:9:61:16 | access to event Event | C4.add_Event(EventHandler) | -| ViableCallable.cs:61:9:61:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:62:9:62:16 | access to event Event | C4.remove_Event(EventHandler) | -| ViableCallable.cs:62:9:62:16 | access to event Event | C6.remove_Event(EventHandler) | -| ViableCallable.cs:65:31:65:54 | call to method Mock | ViableCallable.Mock>() | +| ViableCallable.cs:61:9:61:16 | access to event Event | C4.add_Event(EventHandler) | +| ViableCallable.cs:61:9:61:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:62:9:62:16 | access to event Event | C4.remove_Event(EventHandler) | +| ViableCallable.cs:62:9:62:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:65:31:65:54 | call to method Mock | ViableCallable.Mock>() | | ViableCallable.cs:66:9:66:30 | call to method M | C2.M(string, T3) | | ViableCallable.cs:66:9:66:30 | call to method M | C5.M(string, T3) | | ViableCallable.cs:66:9:66:30 | call to method M | C6.M(string, T3) | @@ -232,12 +232,12 @@ | ViableCallable.cs:70:21:70:29 | access to indexer | C2.get_Item(bool) | | ViableCallable.cs:70:21:70:29 | access to indexer | C5.get_Item(bool) | | ViableCallable.cs:70:21:70:29 | access to indexer | C6.get_Item(bool) | -| ViableCallable.cs:72:9:72:16 | access to event Event | C2.add_Event(EventHandler) | -| ViableCallable.cs:72:9:72:16 | access to event Event | C5.add_Event(EventHandler) | -| ViableCallable.cs:72:9:72:16 | access to event Event | C6.add_Event(EventHandler) | -| ViableCallable.cs:73:9:73:16 | access to event Event | C2.remove_Event(EventHandler) | -| ViableCallable.cs:73:9:73:16 | access to event Event | C5.remove_Event(EventHandler) | -| ViableCallable.cs:73:9:73:16 | access to event Event | C6.remove_Event(EventHandler) | +| ViableCallable.cs:72:9:72:16 | access to event Event | C2.add_Event(EventHandler) | +| ViableCallable.cs:72:9:72:16 | access to event Event | C5.add_Event(EventHandler) | +| ViableCallable.cs:72:9:72:16 | access to event Event | C6.add_Event(EventHandler) | +| ViableCallable.cs:73:9:73:16 | access to event Event | C2.remove_Event(EventHandler) | +| ViableCallable.cs:73:9:73:16 | access to event Event | C5.remove_Event(EventHandler) | +| ViableCallable.cs:73:9:73:16 | access to event Event | C6.remove_Event(EventHandler) | | ViableCallable.cs:77:9:77:29 | call to method M | C6.M(T1, T3) | | ViableCallable.cs:79:9:79:15 | access to property Prop | C6.set_Prop(T1) | | ViableCallable.cs:79:19:79:25 | access to property Prop | C6.get_Prop() | @@ -246,9 +246,9 @@ | ViableCallable.cs:83:9:83:16 | access to event Event | C6.add_Event(EventHandler) | | ViableCallable.cs:84:9:84:16 | access to event Event | C6.remove_Event(EventHandler) | | ViableCallable.cs:87:21:87:30 | call to method Mock | ViableCallable.Mock() | -| ViableCallable.cs:88:9:88:44 | dynamic call to method M | C8.M(IEnumerable>) | -| ViableCallable.cs:88:9:88:44 | dynamic call to method M | C9<>.M(IEnumerable>) | -| ViableCallable.cs:88:13:88:43 | call to method Mock | ViableCallable.Mock>>() | +| ViableCallable.cs:88:9:88:44 | dynamic call to method M | C8.M(IEnumerable>) | +| ViableCallable.cs:88:9:88:44 | dynamic call to method M | C9<>.M(IEnumerable>) | +| ViableCallable.cs:88:13:88:43 | call to method Mock | ViableCallable.Mock>>() | | ViableCallable.cs:90:9:90:15 | dynamic access to member Prop1 | C8.set_Prop1(string) | | ViableCallable.cs:90:9:90:15 | dynamic access to member Prop1 | C9<>.set_Prop1(string) | | ViableCallable.cs:90:19:90:25 | dynamic access to member Prop1 | C8.get_Prop1() | @@ -257,13 +257,13 @@ | ViableCallable.cs:92:9:92:12 | dynamic access to element | C9<>.set_Item(int, string) | | ViableCallable.cs:92:16:92:19 | dynamic access to element | C8.get_Item(int) | | ViableCallable.cs:92:16:92:19 | dynamic access to element | C9<>.get_Item(int) | -| ViableCallable.cs:95:13:95:40 | call to method Mock | ViableCallable.Mock>>() | +| ViableCallable.cs:95:13:95:40 | call to method Mock | ViableCallable.Mock>>() | | ViableCallable.cs:99:9:99:15 | dynamic call to method M | C5.M(int) | | ViableCallable.cs:102:9:102:16 | access to property Prop2 | C5.set_Prop2(string) | -| ViableCallable.cs:105:9:105:17 | access to event Event2 | C5.add_Event2(EventHandler) | -| ViableCallable.cs:106:9:106:17 | access to event Event2 | C5.remove_Event2(EventHandler) | -| ViableCallable.cs:120:9:120:25 | dynamic call to method M2 | C8.M2(decimal[]) | -| ViableCallable.cs:124:9:124:24 | dynamic call to method M2 | C8.M2(string[]) | +| ViableCallable.cs:105:9:105:17 | access to event Event2 | C5.add_Event2(EventHandler) | +| ViableCallable.cs:106:9:106:17 | access to event Event2 | C5.remove_Event2(EventHandler) | +| ViableCallable.cs:120:9:120:25 | dynamic call to method M2 | C8.M2(Decimal[]) | +| ViableCallable.cs:124:9:124:24 | dynamic call to method M2 | C8.M2(String[]) | | ViableCallable.cs:132:9:132:28 | dynamic call to method M | C6.M(T1, T3) | | ViableCallable.cs:134:9:134:14 | dynamic access to member Prop | C6.set_Prop(T1) | | ViableCallable.cs:134:18:134:23 | dynamic access to member Prop | C6.get_Prop() | @@ -272,23 +272,23 @@ | ViableCallable.cs:138:9:138:52 | ... += ... | C6.add_Event(EventHandler) | | ViableCallable.cs:139:9:139:52 | ... -= ... | C6.remove_Event(EventHandler) | | ViableCallable.cs:143:13:143:22 | call to method Mock | ViableCallable.Mock() | -| ViableCallable.cs:144:9:144:14 | dynamic call to method M3 | C8.M3(params double[]) | +| ViableCallable.cs:144:9:144:14 | dynamic call to method M3 | C8.M3(params Double[]) | | ViableCallable.cs:144:9:144:14 | dynamic call to method M3 | C9<>.M3(params T[]) | -| ViableCallable.cs:145:9:145:15 | dynamic call to method M3 | C8.M3(params double[]) | +| ViableCallable.cs:145:9:145:15 | dynamic call to method M3 | C8.M3(params Double[]) | | ViableCallable.cs:145:9:145:15 | dynamic call to method M3 | C9<>.M3(params T[]) | -| ViableCallable.cs:146:9:146:20 | dynamic call to method M3 | C8.M3(params double[]) | +| ViableCallable.cs:146:9:146:20 | dynamic call to method M3 | C8.M3(params Double[]) | | ViableCallable.cs:146:9:146:20 | dynamic call to method M3 | C9<>.M3(params T[]) | -| ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | C8.M3(params double[]) | +| ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | C8.M3(params Double[]) | | ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | C9<>.M3(params T[]) | -| ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | C10.M3(params double[]) | +| ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | C10.M3(params Double[]) | | ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | Test.MainClass.ImplAlpha.M3() | | ViableCallable.cs:149:9:149:16 | dynamic call to method M3 | Test.MainClass.SecondLevelImpl.M3() | -| ViableCallable.cs:150:9:150:17 | dynamic call to method M3 | C8.M3(params double[]) | +| ViableCallable.cs:150:9:150:17 | dynamic call to method M3 | C8.M3(params Double[]) | | ViableCallable.cs:150:9:150:17 | dynamic call to method M3 | C9<>.M3(params T[]) | -| ViableCallable.cs:150:9:150:17 | dynamic call to method M3 | C10.M3(params double[]) | -| ViableCallable.cs:151:9:151:22 | dynamic call to method M3 | C8.M3(params double[]) | +| ViableCallable.cs:150:9:150:17 | dynamic call to method M3 | C10.M3(params Double[]) | +| ViableCallable.cs:151:9:151:22 | dynamic call to method M3 | C8.M3(params Double[]) | | ViableCallable.cs:151:9:151:22 | dynamic call to method M3 | C9<>.M3(params T[]) | -| ViableCallable.cs:151:9:151:22 | dynamic call to method M3 | C10.M3(params double[]) | +| ViableCallable.cs:151:9:151:22 | dynamic call to method M3 | C10.M3(params Double[]) | | ViableCallable.cs:153:9:153:17 | dynamic access to member Prop1 | C8.set_Prop1(string) | | ViableCallable.cs:153:9:153:17 | dynamic access to member Prop1 | C9<>.set_Prop1(string) | | ViableCallable.cs:153:9:153:17 | dynamic access to member Prop1 | C10.set_Prop1(bool) | @@ -323,39 +323,39 @@ | ViableCallable.cs:155:18:155:23 | dynamic access to element | C8.get_Item(int) | | ViableCallable.cs:155:18:155:23 | dynamic access to element | C9<>.get_Item(int) | | ViableCallable.cs:155:18:155:23 | dynamic access to element | C10.get_Item(int) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C2<>.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C2.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C2.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C2.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C3.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C5.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C2<>.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C2.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C2.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C2.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C3.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C5.add_Event(EventHandler) | | ViableCallable.cs:157:9:157:54 | ... += ... | C6<,>.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | | ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | | ViableCallable.cs:157:9:157:54 | ... += ... | C6.add_Event(EventHandler) | | ViableCallable.cs:157:9:157:54 | ... += ... | C7<>.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C8.add_Event(EventHandler) | -| ViableCallable.cs:157:9:157:54 | ... += ... | C9<>.add_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C2<>.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C2.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C2.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C2.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C3.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C5.remove_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C8.add_Event(EventHandler) | +| ViableCallable.cs:157:9:157:54 | ... += ... | C9<>.add_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C2<>.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C2.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C2.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C2.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C3.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C5.remove_Event(EventHandler) | | ViableCallable.cs:158:9:158:54 | ... -= ... | C6<,>.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | | ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | | ViableCallable.cs:158:9:158:54 | ... -= ... | C6.remove_Event(EventHandler) | | ViableCallable.cs:158:9:158:54 | ... -= ... | C7<>.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C8.remove_Event(EventHandler) | -| ViableCallable.cs:158:9:158:54 | ... -= ... | C9<>.remove_Event(EventHandler) | -| ViableCallable.cs:161:9:161:40 | dynamic call to method M4 | C8.M4(byte, IEnumerable) | -| ViableCallable.cs:161:19:161:39 | call to method Mock | ViableCallable.Mock>() | -| ViableCallable.cs:162:9:162:38 | dynamic call to method M4 | C8.M4(byte, IEnumerable) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C8.remove_Event(EventHandler) | +| ViableCallable.cs:158:9:158:54 | ... -= ... | C9<>.remove_Event(EventHandler) | +| ViableCallable.cs:161:9:161:40 | dynamic call to method M4 | C8.M4(byte, IEnumerable) | +| ViableCallable.cs:161:19:161:39 | call to method Mock | ViableCallable.Mock>() | +| ViableCallable.cs:162:9:162:38 | dynamic call to method M4 | C8.M4(byte, IEnumerable) | | ViableCallable.cs:165:9:165:17 | dynamic access to member Prop1 | C10.set_Prop1(bool) | | ViableCallable.cs:175:9:175:15 | dynamic access to element | C2<>.set_Item(T, string) | | ViableCallable.cs:175:9:175:15 | dynamic access to element | C6<,>.set_Item(T2, T1) | @@ -366,16 +366,16 @@ | ViableCallable.cs:191:9:191:149 | call to method InvokeMember | C10.set_Prop3(string) | | ViableCallable.cs:194:9:194:146 | call to method InvokeMember | C10.get_Item(int) | | ViableCallable.cs:195:9:195:152 | call to method InvokeMember | C10.set_Item(int, bool) | -| ViableCallable.cs:199:9:199:147 | call to method InvokeMember | C10.add_Event(EventHandler) | -| ViableCallable.cs:200:9:200:150 | call to method InvokeMember | C10.remove_Event(EventHandler) | +| ViableCallable.cs:199:9:199:147 | call to method InvokeMember | C10.add_Event(EventHandler) | +| ViableCallable.cs:200:9:200:150 | call to method InvokeMember | C10.remove_Event(EventHandler) | | ViableCallable.cs:235:9:235:15 | call to method M | C2.M(string, T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C2.M(string, T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C2.M(string, T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C3.M(string, T3) | -| ViableCallable.cs:235:9:235:15 | call to method M | C4.M(int[], T3) | +| ViableCallable.cs:235:9:235:15 | call to method M | C4.M(Int32[], T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C5.M(string, T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C6.M(bool, T3) | -| ViableCallable.cs:235:9:235:15 | call to method M | C6.M(int[], T3) | +| ViableCallable.cs:235:9:235:15 | call to method M | C6.M(Int32[], T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C6.M(string, T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C6.M(string, T3) | | ViableCallable.cs:235:9:235:15 | call to method M | C6.M(string, T3) | diff --git a/csharp/ql/test/library-tests/frameworks/format/StringFormatItemParameter.expected b/csharp/ql/test/library-tests/frameworks/format/StringFormatItemParameter.expected index 456d7bbea6d8..85e2d82f3ab2 100644 --- a/csharp/ql/test/library-tests/frameworks/format/StringFormatItemParameter.expected +++ b/csharp/ql/test/library-tests/frameworks/format/StringFormatItemParameter.expected @@ -4,57 +4,57 @@ | Console | Write(string, object, object, object) | arg0 | | Console | Write(string, object, object, object) | arg1 | | Console | Write(string, object, object, object) | arg2 | -| Console | Write(string, params object[]) | arg | +| Console | Write(string, params Object[]) | arg | | Console | WriteLine(string, object) | arg0 | | Console | WriteLine(string, object, object) | arg0 | | Console | WriteLine(string, object, object) | arg1 | | Console | WriteLine(string, object, object, object) | arg0 | | Console | WriteLine(string, object, object, object) | arg1 | | Console | WriteLine(string, object, object, object) | arg2 | -| Console | WriteLine(string, params object[]) | arg | -| Debug | Assert(bool, string, string, params object[]) | args | -| Debug | Print(string, params object[]) | args | -| Debug | WriteLine(string, params object[]) | args | +| Console | WriteLine(string, params Object[]) | arg | +| Debug | Assert(bool, string, string, params Object[]) | args | +| Debug | Print(string, params Object[]) | args | +| Debug | WriteLine(string, params Object[]) | args | | StringBuilder | AppendFormat(IFormatProvider, string, object) | arg0 | | StringBuilder | AppendFormat(IFormatProvider, string, object, object) | arg0 | | StringBuilder | AppendFormat(IFormatProvider, string, object, object) | arg1 | | StringBuilder | AppendFormat(IFormatProvider, string, object, object, object) | arg0 | | StringBuilder | AppendFormat(IFormatProvider, string, object, object, object) | arg1 | | StringBuilder | AppendFormat(IFormatProvider, string, object, object, object) | arg2 | -| StringBuilder | AppendFormat(IFormatProvider, string, params object[]) | args | +| StringBuilder | AppendFormat(IFormatProvider, string, params Object[]) | args | | StringBuilder | AppendFormat(string, object) | arg0 | | StringBuilder | AppendFormat(string, object, object) | arg0 | | StringBuilder | AppendFormat(string, object, object) | arg1 | | StringBuilder | AppendFormat(string, object, object, object) | arg0 | | StringBuilder | AppendFormat(string, object, object, object) | arg1 | | StringBuilder | AppendFormat(string, object, object, object) | arg2 | -| StringBuilder | AppendFormat(string, params object[]) | args | -| Strings | MyStringFormat(string, params object[]) | args | +| StringBuilder | AppendFormat(string, params Object[]) | args | +| Strings | MyStringFormat(string, params Object[]) | args | | TextWriter | Write(string, object) | arg0 | | TextWriter | Write(string, object, object) | arg0 | | TextWriter | Write(string, object, object) | arg1 | | TextWriter | Write(string, object, object, object) | arg0 | | TextWriter | Write(string, object, object, object) | arg1 | | TextWriter | Write(string, object, object, object) | arg2 | -| TextWriter | Write(string, params object[]) | arg | +| TextWriter | Write(string, params Object[]) | arg | | TextWriter | WriteLine(string, object) | arg0 | | TextWriter | WriteLine(string, object, object) | arg0 | | TextWriter | WriteLine(string, object, object) | arg1 | | TextWriter | WriteLine(string, object, object, object) | arg0 | | TextWriter | WriteLine(string, object, object, object) | arg1 | | TextWriter | WriteLine(string, object, object, object) | arg2 | -| TextWriter | WriteLine(string, params object[]) | arg | +| TextWriter | WriteLine(string, params Object[]) | arg | | string | Format(IFormatProvider, string, object) | arg0 | | string | Format(IFormatProvider, string, object, object) | arg0 | | string | Format(IFormatProvider, string, object, object) | arg1 | | string | Format(IFormatProvider, string, object, object, object) | arg0 | | string | Format(IFormatProvider, string, object, object, object) | arg1 | | string | Format(IFormatProvider, string, object, object, object) | arg2 | -| string | Format(IFormatProvider, string, params object[]) | args | +| string | Format(IFormatProvider, string, params Object[]) | args | | string | Format(string, object) | arg0 | | string | Format(string, object, object) | arg0 | | string | Format(string, object, object) | arg1 | | string | Format(string, object, object, object) | arg0 | | string | Format(string, object, object, object) | arg1 | | string | Format(string, object, object, object) | arg2 | -| string | Format(string, params object[]) | args | +| string | Format(string, params Object[]) | args | diff --git a/csharp/ql/test/library-tests/methods/Parameters9.expected b/csharp/ql/test/library-tests/methods/Parameters9.expected index 66c1f42c7fd4..2af714b9abcc 100644 --- a/csharp/ql/test/library-tests/methods/Parameters9.expected +++ b/csharp/ql/test/library-tests/methods/Parameters9.expected @@ -3,5 +3,5 @@ | methods.cs:145:65:145:65 | e | methods.cs:145:69:145:77 | ... + ... | Method2(int, int, int, int, string) | | methods.cs:168:51:168:55 | right | methods.cs:168:59:168:59 | 0 | Plus(int, int) | | methods.cs:173:133:173:133 | i | methods.cs:173:137:173:137 | 1 | SkipTwo(IEnumerable, int) | -| methods.cs:173:133:173:133 | i | methods.cs:173:137:173:137 | 1 | SkipTwo(IEnumerable, int) | -| methods.cs:178:137:178:137 | i | methods.cs:178:141:178:141 | 1 | SkipTwoInt(IEnumerable, int) | +| methods.cs:173:133:173:133 | i | methods.cs:173:137:173:137 | 1 | SkipTwo(IEnumerable, int) | +| methods.cs:178:137:178:137 | i | methods.cs:178:141:178:141 | 1 | SkipTwoInt(IEnumerable, int) | diff --git a/csharp/ql/test/library-tests/overrides/Overrides22.expected b/csharp/ql/test/library-tests/overrides/Overrides22.expected index cef719c8adda..11bb9d46cbdc 100644 --- a/csharp/ql/test/library-tests/overrides/Overrides22.expected +++ b/csharp/ql/test/library-tests/overrides/Overrides22.expected @@ -2,15 +2,15 @@ | CallTargets.C3.m() | CallTargets.C2.m() | overrides | | overrides.A1.Event | overrides.I5.Event | implements | | overrides.A1.Item[int] | overrides.I5.Item[int] | implements | -| overrides.A1.M(dynamic[], T) | overrides.I2.M(object[], S) | implements | +| overrides.A1.M(dynamic[], T) | overrides.I2.M(Object[], S) | implements | | overrides.A1.Property | overrides.I5.Property | implements | | overrides.A4.Event | overrides.I5.Event | implements | | overrides.A4.Item[int] | overrides.I5.Item[int] | implements | -| overrides.A4.M(dynamic[], T) | overrides.I2.M(object[], S) | implements | +| overrides.A4.M(dynamic[], T) | overrides.I2.M(Object[], S) | implements | | overrides.A4.Property | overrides.I5.Property | implements | | overrides.A6.Event | overrides.I5.Event | implements | | overrides.A6.Item[int] | overrides.I5.Item[int] | implements | -| overrides.A6.M(object[], T) | overrides.I2.M(object[], S) | implements | +| overrides.A6.M(Object[], T) | overrides.I2.M(Object[], S) | implements | | overrides.A6.Property | overrides.I5.Property | implements | | overrides.A8.Event | overrides.A1.Event | overrides | | overrides.A8.Item[int] | overrides.A1.Item[int] | overrides | diff --git a/csharp/ql/test/library-tests/tostringwithtypes/toStringWithTypes.expected b/csharp/ql/test/library-tests/tostringwithtypes/toStringWithTypes.expected index 228694785c6f..2dd28b7214d4 100644 --- a/csharp/ql/test/library-tests/tostringwithtypes/toStringWithTypes.expected +++ b/csharp/ql/test/library-tests/tostringwithtypes/toStringWithTypes.expected @@ -1,7 +1,7 @@ | Delegate<> | Delegate(int, T) | -| Delegate | Delegate | | Item | Item[T, bool] | -| M | M(IEnumerable) | +| M | M(IEnumerable) | +| M | M(Int32[,,,][][,][,,]) | | M | M(__arglist) | | M | M(bool) | | M | M(byte) | @@ -13,7 +13,6 @@ | M | M(float) | | M | M(int) | | M | M(int*) | -| M | M(int[,,,][][,][,,]) | | M | M(long) | | M | M(object) | | M | M(out T) | @@ -27,6 +26,6 @@ | M | M(ref S) | | M | M(ref char?) | | ToStringWithTypes<> | ToStringWithTypes | -| add_Event | add_Event(Delegate) | +| add_Event | add_Event(Delegate) | | get_Item | get_Item(T, bool) | -| remove_Event | remove_Event(Delegate) | +| remove_Event | remove_Event(Delegate) | From 41b441614b31c7cacf864689d6db1f60991d1385 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Mon, 11 Nov 2019 18:47:46 +0000 Subject: [PATCH 0356/2538] C#: Address review comments part 1. --- .../Entities/Method.cs | 6 +- .../Entities/Types/Nullability.cs | 4 +- .../src/semmle/code/csharp/AnnotatedType.qll | 104 ++++++++++-------- 3 files changed, 63 insertions(+), 51 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs index f3a9a9f0d084..abd104be156e 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Method.cs @@ -264,7 +264,7 @@ public static Method Create(Context cx, IMethodSymbol methodDecl) var methodKind = methodDecl.MethodKind; - if(methodKind == MethodKind.ExplicitInterfaceImplementation) + if (methodKind == MethodKind.ExplicitInterfaceImplementation) { // Retrieve the original method kind methodKind = methodDecl.ExplicitInterfaceImplementations.Select(m => m.MethodKind).FirstOrDefault(); @@ -348,7 +348,9 @@ protected void PopulateGenerics(TextWriter trapFile) child++; } - trapFile.type_nullability(this, NullabilityEntity.Create(Context, new Nullability(symbol))); + var nullability = new Nullability(symbol); + if (!nullability.IsOblivious) + trapFile.type_nullability(this, NullabilityEntity.Create(Context, nullability)); } else { diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs index 4dc0a9046aa6..084ac570fa0a 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs @@ -30,6 +30,8 @@ public static Nullability Create(AnnotatedTypeSymbol ts) return new Nullability(ts); } + public bool IsOblivious => Annotation == 0 && NullableParameters.Length == 0; + static readonly Nullability oblivious = new Nullability(NullableAnnotation.Disabled); static readonly Nullability annotated = new Nullability(NullableAnnotation.Annotated); static readonly Nullability notannotated = new Nullability(NullableAnnotation.NotAnnotated); @@ -113,7 +115,7 @@ public override void Populate(TextWriter trapFile) trapFile.nullability(this, symbol.Annotation); int i = 0; - foreach(var s in symbol.NullableParameters) + foreach (var s in symbol.NullableParameters) { trapFile.nullability_member(this, i, Create(Context, s)); i++; diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index 98e25aa7524b..d1146f5ea1ed 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -18,7 +18,7 @@ private module Annotations { /** An annotation on a type. */ class TypeAnnotation extends TAnnotation { /** Gets the bit position in the bit-field, also used to order the annotations in the text format. */ - abstract int getBit(); + int getBit() { none() } /** Gets the string prefixing the type, if any. */ string getPrefix() { none() } @@ -57,6 +57,41 @@ private module Annotations { override int getBit() { result = 6 } } + /** + * A structured type annotation representing type nullability. + * For example, `IDictionary?` has nullability `?`. + */ + class Nullability extends TypeAnnotation, TNullability { + @nullability nullability; + + Nullability() { this = TNullability(nullability) } + + override string toString() { result = getMemberString() + getSelfNullability() } + + language[monotonicAggregates] + private string getMemberString() { + if nullability_member(nullability, _, _) + then + result = "<" + + concat(int i, Nullability child | + nullability_member(nullability, i, getNullability(child)) + | + child.toString(), "," order by i + ) + ">" + else result = "" + } + + /** + * Gets a string representing the nullability, disregarding child nullability. + * For example, `IDictionary?` has nullability `?`. + */ + string getSelfNullability() { none() } + + override int getBit() { none() } + } + + @nullability getNullability(Nullability n) { n = TNullability(result) } + private newtype TAnnotations = TAnnotationFlags(int flags, Nullability n) { exists(Element e | @@ -75,9 +110,6 @@ private module Annotations { this = TAnnotationsNoFlags(result) } - /** Gets the nullability with no additional flags. */ - Nullability getNoFlagsNullability() { this = TAnnotationsNoFlags(result) } - /** Gets text to be displayed before the type. */ string getTypePrefix() { result = concat(TypeAnnotation a | @@ -114,6 +146,11 @@ private module Annotations { } } + /** Gets the nullability with no additional flags. */ + Nullability getNoFlagsNullability(TypeAnnotations annotations) { + annotations = TAnnotationsNoFlags(result) + } + /** * Gets the `i`th child of type annotations `annotations`. * This is used to represent structured datatypes, where the structure @@ -121,37 +158,7 @@ private module Annotations { */ bindingset[i] TypeAnnotations getChild(TypeAnnotations annotations, int i) { - result.getNoFlagsNullability() = getChildNullability(annotations.getNullability(), i) - } - - /** - * A structured type annotation representing type nullability. - * For example, `IDictionary?` has nullability `?`. - */ - abstract class Nullability extends TypeAnnotation, TNullability { - @nullability nullability; - - Nullability() { this = TNullability(nullability) } - - @nullability getNullability() { result = nullability } - - override string toString() { result = getMemberString() + getSelfNullability() } - - language[monotonicAggregates] - private string getMemberString() { - if nullability_member(nullability, _, _) - then - result = "<" + - concat(int i, Nullability child | - nullability_member(nullability, i, child.getNullability()) - | - child.toString(), "," order by i - ) + ">" - else result = "" - } - - /** Gets a string representing the nullability, disregarding child nullability. */ - string getSelfNullability() { none() } + getNoFlagsNullability(result) = getChildNullability(annotations.getNullability(), i) } /** @@ -162,8 +169,8 @@ private module Annotations { */ bindingset[i] Nullability getChildNullability(Nullability n, int i) { - if nullability_member(n.getNullability(), i, _) - then nullability_member(n.getNullability(), i, result.getNullability()) + if nullability_member(getNullability(n), i, _) + then nullability_member(getNullability(n), i, getNullability(result)) else result = n } @@ -176,8 +183,6 @@ private module Annotations { ObliviousNullability() { nullability instanceof @oblivious } override string getSelfNullability() { result = "_" } - - override int getBit() { none() } } /** @@ -220,7 +225,7 @@ private module Annotations { annotations = TAnnotationFlags(getElementTypeFlags(element), getElementNullability(element)) or not exists(getElementTypeFlags(element)) and - annotations.getNoFlagsNullability() = getElementNullability(element) + getNoFlagsNullability(annotations) = getElementNullability(element) ) and ( type = element.(Assignable).getType() @@ -250,16 +255,18 @@ private Annotations::Nullability getTypeParameterNullability( TypeParameterConstraints constraints, Type type ) { if specific_type_parameter_nullability(constraints, getTypeRef(type), _) - then specific_type_parameter_nullability(constraints, getTypeRef(type), result.getNullability()) + then + specific_type_parameter_nullability(constraints, getTypeRef(type), + Annotations::getNullability(result)) else ( - specific_type_parameter_constraints(constraints, type) and + specific_type_parameter_constraints(constraints, getTypeRef(type)) and result instanceof Annotations::NoNullability ) } private Annotations::Nullability getElementNullability(@has_type_annotation element) { if type_nullability(element, _) - then type_nullability(element, result.getNullability()) + then type_nullability(element, Annotations::getNullability(result)) else result instanceof Annotations::NoNullability } @@ -272,10 +279,10 @@ private newtype TAnnotatedType = annotations = Annotations::getChild(c.getAnnotations(), i) ) or - annotations.getNoFlagsNullability() = getTypeParameterNullability(_, type) + Annotations::getNoFlagsNullability(annotations) = getTypeParameterNullability(_, type) or // All types have at least one annotated type - annotations.getNoFlagsNullability() instanceof Annotations::NoNullability + Annotations::getNoFlagsNullability(annotations) instanceof Annotations::NoNullability or exists(AnnotatedArrayType at | type = at.getType().(ArrayType).getElementType() and @@ -344,16 +351,17 @@ class AnnotatedType extends TAnnotatedType { /** Holds if this annotated type applies to element `e`. */ predicate appliesTo(Element e) { Annotations::elementTypeAnnotations(e, type, annotations) } - /** Holds if this annotated type is the `ith` type argument of constructed generic 'g'. */ + /** Holds if this annotated type is the `i`th type argument of constructed generic 'g'. */ predicate appliesToTypeArgument(ConstructedGeneric g, int i) { - this.getAnnotations().getNoFlagsNullability() = Annotations::getChildNullability(getElementNullability(g), + Annotations::getNoFlagsNullability(this.getAnnotations()) = Annotations::getChildNullability(getElementNullability(g), i) and this.getType() = g.getTypeArgument(i) } /** Holds if this annotated type applies to type parameter constraints `constraints`. */ predicate appliesToTypeConstraint(TypeParameterConstraints constraints) { - this.getAnnotations().getNoFlagsNullability() = getTypeParameterNullability(constraints, type) + Annotations::getNoFlagsNullability(this.getAnnotations()) = getTypeParameterNullability(constraints, + type) } } From 7c21ebb526288f1377c4321ea93ae3b0535b51a1 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Mon, 11 Nov 2019 19:24:48 +0000 Subject: [PATCH 0357/2538] C#: Change dbscheme from nullability_member to nullability_parent --- .../Entities/Types/Nullability.cs | 2 +- .../Semmle.Extraction.CSharp/Tuples.cs | 4 +- .../src/semmle/code/csharp/AnnotatedType.qll | 10 +- csharp/ql/src/semmlecode.csharp.dbscheme | 4 +- .../ql/src/semmlecode.csharp.dbscheme.stats | 14350 ++++++++-------- 5 files changed, 6970 insertions(+), 7400 deletions(-) diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs index 084ac570fa0a..64f4ed587835 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Entities/Types/Nullability.cs @@ -117,7 +117,7 @@ public override void Populate(TextWriter trapFile) int i = 0; foreach (var s in symbol.NullableParameters) { - trapFile.nullability_member(this, i, Create(Context, s)); + trapFile.nullability_parent(Create(Context, s), i, this); i++; } } diff --git a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs index f6de00452d0e..c66376405563 100644 --- a/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs +++ b/csharp/extractor/Semmle.Extraction.CSharp/Tuples.cs @@ -386,9 +386,9 @@ internal static void nullability(this TextWriter trapFile, NullabilityEntity nul trapFile.WriteTuple("nullability", nullability, annotation); } - internal static void nullability_member(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity child) + internal static void nullability_parent(this TextWriter trapFile, NullabilityEntity nullability, int index, NullabilityEntity parent) { - trapFile.WriteTuple("nullability_member", nullability, index, child); + trapFile.WriteTuple("nullability_parent", nullability, index, parent); } internal static void numlines(this TextWriter trapFile, IEntity label, LineCounts lineCounts) diff --git a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll index d1146f5ea1ed..feec749f0978 100644 --- a/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll +++ b/csharp/ql/src/semmle/code/csharp/AnnotatedType.qll @@ -70,11 +70,11 @@ private module Annotations { language[monotonicAggregates] private string getMemberString() { - if nullability_member(nullability, _, _) + if nullability_parent(_, _, nullability) then result = "<" + concat(int i, Nullability child | - nullability_member(nullability, i, getNullability(child)) + nullability_parent(getNullability(child), i, nullability) | child.toString(), "," order by i ) + ">" @@ -169,8 +169,8 @@ private module Annotations { */ bindingset[i] Nullability getChildNullability(Nullability n, int i) { - if nullability_member(getNullability(n), i, _) - then nullability_member(getNullability(n), i, getNullability(result)) + if nullability_parent(_, i, getNullability(n)) + then nullability_parent(getNullability(result), i, getNullability(n)) else result = n } @@ -190,7 +190,7 @@ private module Annotations { * and all type arguments are oblivious. */ class NoNullability extends ObliviousNullability { - NoNullability() { not nullability_member(nullability, _, _) } + NoNullability() { not nullability_parent(_, _, nullability) } } /** A type with annotated nullablity, `?`. */ diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme b/csharp/ql/src/semmlecode.csharp.dbscheme index e55d8c990309..df0118d2d283 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme +++ b/csharp/ql/src/semmlecode.csharp.dbscheme @@ -480,8 +480,8 @@ case @nullability.kind of | 2 = @annotated ; -#keyset[nullability, index] -nullability_member(int nullability: @nullability ref, int index: int ref, int child: @nullability ref) +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref) diff --git a/csharp/ql/src/semmlecode.csharp.dbscheme.stats b/csharp/ql/src/semmlecode.csharp.dbscheme.stats index 426949c20613..08b4255824e9 100644 --- a/csharp/ql/src/semmlecode.csharp.dbscheme.stats +++ b/csharp/ql/src/semmlecode.csharp.dbscheme.stats @@ -5,11 +5,11 @@ @diagnostic -12070 +108998 @extractor_message -57 +55 @externalDefect @@ -21,43 +21,43 @@ @externalDataElement -9 +10 @duplication -20134 +18936 @similarity -149289 +141055 @location_default -11787435 +10628591 @assembly -2863 +2760 @file -24954 +20987 @folder -7016 +6292 @namespace -6505 +5700 @namespace_declaration -22696 +19007 @using_namespace_directive -106992 +86694 @using_static_directive @@ -117,23 +117,23 @@ @enum_type -8073 +11359 @struct_type -31632 +43620 @class_type -126692 +142562 @interface_type -137173 +206665 @delegate_type -40645 +55958 @null_type @@ -141,19 +141,19 @@ @type_parameter -58090 +80353 @pointer_type -383 +456 @nullable_type -1382 +2279 @array_type -7961 +9835 @void_type @@ -168,15 +168,15 @@ 1 -@tuple_type -1768 +@arglist_type +1 -@uint_ptr_type -0 +@tuple_type +2682 -@arglist_type +@uint_ptr_type 0 @@ -185,23 +185,23 @@ @typeref -349451 +462875 @attribute -152979 +144787 @type_mention -2269573 +2181438 @oblivious -58 +57 @not_annotated -47 +49 @annotated @@ -209,7 +209,7 @@ @type_parameter_constraints -389563 +363573 @modifier @@ -217,87 +217,87 @@ @property -268986 +326745 @indexer -25314 +29544 @getter -286438 +338867 @setter -50195 +54213 @event -8976 +7794 @add_event_accessor -7857 +6531 @remove_event_accessor -7857 +6531 @operator -13320 +18266 @method -990339 +1183684 @constructor -149144 +171824 @destructor -388 +569 @local_function -1201 +1225 @addressable_field -178578 +187149 @constant -106769 +147707 @addressable_local_variable -307769 +289247 @local_constant -1627 +1741 @local_variable_ref -54 +70 @parameter -1662795 +2097984 @block_stmt -483215 +470589 @expr_stmt -510339 +484425 @if_stmt -158006 +154912 @switch_stmt @@ -305,107 +305,107 @@ @while_stmt -4304 +4300 @do_stmt -794 +825 @for_stmt -8189 +8294 @foreach_stmt -11629 +10100 @break_stmt -17068 +16413 @continue_stmt -3270 +3174 @goto_stmt -1200 +1297 @goto_case_stmt -330 +328 @goto_default_stmt -252 +266 @throw_stmt -62807 +63215 @return_stmt -172166 +166461 @yield_stmt -1334 +1269 @try_stmt -6286 +6192 @checked_stmt -234 +241 @unchecked_stmt -186 +169 @lock_stmt -1831 +1789 @using_block_stmt -6120 +4219 @var_decl_stmt -269815 +253667 @const_decl_stmt -1623 +1735 @empty_stmt -349 +244 @unsafe_stmt -301 +342 @fixed_stmt -783 +1207 @label_stmt -439 +448 @catch -4711 +4524 @case_stmt -53160 +53221 @local_function_stmt -1199 +1335 @using_decl_stmt @@ -413,271 +413,271 @@ @bool_literal_expr -83252 +76358 @char_literal_expr -16894 +15164 @decimal_literal_expr -134 +100 @int_literal_expr -268458 +275065 @long_literal_expr -178 +193 @uint_literal_expr -2083 +3178 @ulong_literal_expr -227 +249 @float_literal_expr -631 +627 @double_literal_expr -656 +629 @string_literal_expr -402840 +372602 @null_literal_expr -141562 +139157 @this_access_expr -489938 +461644 @base_access_expr -5239 +4040 @local_variable_access_expr -1050542 +991740 @parameter_access_expr -579372 +572331 @field_access_expr -712366 +711987 @property_access_expr -473246 +424606 @method_access_expr -7270 +7195 @event_access_expr -2309 +1273 @indexer_access_expr -31604 +30564 @array_access_expr -25694 +24812 @type_access_expr -724742 +706800 @typeof_expr -26440 +24651 @method_invocation_expr -928336 +873671 @delegate_invocation_expr -4558 +4434 @operator_invocation_expr -41161 +40914 @cast_expr -212776 +210715 @object_creation_expr -104367 +90994 @explicit_delegate_creation_expr -1190 +1143 @implicit_delegate_creation_expr -3755 +3030 @array_creation_expr -22244 +21192 @default_expr -8135 +8491 @plus_expr -73 +64 @minus_expr -6795 +5824 @bit_not_expr -715 +801 @log_not_expr -27569 +28058 @post_incr_expr -12713 +12241 @post_decr_expr -1368 +1467 @pre_incr_expr -1215 +1297 @pre_decr_expr -294 +287 @mul_expr -4053 +4200 @div_expr -1258 +1261 @rem_expr -573 +583 @add_expr -32765 +29468 @sub_expr -10607 +11073 @lshift_expr -1678 +1825 @rshift_expr -1075 +1182 @lt_expr -15042 +15563 @gt_expr -10187 +10285 @le_expr -3530 +3891 @ge_expr -5467 +5876 @eq_expr -78231 +73546 @ne_expr -53191 +52803 @bit_and_expr -5903 +6565 @bit_xor_expr -507 +497 @bit_or_expr -11954 +12259 @log_and_expr -31285 +30520 @log_or_expr -21875 +22295 @is_expr -8517 +8506 @as_expr -7102 +6480 @null_coalescing_expr -4350 +4436 @conditional_expr -14417 +13572 @simple_assign_expr -207337 +196499 @assign_add_expr -3522 +3401 @assign_sub_expr -619 +634 @assign_mul_expr -123 +131 @assign_div_expr -49 +54 @assign_rem_expr @@ -685,67 +685,67 @@ @assign_and_expr -374 +382 @assign_xor_expr -88 +105 @assign_or_expr -1706 +1858 @assign_lshift_expr -69 +90 @assign_rshift_expr -97 +119 @object_init_expr -5120 +3022 @collection_init_expr -1313 +911 @array_init_expr -19188 +17916 @checked_expr -369 +403 @unchecked_expr -1872 +2931 @constructor_init_expr -9978 +9066 @add_event_expr -877 +672 @remove_event_expr -408 +334 @local_var_decl_expr -309563 +291172 @lambda_expr -24042 +16045 @anonymous_method_expr -192 +174 @dynamic_element_access_expr @@ -753,59 +753,55 @@ @dynamic_member_access_expr -444 +89 @pointer_indirection_expr -2768 +3240 @address_of_expr -717 +967 @sizeof_expr -746 +1106 @await_expr -27405 +27481 @nameof_expr -18016 +18864 @interpolated_string_expr -4321 - - -@unknown_expr -22532 +5023 @throw_expr -917 +931 @tuple_expr -2152 +2261 @local_function_invocation_expr -2317 +2434 @ref_expr -108 +145 @discard_expr -471 +544 @switch_expr -34 +35 @recursive_pattern_expr @@ -821,7 +817,7 @@ @switch_case_expr -142 +148 @assign_coalesce_expr @@ -829,11 +825,11 @@ @suppress_nullable_warning_expr -252 +428 @namespace_access_expr -435 +12 @par_expr @@ -844,6 +840,10 @@ 0 +@unknown_expr +0 + + @range_expr 0 @@ -857,11 +857,11 @@ @xmlelement -3426 +1226 @xmlattribute -5138 +1785 @xmlnamespace @@ -869,63 +869,63 @@ @xmlcomment -300 +152 @xmlcharacters -826 +238 @singlelinecomment -330391 +305420 @xmldoccomment -276055 +210408 @multilinecomment -12000 +10871 @commentblock -247138 +216571 @asp_close_tag -1542 - - -@asp_code -244 +22 @asp_comment -14 - - -@asp_data_binding -44 +5 @asp_directive -243 +3 @asp_open_tag -1920 +28 @asp_quoted_string -4545 +31 @asp_text -3522 +58 @asp_xml_directive -16 +1 + + +@asp_code +0 + + +@asp_data_binding +0 @cil_arglist @@ -1013,7 +1013,7 @@ @cil_stsfld -50533 +50535 @cil_stobj @@ -1269,15 +1269,15 @@ @cil_ldarg_0 -1761435 +1761439 @cil_ldarg_1 -666051 +666052 @cil_ldarg_2 -260505 +260506 @cil_ldarg_3 @@ -1285,7 +1285,7 @@ @cil_ldloc_0 -552028 +552030 @cil_ldloc_1 @@ -1301,11 +1301,11 @@ @cil_stloc_0 -366179 +366180 @cil_stloc_1 -199127 +199128 @cil_stloc_2 @@ -1333,7 +1333,7 @@ @cil_ldloca_s -306809 +306810 @cil_stloc_s @@ -1413,11 +1413,11 @@ @cil_call -1478944 +1478950 @cil_ret -867422 +867426 @cil_br_s @@ -1425,11 +1425,11 @@ @cil_brfalse_s -397704 +397705 @cil_brtrue_s -202600 +202602 @cil_beq_s @@ -1693,7 +1693,7 @@ @cil_callvirt -1047788 +1047791 @cil_ldobj @@ -1701,11 +1701,11 @@ @cil_ldstr -267378 +267379 @cil_newobj -283677 +283678 @cil_castclass @@ -1741,7 +1741,7 @@ @cil_ldsfld -153187 +153188 @cil_ldsflda @@ -1801,7 +1801,7 @@ @cil_valueorreftype -249378 +249380 @cil_typeparameter @@ -1817,23 +1817,23 @@ @cil_method -1164170 +1164177 @cil_method_implementation -1351436 +1351440 @cil_field -459117 +459120 @cil_parameter -2241273 +2241281 @cil_property -232995 +232996 @cil_event @@ -1841,7 +1841,7 @@ @cil_local_variable -989635 +989637 @cil_catch_handler @@ -1941,7 +1941,7 @@ arg -1058 +1056 @@ -2046,13 +2046,13 @@ 1 -413 -414 +416 +417 1 -637 -638 +635 +636 1 @@ -2069,12 +2069,12 @@ 1 2 -1045 +1041 2 1058 -13 +15 @@ -2090,12 +2090,12 @@ 1 2 -1054 +1049 2 3 -4 +7 @@ -2105,7 +2105,7 @@ compilation_compiling_files -21036 +21452 id @@ -2117,7 +2117,7 @@ file -18151 +18152 @@ -2135,33 +2135,33 @@ 2 -3 -11 - - -3 4 -224 +18 4 -6 -82 +5 +225 -6 -18 -80 +5 +8 +84 -18 -64 +8 +23 80 -64 +23 +78 +81 + + +78 1094 -79 +68 @@ -2181,33 +2181,33 @@ 2 -3 -11 - - -3 4 -224 +18 4 -6 -82 +5 +225 -6 -18 -80 +5 +8 +84 -18 -64 +8 +23 80 -64 +23 +78 +81 + + +78 1094 -79 +68 @@ -2233,12 +2233,12 @@ 4 5 -213 +212 5 6 -100 +101 6 @@ -2253,7 +2253,7 @@ 9 10 -151 +150 10 @@ -2266,14 +2266,14 @@ 83 -56 -160 +55 +159 82 -165 +160 1058 -17 +18 @@ -2299,12 +2299,12 @@ 4 5 -213 +212 5 6 -100 +101 6 @@ -2319,7 +2319,7 @@ 9 10 -151 +150 10 @@ -2328,17 +2328,17 @@ 20 -54 -82 +55 +83 -54 -152 +55 +155 82 156 -1042 +1047 18 @@ -2364,8 +2364,8 @@ 4 -129 -197 +417 +198 @@ -2381,17 +2381,17 @@ 1 2 -16536 +16531 2 4 -1447 +1449 4 77 -168 +172 @@ -2669,58 +2669,58 @@ 6 -28 +27 21 -28 -49 +27 +46 21 -49 -79 +48 +78 21 -79 -101 +78 +105 21 -101 -141 +110 +146 21 -146 -168 -23 +152 +171 +21 -168 +171 180 -21 +23 -180 -191 +182 +197 24 -191 -196 -22 +197 +202 +19 -196 -203 +202 +208 23 -203 -226 -15 +208 +231 +18 @@ -2807,57 +2807,57 @@ 1 2 -332 +334 2 3 -173 +156 3 4 -164 +189 4 -5 -130 +6 +135 -5 -12 -129 +6 +13 +128 -12 -17 -144 +13 +18 +139 -17 +18 21 -145 +118 21 26 -134 +143 26 35 -141 +145 35 96 -132 +129 96 -116 -77 +123 +85 @@ -2883,7 +2883,7 @@ seconds -3864 +3821 @@ -2929,12 +2929,12 @@ 6 7 -6 +36 7 8 -1051 +1021 @@ -2980,8 +2980,8 @@ 12 -3864 -3865 +3821 +3822 1 @@ -3028,34 +3028,34 @@ 12 -312 -313 -1 +322 +323 +2 -328 -329 +325 +326 1 -369 -370 +336 +337 1 -416 -417 +1017 +1018 1 -1005 -1006 +1056 +1057 1 -1056 -1057 -2 +1057 +1058 +1 @@ -3071,17 +3071,17 @@ 1 2 -3350 +3373 2 -6 -321 +8 +290 -6 -71 -193 +8 +94 +158 @@ -3097,7 +3097,7 @@ 1 2 -3864 +3821 @@ -3113,12 +3113,12 @@ 1 2 -3460 +3445 2 4 -336 +308 4 @@ -3133,15 +3133,15 @@ diagnostic_for -12070 +108998 diagnostic -12070 +108998 compilation -328 +554 file_number @@ -3149,7 +3149,7 @@ file_number_diagnostic_number -1099 +1332 @@ -3163,7 +3163,7 @@ 1 2 -12070 +108998 @@ -3179,7 +3179,7 @@ 1 2 -12070 +108998 @@ -3195,7 +3195,7 @@ 1 2 -12070 +108998 @@ -3209,64 +3209,59 @@ 12 -1 -2 -2 - - 2 -3 -53 +7 +45 -3 -4 -27 +7 +21 +43 -4 -5 -41 +21 +183 +42 -5 -7 -29 +192 +233 +3 -7 -9 -25 +233 +234 +226 -9 -13 -28 +234 +235 +2 -13 -19 -26 +235 +236 +51 -19 -28 -26 +236 +238 +42 -28 -57 -25 +238 +246 +42 -57 -154 -25 +246 +299 +42 -160 -1100 -21 +305 +1333 +16 @@ -3282,7 +3277,7 @@ 1 2 -328 +554 @@ -3296,64 +3291,59 @@ 12 -1 -2 -2 - - 2 -3 -53 +7 +45 -3 -4 -27 +7 +21 +43 -4 -5 -41 +21 +183 +42 -5 -7 -29 +192 +233 +3 -7 -9 -25 +233 +234 +226 -9 -13 -28 +234 +235 +2 -13 -19 -26 +235 +236 +51 -19 -28 -26 +236 +238 +42 -28 -57 -25 +238 +246 +42 -57 -154 -25 +246 +299 +42 -160 -1100 -21 +305 +1333 +16 @@ -3367,8 +3357,8 @@ 12 -12070 -12071 +108998 +108999 1 @@ -3383,8 +3373,8 @@ 12 -328 -329 +554 +555 1 @@ -3399,8 +3389,8 @@ 12 -1099 -1100 +1332 +1333 1 @@ -3417,42 +3407,42 @@ 1 2 -71 +304 2 3 -488 +484 3 -4 -147 +9 +118 -4 -5 -82 +9 +15 +104 -5 -12 -88 +15 +422 +90 -12 -24 -89 +422 +434 +109 -25 -52 -84 +434 +464 +100 -52 -329 -50 +465 +555 +23 @@ -3468,42 +3458,42 @@ 1 2 -71 +304 2 3 -488 +484 3 -4 -147 +9 +118 -4 -5 -82 +9 +15 +104 -5 -12 -88 +15 +422 +90 -12 -24 -89 +422 +434 +109 -25 -52 -84 +434 +464 +100 -52 -329 -50 +465 +555 +23 @@ -3519,7 +3509,7 @@ 1 2 -1099 +1332 @@ -3529,11 +3519,11 @@ diagnostics -12070 +108998 id -12070 +108998 severity @@ -3541,19 +3531,19 @@ error_tag -6 +18 error_message -6 +7 full_error_message -27 +59 location -10395 +10620 @@ -3567,7 +3557,7 @@ 1 2 -12070 +108998 @@ -3583,7 +3573,7 @@ 1 2 -12070 +108998 @@ -3599,7 +3589,7 @@ 1 2 -12070 +108998 @@ -3615,7 +3605,7 @@ 1 2 -12070 +108998 @@ -3631,7 +3621,7 @@ 1 2 -12070 +108998 @@ -3645,13 +3635,13 @@ 12 -242 -243 +11828 +11829 1 -11828 -11829 +97170 +97171 1 @@ -3671,8 +3661,8 @@ 1 -4 -5 +16 +17 1 @@ -3692,8 +3682,8 @@ 1 -4 -5 +5 +6 1 @@ -3713,8 +3703,8 @@ 1 -25 -26 +57 +58 1 @@ -3729,8 +3719,8 @@ 12 -236 -237 +461 +462 1 @@ -3775,10 +3765,45 @@ 1 +416 +417 +4 + + +832 +833 +2 + + +1248 +1249 +2 + + +1664 +1665 +1 + + +2080 +2081 +1 + + +3328 +3329 +1 + + 11824 11825 1 + +84032 +84033 +1 + @@ -3793,7 +3818,7 @@ 1 2 -6 +18 @@ -3809,7 +3834,7 @@ 1 2 -6 +18 @@ -3825,12 +3850,12 @@ 1 2 -2 +11 2 3 -1 +2 5 @@ -3838,9 +3863,14 @@ 2 +8 +9 +1 + + 13 14 -1 +2 @@ -3854,16 +3884,41 @@ 12 +1 +2 +4 + + 2 3 +4 + + +3 +4 2 +4 +5 +1 + + +5 +6 +1 + + 6 7 1 +8 +9 +1 + + 27 28 1 @@ -3874,6 +3929,11 @@ 1 +202 +203 +1 + + 10157 10158 1 @@ -3919,6 +3979,11 @@ 11825 1 + +96928 +96929 +1 + @@ -3933,7 +3998,7 @@ 1 2 -6 +7 @@ -3951,6 +4016,11 @@ 2 6 + +12 +13 +1 + @@ -3982,6 +4052,11 @@ 14 1 + +32 +33 +1 + @@ -4014,6 +4089,11 @@ 1 +225 +226 +1 + + 10157 10158 1 @@ -4036,58 +4116,48 @@ 2 -3 -1 - - -3 -4 -2 - - -4 6 -2 +5 6 -8 -2 +12 +5 -9 -11 -2 +14 +17 +5 -11 -12 -1 +17 +28 +5 -14 -15 -2 +416 +417 +18 -16 -17 -3 +832 +833 +4 -17 -18 -2 +1248 +1249 +5 -21 -23 -2 +1664 +11825 +5 -27 -11825 -2 +65312 +65313 +1 @@ -4103,7 +4173,7 @@ 1 2 -27 +59 @@ -4119,7 +4189,7 @@ 1 2 -27 +59 @@ -4135,7 +4205,7 @@ 1 2 -27 +59 @@ -4151,57 +4221,42 @@ 1 2 -6 +24 2 3 -2 +6 3 4 -2 +7 -5 +4 7 -2 +5 7 -10 -2 - - -10 12 -2 +4 14 -15 -2 - - -16 17 -3 +5 17 -18 -2 - - -21 23 -2 +5 27 10158 -2 +3 @@ -4226,8 +4281,8 @@ 3 -12 -244 +833 +469 @@ -4243,7 +4298,7 @@ 1 2 -10395 +10620 @@ -4259,7 +4314,12 @@ 1 2 -10395 +10612 + + +2 +3 +8 @@ -4275,7 +4335,7 @@ 1 2 -10395 +10620 @@ -4291,12 +4351,12 @@ 1 2 -10389 +10606 2 3 -6 +14 @@ -4306,11 +4366,11 @@ extractor_messages -57 +55 id -57 +55 severity @@ -4322,19 +4382,19 @@ text -4 +3 entity -23 +22 location -34 +32 stack_trace -3 +4 @@ -4348,7 +4408,7 @@ 1 2 -57 +55 @@ -4364,7 +4424,7 @@ 1 2 -57 +55 @@ -4380,7 +4440,7 @@ 1 2 -57 +55 @@ -4396,7 +4456,7 @@ 1 2 -57 +55 @@ -4412,7 +4472,7 @@ 1 2 -57 +55 @@ -4428,7 +4488,7 @@ 1 2 -57 +55 @@ -4442,8 +4502,8 @@ 12 -6 -7 +4 +5 1 @@ -4486,12 +4546,7 @@ 1 2 -2 - - -2 -3 -1 +3 @@ -4510,8 +4565,8 @@ 1 -5 -6 +4 +5 1 @@ -4536,8 +4591,8 @@ 1 -6 -7 +4 +5 1 @@ -4562,8 +4617,8 @@ 2 -2 -3 +3 +4 1 @@ -4578,8 +4633,8 @@ 12 -57 -58 +55 +56 1 @@ -4610,8 +4665,8 @@ 12 -4 -5 +3 +4 1 @@ -4626,8 +4681,8 @@ 12 -23 -24 +22 +23 1 @@ -4642,8 +4697,8 @@ 12 -34 -35 +32 +33 1 @@ -4658,8 +4713,8 @@ 12 -3 -4 +4 +5 1 @@ -4674,11 +4729,6 @@ 12 -2 -3 -1 - - 4 5 1 @@ -4707,7 +4757,7 @@ 1 2 -4 +3 @@ -4723,7 +4773,7 @@ 1 2 -4 +3 @@ -4739,7 +4789,7 @@ 1 2 -2 +1 4 @@ -4768,11 +4818,6 @@ 1 -2 -3 -1 - - 4 5 1 @@ -4796,7 +4841,12 @@ 1 2 -4 +2 + + +3 +4 +1 @@ -4817,7 +4867,7 @@ 2 3 -6 +5 3 @@ -4848,7 +4898,7 @@ 1 2 -23 +22 @@ -4864,7 +4914,7 @@ 1 2 -23 +22 @@ -4880,7 +4930,7 @@ 1 2 -23 +22 @@ -4901,7 +4951,7 @@ 2 3 -5 +4 3 @@ -4922,7 +4972,7 @@ 1 2 -23 +22 @@ -4938,7 +4988,7 @@ 1 2 -24 +22 2 @@ -4964,7 +5014,7 @@ 1 2 -34 +32 @@ -4980,7 +5030,7 @@ 1 2 -34 +32 @@ -4996,7 +5046,7 @@ 1 2 -34 +32 @@ -5012,7 +5062,7 @@ 1 2 -34 +32 @@ -5028,7 +5078,7 @@ 1 2 -34 +32 @@ -5042,13 +5092,13 @@ 12 -2 -3 -1 +1 +2 +2 -4 -5 +2 +3 1 @@ -5070,7 +5120,7 @@ 1 2 -2 +3 2 @@ -5091,7 +5141,7 @@ 1 2 -3 +4 @@ -5107,7 +5157,7 @@ 1 2 -2 +3 2 @@ -5128,11 +5178,11 @@ 1 2 -1 +2 -4 -5 +2 +3 1 @@ -5152,13 +5202,13 @@ 12 -2 -3 -1 +1 +2 +2 -4 -5 +2 +3 1 @@ -5182,11 +5232,11 @@ cpu_seconds -509 +467 elapsed_seconds -1056 +1054 @@ -5232,27 +5282,27 @@ 1 2 -299 +281 2 3 -93 +70 3 4 -41 +43 4 -6 +8 41 -6 -14 -35 +8 +13 +32 @@ -5268,27 +5318,27 @@ 1 2 -299 +281 2 3 -93 +70 3 4 -41 +43 4 -6 +8 41 -6 -14 -35 +8 +13 +32 @@ -5304,12 +5354,12 @@ 1 2 -1055 +1051 2 3 -1 +3 @@ -5325,12 +5375,12 @@ 1 2 -1055 +1051 2 3 -1 +3 @@ -5754,11 +5804,11 @@ externalData -18 +20 id -9 +10 path @@ -5770,7 +5820,7 @@ value -18 +20 @@ -5784,7 +5834,7 @@ 1 2 -9 +10 @@ -5800,7 +5850,7 @@ 2 3 -9 +10 @@ -5816,7 +5866,7 @@ 2 3 -9 +10 @@ -5830,8 +5880,8 @@ 12 -9 -10 +10 +11 1 @@ -5862,8 +5912,8 @@ 12 -18 -19 +20 +21 1 @@ -5878,8 +5928,8 @@ 12 -9 -10 +10 +11 2 @@ -5910,8 +5960,8 @@ 12 -9 -10 +10 +11 2 @@ -5928,7 +5978,7 @@ 1 2 -18 +20 @@ -5944,7 +5994,7 @@ 1 2 -18 +20 @@ -5960,7 +6010,7 @@ 1 2 -18 +20 @@ -5992,19 +6042,19 @@ duplicateCode -20134 +18936 id -20134 +18936 relativePath -2570 +2265 equivClass -7291 +6810 @@ -6018,7 +6068,7 @@ 1 2 -20134 +18936 @@ -6034,7 +6084,7 @@ 1 2 -20134 +18936 @@ -6050,37 +6100,37 @@ 1 2 -1164 +1060 2 3 -511 +418 3 4 -177 +161 4 6 -237 +198 6 11 -217 +179 11 -41 -194 +36 +170 -41 +36 1047 -70 +79 @@ -6096,32 +6146,32 @@ 1 2 -1401 +1248 2 3 -377 +310 3 4 -217 +188 4 6 -225 +195 6 12 -206 +186 12 405 -144 +138 @@ -6142,27 +6192,27 @@ 2 3 -4859 +4495 3 4 -1105 +1051 4 5 -632 +595 5 9 -574 +551 9 11 -116 +113 @@ -6178,22 +6228,22 @@ 1 2 -4521 +4222 2 3 -2071 +1918 3 -6 -603 +5 +520 -6 +5 11 -96 +150 @@ -6203,19 +6253,19 @@ similarCode -149289 +141055 id -149289 +141055 relativePath -5832 +4793 equivClass -43184 +40443 @@ -6229,7 +6279,7 @@ 1 2 -149289 +141055 @@ -6245,7 +6295,7 @@ 1 2 -149289 +141055 @@ -6261,57 +6311,52 @@ 1 2 -1266 +989 2 3 -999 +824 3 4 -428 +334 4 5 -427 +338 5 -6 -317 - - -6 -8 -460 +7 +425 -8 -12 -464 +7 +10 +422 -12 -19 -445 +10 +16 +391 -19 -40 -450 +16 +28 +367 -40 -158 -438 +28 +63 +360 -158 +63 10255 -138 +343 @@ -6327,47 +6372,47 @@ 1 2 -1794 +1419 2 3 -875 +717 3 4 -565 +447 4 5 -436 +353 5 7 -540 +426 7 10 -473 +394 10 17 -467 +400 17 -45 -443 +39 +363 -45 +39 3151 -239 +274 @@ -6383,37 +6428,37 @@ 1 2 -33 +22 2 3 -20582 +18979 3 4 -8089 +7590 4 5 -4987 +4736 5 6 -2926 +2796 6 8 -3616 +3485 8 11 -2951 +2835 @@ -6429,22 +6474,22 @@ 1 2 -29024 +27489 2 3 -9400 +8570 3 5 -3481 +3204 5 11 -1279 +1180 @@ -6454,11 +6499,11 @@ tokens -20596077 +19390833 id -169423 +159991 offset @@ -6466,19 +6511,19 @@ beginLine -66951 +66941 beginColumn -1275 +1274 endLine -65748 +65737 endColumn -1282 +1280 @@ -6492,72 +6537,67 @@ 100 101 -17349 +16507 101 102 -14013 +13400 102 103 -11330 +10706 103 104 -8613 +8227 104 -105 -8343 - - -105 -107 -13200 +106 +14785 -107 -109 -11207 +106 +108 +10905 -109 -112 -13800 +108 +111 +14230 -112 -116 -13475 +111 +115 +13953 -116 -122 -13227 +115 +121 +13841 -122 -132 -13847 +121 +130 +12523 -132 -150 -13094 +130 +145 +12013 -150 -200 -12774 +145 +186 +12027 -200 +186 24726 -5151 +6874 @@ -6573,72 +6613,72 @@ 3 8 -15571 +14714 8 10 -13241 +12264 10 12 -14984 +14261 12 13 -8221 +7803 13 14 -9518 +8972 14 15 -10126 +9603 15 16 -8365 +7805 16 18 -15128 +14115 18 20 -14382 +13499 20 22 -13269 +12619 22 24 -10793 +10282 24 27 -14004 +13441 27 33 -13393 +12806 33 4516 -8428 +7807 @@ -6654,67 +6694,67 @@ 3 30 -13731 +12551 30 35 -12960 +12550 35 -40 -15615 +39 +11810 -40 -44 -13732 +39 +43 +12757 -44 -48 -15209 +43 +47 +14181 -48 +47 51 -11686 +14812 51 54 -12470 +11812 54 57 -12211 +11572 57 61 -15141 +14300 61 65 -13198 +12505 65 71 -14162 +13314 71 83 -13148 +12181 83 356 -6160 +5646 @@ -6730,77 +6770,72 @@ 3 8 -15606 +14749 8 10 -13284 +12307 10 11 -7617 +7233 11 12 -8071 +7732 12 13 -8967 +8549 13 14 -10039 +9485 14 15 -10060 +9545 15 -16 -8163 - - -16 -18 -15038 +17 +14705 -18 -20 -15158 +17 +19 +13999 -20 -22 -13995 +19 +21 +13941 -22 -24 -11189 +21 +23 +12055 -24 -27 -13173 +23 +26 +14297 -27 -35 -13285 +26 +31 +12102 -35 +31 4516 -5778 +9292 @@ -6816,67 +6851,67 @@ 3 32 -13965 +12833 32 38 -14984 +14379 38 43 -15403 +14719 43 47 -13368 +12728 47 51 -14461 +13764 51 55 -15157 +14329 55 58 -11849 +11193 58 62 -15331 +14558 62 66 -13741 +13018 66 71 -14501 +13691 71 78 -13414 +12570 78 -120 -12726 +135 +12009 -120 +135 363 -523 +200 @@ -6906,13 +6941,13 @@ 9 -30 -1856 +28 +1913 -33 -169424 -1429 +29 +159992 +1372 @@ -6942,13 +6977,13 @@ 7 -24 -1856 +22 +1926 -24 -27429 -1429 +22 +27426 +1359 @@ -6978,13 +7013,13 @@ 4 -15 -1894 +13 +1987 -15 -489 -1380 +13 +488 +1287 @@ -7014,13 +7049,13 @@ 7 -24 -1856 +22 +1926 -24 -27395 -1429 +22 +27392 +1359 @@ -7050,13 +7085,13 @@ 4 -15 -1897 +12 +1856 -15 +12 494 -1375 +1416 @@ -7072,52 +7107,52 @@ 1 2 -3940 +3932 2 3 -4614 +4619 3 4 -5107 +5103 4 5 -5049 +5047 5 6 -4513 +4515 6 7 -4086 +4084 7 8 -3748 +3752 8 9 -3319 +3318 9 11 -5799 +5798 11 14 -5802 +5800 14 @@ -7127,7 +7162,7 @@ 19 32 -5188 +5189 32 @@ -7136,13 +7171,13 @@ 80 -1828 +1631 5022 -1830 -5217 -232 +1632 +4188 +230 @@ -7158,22 +7193,22 @@ 1 4 -4906 +4909 4 7 -5029 +5022 7 12 -5528 +5527 12 18 -5048 +5044 18 @@ -7183,22 +7218,22 @@ 26 35 -5342 +5343 35 45 -5030 +5029 45 57 -5139 +5140 57 72 -5082 +5080 72 @@ -7213,17 +7248,17 @@ 114 153 -5067 +5079 153 -499 -5022 +472 +5021 -499 -605 -120 +472 +570 +109 @@ -7239,62 +7274,62 @@ 1 2 -9046 +9053 2 4 -5786 +5791 4 6 -4828 +4819 6 9 -6118 +6109 9 12 -5031 +5030 12 16 -5582 +5585 16 20 -5337 +5338 20 26 -5654 +5652 26 35 -5318 +5315 35 54 -5192 +5190 54 99 -5040 +5046 99 -340 -4019 +339 +4013 @@ -7310,12 +7345,12 @@ 1 2 -56336 +56327 2 3 -5720 +5719 3 @@ -7336,62 +7371,62 @@ 1 2 -9015 +9022 2 4 -5814 +5819 4 6 -4705 +4696 6 9 -6095 +6085 9 12 -5032 +5031 12 16 -5541 +5544 16 20 -5289 +5291 20 26 -5602 +5600 26 35 -5213 +5211 35 -53 -5023 +54 +5217 -53 -94 -5029 +54 +97 +5056 -94 -342 -4593 +97 +341 +4369 @@ -7412,7 +7447,7 @@ 2 3 -77 +76 3 @@ -7421,54 +7456,59 @@ 5 -9 -118 +8 +90 -9 -12 -93 +8 +11 +91 -12 -16 -99 +11 +15 +107 -16 -22 -107 +15 +20 +100 -22 -49 -97 +20 +34 +96 -49 -154 +34 +116 96 -155 -460 +116 +318 96 -460 -2842 +319 +1276 96 -2886 -34163 +1313 +15993 96 -34851 -133446 +16054 +81805 96 + +81831 +126123 +30 + @@ -7483,7 +7523,7 @@ 1 2 -102 +101 2 @@ -7522,28 +7562,28 @@ 46 -99 -98 +97 +96 -99 -152 -96 +97 +150 +97 -153 -273 +150 +265 96 -274 -708 -96 +265 +676 +98 -708 -3646 -77 +676 +3602 +76 @@ -7564,7 +7604,7 @@ 2 3 -85 +84 3 @@ -7578,43 +7618,48 @@ 5 -7 -118 +6 +67 -7 -10 -97 +6 +8 +91 -10 -33 +8 +15 +98 + + +15 +48 97 -33 -80 +48 +106 96 -80 -216 +106 +447 96 -216 -1785 +458 +4412 96 -1861 -10566 +4439 +15076 96 -10669 -36636 -70 +15140 +36635 +29 @@ -7635,7 +7680,7 @@ 2 3 -85 +84 3 @@ -7649,43 +7694,48 @@ 5 -7 -118 +6 +67 -7 -10 -97 +6 +8 +91 -10 -33 +8 +15 +98 + + +15 +48 97 -33 -80 +48 +106 96 -80 -216 +106 +447 96 -216 -1785 +458 +4412 96 -1861 -10566 +4439 +15076 96 -10670 -36635 -70 +15138 +36634 +29 @@ -7701,7 +7751,7 @@ 1 2 -313 +312 2 @@ -7721,32 +7771,32 @@ 5 9 -113 +114 9 15 -102 +103 15 22 -106 +110 22 -35 -98 +36 +96 -35 +37 75 -98 +99 -75 -176 -54 +76 +175 +49 @@ -7762,37 +7812,37 @@ 1 2 -3847 +3838 2 3 -4499 +4504 3 4 -5022 +5018 4 5 -4979 +4977 5 6 -4459 +4461 6 7 -4054 +4052 7 8 -3680 +3684 8 @@ -7802,12 +7852,12 @@ 9 11 -5635 +5632 11 14 -5618 +5617 14 @@ -7817,7 +7867,7 @@ 19 32 -5112 +5113 32 @@ -7826,13 +7876,13 @@ 78 -1307 +1173 4932 -1308 -5199 -348 +1173 +4170 +346 @@ -7848,22 +7898,22 @@ 1 5 -5546 +5550 5 9 -5457 +5452 9 15 -5689 +5683 15 22 -5386 +5385 22 @@ -7873,22 +7923,22 @@ 30 39 -5000 +5001 39 50 -5190 +5186 50 63 -5112 +5115 63 79 -4943 +4940 79 @@ -7903,12 +7953,12 @@ 125 173 -4964 +4975 173 -605 -3456 +570 +3445 @@ -7924,7 +7974,7 @@ 1 2 -53887 +53876 2 @@ -7950,27 +8000,27 @@ 1 2 -6483 +6489 2 3 -3747 +3749 3 5 -5343 +5347 5 7 -5671 +5657 7 10 -4871 +4866 10 @@ -7980,37 +8030,37 @@ 14 17 -5140 +5144 17 22 -5191 +5187 22 28 -5324 +5323 28 39 -5191 +5189 39 62 -5013 +5012 62 118 -4937 +4958 118 -340 -2833 +339 +2812 @@ -8026,67 +8076,67 @@ 1 2 -6454 +6460 2 3 -3708 +3710 3 5 -5420 +5424 5 7 -5487 +5473 7 10 -4895 +4889 10 14 -5972 +5973 14 17 -5077 +5081 17 22 -5177 +5173 22 28 -5282 +5281 28 39 -5107 +5106 39 62 -5051 +5049 62 115 -4947 +4960 115 -342 -3171 +340 +3158 @@ -8107,7 +8157,7 @@ 2 3 -73 +71 3 @@ -8137,37 +8187,37 @@ 21 36 -100 +98 36 -132 +124 97 -133 -348 -97 +125 +331 +96 -350 -1580 -97 +333 +1416 +96 -1614 -21369 -97 +1469 +18166 +96 -21416 -97489 -97 +18253 +87352 +96 -97674 -119719 -23 +87890 +113121 +29 @@ -8183,7 +8233,7 @@ 1 2 -102 +100 2 @@ -8222,33 +8272,33 @@ 32 -81 -98 +80 +96 -81 -133 -97 +80 +132 +98 -133 -232 -97 +132 +224 +98 -232 -491 -97 +226 +480 +96 -491 -1764 -97 +480 +1699 +96 -1819 -3367 -13 +1720 +3280 +15 @@ -8269,7 +8319,7 @@ 2 3 -99 +97 3 @@ -8293,33 +8343,33 @@ 11 -39 -98 +38 +96 -39 -87 -97 +38 +79 +96 -88 -251 +79 +225 97 -256 -2289 -97 +229 +2123 +96 -2295 -11901 -97 +2143 +11420 +96 -12187 -26471 -62 +11472 +26469 +67 @@ -8335,7 +8385,7 @@ 1 2 -309 +307 2 @@ -8359,28 +8409,28 @@ 9 -16 -110 +15 +99 -16 -25 -101 +15 +24 +107 -25 -38 +24 +37 97 -38 -66 -103 +37 +63 +96 -66 +63 110 -67 +79 @@ -8401,7 +8451,7 @@ 2 3 -99 +97 3 @@ -8425,33 +8475,33 @@ 11 -39 -98 +38 +96 -39 -87 -97 +38 +79 +96 -88 -251 +79 +225 97 -256 -2289 -97 +229 +2123 +96 -2295 -11901 -97 +2143 +11428 +96 -12187 -26471 -62 +11469 +26469 +67 @@ -8461,15 +8511,15 @@ locations_default -11787435 +10628591 id -11787435 +10628591 file -22092 +18229 beginLine @@ -8485,7 +8535,7 @@ endColumn -1237 +1234 @@ -8499,7 +8549,7 @@ 1 2 -11787435 +10628591 @@ -8515,7 +8565,7 @@ 1 2 -11787435 +10628591 @@ -8531,7 +8581,7 @@ 1 2 -11787435 +10628591 @@ -8547,7 +8597,7 @@ 1 2 -11787435 +10628591 @@ -8563,7 +8613,7 @@ 1 2 -11787435 +10628591 @@ -8579,72 +8629,72 @@ 1 16 -1739 +1382 16 27 -1704 +1438 27 -35 -1622 +34 +1384 -35 -48 -1689 +34 +47 +1422 -48 +47 70 -1725 +1406 70 -98 -1659 +103 +1387 -98 -141 -1671 +103 +151 +1371 -141 -199 -1668 +151 +215 +1374 -199 -286 -1657 +215 +310 +1375 -286 -425 -1666 +310 +465 +1372 -425 -680 -1657 +465 +754 +1370 -680 -1245 -1658 +754 +1405 +1368 -1245 -4832 -1657 +1405 +6323 +1368 -4835 +6331 167166 -320 +212 @@ -8660,67 +8710,67 @@ 1 9 -1729 +1356 9 14 -1933 +1624 14 19 -1627 +1345 19 -22 -1911 +21 +1382 -22 -29 -1670 +21 +28 +1454 -29 -39 -1774 +28 +38 +1411 -39 +38 52 -1707 +1450 52 -71 -1664 +72 +1390 -71 -99 -1676 +72 +101 +1371 -99 -145 -1659 +101 +148 +1369 -145 -229 -1660 +148 +233 +1376 -229 -454 -1657 +233 +449 +1368 -454 +449 44061 -1425 +1333 @@ -8736,67 +8786,67 @@ 1 7 -1536 +1283 7 -11 -1891 +10 +1423 -11 -15 -1732 +10 +14 +1422 -15 -21 -1867 +14 +20 +1544 -21 +20 27 -1695 +1519 27 34 -1796 +1370 34 42 -1791 +1415 42 51 -1809 +1467 51 62 -1803 +1485 62 -75 -1792 +74 +1378 -75 -91 -1700 +74 +89 +1410 -91 -119 -1673 +89 +113 +1383 -119 +113 781 -1007 +1130 @@ -8812,67 +8862,67 @@ 1 9 -1728 +1355 9 14 -1924 +1629 14 19 -1631 +1340 19 -22 -1915 +21 +1388 -22 -30 -1877 +21 +28 +1450 -30 -40 -1726 +28 +38 +1396 -40 -53 -1657 +38 +52 +1466 -53 -73 -1687 +52 +72 +1390 -73 -102 -1684 +72 +101 +1370 -102 -150 -1678 +101 +148 +1374 -150 -242 -1659 +148 +234 +1377 -242 -504 -1659 +234 +453 +1369 -504 +453 46103 -1267 +1325 @@ -8888,67 +8938,67 @@ 1 13 -1769 +1388 13 20 -1667 +1394 20 25 -1751 +1524 25 31 -1697 +1459 31 -40 -1705 +41 +1454 -40 -50 -1773 +41 +52 +1475 -50 -61 -1688 +52 +64 +1432 -61 -73 -1741 +64 +76 +1407 -73 -86 -1709 +76 +90 +1459 -86 -100 -1727 +90 +104 +1429 -100 -117 -1754 +104 +121 +1373 -117 -142 -1670 +121 +149 +1396 -142 +149 883 -1441 +1039 @@ -9014,17 +9064,17 @@ 28 65 -5497 +5498 65 -290 +289 5443 -290 -39954 -3707 +289 +33315 +3706 @@ -9069,7 +9119,7 @@ 46 -21923 +18137 4695 @@ -9121,7 +9171,7 @@ 9 12 -6072 +6073 12 @@ -9131,17 +9181,17 @@ 18 39 -5563 +5564 39 -110 -5455 +109 +5477 -110 -373 -1927 +109 +370 +1903 @@ -9176,13 +9226,13 @@ 9 -46 -5486 +45 +5468 -46 +45 367 -739 +757 @@ -9253,17 +9303,17 @@ 29 64 -5542 +5543 64 -149 -5479 +147 +5447 -149 -413 -1769 +147 +411 +1800 @@ -9299,42 +9349,37 @@ 5 8 -107 +106 8 17 -90 +95 17 -55 -88 - - -55 -175 +56 88 -176 -1176 +56 +168 88 -1256 -16999 +172 +1186 88 -17523 -646623 +1190 +16937 88 -1430464 -1573394 -2 +18267 +1428349 +86 @@ -9350,52 +9395,52 @@ 1 2 -369 +368 2 3 -129 +131 3 4 -75 +74 4 6 -88 +90 6 13 -88 +89 13 -29 +28 91 -29 -106 +28 +97 88 -110 -1029 +97 +958 88 -1033 -7700 +962 +6873 88 -7907 -21381 -57 +6919 +17795 +54 @@ -9411,12 +9456,12 @@ 1 2 -345 +344 2 3 -89 +91 3 @@ -9431,37 +9476,37 @@ 6 11 -96 +94 11 -29 +28 90 -30 -94 -91 +28 +86 +90 -94 -413 +86 +357 88 -415 -2920 +370 +2712 88 -2932 -9215 +2841 +9048 88 -9290 -50368 -28 +9055 +50367 +30 @@ -9477,17 +9522,17 @@ 1 2 -345 +344 2 3 -89 +90 3 4 -58 +59 4 @@ -9497,37 +9542,37 @@ 6 11 -96 +94 11 -29 +28 90 -30 -94 -91 +28 +86 +90 -94 -413 +86 +357 88 -415 -2918 +371 +2711 88 -2936 -9228 +2842 +9053 88 -9288 -53430 -28 +9106 +53429 +30 @@ -9543,7 +9588,7 @@ 1 2 -352 +351 2 @@ -9553,7 +9598,7 @@ 3 4 -76 +77 4 @@ -9563,37 +9608,32 @@ 6 11 -94 +95 11 -24 -89 +23 +91 -24 -41 -89 +23 +39 +92 -41 +39 68 -89 - - -68 -162 88 -162 -383 +68 +157 88 -429 -454 -4 +157 +450 +87 @@ -9654,17 +9694,17 @@ 29 73 -5604 +5605 73 -410 +407 5557 -410 -38993 -3137 +407 +32723 +3136 @@ -9709,7 +9749,7 @@ 46 -21919 +18133 4812 @@ -9741,17 +9781,17 @@ 4 8 -6068 +6069 8 35 -5571 +5605 35 -82 -1341 +80 +1306 @@ -9802,7 +9842,7 @@ 9 12 -6159 +6160 12 @@ -9812,17 +9852,17 @@ 18 39 -5609 +5610 39 -113 -5569 +112 +5598 -113 -373 -1810 +112 +370 +1779 @@ -9883,17 +9923,17 @@ 30 68 -5606 +5607 68 -166 -5572 +165 +5575 -166 +165 413 -1180 +1176 @@ -9909,57 +9949,57 @@ 1 2 -305 +307 2 3 -103 +102 3 4 -82 +78 4 6 -100 +102 6 10 -98 +100 10 -32 -94 +33 +93 -32 -90 +33 +85 93 -90 -312 +85 +287 93 -318 -3282 +290 +3095 93 -3320 -47350 +3150 +47095 93 -48707 -290233 -83 +47807 +264670 +80 @@ -9975,52 +10015,52 @@ 1 2 -385 +383 2 3 -150 +148 3 4 -79 +78 4 7 -99 +105 7 23 -95 +101 23 -47 -94 +46 +93 -47 -204 +46 +232 93 -212 -1974 +233 +2143 93 -2010 -11406 +2153 +10467 93 -11549 -16182 -56 +10478 +13226 +47 @@ -10036,7 +10076,7 @@ 1 2 -344 +345 2 @@ -10046,7 +10086,7 @@ 3 4 -73 +72 4 @@ -10056,7 +10096,7 @@ 6 11 -102 +101 11 @@ -10065,28 +10105,28 @@ 37 -110 -94 +102 +93 -110 -456 +103 +442 93 -460 -3065 +443 +3057 93 -3078 -11825 +3249 +11842 93 -11842 +11855 22748 -52 +51 @@ -10102,57 +10142,57 @@ 1 2 -333 +332 2 3 -136 +133 3 4 -87 +85 4 -7 -112 +6 +93 -7 -15 -95 +6 +12 +94 -15 -35 -96 +12 +26 +93 -35 -68 -94 +26 +54 +93 -68 -93 -95 +54 +80 +94 -93 -138 +80 +117 93 -138 -177 -94 +117 +164 +95 -177 -179 -2 +164 +178 +29 @@ -10188,7 +10228,7 @@ 6 11 -103 +102 11 @@ -10197,28 +10237,28 @@ 37 -110 -94 +101 +93 -110 -450 +102 +439 93 -452 -3056 +442 +3053 93 -3072 -11597 +3217 +11609 93 -11609 +11646 22648 -52 +51 @@ -10228,23 +10268,23 @@ numlines -344316 +333286 element_id -321238 +314329 num_lines -1544 +1502 num_code -1300 +1276 num_comment -506 +491 @@ -10258,12 +10298,12 @@ 1 2 -298186 +295373 2 -4 -23052 +3 +18956 @@ -10279,12 +10319,12 @@ 1 2 -298202 +295380 2 -4 -23036 +3 +18949 @@ -10300,12 +10340,12 @@ 1 2 -318086 +311689 2 -4 -3152 +3 +2640 @@ -10321,42 +10361,42 @@ 1 2 -638 +633 2 3 -199 +203 3 4 -118 +113 4 6 -114 +108 6 10 -123 +116 10 -20 -121 +21 +116 -20 -76 -116 +21 +93 +114 -77 -72660 -115 +93 +79337 +99 @@ -10372,22 +10412,22 @@ 1 2 -640 +636 2 3 -201 +204 3 4 -117 +113 4 6 -124 +116 6 @@ -10397,17 +10437,17 @@ 10 18 -124 +115 18 -34 -116 +35 +115 -34 -53 -96 +35 +48 +77 @@ -10423,42 +10463,42 @@ 1 2 -640 +635 2 3 -199 +205 3 4 -117 +111 4 6 -122 +113 6 10 -131 +126 10 17 -120 +122 17 30 -116 +117 30 -44 -99 +41 +73 @@ -10474,42 +10514,42 @@ 1 2 -523 +522 2 3 -165 +174 3 4 -102 +98 4 6 -114 +106 6 -11 -103 +12 +112 -11 -23 +12 +26 98 -23 -82 -98 +26 +137 +96 -84 -101108 -97 +143 +104495 +70 @@ -10525,42 +10565,42 @@ 1 2 -524 +523 2 3 -169 +176 3 4 -99 +98 4 6 -116 +108 6 11 -107 +100 11 -22 -104 +21 +99 -22 -45 -101 +21 +43 +99 -45 -60 -80 +43 +58 +73 @@ -10576,42 +10616,42 @@ 1 2 -526 +525 2 3 -163 +172 3 4 -103 +100 4 6 -118 +111 6 11 -113 +106 11 -21 +20 100 -21 -36 -99 +20 +35 +107 -36 -51 -78 +35 +48 +55 @@ -10627,47 +10667,47 @@ 1 2 -192 +198 2 3 -61 +66 3 4 -45 +40 4 6 -43 +36 6 10 -40 +39 10 -21 -40 +24 +37 -21 -69 -39 +24 +82 +37 -69 -1913 -38 +82 +15817 +37 -1919 -255606 -8 +254391 +254392 +1 @@ -10683,47 +10723,47 @@ 1 2 -193 +199 2 3 -60 +65 3 4 -45 +41 4 6 -43 +36 6 10 -41 +38 10 -21 -39 +23 +37 -21 -57 -38 +23 +70 +37 -58 -227 -38 +70 +309 +37 -227 -375 -9 +372 +373 +1 @@ -10739,47 +10779,42 @@ 1 2 -193 +199 2 3 -60 +65 3 4 -45 +40 4 6 -43 +37 6 10 -40 +39 10 -21 -42 - - -22 -64 -38 +23 +37 -66 -210 -38 +23 +71 +37 -211 -333 -7 +79 +331 +37 @@ -10789,27 +10824,27 @@ assemblies -2863 +2760 id -2863 +2760 file -2861 +2758 fullname -1321 +1253 name -605 +553 version -124 +95 @@ -10823,7 +10858,7 @@ 1 2 -2863 +2760 @@ -10839,7 +10874,7 @@ 1 2 -2863 +2760 @@ -10855,7 +10890,7 @@ 1 2 -2863 +2760 @@ -10871,7 +10906,7 @@ 1 2 -2863 +2760 @@ -10887,7 +10922,7 @@ 1 2 -2859 +2756 2 @@ -10908,7 +10943,7 @@ 1 2 -2859 +2756 2 @@ -10929,7 +10964,7 @@ 1 2 -2861 +2758 @@ -10945,7 +10980,7 @@ 1 2 -2861 +2758 @@ -10961,7 +10996,7 @@ 1 2 -782 +722 2 @@ -10971,17 +11006,22 @@ 3 4 -92 +84 4 -7 -114 +6 +65 -7 +6 +8 +116 + + +8 13 -99 +32 @@ -10997,7 +11037,7 @@ 1 2 -782 +722 2 @@ -11007,17 +11047,22 @@ 3 4 -92 +84 4 -7 -114 +6 +65 -7 +6 +8 +116 + + +8 13 -99 +32 @@ -11033,7 +11078,7 @@ 1 2 -1321 +1253 @@ -11049,7 +11094,7 @@ 1 2 -1321 +1253 @@ -11065,42 +11110,47 @@ 1 2 -231 +181 2 3 -70 +73 3 4 -52 +47 4 -6 -55 +5 +36 -6 +5 +7 +42 + + +7 9 -53 +33 9 11 -43 +48 11 13 -39 +37 13 15 -56 +50 15 @@ -11121,42 +11171,47 @@ 1 2 -231 +181 2 3 -71 +74 3 4 -52 +47 4 -6 -54 +5 +35 -6 +5 +7 +42 + + +7 9 -53 +33 9 11 -43 +48 11 13 -39 +37 13 15 -56 +50 15 @@ -11177,22 +11232,22 @@ 1 2 -416 +368 2 3 -61 +66 3 4 -48 +42 4 6 -45 +42 13 @@ -11213,22 +11268,22 @@ 1 2 -452 +404 2 3 -61 +66 3 4 -47 +41 4 6 -45 +42 @@ -11244,47 +11299,52 @@ 1 2 -47 +25 2 3 -16 +15 3 4 -9 +6 4 6 -9 +8 6 -8 -9 +7 +7 -8 -10 -9 +7 +9 +6 -10 -28 -10 +9 +11 +8 -28 -103 -10 +12 +31 +8 -147 +33 +142 +8 + + +157 756 -5 +4 @@ -11300,47 +11360,52 @@ 1 2 -47 +25 2 3 -17 +16 3 4 -9 +6 4 6 -8 +7 6 -8 -9 +7 +7 -8 -10 -9 +7 +9 +6 -10 -28 -10 +9 +11 +8 -28 -103 -10 +12 +31 +8 -147 +33 +142 +8 + + +157 756 -5 +4 @@ -11356,37 +11421,37 @@ 1 2 -68 +45 2 3 -15 +14 3 4 -9 +8 4 -7 -10 +6 +6 -7 -20 -10 +6 +13 +8 -22 -71 -10 +15 +27 +8 -123 +30 586 -2 +6 @@ -11402,37 +11467,37 @@ 1 2 -69 +46 2 3 -14 +13 3 4 -9 +8 4 -7 -10 +6 +6 -7 -20 -10 +6 +13 +8 -22 -71 -10 +15 +27 +8 -122 +30 166 -2 +6 @@ -11442,23 +11507,23 @@ files -24954 +20987 id -24954 +20987 name -24954 +20987 simple -20050 +16459 ext -8 +7 fromSource @@ -11476,7 +11541,7 @@ 1 2 -24954 +20987 @@ -11492,7 +11557,7 @@ 1 2 -24954 +20987 @@ -11508,7 +11573,7 @@ 1 2 -24954 +20987 @@ -11524,7 +11589,7 @@ 1 2 -24954 +20987 @@ -11540,7 +11605,7 @@ 1 2 -24954 +20987 @@ -11556,7 +11621,7 @@ 1 2 -24954 +20987 @@ -11572,7 +11637,7 @@ 1 2 -24954 +20987 @@ -11588,7 +11653,7 @@ 1 2 -24954 +20987 @@ -11604,12 +11669,12 @@ 1 2 -18724 +15342 2 417 -1326 +1117 @@ -11625,12 +11690,12 @@ 1 2 -18724 +15342 2 417 -1326 +1117 @@ -11646,12 +11711,12 @@ 1 2 -19838 +16251 2 4 -212 +208 @@ -11667,7 +11732,7 @@ 1 2 -20050 +16459 @@ -11683,7 +11748,7 @@ 1 2 -1 +2 2 @@ -11691,33 +11756,23 @@ 1 -9 -10 -1 - - 17 18 1 -98 -99 -1 - - -112 -113 +58 +59 1 -2842 -2843 +2740 +2741 1 -21873 -21874 +18168 +18169 1 @@ -11734,7 +11789,7 @@ 1 2 -1 +2 2 @@ -11742,33 +11797,23 @@ 1 -9 -10 -1 - - 17 18 1 -98 -99 -1 - - -112 -113 +58 +59 1 -2842 -2843 +2740 +2741 1 -21873 -21874 +18168 +18169 1 @@ -11785,12 +11830,7 @@ 1 2 -2 - - -7 -8 -1 +3 11 @@ -11798,23 +11838,18 @@ 1 -56 -57 -1 - - -58 -59 +31 +32 1 -597 -598 +545 +546 1 -19532 -19533 +16078 +16079 1 @@ -11831,7 +11866,7 @@ 1 2 -8 +7 @@ -11845,8 +11880,8 @@ 12 -24954 -24955 +20987 +20988 1 @@ -11861,8 +11896,8 @@ 12 -24954 -24955 +20987 +20988 1 @@ -11877,8 +11912,8 @@ 12 -20050 -20051 +16459 +16460 1 @@ -11893,8 +11928,8 @@ 12 -8 -9 +7 +8 1 @@ -11905,19 +11940,19 @@ folders -7016 +6292 id -7016 +6292 name -6927 +6258 simple -1989 +1648 @@ -11931,7 +11966,7 @@ 1 2 -7016 +6292 @@ -11947,7 +11982,7 @@ 1 2 -7016 +6292 @@ -11963,12 +11998,12 @@ 1 2 -6838 +6224 2 3 -89 +34 @@ -11984,7 +12019,7 @@ 1 2 -6927 +6258 @@ -12000,27 +12035,32 @@ 1 2 -1079 +841 2 3 -347 +293 3 4 -258 +236 4 6 -170 +152 6 -352 -135 +211 +124 + + +301 +342 +2 @@ -12036,27 +12076,32 @@ 1 2 -1114 +853 2 3 -334 +286 3 4 -252 +237 4 6 -156 +147 6 -352 -133 +302 +124 + + +341 +342 +1 @@ -12066,15 +12111,15 @@ containerparent -31967 +27276 parent -7016 +6292 child -31967 +27276 @@ -12088,32 +12133,32 @@ 1 2 -3597 +3258 2 3 -1293 +1213 3 4 -556 +509 4 6 -568 +500 6 -14 -536 +16 +474 -14 -229 -466 +16 +230 +338 @@ -12129,7 +12174,7 @@ 1 2 -31967 +27276 @@ -12139,15 +12184,15 @@ file_extraction_mode -24734 +20927 file -24734 +20927 mode -2 +1 @@ -12161,7 +12206,7 @@ 1 2 -24734 +20927 @@ -12175,13 +12220,8 @@ 12 -3808 -3809 -1 - - -20926 -20927 +20927 +20928 1 @@ -12192,15 +12232,15 @@ namespaces -6505 +5700 id -6505 +5700 name -1717 +1313 @@ -12214,7 +12254,7 @@ 1 2 -6505 +5700 @@ -12230,37 +12270,42 @@ 1 2 -407 +67 2 3 -730 +744 3 4 -103 +55 4 5 -132 +127 5 7 -86 +81 7 -10 -137 +9 +113 -10 -69 -122 +9 +21 +103 + + +21 +66 +23 @@ -12270,15 +12315,15 @@ namespace_declarations -22696 +19007 id -22696 +19007 namespace_id -1922 +1509 @@ -12292,7 +12337,7 @@ 1 2 -22696 +19007 @@ -12308,47 +12353,47 @@ 1 2 -638 +558 2 3 -295 +223 3 4 -144 +107 4 -5 -105 +6 +125 -5 -7 -148 +6 +9 +126 -7 -10 -147 +9 +15 +114 -10 -17 -157 +15 +32 +117 -17 -35 -147 +32 +112 +114 -35 +115 646 -141 +25 @@ -12358,15 +12403,15 @@ namespace_declaration_location -22696 +19007 id -22696 +19007 loc -19757 +16071 @@ -12380,7 +12425,7 @@ 1 2 -22696 +19007 @@ -12396,16 +12441,16 @@ 1 2 -17726 +14045 2 3 -1611 +1606 3 -128 +129 420 @@ -12416,15 +12461,15 @@ parent_namespace -360683 +501755 child_id -360683 +501755 namespace_id -4420 +3630 @@ -12438,7 +12483,7 @@ 1 2 -360683 +501755 @@ -12454,52 +12499,52 @@ 1 2 -1289 +1108 2 3 -494 +423 3 4 -306 +245 4 -5 -217 +6 +334 -5 -7 -382 +6 +9 +286 -7 -11 -402 +9 +15 +308 -11 -17 -338 +15 +28 +282 -17 -30 -338 +28 +58 +276 -30 -66 -335 +58 +254 +273 -66 -108885 -319 +255 +170410 +95 @@ -12509,15 +12554,15 @@ parent_namespace_declaration -34436 +30406 child_id -24003 +21983 namespace_id -22688 +19004 @@ -12531,22 +12576,17 @@ 1 2 -17774 +16376 2 3 -4375 +4192 3 -11 -1807 - - -11 -259 -47 +143 +1415 @@ -12562,17 +12602,17 @@ 1 2 -20681 +17129 2 -10 -1727 +7 +1458 -10 +7 299 -280 +417 @@ -12582,15 +12622,15 @@ using_namespace_directives -106992 +86694 id -106992 +86694 namespace_id -1422 +1088 @@ -12604,7 +12644,7 @@ 1 2 -106992 +86694 @@ -12620,52 +12660,52 @@ 1 2 -341 +291 2 3 -202 +138 3 4 -112 +85 4 6 -131 +100 6 9 -112 +82 9 15 -117 +86 15 -28 -111 +27 +91 -28 -55 -107 +27 +53 +82 -55 -180 -107 +54 +237 +82 -180 -10946 -82 +241 +8479 +51 @@ -12683,7 +12723,7 @@ type_id -75 +98 @@ -12713,42 +12753,37 @@ 1 2 -17 +29 2 3 -21 +32 3 4 -10 +9 4 5 -6 +10 5 -8 -6 - - -8 -11 -6 +9 +9 -11 +9 15 -6 +8 15 -19 -3 +16 +1 @@ -12758,15 +12793,15 @@ using_directive_location -107313 +87015 id -107313 +87015 loc -91983 +71734 @@ -12780,7 +12815,7 @@ 1 2 -107313 +87015 @@ -12796,16 +12831,16 @@ 1 2 -79730 +59536 2 3 -10544 +10489 3 -128 +129 1709 @@ -12816,19 +12851,19 @@ types -413820 +555841 id -413820 +555841 kind -27 +28 name -180164 +158850 @@ -12842,7 +12877,7 @@ 1 2 -413820 +555841 @@ -12858,7 +12893,7 @@ 1 2 -413820 +555841 @@ -12874,31 +12909,31 @@ 1 2 -17 +18 -383 -1383 +456 +2280 2 -1768 -7962 +2682 +9836 2 -8073 -31633 +11359 +43621 2 -40645 -58091 +55958 +80354 2 -126692 -137174 +142562 +206666 2 @@ -12915,31 +12950,31 @@ 1 2 -17 +18 -317 -580 +312 +578 2 -1014 -1043 +852 +994 2 -3386 -6731 +2988 +6687 2 -14006 -23824 +13823 +21622 2 -62903 -69095 +55697 +56500 2 @@ -12956,17 +12991,27 @@ 1 2 -158707 +105413 2 +3 +27307 + + +3 4 -15195 +9579 4 -8751 -6262 +8 +12599 + + +8 +11441 +3952 @@ -12982,12 +13027,12 @@ 1 2 -177472 +157673 2 5 -2692 +1177 @@ -12997,15 +13042,15 @@ typerefs -349451 +462875 id -349451 +462875 name -79294 +69295 @@ -13019,7 +13064,7 @@ 1 2 -349451 +462875 @@ -13035,17 +13080,22 @@ 1 2 -69433 +50533 2 3 -5934 +10126 3 -26887 -3927 +6 +6047 + + +6 +37752 +2589 @@ -13055,15 +13105,15 @@ typeref_type -343625 +462440 id -343625 +462440 typeId -343625 +462440 @@ -13077,7 +13127,7 @@ 1 2 -343625 +462440 @@ -13093,7 +13143,7 @@ 1 2 -343625 +462440 @@ -13103,11 +13153,11 @@ array_element_type -7961 +9835 array -7961 +9835 dimension @@ -13119,7 +13169,7 @@ element -7932 +9808 @@ -13133,7 +13183,7 @@ 1 2 -7961 +9835 @@ -13149,7 +13199,7 @@ 1 2 -7961 +9835 @@ -13165,7 +13215,7 @@ 1 2 -7961 +9835 @@ -13184,13 +13234,13 @@ 1 -49 -50 +54 +55 1 -7910 -7911 +9779 +9780 1 @@ -13236,13 +13286,13 @@ 1 -48 -49 +53 +54 1 -7882 -7883 +9753 +9754 1 @@ -13262,8 +13312,8 @@ 1 -10 -11 +11 +12 1 @@ -13272,8 +13322,8 @@ 1 -7926 -7927 +9799 +9800 1 @@ -13319,8 +13369,8 @@ 1 -10 -11 +11 +12 1 @@ -13329,8 +13379,8 @@ 1 -7926 -7927 +9799 +9800 1 @@ -13347,12 +13397,12 @@ 1 2 -7908 +9786 2 5 -24 +22 @@ -13368,7 +13418,7 @@ 1 2 -7932 +9808 @@ -13384,12 +13434,12 @@ 1 2 -7908 +9786 2 5 -24 +22 @@ -13399,15 +13449,15 @@ nullable_underlying_type -1382 +2279 nullable -1382 +2279 underlying -1382 +1665 @@ -13421,7 +13471,7 @@ 1 2 -1382 +2279 @@ -13437,7 +13487,22 @@ 1 2 -1382 +1243 + + +2 +3 +266 + + +3 +4 +139 + + +4 +8 +17 @@ -13447,15 +13512,15 @@ pointer_referent_type -383 +456 pointer -383 +456 referent -383 +456 @@ -13469,7 +13534,7 @@ 1 2 -383 +456 @@ -13485,7 +13550,7 @@ 1 2 -383 +456 @@ -13495,11 +13560,11 @@ enum_underlying_type -8079 +11359 enum_id -8079 +11359 underlying_type_id @@ -13517,7 +13582,7 @@ 1 2 -8079 +11359 @@ -13531,43 +13596,43 @@ 12 -5 -6 +7 +8 1 -6 -7 +10 +11 1 -16 -17 +27 +28 1 -41 -42 +103 +104 1 -82 -83 +106 +107 1 -289 -290 +435 +436 1 -392 -393 +461 +462 1 -7248 -7249 +10210 +10211 1 @@ -13578,15 +13643,15 @@ delegate_return_type -40602 +55985 delegate_id -40602 +55985 return_type_id -17705 +23894 @@ -13600,7 +13665,7 @@ 1 2 -40602 +55985 @@ -13616,17 +13681,17 @@ 1 2 -16003 +21161 2 -4 -1360 +3 +1803 -4 -7208 -342 +3 +9114 +930 @@ -13636,15 +13701,15 @@ extend -206708 +557003 sub -206708 +557003 super -10856 +12849 @@ -13658,7 +13723,7 @@ 1 2 -206708 +557003 @@ -13674,32 +13739,32 @@ 1 2 -6157 +6927 2 3 -2069 +2601 3 4 -789 +1039 4 6 -902 +1131 6 -34 -815 +31 +966 -34 -52181 -124 +31 +206666 +185 @@ -13709,15 +13774,15 @@ implement -501419 +752149 sub -165927 +235420 super -111188 +170825 @@ -13731,37 +13796,32 @@ 1 2 -46744 +59364 2 3 -48255 +74329 3 4 -35908 +54343 4 -5 -9804 - - -5 -8 -10322 +6 +19213 -8 -14 -14877 +6 +11 +18398 -14 -31 -17 +11 +44 +9773 @@ -13777,32 +13837,32 @@ 1 2 -52605 +78466 2 3 -27664 +44401 3 4 -11959 +19338 4 6 -9609 +13428 6 -10 -8459 +9 +13436 -10 -113783 -892 +9 +175652 +1756 @@ -13812,15 +13872,15 @@ type_location -445714 +430401 id -185891 +224933 loc -52345 +46244 @@ -13834,27 +13894,27 @@ 1 2 -99018 +121778 2 3 -41333 +57052 3 4 -18115 +17460 4 -7 -16473 +5 +19506 -7 -717 -10952 +5 +77 +9137 @@ -13870,12 +13930,17 @@ 1 2 -49945 +41878 2 +29 +3484 + + +29 17019 -2400 +882 @@ -13885,15 +13950,15 @@ tuple_underlying_type -1768 +3134 tuple -1768 +3134 struct -699 +1704 @@ -13907,7 +13972,7 @@ 1 2 -1768 +3134 @@ -13923,27 +13988,22 @@ 1 2 -228 +961 2 3 -259 +472 3 4 -123 +158 4 -6 -64 - - -6 -153 -25 +101 +113 @@ -13953,11 +14013,11 @@ tuple_element -4528 +10263 tuple -1768 +2682 index @@ -13965,7 +14025,7 @@ field -4528 +10263 @@ -13979,27 +14039,37 @@ 1 2 -10 +67 2 3 -1395 +1670 3 4 -221 +306 4 -18 -134 +6 +193 -18 +6 +11 +219 + + +11 +21 +212 + + +21 22 -8 +15 @@ -14015,27 +14085,37 @@ 1 2 -10 +67 2 3 -1395 +1670 3 4 -221 +306 4 -18 -134 +6 +193 -18 +6 +11 +219 + + +11 +21 +212 + + +21 22 -8 +15 @@ -14049,108 +14129,108 @@ 12 -2 -3 +15 +16 1 -4 -5 +30 +31 1 -6 -7 +45 +46 1 -8 -9 +60 +61 1 -10 -11 +75 +76 1 -12 -13 +90 +91 1 -14 -15 +105 +106 1 -18 -19 +135 +136 1 -22 -23 +165 +166 1 -26 -27 +195 +196 1 -32 -33 +227 +228 1 -36 -37 +257 +258 1 -40 -41 +287 +288 1 -47 -48 +326 +327 1 -55 -56 +385 +386 1 -65 -66 +446 +447 1 -100 -101 +539 +540 1 -142 -143 +639 +640 1 -363 -364 +945 +946 1 -1758 -1759 +2615 +2616 1 -1768 -1769 +2682 +2683 1 @@ -14165,108 +14245,108 @@ 12 -2 -3 +15 +16 1 -4 -5 +30 +31 1 -6 -7 +45 +46 1 -8 -9 +60 +61 1 -10 -11 +75 +76 1 -12 -13 +90 +91 1 -14 -15 +105 +106 1 -18 -19 +135 +136 1 -22 -23 +165 +166 1 -26 -27 +195 +196 1 -32 -33 +227 +228 1 -36 -37 +257 +258 1 -40 -41 +287 +288 1 -47 -48 +326 +327 1 -55 -56 +385 +386 1 -65 -66 +446 +447 1 -100 -101 +539 +540 1 -142 -143 +639 +640 1 -363 -364 +945 +946 1 -1758 -1759 +2615 +2616 1 -1768 -1769 +2682 +2683 1 @@ -14283,7 +14363,7 @@ 1 2 -4528 +10263 @@ -14299,7 +14379,7 @@ 1 2 -4528 +10263 @@ -14309,19 +14389,19 @@ attributes -152979 +144787 id -152979 +144787 type_id -468 +517 target -78814 +74146 @@ -14335,7 +14415,7 @@ 1 2 -152979 +144787 @@ -14351,7 +14431,7 @@ 1 2 -152979 +144787 @@ -14367,62 +14447,67 @@ 1 2 -71 +46 2 3 -52 +50 3 -4 -28 +5 +45 -4 -6 +5 +8 +41 + + +8 +11 42 -6 -9 -36 +11 +16 +43 -9 -14 -36 +16 +25 +39 -14 -23 -36 +25 +49 +46 -23 -45 -36 +49 +84 +40 -45 -81 -37 +84 +161 +39 -86 -205 -37 +164 +296 +44 -217 -1059 +315 +7070 39 -1079 +14098 49629 -18 +3 @@ -14438,57 +14523,62 @@ 1 2 -93 +72 2 3 -51 +49 3 -4 -32 +5 +40 -4 -6 -35 +5 +8 +44 -6 -9 -39 +8 +12 +45 -9 -16 -38 +12 +19 +43 -16 -28 -36 +19 +31 +40 -28 +31 56 -36 +39 56 -121 -36 +95 +41 -124 -417 -38 +95 +196 +39 -421 -49626 -34 +201 +326 +40 + + +339 +49629 +25 @@ -14504,22 +14594,22 @@ 1 2 -40545 +37641 2 3 -28536 +27423 3 4 -7103 +6746 4 2518 -2630 +2336 @@ -14535,22 +14625,22 @@ 1 2 -42542 +38510 2 3 -28029 +27709 3 4 -6770 +6480 4 16 -1473 +1447 @@ -14560,15 +14650,15 @@ attribute_location -295887 +289574 id -152979 +144787 loc -150274 +140232 @@ -14580,14 +14670,9 @@ 12 -1 -2 -10071 - - 2 3 -142908 +144787 @@ -14603,12 +14688,12 @@ 1 2 -147783 +137280 2 33350 -2491 +2952 @@ -14618,19 +14703,19 @@ type_mention -2269573 +2181438 id -2269573 +2181438 type_id -62260 +64029 parent -2098317 +2040856 @@ -14644,7 +14729,7 @@ 1 2 -2269573 +2181438 @@ -14660,7 +14745,7 @@ 1 2 -2269573 +2181438 @@ -14676,47 +14761,47 @@ 1 2 -16389 +17289 2 3 -12921 +13682 3 4 -5673 +5842 4 5 -4952 +5042 5 7 -4946 +4865 7 -11 -4873 +12 +5498 -11 -21 -4739 +12 +25 +4984 -21 -62 -4682 +25 +99 +4820 -62 -170762 -3085 +99 +161715 +2007 @@ -14732,47 +14817,47 @@ 1 2 -19486 +20094 2 3 -12123 +12833 3 4 -5422 +5717 4 5 -4489 +4591 5 7 -4628 +4623 7 12 -5228 +5197 12 -25 -4788 +26 +4929 -25 -127 -4672 +26 +155 +4805 -127 -157226 -1424 +155 +154065 +1240 @@ -14788,12 +14873,12 @@ 1 2 -1990082 +1950128 2 953 -108235 +90728 @@ -14809,12 +14894,12 @@ 1 2 -2068929 +2012696 2 29 -29388 +28160 @@ -14824,15 +14909,15 @@ type_mention_location -2269573 +2181438 id -2269573 +2181438 loc -2163726 +1978560 @@ -14846,7 +14931,7 @@ 1 2 -2269573 +2181438 @@ -14862,12 +14947,12 @@ 1 2 -2129500 +1892284 2 227 -34226 +86276 @@ -14877,11 +14962,11 @@ type_annotation -45915 +59922 id -45915 +59922 annotation @@ -14899,7 +14984,7 @@ 1 2 -45915 +59922 @@ -14913,18 +14998,18 @@ 12 -1956 -1957 +2330 +2331 1 -13501 -13502 +17268 +17269 1 -30458 -30459 +40324 +40325 1 @@ -14935,11 +15020,11 @@ nullability -116 +117 nullability -116 +117 kind @@ -14957,7 +15042,7 @@ 1 2 -116 +117 @@ -14976,13 +15061,13 @@ 1 -47 -48 +49 +50 1 -58 -59 +57 +58 1 @@ -14992,20 +15077,20 @@ -nullability_member -381 +nullability_parent +386 nullability -113 +25 index 17 -child -25 +parent +114 @@ -15019,45 +15104,81 @@ 1 2 -34 +16 2 3 -33 +3 3 4 +2 + + +5 +8 +2 + + +16 +18 +2 + + + + + + +nullability +parent + + +12 + + +1 +2 14 +3 +4 +1 + + 4 5 -10 +2 5 -8 -10 +6 +2 -8 -15 -9 +6 +7 +2 -15 -18 -3 +23 +26 +2 + + +30 +64 +2 -nullability -child +index +nullability 12 @@ -15065,17 +15186,37 @@ 1 2 -50 +1 2 3 -54 +9 3 4 -9 +2 + + +4 +5 +1 + + +5 +6 +2 + + +9 +10 +1 + + +25 +26 +1 @@ -15083,7 +15224,7 @@ index -nullability +parent 12 @@ -15154,23 +15295,23 @@ 1 -32 -33 +33 +34 1 -46 -47 +48 +49 1 -79 -80 +80 +81 1 -113 -114 +114 +115 1 @@ -15178,8 +15319,8 @@ -index -child +parent +nullability 12 @@ -15187,90 +15328,24 @@ 1 2 -1 +49 2 3 -9 - - -3 -4 -2 - - -4 -5 -1 - - -5 -6 -2 - - -9 -10 -1 - - -25 -26 -1 - - - - - - -child -nullability - - -12 - - -1 -2 -14 +56 3 4 -1 - - -4 -5 -2 - - -5 -6 -2 - - -6 -7 -2 - - -23 -27 -2 - - -28 -62 -2 +9 -child +parent index @@ -15279,27 +15354,37 @@ 1 2 -16 +34 2 3 -3 +32 3 4 -2 +15 + + +4 +5 +11 5 8 -2 +10 -16 +8 +15 +9 + + +15 18 -2 +3 @@ -15309,15 +15394,15 @@ type_nullability -243176 +297491 id -239388 +293770 nullability -107 +108 @@ -15331,12 +15416,12 @@ 1 2 -235606 +290049 2 -4 -3782 +3 +3721 @@ -15356,13 +15441,8 @@ 2 -3 -7 - - -3 4 -4 +10 4 @@ -15371,43 +15451,43 @@ 6 -7 -9 +9 +10 -7 -10 -5 +9 +13 +10 -10 -15 +14 +30 9 -19 -31 +30 +76 9 -40 -106 +76 +285 9 -119 -481 +292 +788 9 -540 -3383 +1023 +28413 9 -14434 -154277 -5 +188323 +188324 +1 @@ -15417,33 +15497,33 @@ is_generic -60403 +73607 id -60403 +73607 is_constructed -237565 +339924 id -237565 +339924 type_parameters -58092 +80200 id -58092 +80200 index @@ -15451,7 +15531,7 @@ generic_id -37990 +49295 variance @@ -15469,7 +15549,7 @@ 1 2 -58092 +80200 @@ -15485,7 +15565,7 @@ 1 2 -58092 +80200 @@ -15501,7 +15581,7 @@ 1 2 -58092 +80200 @@ -15515,48 +15595,48 @@ 12 -1 -2 +4 +5 16 -2 -4 +6 +9 3 -7 -15 +33 +84 3 -18 -150 +110 +317 3 -270 -511 +489 +836 3 -632 -887 +1009 +1369 3 -1013 -1291 +1550 +1995 3 -1461 -1881 +2233 +2928 3 -2310 -37991 +3776 +49278 3 @@ -15571,48 +15651,48 @@ 12 -1 -2 +4 +5 16 -2 -4 +6 +9 3 -7 -15 +33 +84 3 -18 -150 +110 +317 3 -270 -511 +489 +836 3 -632 -887 +1009 +1369 3 -1013 -1291 +1550 +1995 3 -1461 -1881 +2233 +2928 3 -2310 -37991 +3776 +49296 3 @@ -15655,17 +15735,22 @@ 1 2 -32308 +41484 2 3 -3372 +4035 3 +20 +3720 + + +20 41 -2310 +56 @@ -15681,17 +15766,22 @@ 1 2 -32308 +41484 2 3 -3372 +4035 3 +20 +3720 + + +20 41 -2310 +56 @@ -15707,12 +15797,12 @@ 1 2 -37946 +49186 2 3 -44 +109 @@ -15726,18 +15816,18 @@ 12 -63 -64 +180 +181 1 -312 -313 +1500 +1501 1 -57717 -57718 +78502 +78503 1 @@ -15778,18 +15868,18 @@ 12 -61 -62 +186 +187 1 -71 -72 +244 +245 1 -37902 -37903 +48974 +48975 1 @@ -15800,11 +15890,11 @@ type_arguments -312757 +446484 id -87949 +118281 index @@ -15812,7 +15902,7 @@ constructed_id -237565 +339924 @@ -15826,17 +15916,17 @@ 1 2 -68801 +93801 2 3 -18339 +23468 3 18 -809 +1012 @@ -15852,37 +15942,32 @@ 1 2 -44933 +54689 2 3 -16977 +26868 3 -5 -7885 +4 +8139 -5 +4 7 -4344 +10745 7 -8 -6689 - - -8 -28 -6603 +9 +9001 -28 -7377 -518 +9 +9658 +8839 @@ -15896,93 +15981,93 @@ 12 -2 -3 +4 +5 4 -32 -33 +37 +38 1 -146 -147 +175 +176 1 -259 -260 +313 +314 1 -372 -373 +451 +452 1 -485 -486 +589 +590 1 -600 -601 +729 +730 1 -716 -717 +870 +871 1 -836 -837 +1017 +1018 1 -953 -954 +1161 +1162 1 -1185 -1186 +2044 +2045 1 -1279 -1280 +2144 +2145 1 -1436 -1437 +2297 +2298 1 -1645 -1646 +2628 +2629 1 -1998 -1999 +3171 +3172 1 -7659 -7660 +10871 +10872 1 -21869 -21870 +27900 +27901 1 -67117 -67118 +88130 +88131 1 @@ -15997,93 +16082,93 @@ 12 -2 -3 +4 +5 4 -77 -78 +94 +95 1 -192 -193 +233 +234 1 -307 -308 +372 +373 1 -422 -423 +511 +512 1 -537 -538 +650 +651 1 -654 -655 +791 +792 1 -773 -774 +934 +935 1 -894 -895 +1081 +1082 1 -1014 -1015 +1227 +1228 1 -1253 -1254 +2216 +2217 1 -1404 -1405 +2506 +2507 1 -1616 -1617 +2884 +2885 1 -1958 -1959 +3505 +3506 1 -2634 -2635 +4555 +4556 1 -9388 -9389 +13989 +13990 1 -52061 -52062 +70996 +70997 1 -237565 -237566 +339924 +339925 1 @@ -16100,17 +16185,17 @@ 1 2 -186726 +270905 2 3 -42264 +56336 3 22 -8575 +12683 @@ -16126,17 +16211,17 @@ 1 2 -185504 +268928 2 3 -42673 +57007 3 22 -9388 +13989 @@ -16146,15 +16231,15 @@ constructed_generic -237565 +339924 constructed -237565 +339924 generic -5449 +6639 @@ -16168,7 +16253,7 @@ 1 2 -237565 +339924 @@ -16184,37 +16269,42 @@ 1 2 -2207 +2575 2 3 -1075 +1249 3 4 -506 +557 4 6 -479 +565 6 11 -442 +554 11 -33 -409 +25 +502 -33 -21877 -331 +25 +213 +499 + + +214 +37705 +138 @@ -16224,15 +16314,15 @@ type_parameter_constraints -389563 +363573 id -389563 +363573 param_id -58090 +80353 @@ -16246,7 +16336,7 @@ 1 2 -389563 +363573 @@ -16262,32 +16352,27 @@ 1 2 -32353 +50203 2 3 -9062 +14018 3 -4 -5333 - - -4 -7 -4581 +5 +7399 -7 -17 -4653 +5 +14 +6191 -17 -10899 -2108 +14 +9487 +2542 @@ -16333,11 +16418,11 @@ general_type_parameter_constraints -49753 +48124 id -49483 +47846 kind @@ -16355,12 +16440,12 @@ 1 2 -49213 +47568 2 3 -270 +278 @@ -16379,23 +16464,23 @@ 1 -176 -177 +186 +187 1 -372 -373 +324 +325 1 -4647 -4648 +4170 +4171 1 -44498 -44499 +43384 +43385 1 @@ -16406,15 +16491,15 @@ specific_type_parameter_constraints -41475 +38432 id -40987 +37993 base_id -2496 +2291 @@ -16428,12 +16513,12 @@ 1 2 -40536 +37585 2 5 -451 +408 @@ -16449,47 +16534,47 @@ 1 2 -951 +717 2 3 -329 +296 3 4 -224 +255 4 -6 -231 +5 +256 -6 +5 8 -172 +210 8 12 -204 +180 12 -25 -191 +22 +176 -25 -671 -188 +22 +185 +172 -947 -6057 -6 +186 +5259 +29 @@ -16499,15 +16584,15 @@ specific_type_parameter_nullability -305 +306 id -305 +306 base_id -24 +36 nullability @@ -16525,7 +16610,7 @@ 1 2 -305 +306 @@ -16541,7 +16626,7 @@ 1 2 -305 +306 @@ -16557,47 +16642,37 @@ 1 2 -1 +3 2 3 -7 +10 3 4 -2 +11 4 5 -2 - - -5 -6 -5 - - -6 -8 -2 +3 8 -9 -1 +13 +3 -34 -35 -2 +22 +25 +3 -60 -103 -2 +36 +67 +3 @@ -16613,12 +16688,12 @@ 1 2 -21 +35 2 3 -3 +1 @@ -16652,8 +16727,8 @@ 1 -288 -289 +289 +290 1 @@ -16675,11 +16750,16 @@ 2 3 -2 +1 -21 -22 +3 +4 +1 + + +30 +31 1 @@ -16738,11 +16818,11 @@ has_modifiers -3644548 +4409612 id -2423233 +2914166 mod_id @@ -16760,17 +16840,17 @@ 1 2 -1294970 +1527243 2 3 -1036528 +1280137 3 6 -91735 +106786 @@ -16784,93 +16864,93 @@ 12 -474 -475 +608 +609 1 -595 -596 +876 +877 1 -858 -859 +979 +980 1 -1986 -1987 +2568 +2569 1 -3632 -3633 +4159 +4160 1 -9430 -9431 +10471 +10472 1 -22226 -22227 +22235 +22236 1 -29654 -29655 +41832 +41833 1 -53969 -53970 +62104 +62105 1 -70891 -70892 +77024 +77025 1 -106769 -106770 +147707 +147708 1 -143771 -143772 +183303 +183304 1 -147924 -147925 +191235 +191236 1 -199833 -199834 +235884 +235885 1 -247611 -247612 +310096 +310097 1 -373610 -373611 +418191 +418192 1 -443150 -443151 +513043 +513044 1 -1788165 -1788166 +2187297 +2187298 1 @@ -16881,22 +16961,22 @@ compiler_generated -78129 +76391 id -78129 +76391 exprorstmt_name -1656 +1762 parent_id -1656 +1762 name @@ -16914,7 +16994,7 @@ 1 2 -1656 +1762 @@ -16935,7 +17015,7 @@ 2 3 -75 +74 3 @@ -16945,7 +17025,7 @@ 4 5 -31 +30 5 @@ -16960,17 +17040,17 @@ 8 13 -19 +20 13 -85 +55 17 111 176 -3 +4 @@ -16980,19 +17060,19 @@ nested_types -57581 +59639 id -57581 +59639 declaring_type_id -18925 +22408 unbound_id -36015 +36073 @@ -17006,7 +17086,7 @@ 1 2 -57581 +59639 @@ -17022,7 +17102,7 @@ 1 2 -57581 +59639 @@ -17038,32 +17118,27 @@ 1 2 -9127 +12009 2 3 -2917 +3462 3 4 -3625 +3848 4 -6 -1378 - - -6 -14 -1452 +8 +1847 -14 +8 592 -426 +1242 @@ -17079,32 +17154,27 @@ 1 2 -9216 +12105 2 3 -2893 +3437 3 4 -3605 +3833 4 -6 -1380 - - -6 -14 -1427 +8 +1847 -14 +8 592 -404 +1186 @@ -17120,12 +17190,12 @@ 1 2 -34018 +33986 2 -1347 -1997 +1139 +2087 @@ -17141,12 +17211,12 @@ 1 2 -34383 +34409 2 -1347 -1632 +1139 +1664 @@ -17156,27 +17226,27 @@ properties -268986 +326745 id -268986 +326745 name -58896 +53824 declaring_type_id -66590 +77800 type_id -27500 +34329 unbound_id -174793 +209618 @@ -17190,7 +17260,7 @@ 1 2 -268986 +326745 @@ -17206,7 +17276,7 @@ 1 2 -268986 +326745 @@ -17222,7 +17292,7 @@ 1 2 -268986 +326745 @@ -17238,7 +17308,7 @@ 1 2 -268986 +326745 @@ -17254,27 +17324,32 @@ 1 2 -37823 +29682 2 3 -11142 +12552 3 -5 -4879 +4 +2436 -5 -31 -4418 +4 +7 +4763 -31 -20332 -634 +7 +66 +4039 + + +66 +26166 +352 @@ -17290,27 +17365,32 @@ 1 2 -37823 +29682 2 3 -11174 +12553 3 -5 -4870 +4 +2443 -5 -32 -4435 +4 +7 +4758 -32 -18333 -594 +7 +66 +4041 + + +66 +22680 +347 @@ -17326,17 +17406,22 @@ 1 2 -53616 +45461 2 -6 -4499 +3 +4275 -6 -3187 -781 +3 +55 +4037 + + +58 +3744 +51 @@ -17352,27 +17437,27 @@ 1 2 -38193 +29905 2 3 -11213 +12628 3 5 -4821 +4979 5 -55 -4419 +13 +4389 -55 -5009 -250 +13 +5665 +1923 @@ -17388,37 +17473,37 @@ 1 2 -21446 +26097 2 3 -21133 +23827 3 4 -5984 +7432 4 -5 -4091 +6 +6926 -5 -7 -3967 +6 +10 +6616 -7 -12 -5094 +10 +25 +5868 -12 -6356 -4875 +25 +3766 +1034 @@ -17434,37 +17519,37 @@ 1 2 -23866 +28521 2 3 -18876 +22076 3 4 -5924 +6893 4 -5 -4042 +6 +6926 -5 -7 -5519 +6 +9 +7156 -7 -11 -5515 +9 +36 +5835 -11 -6356 -2848 +36 +3766 +393 @@ -17480,32 +17565,32 @@ 1 2 -25457 +29504 2 3 -22110 +25881 3 4 -7831 +8656 4 -5 -4467 +6 +7061 -5 -12 -6097 +6 +13 +5868 -12 -51 -628 +13 +54 +830 @@ -17521,37 +17606,37 @@ 1 2 -21446 +26097 2 3 -21133 +23827 3 4 -5984 +7432 4 -5 -4091 +6 +6926 -5 -7 -3967 +6 +10 +6616 -7 -12 -5094 +10 +25 +5868 -12 -6356 -4875 +25 +3766 +1034 @@ -17567,27 +17652,27 @@ 1 2 -15184 +18227 2 3 -6965 +8740 3 4 -1444 +1980 4 7 -2106 +2891 7 -55172 -1801 +70171 +2491 @@ -17603,17 +17688,17 @@ 1 2 -23189 +28616 2 3 -2495 +3226 3 -19160 -1816 +17827 +2487 @@ -17629,27 +17714,27 @@ 1 2 -15664 +18941 2 3 -6934 +8659 3 4 -1415 +2056 4 8 -2095 +2771 8 -25360 -1392 +30299 +1902 @@ -17665,27 +17750,27 @@ 1 2 -15350 +18408 2 3 -7099 +9025 3 4 -1492 +2096 4 8 -2176 +2843 8 -37193 -1383 +41346 +1957 @@ -17701,12 +17786,12 @@ 1 2 -172012 +205640 2 -5604 -2781 +7099 +3978 @@ -17722,7 +17807,7 @@ 1 2 -174793 +209618 @@ -17738,12 +17823,12 @@ 1 2 -172012 +205640 2 -5604 -2781 +7099 +3978 @@ -17759,12 +17844,12 @@ 1 2 -173873 +200534 2 -1060 -920 +1517 +9084 @@ -17774,15 +17859,15 @@ property_location -621543 +596956 id -268771 +317336 loc -73027 +64445 @@ -17796,32 +17881,27 @@ 1 2 -137047 +170365 2 3 -73922 +91549 3 4 -19805 +15062 4 -6 -13360 - - -6 -15 -20275 +5 +28727 -15 -257 -4362 +5 +18 +11633 @@ -17837,12 +17917,12 @@ 1 2 -70153 +60908 2 29742 -2874 +3537 @@ -17852,27 +17932,27 @@ indexers -25314 +29544 id -25314 +29544 name -7 +49 declaring_type_id -18446 +21477 type_id -5634 +6092 unbound_id -2521 +3019 @@ -17886,7 +17966,7 @@ 1 2 -25314 +29544 @@ -17902,7 +17982,7 @@ 1 2 -25314 +29544 @@ -17918,7 +17998,7 @@ 1 2 -25314 +29544 @@ -17934,7 +18014,7 @@ 1 2 -25314 +29544 @@ -17950,22 +18030,32 @@ 1 2 -3 +11 2 3 -2 +20 -6 -7 -1 +3 +4 +8 -25301 -25302 -1 +5 +10 +4 + + +10 +43 +4 + + +53 +29271 +2 @@ -17981,22 +18071,32 @@ 1 2 -3 +11 2 3 -2 +21 -4 -5 -1 +3 +4 +7 -18438 -18439 -1 +5 +10 +4 + + +10 +33 +4 + + +53 +21309 +2 @@ -18012,17 +18112,17 @@ 1 2 -5 +37 -4 -5 -1 +2 +3 +10 -5631 -5632 -1 +14 +6068 +2 @@ -18038,21 +18138,31 @@ 1 2 -3 +11 2 3 -2 +21 -6 -7 -1 +3 +4 +8 + + +5 +11 +4 -2508 -2509 +21 +54 +4 + + +2780 +2781 1 @@ -18069,22 +18179,22 @@ 1 2 -14068 +16476 2 3 -2930 +3218 3 5 -1421 +1749 5 -7 -27 +11 +34 @@ -18100,12 +18210,12 @@ 1 2 -18443 +21440 2 -3 -3 +11 +37 @@ -18121,12 +18231,17 @@ 1 2 -14223 +16763 2 3 -4223 +4706 + + +3 +11 +8 @@ -18142,22 +18257,22 @@ 1 2 -14068 +16476 2 3 -2930 +3218 3 5 -1421 +1749 5 -7 -27 +11 +34 @@ -18173,37 +18288,42 @@ 1 2 -739 +869 2 3 -1537 +1573 3 4 -1740 +1581 4 5 -261 +382 5 6 -630 +681 6 7 -435 +458 7 -5790 -292 +15 +460 + + +15 +5910 +88 @@ -18219,12 +18339,12 @@ 1 2 -5629 +6080 2 -4 -5 +19 +12 @@ -18240,32 +18360,32 @@ 1 2 -786 +984 2 3 -1495 +1477 3 4 -2375 +2243 4 5 -550 +584 5 -32 -423 +8 +497 -44 -5703 -5 +8 +5744 +307 @@ -18281,37 +18401,37 @@ 1 2 -739 +938 2 3 -1537 +1689 3 4 -1776 +1624 4 5 -265 +317 5 6 -643 +726 6 -7 -425 +8 +552 -7 -1531 -249 +8 +1274 +246 @@ -18327,12 +18447,17 @@ 1 2 -2371 +2690 2 -3967 -150 +20 +227 + + +20 +4903 +102 @@ -18348,7 +18473,7 @@ 1 2 -2521 +3019 @@ -18364,12 +18489,17 @@ 1 2 -2371 +2690 2 -3967 -150 +20 +227 + + +20 +4903 +102 @@ -18385,12 +18515,17 @@ 1 2 -2407 +2786 2 -3967 -114 +555 +227 + + +562 +4006 +6 @@ -18400,15 +18535,15 @@ indexer_location -40309 +38478 id -25314 +29534 loc -1604 +1544 @@ -18422,22 +18557,17 @@ 1 2 -19371 +24841 2 3 -3547 +3236 3 -10 -1912 - - -10 -19 -484 +18 +1457 @@ -18453,37 +18583,37 @@ 1 2 -1040 +984 2 3 -77 +85 3 4 -72 +66 4 6 -120 +115 6 -14 -144 +13 +119 -14 -127 -121 +13 +57 +117 -127 -6138 -30 +59 +6373 +58 @@ -18493,11 +18623,11 @@ accessors -336633 +393080 id -336633 +393080 kind @@ -18505,15 +18635,15 @@ name -74791 +67062 declaring_member_id -286717 +339184 unbound_id -211967 +251384 @@ -18527,7 +18657,7 @@ 1 2 -336633 +393080 @@ -18543,7 +18673,7 @@ 1 2 -336633 +393080 @@ -18559,7 +18689,7 @@ 1 2 -336633 +393080 @@ -18575,7 +18705,7 @@ 1 2 -336633 +393080 @@ -18589,13 +18719,13 @@ 12 -50195 -50196 +54213 +54214 1 -286438 -286439 +338867 +338868 1 @@ -18610,13 +18740,13 @@ 12 -14093 -14094 +11762 +11763 1 -60698 -60699 +55300 +55301 1 @@ -18631,13 +18761,13 @@ 12 -50186 -50187 +52525 +52526 1 -286438 -286439 +338844 +338845 1 @@ -18652,13 +18782,13 @@ 12 -36119 -36120 +39797 +39798 1 -175848 -175849 +211587 +211588 1 @@ -18675,27 +18805,32 @@ 1 2 -46914 +35118 2 3 -15055 +16521 3 -5 -6355 +4 +3142 -5 -29 -5645 +4 +6 +5072 -29 -17446 -822 +6 +15 +5054 + + +15 +21474 +2155 @@ -18711,7 +18846,7 @@ 1 2 -74791 +67062 @@ -18727,27 +18862,32 @@ 1 2 -46917 +35213 2 3 -15053 +16742 3 -5 -6354 +4 +3102 -5 -29 -5645 +4 +6 +4876 -29 -17446 -822 +6 +16 +5111 + + +16 +21474 +2018 @@ -18763,27 +18903,32 @@ 1 2 -47440 +35393 2 3 -15185 +16651 3 -5 -6280 +4 +3073 -5 -55 -5613 +4 +6 +5095 -55 -2297 -273 +6 +17 +5105 + + +17 +3014 +1745 @@ -18799,17 +18944,17 @@ 1 2 -236810 +286982 2 3 -49898 +50646 3 -4 -9 +6 +1556 @@ -18825,12 +18970,12 @@ 1 2 -236810 +286999 2 3 -49907 +52185 @@ -18846,12 +18991,12 @@ 1 2 -236810 +286999 2 3 -49907 +52185 @@ -18867,17 +19012,17 @@ 1 2 -236810 +286982 2 3 -49898 +50646 3 -4 -9 +6 +1556 @@ -18893,12 +19038,12 @@ 1 2 -208543 +246685 2 -5604 -3424 +7099 +4699 @@ -18914,7 +19059,7 @@ 1 2 -211967 +251384 @@ -18930,7 +19075,7 @@ 1 2 -211967 +251384 @@ -18946,12 +19091,12 @@ 1 2 -208543 +246685 2 -5604 -3424 +7099 +4699 @@ -18961,15 +19106,15 @@ accessor_location -760991 +728766 id -336633 +393080 loc -87557 +75018 @@ -18983,27 +19128,27 @@ 1 2 -178438 +218037 2 3 -91540 +109741 3 4 -22414 +17821 4 -7 -27767 +5 +32479 -7 -257 -16474 +5 +18 +15002 @@ -19019,12 +19164,12 @@ 1 2 -84261 +70907 2 -38689 -3296 +39694 +4111 @@ -19034,27 +19179,27 @@ events -8976 +7794 id -8976 +7794 name -3901 +2035 declaring_type_id -2161 +2249 type_id -2621 +1984 unbound_id -8739 +7233 @@ -19068,7 +19213,7 @@ 1 2 -8976 +7794 @@ -19084,7 +19229,7 @@ 1 2 -8976 +7794 @@ -19100,7 +19245,7 @@ 1 2 -8976 +7794 @@ -19116,7 +19261,7 @@ 1 2 -8976 +7794 @@ -19132,27 +19277,37 @@ 1 2 -2559 +676 2 3 -356 +303 3 4 -557 +561 4 -9 -293 +5 +135 -9 -148 -136 +5 +7 +158 + + +7 +16 +157 + + +16 +173 +45 @@ -19168,22 +19323,32 @@ 1 2 -2559 +676 2 3 -824 +772 3 -6 -315 +4 +116 -6 -107 -203 +4 +5 +199 + + +5 +8 +154 + + +8 +125 +118 @@ -19199,17 +19364,22 @@ 1 2 -3548 +1496 2 +3 +268 + + +3 5 -304 +173 5 -26 -49 +27 +98 @@ -19225,27 +19395,37 @@ 1 2 -2577 +677 2 3 -351 +308 3 4 -554 +556 4 -10 -311 +5 +136 -10 -76 -108 +5 +7 +159 + + +7 +16 +156 + + +16 +101 +43 @@ -19261,37 +19441,32 @@ 1 2 -877 +970 2 3 -532 +554 3 4 -187 +192 4 5 -172 +177 5 -8 -181 - - -8 -19 -163 +9 +206 -19 -465 -49 +9 +127 +150 @@ -19307,32 +19482,32 @@ 1 2 -1091 +1184 2 3 -429 +459 3 4 -204 +205 4 -5 -112 +6 +204 -5 -8 -179 +6 +18 +169 -8 -465 -146 +18 +127 +28 @@ -19348,27 +19523,27 @@ 1 2 -1345 +1282 2 3 -373 +518 3 4 -195 +182 4 7 -166 +194 7 -181 -82 +39 +73 @@ -19384,37 +19559,32 @@ 1 2 -877 +970 2 3 -532 +554 3 4 -187 +192 4 5 -172 +177 5 -8 -181 - - -8 -19 -163 +9 +206 -19 -465 -49 +9 +127 +150 @@ -19430,27 +19600,32 @@ 1 2 -1063 +643 2 3 -456 +313 3 4 -764 +717 4 -7 -204 +6 +109 -7 -1070 -134 +6 +13 +152 + + +13 +1024 +50 @@ -19466,22 +19641,17 @@ 1 2 -2009 +1649 2 3 -384 +204 3 -9 -197 - - -9 -435 -31 +402 +131 @@ -19497,17 +19667,22 @@ 1 2 -1456 +766 2 3 -987 +1012 3 -363 -178 +7 +169 + + +7 +346 +37 @@ -19523,27 +19698,32 @@ 1 2 -1065 +645 2 3 -457 +313 3 4 -763 +717 4 -7 -206 +6 +110 -7 -1059 -130 +6 +13 +150 + + +13 +1024 +49 @@ -19559,12 +19739,12 @@ 1 2 -8689 +7200 2 33 -50 +33 @@ -19580,7 +19760,7 @@ 1 2 -8739 +7233 @@ -19596,12 +19776,12 @@ 1 2 -8689 +7200 2 33 -50 +33 @@ -19617,12 +19797,12 @@ 1 2 -8725 +6901 2 -26 -14 +6 +332 @@ -19632,15 +19812,15 @@ event_location -13927 +11829 id -8976 +7413 loc -1497 +1034 @@ -19654,17 +19834,22 @@ 1 2 -6948 +5015 2 3 -1532 +1707 3 -19 -496 +8 +567 + + +8 +11 +124 @@ -19680,22 +19865,32 @@ 1 2 -1123 +693 2 -4 -136 +3 +64 -4 -13 -126 +3 +6 +89 -13 +6 +14 +80 + + +14 +34 +78 + + +36 2320 -112 +30 @@ -19705,11 +19900,11 @@ event_accessors -15714 +13062 id -15714 +13062 kind @@ -19717,15 +19912,15 @@ name -7856 +4162 declaring_event_id -7857 +6326 unbound_id -15240 +12702 @@ -19739,7 +19934,7 @@ 1 2 -15714 +13062 @@ -19755,7 +19950,7 @@ 1 2 -15714 +13062 @@ -19771,7 +19966,7 @@ 1 2 -15714 +13062 @@ -19787,7 +19982,7 @@ 1 2 -15714 +13062 @@ -19801,8 +19996,8 @@ 12 -7857 -7858 +6531 +6532 2 @@ -19817,8 +20012,8 @@ 12 -3928 -3929 +2081 +2082 2 @@ -19833,8 +20028,8 @@ 12 -7857 -7858 +6326 +6327 2 @@ -19849,8 +20044,8 @@ 12 -7620 -7621 +6351 +6352 2 @@ -19867,22 +20062,32 @@ 1 2 -5204 +1424 2 3 -1630 +1530 3 -6 -616 +4 +210 -6 -97 -406 +4 +5 +448 + + +5 +9 +358 + + +9 +117 +192 @@ -19898,7 +20103,7 @@ 1 2 -7856 +4162 @@ -19914,22 +20119,32 @@ 1 2 -5204 +1436 2 3 -1630 +1560 3 -6 -616 +4 +220 -6 -97 -406 +4 +5 +434 + + +5 +9 +326 + + +9 +111 +186 @@ -19945,22 +20160,32 @@ 1 2 -5240 +1426 2 3 -1622 +1540 3 -6 -596 +4 +200 -6 -58 -398 +4 +5 +450 + + +5 +9 +356 + + +9 +78 +190 @@ -19976,7 +20201,12 @@ 2 3 -7857 +6176 + + +4 +11 +150 @@ -19992,7 +20222,7 @@ 2 3 -7857 +6326 @@ -20008,7 +20238,7 @@ 2 3 -7857 +6326 @@ -20024,7 +20254,12 @@ 2 3 -7857 +6176 + + +4 +11 +150 @@ -20040,12 +20275,12 @@ 1 2 -15140 +12636 2 33 -100 +66 @@ -20061,7 +20296,7 @@ 1 2 -15240 +12702 @@ -20077,7 +20312,7 @@ 1 2 -15240 +12702 @@ -20093,12 +20328,12 @@ 1 2 -15140 +12636 2 33 -100 +66 @@ -20108,15 +20343,15 @@ event_accessor_location -23116 +19010 id -15714 +13062 loc -1813 +1353 @@ -20130,17 +20365,22 @@ 1 2 -14122 +10644 2 -8 -1180 +3 +1092 -8 -19 -412 +3 +6 +994 + + +6 +11 +332 @@ -20156,27 +20396,32 @@ 1 2 -648 +634 2 3 -798 +382 4 7 -136 +119 8 -29 -137 +25 +108 -30 +26 +221 +102 + + +262 4639 -94 +8 @@ -20186,11 +20431,11 @@ operators -13320 +18266 id -13320 +18266 name @@ -20202,15 +20447,15 @@ declaring_type_id -5147 +5817 type_id -1724 +2366 unbound_id -7036 +10445 @@ -20224,7 +20469,7 @@ 1 2 -13320 +18266 @@ -20240,7 +20485,7 @@ 1 2 -13320 +18266 @@ -20256,7 +20501,7 @@ 1 2 -13320 +18266 @@ -20272,7 +20517,7 @@ 1 2 -13320 +18266 @@ -20288,7 +20533,7 @@ 1 2 -13320 +18266 @@ -20302,69 +20547,69 @@ 12 -4 -5 -2 +6 +7 +3 -5 -6 +9 +10 2 -6 -12 +19 +22 2 -12 -18 +28 +32 2 -20 -30 +43 +86 2 -31 -53 +107 +165 2 -94 -127 +178 +209 2 -128 -134 +212 +231 2 -142 -168 +253 +290 2 -205 -215 +298 +427 2 -332 -346 +457 +1688 2 -723 -1751 +2364 +5359 2 -4233 -4530 -2 +5757 +5758 +1 @@ -20394,69 +20639,69 @@ 12 -4 -5 -2 +6 +7 +3 -5 -6 +9 +10 2 -6 -12 +19 +22 2 -12 -18 +28 +32 2 -20 -30 +42 +84 2 -31 -36 +84 +102 2 -47 -119 +163 +189 2 -124 -127 +192 +196 2 -129 -142 +229 +270 2 -201 -211 +278 +426 2 -330 -344 +456 +720 2 -432 -1105 +1349 +3839 2 -3261 -3558 -2 +4237 +4238 +1 @@ -20475,58 +20720,53 @@ 2 -2 -3 -6 - - -3 -4 -1 - - 5 6 -2 +7 -11 -13 +9 +10 2 -17 -21 +19 +22 2 -29 +28 32 2 -35 -48 +43 +85 2 -103 -127 +85 +103 2 -141 -330 +164 +182 2 -342 -435 +230 +427 2 -882 -883 +457 +722 +2 + + +1182 +1183 1 @@ -20541,73 +20781,68 @@ 12 -4 -5 -2 +6 +7 +3 -5 -6 +9 +10 2 -6 -12 +19 +22 2 -12 -13 -1 - - -17 -18 +28 +32 2 -28 -30 +40 +83 2 -49 -86 +104 +162 2 -123 -129 +169 +209 2 -133 -140 +212 +228 2 -164 -206 +250 +290 2 -214 -330 +298 +424 2 -342 -380 +454 +948 2 -488 -1913 +1223 +2413 2 -2208 -2209 +2811 +2812 1 @@ -20622,64 +20857,64 @@ 12 -4 -5 -2 +6 +7 +3 -5 -6 +9 +10 2 -6 -13 +19 +29 2 -17 -21 +31 +44 2 -29 -53 +107 +165 2 -94 -127 +178 +209 2 -128 -134 +212 +275 2 -173 -179 +289 +299 2 -205 -215 +315 +427 2 -332 -346 +457 +1688 2 -723 -1751 +2364 +5359 2 -4233 -4530 -2 +5757 +5758 +1 @@ -20714,64 +20949,64 @@ 12 -4 -5 -2 +6 +7 +3 -5 -6 +9 +10 2 -6 -13 +19 +29 2 -17 -21 +31 +43 2 -29 -36 +83 +102 2 -47 -121 +163 +189 2 -124 -127 +192 +197 2 -129 -142 +229 +270 2 -201 -211 +278 +426 2 -330 -344 +456 +720 2 -432 -1105 +1349 +3839 2 -3261 -3558 -2 +4237 +4238 +1 @@ -20790,53 +21025,48 @@ 2 -2 -3 -6 - - -3 -4 -1 - - 5 6 +7 + + +9 +10 2 -12 -18 +19 +29 2 -20 -30 +31 +44 2 -35 -48 +84 +103 2 -105 -127 +164 +183 2 -141 -330 +230 +427 2 -342 -435 +457 +722 2 -882 -883 +1182 +1183 1 @@ -20851,64 +21081,64 @@ 12 -4 -5 -2 +6 +7 +3 -5 -6 +9 +10 2 -6 -13 +19 +29 2 -17 -18 +31 +41 2 -29 -50 +104 +162 2 -85 -124 +169 +209 2 -128 -134 +212 +272 2 -167 -176 +289 +299 2 -205 -215 +309 +424 2 -329 -343 +454 +948 2 -379 -489 +1223 +2413 2 -1912 -2209 -2 +2811 +2812 +1 @@ -20924,27 +21154,32 @@ 1 2 -1742 +1558 2 3 -1542 +1877 3 4 -257 +306 4 5 -1272 +1290 5 -77 -334 +7 +493 + + +7 +114 +293 @@ -20960,27 +21195,27 @@ 1 2 -1880 +1727 2 3 -2392 +2878 3 4 -476 +588 4 -14 -387 +7 +490 -14 +7 24 -12 +134 @@ -20996,27 +21231,27 @@ 1 2 -1880 +1727 2 3 -2393 +2878 3 4 -475 +588 4 -13 -388 +7 +506 -15 +7 22 -11 +118 @@ -21032,17 +21267,22 @@ 1 2 -3956 +4141 2 3 -890 +1168 3 -41 -301 +5 +474 + + +5 +60 +34 @@ -21058,27 +21298,32 @@ 1 2 -1742 +1558 2 3 -1542 +1877 3 4 -255 +303 4 5 -1273 +1290 5 -77 -335 +7 +494 + + +7 +114 +295 @@ -21094,22 +21339,27 @@ 1 2 -1083 +1331 2 3 -364 +576 3 4 -154 +228 4 -9483 -123 +18 +178 + + +18 +11857 +53 @@ -21125,22 +21375,22 @@ 1 2 -1305 +1779 2 3 -240 +307 3 5 -139 +185 5 18 -40 +95 @@ -21156,22 +21406,22 @@ 1 2 -1305 +1779 2 3 -241 +308 3 5 -143 +203 5 16 -35 +76 @@ -21187,17 +21437,17 @@ 1 2 -1553 +2031 2 -5 -135 +3 +181 -5 -4333 -36 +3 +4808 +154 @@ -21213,22 +21463,27 @@ 1 2 -1092 +1375 2 3 -367 +566 3 4 -157 +214 4 -4753 -108 +21 +182 + + +23 +5960 +29 @@ -21244,12 +21499,12 @@ 1 2 -6925 +10278 2 -954 -111 +957 +167 @@ -21265,7 +21520,7 @@ 1 2 -7036 +10445 @@ -21281,7 +21536,7 @@ 1 2 -7036 +10445 @@ -21297,12 +21552,12 @@ 1 2 -6925 +10278 2 -954 -111 +957 +167 @@ -21318,12 +21573,12 @@ 1 2 -6996 +10375 2 -316 -40 +436 +70 @@ -21333,15 +21588,15 @@ operator_location -26888 +27407 id -8870 +13504 loc -2942 +2763 @@ -21355,32 +21610,27 @@ 1 2 -5627 +8747 2 3 -1265 +2266 3 -5 -670 +4 +753 -5 -15 -602 +4 +8 +911 -15 +8 18 -699 - - -18 -21 -7 +827 @@ -21396,22 +21646,22 @@ 1 2 -2404 +2250 2 -5 -270 +4 +220 -5 -121 -221 +4 +58 +209 -136 -3457 -47 +58 +4153 +84 @@ -21421,15 +21671,15 @@ constant_value -109873 +149474 id -108394 +149448 value -26585 +25399 @@ -21443,12 +21693,12 @@ 1 2 -107086 +149422 2 -5 -1308 +3 +26 @@ -21464,22 +21714,27 @@ 1 2 -20463 +15881 2 3 -3137 +4778 3 -8 -2119 +5 +2077 -8 -8085 -866 +5 +12 +1909 + + +12 +10788 +754 @@ -21489,27 +21744,27 @@ methods -990339 +1183684 id -990339 +1183684 name -145323 +134084 declaring_type_id -115072 +133860 type_id -75864 +95938 unbound_id -416703 +526541 @@ -21523,7 +21778,7 @@ 1 2 -990339 +1183684 @@ -21539,7 +21794,7 @@ 1 2 -990339 +1183684 @@ -21555,7 +21810,7 @@ 1 2 -990339 +1183684 @@ -21571,7 +21826,7 @@ 1 2 -990339 +1183684 @@ -21587,27 +21842,27 @@ 1 2 -103232 +88559 2 3 -18945 +18867 3 5 -11241 +11037 5 -60 -10906 +13 +10205 -60 -33554 -999 +13 +41109 +5416 @@ -21623,22 +21878,27 @@ 1 2 -107949 +92496 2 3 -17436 +18555 3 -6 -12134 +5 +10104 -6 -17745 -7804 +5 +19 +10202 + + +19 +21909 +2727 @@ -21654,17 +21914,17 @@ 1 2 -134024 +118086 2 -124 -10936 +4 +10444 -124 -13470 -363 +4 +16981 +5554 @@ -21680,22 +21940,27 @@ 1 2 -105154 +89804 2 3 -19254 +19187 3 5 -11116 +11028 5 -8756 -9799 +15 +10315 + + +15 +9650 +3750 @@ -21711,47 +21976,47 @@ 1 2 -30339 +37015 2 3 -17979 +17719 3 4 -20209 +23020 4 5 -7063 +9486 5 6 -11230 +13094 6 10 -9248 +10992 10 21 -8656 +10067 21 82 -9133 +10827 82 -4659 -1215 +2721 +1640 @@ -21767,42 +22032,42 @@ 1 2 -31840 +39708 2 3 -18946 +20610 3 4 -20938 +24897 4 5 -10198 +10091 5 6 -9143 +10989 6 10 -8968 +10083 10 -22 -8901 +21 +10169 -22 +21 2630 -6138 +7313 @@ -21818,32 +22083,32 @@ 1 2 -46532 +53734 2 3 -36855 +44021 3 4 -8749 +9050 4 -5 -8055 +6 +12331 -5 -9 -8673 +6 +13 +10314 -9 -2310 -6208 +13 +1435 +4410 @@ -21859,47 +22124,47 @@ 1 2 -30464 +37120 2 3 -17990 +17732 3 4 -20224 +23026 4 5 -7078 +9496 5 6 -11238 +13109 6 10 -9259 +11009 10 -22 -8857 +21 +10050 -22 +21 82 -8820 +10745 82 -2631 -1142 +2634 +1573 @@ -21915,32 +22180,27 @@ 1 2 -45668 +58934 2 3 -13238 +16031 3 -4 -5192 - - -4 -10 -5878 +5 +8772 -10 -221 -5798 +5 +17 +7197 -224 -281834 -90 +17 +325334 +5004 @@ -21956,22 +22216,22 @@ 1 2 -56967 +74195 2 3 -7755 +8668 3 -7 -5788 +8 +7691 -7 -66425 -5354 +8 +61151 +5384 @@ -21987,22 +22247,22 @@ 1 2 -53716 +67793 2 3 -13964 +17642 3 -7 -6247 +6 +7213 -7 -56084 -1937 +6 +63071 +3290 @@ -22018,32 +22278,27 @@ 1 2 -45760 +58983 2 3 -13288 +16197 3 -4 -5214 - - -4 -10 -5845 +5 +8734 -10 -252 -5691 +5 +18 +7281 -254 -149113 -66 +18 +175281 +4743 @@ -22059,12 +22314,12 @@ 1 2 -401515 +504345 2 -8127 -15188 +10883 +22196 @@ -22080,7 +22335,7 @@ 1 2 -416703 +526541 @@ -22096,12 +22351,12 @@ 1 2 -404324 +507671 2 -8127 -12379 +10883 +18870 @@ -22117,12 +22372,12 @@ 1 2 -410109 +511409 2 -8127 -6594 +10889 +15132 @@ -22132,15 +22387,15 @@ method_location -2069011 +2029259 id -989823 +1176044 loc -225377 +207281 @@ -22154,27 +22409,27 @@ 1 2 -481413 +641931 2 3 -351054 +392731 3 4 -59147 +45310 4 9 -74877 +90857 9 -24 -23332 +18 +5215 @@ -22190,12 +22445,17 @@ 1 2 -213144 +190293 2 -117240 -12233 +97 +15549 + + +97 +122930 +1439 @@ -22205,23 +22465,23 @@ constructors -149144 +171824 id -149144 +171824 name -54143 +47516 declaring_type_id -101619 +112258 unbound_id -98805 +118081 @@ -22235,7 +22495,7 @@ 1 2 -149144 +171824 @@ -22251,7 +22511,7 @@ 1 2 -149144 +171824 @@ -22267,7 +22527,7 @@ 1 2 -149144 +171824 @@ -22283,22 +22543,27 @@ 1 2 -39528 +29299 2 3 -8842 +9048 3 +4 +2448 + + +4 7 -4536 +4174 7 -7428 -1237 +9204 +2547 @@ -22314,17 +22579,22 @@ 1 2 -47190 +34025 2 3 -4506 +7559 3 -5277 -2447 +6 +4238 + + +6 +6154 +1694 @@ -22340,22 +22610,27 @@ 1 2 -40238 +29766 2 3 -8855 +9080 3 +4 +2367 + + +4 7 -4181 +4051 7 -4418 -869 +3757 +2252 @@ -22371,22 +22646,22 @@ 1 2 -80662 +87385 2 3 -11743 +13079 3 -8 -7758 +7 +8631 -8 -42 -1456 +7 +84 +3163 @@ -22402,7 +22677,7 @@ 1 2 -101619 +112258 @@ -22418,22 +22693,22 @@ 1 2 -80662 +87383 2 3 -11743 +13081 3 -8 -7758 +7 +8629 -8 -42 -1456 +7 +84 +3165 @@ -22449,12 +22724,12 @@ 1 2 -96762 +115422 2 -3787 -2043 +1848 +2659 @@ -22470,7 +22745,7 @@ 1 2 -98805 +118081 @@ -22486,12 +22761,12 @@ 1 2 -96762 +115422 2 -3787 -2043 +1848 +2659 @@ -22501,15 +22776,15 @@ constructor_location -294390 +283625 id -149141 +171819 loc -44163 +37542 @@ -22523,27 +22798,22 @@ 1 2 -95933 +109508 2 3 -26780 +35225 3 4 -12519 +14677 4 -13 -11784 - - -13 -591 -2125 +17 +12409 @@ -22559,17 +22829,17 @@ 1 2 -39468 +33267 2 -7 -3388 +6 +2946 -7 -17601 -1307 +6 +17817 +1329 @@ -22579,23 +22849,23 @@ destructors -388 +569 id -388 +569 name -300 +313 declaring_type_id -388 +569 unbound_id -315 +503 @@ -22609,7 +22879,7 @@ 1 2 -388 +569 @@ -22625,7 +22895,7 @@ 1 2 -388 +569 @@ -22641,7 +22911,7 @@ 1 2 -388 +569 @@ -22657,12 +22927,22 @@ 1 2 -278 +214 2 -23 -22 +3 +61 + + +3 +6 +27 + + +6 +26 +11 @@ -22678,12 +22958,22 @@ 1 2 -278 +214 2 -23 -22 +3 +61 + + +3 +6 +27 + + +6 +26 +11 @@ -22699,12 +22989,22 @@ 1 2 -287 +217 2 -4 -13 +3 +62 + + +3 +6 +26 + + +6 +12 +8 @@ -22720,7 +23020,7 @@ 1 2 -388 +569 @@ -22736,7 +23036,7 @@ 1 2 -388 +569 @@ -22752,7 +23052,7 @@ 1 2 -388 +569 @@ -22768,12 +23068,12 @@ 1 2 -304 +491 2 -23 -11 +22 +12 @@ -22789,7 +23089,7 @@ 1 2 -315 +503 @@ -22805,12 +23105,12 @@ 1 2 -304 +491 2 -23 -11 +22 +12 @@ -22820,15 +23120,15 @@ destructor_location -1101 +1270 id -388 +569 loc -381 +371 @@ -22842,32 +23142,27 @@ 1 2 -197 +247 2 3 -69 +143 3 4 -38 +53 4 -7 -35 - - -7 -12 -35 +5 +93 -12 -18 -14 +5 +17 +33 @@ -22883,7 +23178,7 @@ 1 2 -256 +243 2 @@ -22898,17 +23193,17 @@ 4 6 -33 +32 6 -22 -29 +20 +28 -22 -33 -7 +20 +75 +12 @@ -22918,15 +23213,15 @@ overrides -117202 +157613 id -116553 +153631 base_id -31431 +45218 @@ -22940,12 +23235,12 @@ 1 2 -115904 +149718 2 -3 -649 +6 +3913 @@ -22961,27 +23256,32 @@ 1 2 -18013 +24514 2 3 -6343 +9725 3 4 -2243 +3456 4 7 -2620 +4118 7 -3939 -2212 +466 +3392 + + +466 +3858 +13 @@ -22991,15 +23291,15 @@ explicitly_implements -181041 +219576 id -181041 +219576 interface_id -21520 +26939 @@ -23013,7 +23313,7 @@ 1 2 -181041 +219576 @@ -23029,42 +23329,42 @@ 1 2 -8591 +10815 2 3 -4158 +5175 3 4 -1973 +2496 4 5 -666 +901 5 6 -2548 +3149 6 -10 -1626 +11 +2183 -10 -19 -1621 +11 +43 +2025 -19 -24037 -337 +43 +11723 +195 @@ -23074,11 +23374,11 @@ local_functions -1201 +1225 id -1201 +1225 name @@ -23086,11 +23386,11 @@ return_type -169 +173 unbound_id -1199 +1223 @@ -23104,7 +23404,7 @@ 1 2 -1201 +1225 @@ -23120,7 +23420,7 @@ 1 2 -1201 +1225 @@ -23136,7 +23436,7 @@ 1 2 -1201 +1225 @@ -23152,17 +23452,17 @@ 1 2 -668 +655 2 4 -60 +68 4 102 -27 +32 @@ -23178,12 +23478,12 @@ 1 2 -747 +746 2 4 -8 +9 @@ -23199,17 +23499,17 @@ 1 2 -669 +656 2 4 -59 +67 4 102 -27 +32 @@ -23235,12 +23535,17 @@ 3 5 -13 +15 5 -697 -12 +171 +13 + + +708 +709 +1 @@ -23256,7 +23561,7 @@ 1 2 -133 +135 2 @@ -23265,11 +23570,11 @@ 3 -8 -13 +7 +15 -15 +9 301 6 @@ -23297,12 +23602,17 @@ 3 5 -13 +15 5 -697 -12 +171 +13 + + +708 +709 +1 @@ -23318,7 +23628,7 @@ 1 2 -1198 +1222 3 @@ -23339,7 +23649,7 @@ 1 2 -1199 +1223 @@ -23355,7 +23665,7 @@ 1 2 -1198 +1222 3 @@ -23370,15 +23680,15 @@ local_function_stmts -1199 +1335 fn -1199 +1335 stmt -1199 +1223 @@ -23392,7 +23702,7 @@ 1 2 -1199 +1335 @@ -23408,7 +23718,12 @@ 1 2 -1199 +1163 + + +2 +4 +60 @@ -23418,11 +23733,11 @@ fields -285648 +345655 id -285648 +345655 kind @@ -23430,19 +23745,19 @@ name -127772 +119955 declaring_type_id -58158 +63411 type_id -47955 +61091 unbound_id -267317 +316899 @@ -23456,7 +23771,7 @@ 1 2 -285648 +345655 @@ -23472,7 +23787,7 @@ 1 2 -285648 +345655 @@ -23488,7 +23803,7 @@ 1 2 -285648 +345655 @@ -23504,7 +23819,7 @@ 1 2 -285648 +345655 @@ -23520,7 +23835,7 @@ 1 2 -285648 +345655 @@ -23534,13 +23849,13 @@ 12 -106769 -106770 +147707 +147708 1 -178578 -178579 +187149 +187150 1 @@ -23555,13 +23870,13 @@ 12 -54214 -54215 +49719 +49720 1 -76116 -76117 +72553 +72554 1 @@ -23576,13 +23891,13 @@ 12 -10999 -11000 +14304 +14305 1 -49829 -49830 +50951 +50952 1 @@ -23597,13 +23912,13 @@ 12 -7955 -7956 +10750 +10751 1 -41759 -41760 +52512 +52513 1 @@ -23618,13 +23933,13 @@ 12 -106161 -106162 +147035 +147036 1 -161161 -161162 +169869 +169870 1 @@ -23641,22 +23956,27 @@ 1 2 -101759 +79665 2 3 -13893 +21311 3 -9 -9606 +5 +9796 -9 -7502 -2514 +5 +92 +8997 + + +92 +6652 +186 @@ -23672,12 +23992,12 @@ 1 2 -125214 +117638 2 3 -2558 +2317 @@ -23693,22 +24013,27 @@ 1 2 -101759 +79665 2 3 -13893 +21311 3 -9 -9606 +5 +9796 -9 -7502 -2514 +5 +92 +8997 + + +92 +6652 +186 @@ -23724,17 +24049,22 @@ 1 2 -111990 +90184 2 3 -9417 +17169 3 -4791 -6365 +8 +9686 + + +8 +4099 +2916 @@ -23750,22 +24080,22 @@ 1 2 -102538 +80248 2 3 -13899 +21408 3 -11 -9600 +5 +9617 -11 -7502 -1735 +5 +6652 +8682 @@ -23781,42 +24111,42 @@ 1 2 -13468 +14274 2 3 -13970 +14991 3 4 -9308 +10294 4 5 -5925 +6512 5 6 -3861 +3957 6 8 -4917 +5374 8 -15 -4612 +14 +4901 -15 +14 4792 -2097 +3108 @@ -23832,12 +24162,12 @@ 1 2 -55488 +61567 2 3 -2670 +1844 @@ -23853,42 +24183,42 @@ 1 2 -13468 +14274 2 3 -13970 +14991 3 4 -9308 +10294 4 5 -5925 +6512 5 6 -3861 +3957 6 8 -4917 +5374 8 -15 -4612 +14 +4901 -15 +14 4792 -2097 +3108 @@ -23904,32 +24234,32 @@ 1 2 -23657 +28364 2 3 -16254 +15388 3 4 -6661 +7113 4 5 -3854 +3655 5 -7 -4345 +8 +5720 -7 +8 569 -3387 +3171 @@ -23945,42 +24275,42 @@ 1 2 -13468 +14274 2 3 -13970 +14991 3 4 -9308 +10294 4 5 -5925 +6512 5 6 -3861 +3957 6 8 -4917 +5374 8 -15 -4612 +14 +4901 -15 +14 4792 -2097 +3108 @@ -23996,32 +24326,32 @@ 1 2 -28567 +36047 2 3 -6526 +8714 3 4 -3634 +4830 4 6 -3781 +4598 6 15 -3728 +4677 15 -38777 -1719 +44112 +2225 @@ -24037,12 +24367,12 @@ 1 2 -46196 +58920 2 3 -1759 +2171 @@ -24058,27 +24388,27 @@ 1 2 -31776 +39393 2 3 -5924 +7943 3 4 -3057 +4291 4 7 -3977 +5065 7 -22007 -3221 +21402 +4399 @@ -24094,22 +24424,22 @@ 1 2 -36247 +46553 2 3 -5872 +8053 3 -6 -3680 +7 +4656 -6 -13299 -2156 +7 +13834 +1829 @@ -24125,32 +24455,32 @@ 1 2 -28687 +36177 2 3 -6534 +8726 3 4 -3601 +4784 4 6 -3767 +4580 6 15 -3691 +4634 15 -36782 -1675 +42017 +2190 @@ -24166,12 +24496,12 @@ 1 2 -264767 +314171 2 -954 -2550 +957 +2728 @@ -24187,7 +24517,7 @@ 1 2 -267312 +316894 2 @@ -24208,7 +24538,7 @@ 1 2 -267317 +316899 @@ -24224,12 +24554,12 @@ 1 2 -264767 +314171 2 -954 -2550 +957 +2728 @@ -24245,12 +24575,12 @@ 1 2 -265821 +305378 2 -954 -1496 +957 +11521 @@ -24260,15 +24590,15 @@ field_location -665606 +680142 id -283536 +327265 loc -100719 +93985 @@ -24282,27 +24612,27 @@ 1 2 -110804 +114298 2 3 -112944 +143264 3 4 -21535 +28161 4 -7 -25436 +5 +32658 -7 -534 -12817 +5 +18 +8884 @@ -24318,12 +24648,17 @@ 1 2 -95087 +83759 2 +5 +7464 + + +5 9082 -5632 +2762 @@ -24333,11 +24668,11 @@ localvars -309450 +291058 id -309450 +291058 kind @@ -24345,7 +24680,7 @@ name -50758 +45721 implicitly_typed @@ -24353,11 +24688,11 @@ type_id -19087 +18890 parent_id -309450 +291058 @@ -24371,7 +24706,7 @@ 1 2 -309450 +291058 @@ -24387,7 +24722,7 @@ 1 2 -309450 +291058 @@ -24403,7 +24738,7 @@ 1 2 -309450 +291058 @@ -24419,7 +24754,7 @@ 1 2 -309450 +291058 @@ -24435,7 +24770,7 @@ 1 2 -309450 +291058 @@ -24449,18 +24784,18 @@ 12 -54 -55 +70 +71 1 -1627 -1628 +1741 +1742 1 -307769 -307770 +289247 +289248 1 @@ -24480,13 +24815,13 @@ 1 -783 -784 +719 +720 1 -50117 -50118 +45123 +45124 1 @@ -24522,18 +24857,18 @@ 12 -21 -22 +29 +30 1 -43 -44 +49 +50 1 -19072 -19073 +18869 +18870 1 @@ -24548,18 +24883,18 @@ 12 -54 -55 +70 +71 1 -1627 -1628 +1741 +1742 1 -307769 -307770 +289247 +289248 1 @@ -24576,27 +24911,32 @@ 1 2 -31599 +27463 2 3 -8221 +7549 3 4 -3292 +3193 4 -8 -4188 +7 +3665 -8 -14339 -3458 +7 +76 +3434 + + +76 +14308 +417 @@ -24612,12 +24952,12 @@ 1 2 -50585 +45569 2 3 -173 +152 @@ -24633,12 +24973,12 @@ 1 2 -45779 +41398 2 3 -4979 +4323 @@ -24654,17 +24994,17 @@ 1 2 -43415 +38504 2 3 -4121 +4024 3 -1514 -3222 +1437 +3193 @@ -24680,27 +25020,32 @@ 1 2 -31599 +27463 2 3 -8221 +7549 3 4 -3292 +3193 4 -8 -4188 +7 +3665 -8 -14339 -3458 +7 +76 +3434 + + +76 +14308 +417 @@ -24714,13 +25059,13 @@ 12 -119948 -119949 +120891 +120892 1 -189502 -189503 +170167 +170168 1 @@ -24756,13 +25101,13 @@ 12 -27809 -27810 +23673 +23674 1 -27928 -27929 +26371 +26372 1 @@ -24777,13 +25122,13 @@ 12 -9524 -9525 +10122 +10123 1 -12356 -12357 +11399 +11400 1 @@ -24798,13 +25143,13 @@ 12 -119948 -119949 +120891 +120892 1 -189502 -189503 +170167 +170168 1 @@ -24821,37 +25166,37 @@ 1 2 -8834 +8936 2 3 -3200 +3256 3 4 -1561 +1573 4 6 -1732 +1639 6 10 -1473 +1418 10 -29 -1446 +34 +1423 -29 -57038 -841 +34 +54940 +645 @@ -24867,12 +25212,12 @@ 1 2 -19041 +18836 2 4 -46 +54 @@ -24888,27 +25233,27 @@ 1 2 -11861 +11811 2 3 -3127 +3125 3 4 -1302 +1288 4 7 -1505 +1453 7 -5718 -1292 +5354 +1213 @@ -24924,12 +25269,12 @@ 1 2 -16294 +16259 2 3 -2793 +2631 @@ -24945,37 +25290,37 @@ 1 2 -8834 +8936 2 3 -3200 +3256 3 4 -1561 +1573 4 6 -1732 +1639 6 10 -1473 +1418 10 -29 -1446 +34 +1423 -29 -57038 -841 +34 +54940 +645 @@ -24991,7 +25336,7 @@ 1 2 -309450 +291058 @@ -25007,7 +25352,7 @@ 1 2 -309450 +291058 @@ -25023,7 +25368,7 @@ 1 2 -309450 +291058 @@ -25039,7 +25384,7 @@ 1 2 -309450 +291058 @@ -25055,7 +25400,7 @@ 1 2 -309450 +291058 @@ -25065,15 +25410,15 @@ localvar_location -309450 +291058 id -309450 +291058 loc -309085 +278972 @@ -25087,7 +25432,7 @@ 1 2 -309450 +291058 @@ -25103,12 +25448,12 @@ 1 2 -308720 +272069 2 -3 -365 +129 +6903 @@ -25118,19 +25463,19 @@ params -1662795 +2097984 id -1662795 +2097984 name -48172 +44551 type_id -127333 +175674 index @@ -25142,11 +25487,11 @@ parent_id -1009707 +1234259 unbound_id -709589 +987535 @@ -25160,7 +25505,7 @@ 1 2 -1662795 +2097984 @@ -25176,7 +25521,7 @@ 1 2 -1662795 +2097984 @@ -25192,7 +25537,7 @@ 1 2 -1662795 +2097984 @@ -25208,7 +25553,7 @@ 1 2 -1662795 +2097984 @@ -25224,7 +25569,7 @@ 1 2 -1662795 +2097984 @@ -25240,7 +25585,7 @@ 1 2 -1662795 +2097984 @@ -25256,42 +25601,47 @@ 1 2 -18527 +14198 2 3 -8846 +7897 3 4 -4277 +4014 4 5 -3465 +3556 5 -8 -4374 +7 +3451 -8 -15 -3854 +7 +11 +3507 -15 -65 -3617 +11 +21 +3528 -65 -115038 -1212 +21 +104 +3342 + + +104 +140662 +1058 @@ -25307,22 +25657,27 @@ 1 2 -38960 +32125 2 3 -4760 +5671 3 -12 -3615 +5 +3322 -12 -13741 -837 +5 +372 +3342 + + +376 +16189 +91 @@ -25338,22 +25693,22 @@ 1 2 -32920 +30618 2 3 -8631 +7837 3 4 -3251 +3003 4 28 -3370 +3093 @@ -25369,17 +25724,17 @@ 1 2 -44430 +41046 2 5 -3689 +3456 5 7 -53 +49 @@ -25395,42 +25750,47 @@ 1 2 -18527 +14198 2 3 -8846 +7897 3 4 -4277 +4014 4 5 -3465 +3556 5 -8 -4374 +7 +3451 -8 -15 -3854 +7 +11 +3507 -15 -65 -3617 +11 +21 +3528 -65 -115038 -1212 +21 +104 +3342 + + +104 +140662 +1058 @@ -25446,42 +25806,47 @@ 1 2 -19226 +14654 2 3 -9088 +8134 3 4 -4287 +4041 4 5 -3445 +3605 5 -8 -4279 +7 +3383 -8 -15 -3620 +7 +11 +3502 -15 -107 -3613 +11 +22 +3393 -107 -59449 -614 +22 +202 +3342 + + +202 +78950 +497 @@ -25497,37 +25862,37 @@ 1 2 -66747 +95806 2 3 -14274 +20579 3 4 -7070 +9813 4 5 -10049 +12543 5 -8 -10159 +9 +14829 -8 -16 -10230 +9 +20 +13388 -16 -250157 -8804 +20 +307642 +8716 @@ -25543,22 +25908,22 @@ 1 2 -98326 +138567 2 3 -13720 +18845 3 -6 -10307 +7 +13967 -6 -7254 -4980 +7 +6231 +4295 @@ -25574,22 +25939,22 @@ 1 2 -95270 +135400 2 3 -20230 +26087 3 -5 -10443 +7 +13560 -5 +7 50 -1390 +627 @@ -25605,12 +25970,12 @@ 1 2 -119091 +165275 2 6 -8242 +10399 @@ -25626,37 +25991,37 @@ 1 2 -67557 +97258 2 3 -15267 +21625 3 4 -7257 +10035 4 5 -8928 +10868 5 -8 -9845 +9 +14535 -8 -16 -10012 +9 +21 +13364 -16 -203397 -8467 +21 +247760 +7989 @@ -25672,37 +26037,37 @@ 1 2 -67273 +96636 2 3 -14078 +20263 3 4 -7143 +10275 4 5 -10798 +13284 5 8 -10706 +13488 8 -17 -10208 +19 +13600 -17 -82653 -7127 +19 +105466 +8128 @@ -25721,48 +26086,48 @@ 11 -2 -3 +5 +6 8 -6 -19 +9 +28 4 -20 -37 +31 +56 4 -42 -68 +63 +109 4 -74 -119 +124 +234 4 -285 -932 +476 +1355 4 -1269 -3439 +1804 +4752 4 -5388 -26515 +7904 +37970 4 -60694 -1006637 +83795 +1234260 4 @@ -25787,45 +26152,50 @@ 8 -4 -10 +3 +9 4 -11 -21 -4 +10 +17 +3 -21 -32 +18 +26 4 -36 -56 +28 +42 4 -80 -187 +48 +126 4 -270 -852 +166 +532 4 -1380 -5216 +781 +3084 4 -8435 -22372 +4858 +17361 4 + +20606 +20607 +1 + @@ -25843,54 +26213,49 @@ 11 -2 -3 +5 +6 8 -4 -9 +7 +13 4 -10 -15 -2 - - -16 -20 +15 +23 4 -25 -27 -3 +23 +51 +4 -32 -176 +56 +101 4 -297 -767 +278 +841 4 -936 -1850 +1072 +1974 4 -2277 -8796 +2807 +6378 4 -17296 -92711 -3 +12473 +122056 +4 @@ -25950,48 +26315,48 @@ 11 -2 -3 +5 +6 8 -6 -19 +9 +28 4 -20 -37 +31 +56 4 -42 -68 +63 +109 4 -74 -119 +124 +234 4 -285 -932 +476 +1355 4 -1269 -3439 +1804 +4752 4 -5388 -26515 +7904 +37970 4 -60694 -1006637 +83795 +1234260 4 @@ -26011,48 +26376,48 @@ 11 -2 -3 +5 +6 8 -6 -19 +9 +28 4 -20 -37 +31 +56 4 -42 -68 +63 +109 4 -74 -119 +124 +234 4 -174 -451 +341 +766 4 -664 -2379 +1065 +3474 4 -3992 -20329 +6189 +30065 4 -38390 -389589 +56290 +522599 4 @@ -26067,33 +26432,33 @@ 12 -733 -734 +922 +923 1 -6510 -6511 +6880 +6881 1 -13337 -13338 +17011 +17012 1 -20276 -20277 +28998 +28999 1 -30458 -30459 +40324 +40325 1 -1591179 -1591180 +2002611 +2002612 1 @@ -26113,28 +26478,28 @@ 1 -483 -484 +395 +396 1 -1013 -1014 +877 +878 1 -2257 -2258 +2127 +2128 1 -5499 -5500 +5406 +5407 1 -43559 -43560 +40079 +40080 1 @@ -26149,33 +26514,33 @@ 12 -147 -148 +180 +181 1 -1038 -1039 +1278 +1279 1 -2115 -2116 +2819 +2820 1 -4196 -4197 +7076 +7077 1 -5987 -5988 +11152 +11153 1 -123175 -123176 +164786 +164787 1 @@ -26231,33 +26596,33 @@ 12 -652 -653 +839 +840 1 -6510 -6511 +6880 +6881 1 -10961 -10962 +14029 +14030 1 -20276 -20277 +28998 +28999 1 -24590 -24591 +31219 +31220 1 -991551 -991552 +1210324 +1210325 1 @@ -26272,33 +26637,33 @@ 12 -353 -354 +463 +464 1 -3872 -3873 +4979 +4980 1 -10322 -10323 +14099 +14100 1 -10847 -10848 +17330 +17331 1 -21440 -21441 +29956 +29957 1 -662845 -662846 +920725 +920726 1 @@ -26315,22 +26680,22 @@ 1 2 -614133 +728545 2 3 -263888 +327567 3 4 -71715 +94352 4 52 -59971 +83795 @@ -26346,22 +26711,22 @@ 1 2 -614072 +728528 2 3 -263868 +327562 3 4 -71736 +94369 4 52 -60031 +83800 @@ -26377,22 +26742,22 @@ 1 2 -660352 +787670 2 3 -255417 +315961 3 5 -77910 +106814 5 41 -16028 +23814 @@ -26408,22 +26773,22 @@ 1 2 -614133 +728545 2 3 -263888 +327567 3 4 -71715 +94352 4 52 -59971 +83795 @@ -26439,12 +26804,12 @@ 1 2 -966434 +1178256 2 5 -43273 +56003 @@ -26460,22 +26825,22 @@ 1 2 -614125 +728513 2 3 -263896 +327545 3 4 -71715 +94316 4 52 -59971 +83885 @@ -26491,12 +26856,12 @@ 1 2 -681004 +945854 2 -15458 -28585 +9523 +41681 @@ -26512,12 +26877,12 @@ 1 2 -709322 +987486 2 -4 -267 +3 +49 @@ -26533,12 +26898,12 @@ 1 2 -698010 +968168 2 -5635 -11579 +6040 +19367 @@ -26554,7 +26919,7 @@ 1 2 -709589 +987535 @@ -26570,12 +26935,12 @@ 1 2 -709499 +987518 2 3 -90 +17 @@ -26591,12 +26956,12 @@ 1 2 -681004 +945854 2 -15458 -28585 +9523 +41681 @@ -26606,15 +26971,15 @@ param_location -3009317 +2973125 id -1650966 +2084755 loc -370027 +335646 @@ -26628,27 +26993,22 @@ 1 2 -1174826 +1599701 2 3 -203043 +253142 3 -4 -134596 - - -4 -15 -131678 +5 +191770 -15 -534 -6823 +5 +17 +40142 @@ -26664,12 +27024,17 @@ 1 2 -345724 +299339 2 -215283 -24303 +4 +25464 + + +4 +207747 +10843 @@ -26679,11 +27044,11 @@ statements -1789979 +1723240 id -1789979 +1723240 kind @@ -26701,7 +27066,7 @@ 1 2 -1789979 +1723240 @@ -26716,82 +27081,82 @@ 18 -187 +170 2 -234 -253 +241 +245 2 -301 -331 +266 +329 2 -349 -440 +342 +449 2 -783 -795 +825 +1208 2 -1199 -1201 +1269 +1298 2 -1334 -1624 +1335 +1736 2 -1831 -3271 +1789 +3175 2 -4304 -4712 +4219 +4301 2 -6120 -6287 +4524 +6193 2 8021 -8190 +8295 2 -11629 -17069 +10100 +16414 2 -53160 -62808 +53221 +63216 2 -158006 -172167 +154912 +166462 2 -269815 -483216 +253667 +470590 2 -510339 -510340 +484425 +484426 1 @@ -26802,19 +27167,19 @@ stmt_parent -1511647 +1456112 stmt -1511647 +1456112 index -2123 +437 parent -672991 +653326 @@ -26828,7 +27193,7 @@ 1 2 -1511647 +1456112 @@ -26844,7 +27209,7 @@ 1 2 -1511647 +1456112 @@ -26860,22 +27225,72 @@ 1 2 -1686 +34 -2 -16 -162 +4 +5 +36 -16 -98 -160 +6 +10 +23 -99 -477408 -115 +10 +11 +18 + + +11 +13 +37 + + +13 +19 +33 + + +19 +27 +39 + + +28 +36 +34 + + +36 +58 +35 + + +59 +102 +33 + + +103 +187 +33 + + +191 +566 +33 + + +611 +5634 +33 + + +6311 +464364 +16 @@ -26891,22 +27306,72 @@ 1 2 -1686 +34 -2 -16 -162 +4 +5 +36 -16 -98 -160 +6 +10 +23 -99 -477408 -115 +10 +11 +18 + + +11 +13 +37 + + +13 +19 +33 + + +19 +27 +39 + + +28 +36 +34 + + +36 +58 +35 + + +59 +102 +33 + + +103 +187 +33 + + +191 +566 +33 + + +611 +5634 +33 + + +6311 +464364 +16 @@ -26922,27 +27387,27 @@ 1 2 -417292 +406302 2 3 -117594 +114821 3 4 -47441 +45603 4 7 -56561 +54347 7 -2123 -34103 +437 +32253 @@ -26958,27 +27423,27 @@ 1 2 -417292 +406302 2 3 -117594 +114821 3 4 -47441 +45603 4 7 -56561 +54347 7 -2123 -34103 +437 +32253 @@ -26988,11 +27453,11 @@ stmt_parent_top_level -278332 +267128 stmt -278332 +267128 index @@ -27000,7 +27465,7 @@ parent -250974 +245404 @@ -27014,7 +27479,7 @@ 1 2 -278332 +267128 @@ -27030,7 +27495,7 @@ 1 2 -278332 +267128 @@ -27044,8 +27509,8 @@ 12 -278332 -278333 +267128 +267129 1 @@ -27060,8 +27525,8 @@ 12 -250974 -250975 +245404 +245405 1 @@ -27078,17 +27543,12 @@ 1 2 -223812 +223680 2 3 -26967 - - -3 -5 -195 +21724 @@ -27104,7 +27564,7 @@ 1 2 -250974 +245404 @@ -27114,15 +27574,15 @@ stmt_location -1789979 +1723240 id -1789979 +1723240 loc -1784517 +1626301 @@ -27136,7 +27596,7 @@ 1 2 -1789979 +1723240 @@ -27152,12 +27612,12 @@ 1 2 -1781311 +1574917 2 -45 -3206 +129 +51384 @@ -27167,15 +27627,15 @@ catch_type -4711 +4524 catch_id -4711 +4524 type_id -163 +249 kind @@ -27193,7 +27653,7 @@ 1 2 -4711 +4524 @@ -27209,7 +27669,7 @@ 1 2 -4711 +4524 @@ -27225,47 +27685,47 @@ 1 2 -48 +73 2 3 -27 +41 3 4 -14 +21 4 5 -11 +28 5 8 -15 +18 8 -11 -15 +12 +22 -11 -28 -13 +12 +22 +19 -30 -91 -13 +22 +111 +19 -114 -1687 -7 +134 +766 +8 @@ -27281,7 +27741,7 @@ 1 2 -163 +249 @@ -27295,13 +27755,13 @@ 12 -758 -759 +685 +686 1 -3953 -3954 +3839 +3840 1 @@ -27316,13 +27776,13 @@ 12 -1 -2 +6 +7 1 -162 -163 +243 +244 1 @@ -27333,19 +27793,19 @@ expressions -7417345 +7076055 id -7417345 +7076055 kind -106 +105 type_id -63982 +64483 @@ -27359,7 +27819,7 @@ 1 2 -7417345 +7076055 @@ -27375,7 +27835,7 @@ 1 2 -7417345 +7076055 @@ -27390,73 +27850,73 @@ 8 -50 +49 8 -69 -143 +54 +132 8 -178 -409 +145 +383 8 -435 -657 +403 +635 8 -715 -1216 +672 +1183 8 -1258 -2153 +1261 +2435 8 -2309 -4322 +2931 +4041 8 -4350 -7103 +4200 +6566 8 -7270 -12714 +7195 +12260 8 -14417 -22533 +13572 +22296 8 -24042 -32766 +24651 +40915 8 -41161 -212777 +52803 +275066 8 -268458 -724743 +291172 +873672 8 -928336 -1050543 -2 +991740 +991741 +1 @@ -27472,57 +27932,57 @@ 1 2 -29 +33 2 -6 -8 +7 +5 -6 +7 8 8 8 -12 +14 8 -13 -55 +23 +62 8 -59 -114 +64 +152 8 -115 -319 +164 +419 8 -327 -1055 +532 +1073 8 -1063 -2159 +1104 +4709 8 -2975 -17362 +6810 +18882 8 -18530 -20120 -5 +18895 +20864 +3 @@ -27538,57 +27998,57 @@ 1 2 -14334 +14844 2 3 -5964 +6684 3 4 -3755 +4053 4 5 -4381 +4062 5 7 -5869 +5754 7 10 -5162 +4976 10 15 -5056 +5000 15 24 -4964 +4858 24 -44 -4940 +45 +4995 -44 -108 -4809 +45 +115 +4837 -108 -977236 -4748 +115 +911533 +4420 @@ -27604,42 +28064,42 @@ 1 2 -26518 +27769 2 3 -8251 +7925 3 4 -9231 +9070 4 5 -5758 +5626 5 6 -3874 +3807 6 8 -4706 +4690 8 13 -4969 +4982 13 56 -675 +614 @@ -27649,11 +28109,11 @@ expr_parent -7178046 +6837747 expr -7178046 +6837747 index @@ -27661,7 +28121,7 @@ parent -4743008 +4501731 @@ -27675,7 +28135,7 @@ 1 2 -7178046 +6837747 @@ -27691,7 +28151,7 @@ 1 2 -7178046 +6837747 @@ -27712,21 +28172,26 @@ 2 3 -3435 +1 3 4 -2522 +3434 4 -9 +5 +2522 + + +5 +10 699 -9 -3426742 +10 +3276180 516 @@ -27748,21 +28213,26 @@ 2 3 -3435 +1 3 4 -2522 +3434 4 -9 +5 +2522 + + +5 +10 699 -9 -3426742 +10 +3276180 516 @@ -27779,22 +28249,22 @@ 1 2 -2972682 +2815953 2 3 -1395233 +1327530 3 7 -359960 +343499 7 8193 -15133 +14749 @@ -27810,22 +28280,22 @@ 1 2 -2972682 +2815953 2 3 -1395233 +1327530 3 7 -359960 +343499 7 8193 -15133 +14749 @@ -27835,11 +28305,11 @@ expr_parent_top_level -239299 +238308 expr -239299 +238308 index @@ -27847,7 +28317,7 @@ parent -179958 +185165 @@ -27861,7 +28331,7 @@ 1 2 -239299 +238308 @@ -27877,7 +28347,7 @@ 1 2 -239299 +238308 @@ -27891,48 +28361,48 @@ 12 -13 -14 +12 +13 1 -39 -40 +26 +27 1 -135 -136 +98 +99 1 -383 -384 +243 +244 1 -1297 -1298 +942 +943 1 -3062 -3063 +2399 +2400 1 -9978 -9979 +9066 +9067 1 -46561 -46562 +44849 +44850 1 -177831 -177832 +180673 +180674 1 @@ -27947,48 +28417,48 @@ 12 -13 -14 +12 +13 1 -39 -40 +26 +27 1 -135 -136 +98 +99 1 -383 -384 +243 +244 1 -1297 -1298 +942 +943 1 -3062 -3063 +2399 +2400 1 -9593 -9594 +8788 +8789 1 -46561 -46562 +44849 +44850 1 -169840 -169841 +175784 +175785 1 @@ -28005,17 +28475,17 @@ 1 2 -126296 +135742 2 3 -50329 +47024 3 -129 -3333 +9 +2399 @@ -28031,17 +28501,17 @@ 1 2 -133922 +140909 2 3 -42974 +41857 3 9 -3062 +2399 @@ -28051,22 +28521,22 @@ implicitly_typed_array_creation -12576 +11665 id -12576 +11665 explicitly_sized_array_creation -4077 +4292 id -4077 +4292 @@ -28115,26 +28585,26 @@ expr_compiler_generated -593552 +565505 id -593552 +565505 expr_value -1399433 +1376292 id -1399433 +1376292 value -185734 +170997 @@ -28148,7 +28618,7 @@ 1 2 -1399433 +1376292 @@ -28164,22 +28634,22 @@ 1 2 -135437 +124844 2 3 -25714 +23274 3 7 -15324 +13927 7 -144837 -9259 +142428 +8952 @@ -28189,15 +28659,15 @@ expr_call -1347739 +1301429 caller_id -1347739 +1301429 target_id -157393 +157417 @@ -28211,7 +28681,7 @@ 1 2 -1347739 +1301429 @@ -28227,32 +28697,32 @@ 1 2 -85183 +85870 2 3 -29466 +29491 3 4 -12338 +12178 4 7 -14239 +14128 7 -25 -11905 +27 +11933 -25 -35631 -4262 +27 +35604 +3817 @@ -28262,15 +28732,15 @@ expr_access -2855307 +2739712 accesser_id -2855307 +2739712 target_id -725838 +704804 @@ -28284,7 +28754,7 @@ 1 2 -2855307 +2739712 @@ -28300,37 +28770,37 @@ 1 2 -216414 +211418 2 3 -211536 +204592 3 4 -116569 +113092 4 5 -63157 +61793 5 7 -55255 +53915 7 -24 -54454 +26 +52934 -24 +26 20125 -8453 +7060 @@ -28340,15 +28810,15 @@ expr_location -7417345 +7076055 id -7417345 +7076055 loc -6768067 +6141754 @@ -28362,7 +28832,7 @@ 1 2 -7417345 +7076055 @@ -28378,17 +28848,17 @@ 1 2 -6140047 +5428525 2 3 -613291 +624132 3 143 -14729 +89097 @@ -28398,15 +28868,15 @@ dynamic_member_name -977 +161 id -977 +161 name -294 +33 @@ -28420,7 +28890,7 @@ 1 2 -977 +161 @@ -28436,32 +28906,42 @@ 1 2 -155 +16 2 3 -50 +2 3 4 -31 +3 4 5 -23 +3 -5 -14 -24 +7 +8 +2 -14 -106 -11 +8 +9 +3 + + +12 +19 +3 + + +39 +40 +1 @@ -28471,22 +28951,22 @@ conditional_access -3445 +3675 id -3445 +3675 expr_argument -1536561 +1471073 id -1536561 +1471073 mode @@ -28504,7 +28984,7 @@ 1 2 -1536561 +1471073 @@ -28518,23 +28998,23 @@ 12 -123 -124 +143 +144 1 -10881 -10882 +11416 +11417 1 -16880 -16881 +17078 +17079 1 -1508677 -1508678 +1442436 +1442437 1 @@ -28545,15 +29025,15 @@ expr_argument_name -75690 +75494 id -75690 +75494 name -4374 +4229 @@ -28567,7 +29047,7 @@ 1 2 -75690 +75494 @@ -28583,47 +29063,47 @@ 1 2 -1356 +1270 2 3 -859 +838 3 4 -424 +409 4 5 -327 +331 5 7 -331 +329 7 12 -375 +348 12 25 -340 +329 25 -259 -329 +159 +318 -262 -10879 -33 +159 +10921 +57 @@ -28633,11 +29113,11 @@ xmlEncoding -112 +58 id -112 +58 encoding @@ -28655,7 +29135,7 @@ 1 2 -112 +58 @@ -28669,8 +29149,8 @@ 12 -112 -113 +58 +59 1 @@ -29029,27 +29509,27 @@ xmlElements -3426 +1226 id -3426 +1226 name -333 +207 parentid -1038 +418 idx -106 +34 fileid -112 +58 @@ -29063,7 +29543,7 @@ 1 2 -3426 +1226 @@ -29079,7 +29559,7 @@ 1 2 -3426 +1226 @@ -29095,7 +29575,7 @@ 1 2 -3426 +1226 @@ -29111,7 +29591,7 @@ 1 2 -3426 +1226 @@ -29127,42 +29607,37 @@ 1 2 -97 +78 2 3 -80 +45 3 4 -38 +23 4 5 -28 +17 5 -8 -27 - - -8 -17 -25 +11 +16 -20 -53 -25 +11 +26 +19 -62 -413 -13 +26 +138 +9 @@ -29178,37 +29653,37 @@ 1 2 -107 +86 2 3 -87 +46 3 4 -44 +23 4 5 -24 +17 5 -9 -25 +13 +18 -9 -23 -23 +13 +41 +16 -25 -162 -23 +51 +52 +1 @@ -29224,27 +29699,27 @@ 1 2 -197 +132 2 3 -64 +38 3 -4 -26 +5 +13 -4 -6 -22 +5 +8 +16 -6 -107 -24 +9 +35 +8 @@ -29260,32 +29735,32 @@ 1 2 -118 +102 2 3 -106 +47 3 4 -50 +24 4 -6 -30 +5 +16 -6 -21 -25 +5 +13 +16 -22 -51 -4 +21 +41 +2 @@ -29301,37 +29776,32 @@ 1 2 -434 +222 2 3 -298 +93 3 -4 -96 - - -4 5 -22 +36 5 -6 -84 +9 +22 -6 -17 -78 +9 +14 +33 -17 -107 -26 +14 +35 +12 @@ -29347,27 +29817,22 @@ 1 2 -561 +265 2 3 -284 +87 3 -5 -76 - - -5 -8 -81 +6 +34 -8 -26 -36 +6 +18 +32 @@ -29383,37 +29848,32 @@ 1 2 -434 +222 2 3 -298 +93 3 -4 -96 - - -4 5 -22 +36 5 -6 -84 +9 +22 -6 -17 -78 +9 +14 +33 -17 -107 -26 +14 +35 +12 @@ -29429,7 +29889,7 @@ 1 2 -1038 +418 @@ -29444,13 +29904,8 @@ 1 -2 -42 - - -2 3 -6 +3 3 @@ -29458,34 +29913,39 @@ 5 -5 -6 -14 +4 +5 +8 -6 -10 -9 +5 +9 +3 -11 -18 -8 +9 +15 +3 18 -31 -8 +29 +3 -33 -97 -8 +45 +50 +3 -104 -1039 -6 +53 +73 +3 + + +103 +419 +3 @@ -29501,7 +29961,7 @@ 1 2 -48 +3 2 @@ -29511,31 +29971,41 @@ 3 4 -21 +8 4 -8 -7 +6 +2 -8 -12 -8 +7 +11 +3 -13 -27 -8 +11 +15 +3 -28 -114 -8 +16 +18 +3 -180 -181 +19 +30 +3 + + +33 +73 +3 + + +121 +122 1 @@ -29551,13 +30021,8 @@ 1 -2 -42 - - -2 3 -6 +3 3 @@ -29565,34 +30030,39 @@ 5 -5 -6 -14 +4 +5 +8 -6 -10 -9 +5 +9 +3 -11 -18 -8 +9 +15 +3 18 -31 -8 +29 +3 -33 -97 -8 +45 +50 +3 -104 -1039 -6 +53 +73 +3 + + +103 +419 +3 @@ -29607,48 +30077,48 @@ 1 -2 -42 - - -2 3 -6 +3 3 4 -19 +5 4 +5 +8 + + +5 +7 +2 + + +7 8 -9 +4 -9 -13 -5 +8 +12 +3 13 -17 -8 +15 +3 17 -29 -8 - - -32 -92 -8 +21 +3 -112 -113 -1 +28 +59 +3 @@ -29662,69 +30132,64 @@ 12 -1 +2 3 -8 +2 3 4 -8 +9 4 5 -7 +5 5 6 -9 +4 6 7 -10 +6 7 +8 +2 + + +8 9 -9 +6 9 -11 -9 +10 +5 -11 -18 -10 +10 +17 +4 19 -27 -7 - - -29 -31 -9 - - -31 -49 -9 +32 +5 -51 -78 -9 +32 +54 +5 -107 -327 -8 +63 +238 +5 @@ -29738,34 +30203,29 @@ 12 -1 -2 -3 - - 2 3 -27 +4 3 4 -8 +11 4 5 -9 +6 5 6 -8 +4 6 7 -15 +11 7 @@ -29775,27 +30235,27 @@ 8 9 -13 +4 9 13 -8 +5 14 18 -9 +4 -18 -77 -9 +19 +32 +5 -81 -82 -1 +52 +56 +2 @@ -29809,59 +30269,49 @@ 12 -1 -2 -3 - - 2 3 -27 +4 3 4 -11 +14 4 5 -14 +8 5 6 -12 +14 6 -8 -9 +7 +3 8 -13 +10 4 13 -14 -8 - - -14 -19 -9 +15 +4 -20 -33 -9 +15 +25 +5 -37 -65 -6 +26 +48 +2 @@ -29877,57 +30327,42 @@ 1 2 -21 +16 2 3 -19 +14 3 4 -10 +8 4 -5 -6 - - -5 -7 -8 +6 +3 -7 +6 8 -5 - - -8 -9 -11 +4 9 12 -9 +5 12 -19 -9 - - -19 -33 -9 +27 +5 -37 -107 -5 +31 +35 +3 @@ -29937,23 +30372,23 @@ xmlAttrs -5138 +1785 id -5138 +1785 elementid -1923 +590 name -197 +152 value -1313 +728 idx @@ -29961,7 +30396,7 @@ fileid -107 +56 @@ -29975,7 +30410,7 @@ 1 2 -5138 +1785 @@ -29991,7 +30426,7 @@ 1 2 -5138 +1785 @@ -30007,7 +30442,7 @@ 1 2 -5138 +1785 @@ -30023,7 +30458,7 @@ 1 2 -5138 +1785 @@ -30039,7 +30474,7 @@ 1 2 -5138 +1785 @@ -30055,27 +30490,27 @@ 1 2 -546 +175 2 3 -450 +203 3 4 -736 +135 4 -10 -151 +12 +41 -10 +16 17 -40 +36 @@ -30091,27 +30526,27 @@ 1 2 -546 +175 2 3 -450 +203 3 4 -736 +135 4 -10 -151 +12 +41 -10 +16 17 -40 +36 @@ -30127,22 +30562,27 @@ 1 2 -549 +178 2 3 -489 +208 3 4 -710 +130 4 +14 +43 + + +14 15 -175 +31 @@ -30158,27 +30598,27 @@ 1 2 -546 +175 2 3 -450 +203 3 4 -736 +135 4 -10 -151 +12 +41 -10 +16 17 -40 +36 @@ -30194,7 +30634,7 @@ 1 2 -1923 +590 @@ -30210,46 +30650,41 @@ 1 2 -65 +62 2 3 -31 +25 3 4 -20 +15 4 -6 -13 +9 +12 -6 -13 -15 +11 +27 +12 -14 -33 -15 +27 +31 +4 36 -52 -15 - - -52 -179 -15 +37 +14 -216 -461 +54 +230 8 @@ -30266,46 +30701,41 @@ 1 2 -65 +62 2 3 -31 +25 3 4 -20 +15 4 -6 -13 +9 +12 -6 -13 -15 +11 +27 +12 -14 -33 -15 +27 +31 +4 36 -52 -15 - - -52 -179 -15 +37 +14 -216 -461 +54 +230 8 @@ -30322,32 +30752,27 @@ 1 2 -109 +98 2 3 -34 +19 3 -5 -16 - - -5 -12 -15 +7 +14 -12 -42 -15 +7 +27 +12 -43 -208 -8 +29 +139 +9 @@ -30363,22 +30788,17 @@ 1 2 -157 +128 2 3 -22 +17 3 -6 -15 - - -6 -10 -3 +7 +7 @@ -30394,27 +30814,27 @@ 1 2 -82 +72 2 3 -59 +48 3 4 -26 +11 4 -12 -16 +7 +12 -12 -48 -14 +7 +24 +9 @@ -30430,27 +30850,22 @@ 1 2 -592 +429 2 3 -421 +215 3 -4 -110 - - -4 -8 -107 +10 +57 -8 -192 -83 +10 +76 +27 @@ -30466,27 +30881,22 @@ 1 2 -603 +430 2 3 -415 +214 3 -4 -107 - - -4 -8 -106 +10 +57 -8 -174 -82 +10 +54 +27 @@ -30502,17 +30912,12 @@ 1 2 -1192 +690 2 -3 -100 - - -3 -37 -21 +28 +38 @@ -30528,12 +30933,12 @@ 1 2 -1217 +682 2 11 -96 +46 @@ -30549,22 +30954,17 @@ 1 2 -675 +486 2 3 -438 +195 3 -5 -116 - - -5 -35 -84 +21 +47 @@ -30593,48 +30993,43 @@ 1 -49 -50 -1 - - -80 -81 -1 +41 +42 +2 -102 -103 +42 +43 1 -104 -105 +46 +47 1 -127 -128 +63 +64 1 -191 -192 +77 +78 1 -927 -928 +212 +213 1 -1377 -1378 +415 +416 1 -1923 -1924 +590 +591 1 @@ -30664,48 +31059,43 @@ 1 -49 -50 -1 - - -80 -81 -1 +41 +42 +2 -102 -103 +42 +43 1 -104 -105 +46 +47 1 -127 -128 +63 +64 1 -191 -192 +77 +78 1 -927 -928 +212 +213 1 -1377 -1378 +415 +416 1 -1923 -1924 +590 +591 1 @@ -30732,7 +31122,12 @@ 4 5 -1 +2 + + +5 +6 +2 7 @@ -30740,18 +31135,13 @@ 1 -8 -9 +13 +14 1 -11 -12 -2 - - -19 -20 +22 +23 1 @@ -30760,18 +31150,13 @@ 1 -54 -55 -1 - - -57 -58 +40 +41 1 -67 -68 +49 +50 1 @@ -30796,43 +31181,58 @@ 1 -26 -27 +14 +15 1 -29 -30 -4 +16 +17 +1 -31 -32 -2 +17 +18 +1 -39 -40 +18 +19 1 -66 -67 +23 +24 1 -146 -147 +25 +26 1 -345 -346 +29 +30 +2 + + +31 +32 1 -670 -671 +47 +48 +1 + + +211 +212 +1 + + +330 +331 1 @@ -30862,13 +31262,13 @@ 1 -8 -9 -1 +6 +7 +2 -9 -10 +7 +8 1 @@ -30877,33 +31277,28 @@ 1 -11 -12 -1 - - -22 -23 +15 +16 1 -35 -36 +18 +19 1 -73 -74 +28 +29 1 -101 -102 +52 +53 1 -107 -108 +56 +57 1 @@ -30919,63 +31314,58 @@ 1 +2 +2 + + +2 3 -9 +10 3 4 -11 +8 4 5 -11 +6 -5 +6 8 -7 +4 8 -11 -9 +10 +5 -11 +10 15 -8 +5 18 32 -9 - - -32 -40 -8 - - -40 -45 -9 +3 -47 -61 -9 +33 +39 +5 -67 -118 -9 +73 +115 +5 -174 -794 -8 +241 +338 +3 @@ -30991,62 +31381,42 @@ 1 2 -18 +17 2 3 -11 +8 3 4 -11 +8 4 -5 -9 - - -5 -8 -7 +6 +5 -8 +6 13 -7 - - -13 -17 -8 - - -17 -18 -7 - - -19 -26 -9 +5 -27 -38 -9 +16 +23 +5 -39 -72 -9 +23 +36 +4 -274 -306 -2 +41 +127 +4 @@ -31062,51 +31432,51 @@ 1 2 -5 +3 2 3 -15 +18 3 4 -25 +8 4 5 -13 +4 5 6 -8 +3 6 7 -5 +3 7 8 -14 +3 8 -11 -9 +12 +5 -11 -19 -9 +12 +18 +5 -23 -69 +18 +62 4 @@ -31122,67 +31492,52 @@ 1 +2 +2 + + +2 3 -9 +10 3 4 -12 +8 4 5 -11 - - -5 -6 -7 - - -6 -8 8 -9 -13 -8 +5 +7 +5 -13 -17 -9 +7 +10 +5 -19 +11 24 -6 - - -24 -28 -7 +5 -28 -33 -9 +27 +32 +5 33 -49 -9 - - -54 -111 -9 +78 +5 -141 -327 +95 +168 3 @@ -31199,37 +31554,37 @@ 1 2 -6 +4 2 3 -28 +24 3 4 -38 +10 4 5 -13 +3 5 6 -11 +5 6 -12 -9 +10 +5 -16 +10 17 -2 +5 @@ -31239,7 +31594,7 @@ xmlNs -20 +8 id @@ -31255,7 +31610,7 @@ fileid -19 +7 @@ -31301,12 +31656,7 @@ 4 5 -1 - - -16 -17 -1 +2 @@ -31354,12 +31704,7 @@ 4 5 -1 - - -16 -17 -1 +2 @@ -31407,12 +31752,7 @@ 4 5 -1 - - -16 -17 -1 +2 @@ -31428,7 +31768,7 @@ 1 2 -18 +6 2 @@ -31449,7 +31789,7 @@ 1 2 -18 +6 2 @@ -31470,7 +31810,7 @@ 1 2 -18 +6 2 @@ -31485,11 +31825,11 @@ xmlHasNs -982 +140 elementId -982 +140 nsId @@ -31497,7 +31837,7 @@ fileid -18 +6 @@ -31511,7 +31851,7 @@ 1 2 -982 +140 @@ -31527,7 +31867,7 @@ 1 2 -982 +140 @@ -31541,13 +31881,13 @@ 12 -470 -471 +37 +38 1 -512 -513 +103 +104 1 @@ -31567,8 +31907,8 @@ 1 -16 -17 +4 +5 1 @@ -31598,38 +31938,13 @@ 1 -25 -26 -8 - - -34 -35 +31 +32 2 -40 -41 -1 - - -43 -44 -1 - - -49 -50 -1 - - -55 -56 -1 - - -520 -521 +71 +72 1 @@ -31646,7 +31961,7 @@ 1 2 -17 +5 2 @@ -31661,23 +31976,23 @@ xmlComments -300 +152 id -300 +152 text -187 +109 parentid -120 +74 fileid -52 +37 @@ -31691,7 +32006,7 @@ 1 2 -300 +152 @@ -31707,7 +32022,7 @@ 1 2 -300 +152 @@ -31723,7 +32038,7 @@ 1 2 -300 +152 @@ -31739,17 +32054,17 @@ 1 2 -92 +79 2 3 -83 +23 3 9 -12 +7 @@ -31765,17 +32080,17 @@ 1 2 -92 +79 2 3 -83 +25 3 9 -12 +5 @@ -31791,17 +32106,17 @@ 1 2 -92 +79 2 3 -83 +25 3 9 -12 +5 @@ -31817,27 +32132,22 @@ 1 2 -71 +49 2 3 -15 +10 3 4 -21 - - -4 -15 9 -15 -25 -4 +4 +24 +6 @@ -31853,27 +32163,22 @@ 1 2 -71 +49 2 3 -15 +10 3 4 -21 - - -4 -15 9 -15 -25 -4 +4 +22 +6 @@ -31889,7 +32194,7 @@ 1 2 -120 +74 @@ -31905,37 +32210,37 @@ 1 2 -24 +18 2 3 -6 +5 3 4 -6 +5 4 -5 -5 +6 +2 -5 -10 -4 +10 +11 +2 14 -20 -4 +15 +3 -25 -62 -3 +15 +24 +2 @@ -31951,37 +32256,37 @@ 1 2 -24 +18 2 3 -6 +5 3 4 -6 +5 4 -5 -5 +6 +2 -5 -10 -4 +10 +11 +2 14 -20 -4 +15 +3 -25 -62 -3 +15 +22 +2 @@ -31997,27 +32302,27 @@ 1 2 -32 +23 2 3 -7 +4 3 4 -8 +5 4 -14 -4 +6 +2 -17 -18 -1 +6 +8 +3 @@ -32027,19 +32332,19 @@ xmlChars -826 +238 id -826 +238 text -357 +123 parentid -826 +238 idx @@ -32051,7 +32356,7 @@ fileid -17 +10 @@ -32065,7 +32370,7 @@ 1 2 -826 +238 @@ -32081,7 +32386,7 @@ 1 2 -826 +238 @@ -32097,7 +32402,7 @@ 1 2 -826 +238 @@ -32113,7 +32418,7 @@ 1 2 -826 +238 @@ -32129,7 +32434,7 @@ 1 2 -826 +238 @@ -32145,27 +32450,22 @@ 1 2 -112 +82 2 3 -179 +26 3 -4 -17 - - -4 -5 -31 +6 +10 -5 -32 -18 +6 +28 +5 @@ -32181,27 +32481,22 @@ 1 2 -112 +82 2 3 -179 +26 3 -4 -17 - - -4 -5 -31 +6 +10 -5 -32 -18 +6 +28 +5 @@ -32217,7 +32512,7 @@ 1 2 -357 +123 @@ -32233,7 +32528,7 @@ 1 2 -357 +123 @@ -32249,17 +32544,17 @@ 1 2 -116 +89 2 3 -220 +30 3 -9 -21 +5 +4 @@ -32275,7 +32570,7 @@ 1 2 -826 +238 @@ -32291,7 +32586,7 @@ 1 2 -826 +238 @@ -32307,7 +32602,7 @@ 1 2 -826 +238 @@ -32323,7 +32618,7 @@ 1 2 -826 +238 @@ -32339,7 +32634,7 @@ 1 2 -826 +238 @@ -32353,8 +32648,8 @@ 12 -826 -827 +238 +239 1 @@ -32369,8 +32664,8 @@ 12 -357 -358 +123 +124 1 @@ -32385,8 +32680,8 @@ 12 -826 -827 +238 +239 1 @@ -32417,8 +32712,8 @@ 12 -17 -18 +10 +11 1 @@ -32433,13 +32728,13 @@ 12 -117 -118 +47 +48 1 -709 -710 +191 +192 1 @@ -32454,13 +32749,13 @@ 12 -74 -75 +37 +38 1 -283 -284 +86 +87 1 @@ -32475,13 +32770,13 @@ 12 -117 -118 +47 +48 1 -709 -710 +191 +192 1 @@ -32512,13 +32807,13 @@ 12 -8 -9 +6 +7 1 -17 -18 +10 +11 1 @@ -32540,41 +32835,26 @@ 2 3 -1 - - -3 -4 -1 - - -4 -5 -1 - - -5 -6 -1 +2 -16 -17 -1 +9 +10 +2 -21 -22 +14 +15 1 -25 -26 +15 +16 1 -30 -31 +36 +37 1 @@ -32583,30 +32863,10 @@ 1 -41 -42 -2 - - -63 -64 -1 - - -80 -81 -1 - - 110 111 1 - -172 -173 -2 - @@ -32626,22 +32886,12 @@ 2 3 -1 - - -3 -4 -1 - - -4 -5 -1 +2 -5 -6 -1 +8 +9 +2 11 @@ -32649,38 +32899,18 @@ 1 -12 -13 -1 - - -18 -19 -1 - - -20 -21 -1 - - -29 -30 +14 +15 1 -38 -39 -2 - - -41 -42 +15 +16 1 -57 -58 +28 +29 1 @@ -32688,11 +32918,6 @@ 74 1 - -138 -139 -2 - @@ -32712,41 +32937,26 @@ 2 3 -1 - - -3 -4 -1 - - -4 -5 -1 - - -5 -6 -1 +2 -16 -17 -1 +9 +10 +2 -21 -22 +14 +15 1 -25 -26 +15 +16 1 -30 -31 +36 +37 1 @@ -32755,30 +32965,10 @@ 1 -41 -42 -2 - - -63 -64 -1 - - -80 -81 -1 - - 110 111 1 - -172 -173 -2 - @@ -32793,7 +32983,7 @@ 1 2 -17 +10 @@ -32809,12 +32999,12 @@ 1 2 -9 +4 2 3 -8 +6 @@ -32824,15 +33014,15 @@ xmllocations -9824 +3469 xmlElement -9806 +3463 location -9824 +3469 @@ -32846,11 +33036,11 @@ 1 2 -9804 +3461 4 -17 +5 2 @@ -32867,7 +33057,7 @@ 1 2 -9824 +3469 @@ -32877,11 +33067,11 @@ commentline -618446 +526699 id -618446 +526699 kind @@ -32889,11 +33079,11 @@ text -304702 +269293 rawtext -309171 +273305 @@ -32907,7 +33097,7 @@ 1 2 -618446 +526699 @@ -32923,7 +33113,7 @@ 1 2 -618446 +526699 @@ -32939,7 +33129,7 @@ 1 2 -618446 +526699 @@ -32953,18 +33143,18 @@ 12 -12000 -12001 +10871 +10872 1 -276055 -276056 +210408 +210409 1 -330391 -330392 +305420 +305421 1 @@ -32979,18 +33169,18 @@ 12 -5817 -5818 +5341 +5342 1 -98398 -98399 +80159 +80160 1 -201704 -201705 +184908 +184909 1 @@ -33005,18 +33195,18 @@ 12 -6340 -6341 +5828 +5829 1 -99142 -99143 +80802 +80803 1 -203689 -203690 +186675 +186676 1 @@ -33033,17 +33223,17 @@ 1 2 -252156 +224371 2 3 -34923 +30221 3 -49511 -17623 +37016 +14701 @@ -33059,12 +33249,12 @@ 1 2 -303526 +268207 2 4 -1176 +1086 @@ -33080,12 +33270,12 @@ 1 2 -301509 +266406 2 -86 -3193 +76 +2887 @@ -33101,17 +33291,17 @@ 1 2 -256975 +228701 2 3 -34845 +30180 3 -49420 -17351 +36967 +14424 @@ -33127,7 +33317,7 @@ 1 2 -309171 +273305 @@ -33143,7 +33333,7 @@ 1 2 -309171 +273305 @@ -33153,15 +33343,15 @@ commentline_location -618446 +526699 id -618446 +526699 loc -618446 +526699 @@ -33175,7 +33365,7 @@ 1 2 -618446 +526699 @@ -33191,7 +33381,7 @@ 1 2 -618446 +526699 @@ -33201,26 +33391,26 @@ commentblock -247138 +216571 id -247138 +216571 commentblock_location -247138 +216571 id -247138 +216571 loc -247138 +216571 @@ -33234,7 +33424,7 @@ 1 2 -247138 +216571 @@ -33250,7 +33440,7 @@ 1 2 -247138 +216571 @@ -33260,15 +33450,15 @@ commentblock_binding -794277 +724338 id -247103 +216569 entity -339770 +311724 bindtype @@ -33286,22 +33476,22 @@ 1 2 -64059 +60480 2 3 -47892 +40519 3 4 -134744 +109785 4 -7 -408 +257 +5785 @@ -33317,22 +33507,22 @@ 1 2 -19446 +19145 2 3 -44772 +42539 3 4 -47839 +41305 4 5 -135046 +113580 @@ -33348,17 +33538,17 @@ 1 2 -247642 +226442 2 3 -67118 +64133 3 -8449 -25010 +1882 +21149 @@ -33374,22 +33564,22 @@ 1 2 -146681 +134634 2 3 -146587 +135222 3 4 -45202 +40684 4 5 -1300 +1184 @@ -33403,23 +33593,23 @@ 12 -143047 -143048 +120670 +120671 1 -202047 -202048 +172840 +172841 1 -220046 -220047 +191618 +191619 1 -227551 -227552 +197330 +197331 1 @@ -33434,23 +33624,23 @@ 12 -85120 -85121 +79358 +79359 1 -134653 -134654 +122819 +122820 1 -175047 -175048 +158785 +158786 1 -185841 -185842 +170904 +170905 1 @@ -33461,15 +33651,15 @@ commentblock_child -618012 +526620 id -247138 +216571 commentline -618012 +526620 index @@ -33487,32 +33677,27 @@ 1 2 -119292 +104360 2 3 -47018 +45412 3 4 -42534 +37592 4 -6 -19386 - - -6 -32 -18550 +7 +18798 -32 +7 1136 -358 +10409 @@ -33528,32 +33713,27 @@ 1 2 -119292 +104360 2 3 -47018 +45412 3 4 -42534 +37592 4 -6 -19386 - - -6 -32 -18550 +7 +18798 -32 +7 1136 -358 +10409 @@ -33569,7 +33749,7 @@ 1 2 -618012 +526620 @@ -33585,7 +33765,7 @@ 1 2 -618012 +526620 @@ -33625,12 +33805,12 @@ 12 -95 +90 86 -96 -247139 +91 +216572 54 @@ -33671,12 +33851,12 @@ 12 -95 +90 86 -96 -247139 +91 +216572 54 @@ -33687,19 +33867,19 @@ asp_elements -12090 +148 id -12090 +148 kind -9 +7 loc -12090 +148 @@ -33713,7 +33893,7 @@ 1 2 -12090 +148 @@ -33729,7 +33909,7 @@ 1 2 -12090 +148 @@ -33743,48 +33923,38 @@ 12 -14 -15 -1 - - -16 -17 -1 - - -44 -45 +1 +2 1 -243 -244 +3 +4 1 -244 -245 +5 +6 1 -1542 -1543 +22 +23 1 -1920 -1921 +28 +29 1 -3522 -3523 +31 +32 1 -4545 -4546 +58 +59 1 @@ -33799,48 +33969,38 @@ 12 -14 -15 -1 - - -16 -17 -1 - - -44 -45 +1 +2 1 -243 -244 +3 +4 1 -244 -245 +5 +6 1 -1542 -1543 +22 +23 1 -1920 -1921 +28 +29 1 -3522 -3523 +31 +32 1 -4545 -4546 +58 +59 1 @@ -33857,7 +34017,7 @@ 1 2 -12090 +148 @@ -33873,7 +34033,7 @@ 1 2 -12090 +148 @@ -33883,45 +34043,45 @@ asp_comment_server -2 +0 comment -2 +0 asp_code_inline -238 +0 code -238 +0 asp_directive_attribute -879 +6 directive -243 +3 index -7 +4 name -21 +5 value -879 +6 @@ -33935,32 +34095,12 @@ 1 2 -22 - - -2 -3 -3 - - -3 -4 -117 +2 4 5 -30 - - -5 -6 -50 - - -6 -8 -21 +1 @@ -33976,32 +34116,12 @@ 1 2 -22 - - -2 -3 -3 - - -3 -4 -117 +2 4 5 -30 - - -5 -6 -50 - - -6 -8 -21 +1 @@ -34017,32 +34137,12 @@ 1 2 -22 - - -2 -3 -3 - - -3 -4 -117 +2 4 5 -30 - - -5 -6 -50 - - -6 -8 -21 +1 @@ -34056,38 +34156,13 @@ 12 -4 -5 -1 - - -21 -22 -1 - - -71 -72 -1 - - -101 -102 -1 - - -218 -219 -1 - - -221 -222 -1 +1 +2 +3 -243 -244 +3 +4 1 @@ -34102,30 +34177,15 @@ 12 -2 -3 -1 - - -6 -7 -1 +1 +2 +3 -7 -8 +2 +3 1 - -8 -9 -2 - - -10 -11 -2 - @@ -34138,38 +34198,13 @@ 12 -4 -5 -1 - - -21 -22 -1 - - -71 -72 -1 - - -101 -102 -1 - - -218 -219 -1 - - -221 -222 -1 +1 +2 +3 -243 -244 +3 +4 1 @@ -34186,81 +34221,11 @@ 1 2 -3 +4 2 3 -3 - - -3 -4 -1 - - -5 -6 -2 - - -9 -10 -1 - - -10 -11 -1 - - -13 -14 -1 - - -31 -32 -1 - - -63 -64 -1 - - -72 -73 -1 - - -98 -99 -1 - - -105 -106 -1 - - -106 -107 -1 - - -108 -109 -1 - - -113 -114 -1 - - -129 -130 1 @@ -34277,27 +34242,7 @@ 1 2 -9 - - -2 -3 -3 - - -3 -4 -4 - - -4 -5 -1 - - -5 -6 -4 +5 @@ -34313,81 +34258,11 @@ 1 2 -3 +4 2 3 -3 - - -3 -4 -1 - - -5 -6 -2 - - -9 -10 -1 - - -10 -11 -1 - - -13 -14 -1 - - -31 -32 -1 - - -63 -64 -1 - - -72 -73 -1 - - -98 -99 -1 - - -105 -106 -1 - - -106 -107 -1 - - -108 -109 -1 - - -113 -114 -1 - - -129 -130 1 @@ -34404,7 +34279,7 @@ 1 2 -879 +6 @@ -34420,7 +34295,7 @@ 1 2 -879 +6 @@ -34436,7 +34311,7 @@ 1 2 -879 +6 @@ -34446,15 +34321,15 @@ asp_directive_name -243 +3 directive -243 +3 name -5 +2 @@ -34468,7 +34343,7 @@ 1 2 -243 +3 @@ -34482,28 +34357,13 @@ 12 -2 -3 -1 - - -9 -10 -1 - - -21 -22 -1 - - -98 -99 +1 +2 1 -113 -114 +2 +3 1 @@ -34514,15 +34374,15 @@ asp_element_body -9927 +117 element -9927 +117 body -1800 +73 @@ -34536,7 +34396,7 @@ 1 2 -9927 +117 @@ -34552,32 +34412,22 @@ 1 2 -815 +55 2 3 -601 +10 3 -4 -62 - - -4 -7 -159 - - -7 -55 -135 +6 +5 -57 -982 -28 +6 +11 +3 @@ -34587,23 +34437,23 @@ asp_tag_attribute -3666 +25 tag -1455 +16 index -10 +2 name -119 +10 attribute -3666 +25 @@ -34617,27 +34467,12 @@ 1 2 -321 +7 2 3 -506 - - -3 -4 -368 - - -4 -5 -153 - - -5 -11 -107 +9 @@ -34653,27 +34488,12 @@ 1 2 -321 +7 2 3 -506 - - -3 -4 -368 - - -4 -5 -153 - - -5 -11 -107 +9 @@ -34689,27 +34509,12 @@ 1 2 -321 +7 2 3 -506 - - -3 -4 -368 - - -4 -5 -153 - - -5 -11 -107 +9 @@ -34723,53 +34528,13 @@ 12 -1 -2 -1 - - -4 -5 -1 - - -10 -11 -1 - - -19 -20 -1 - - -48 -49 -1 - - -107 -108 -1 - - -260 -261 -1 - - -628 -629 -1 - - -1134 -1135 +9 +10 1 -1455 -1456 +16 +17 1 @@ -34784,53 +34549,13 @@ 12 -1 -2 -1 - - -2 -3 -1 - - -4 -5 -1 - - -8 -9 -1 - - -17 -18 -1 - - -30 -31 -1 - - -42 -43 -1 - - -43 -44 -1 - - -50 -51 +5 +6 1 -60 -61 +7 +8 1 @@ -34845,53 +34570,13 @@ 12 -1 -2 -1 - - -4 -5 -1 - - -10 -11 -1 - - -19 -20 -1 - - -48 -49 -1 - - -107 -108 -1 - - -260 -261 -1 - - -628 -629 -1 - - -1134 -1135 +9 +10 1 -1455 -1456 +16 +17 1 @@ -34908,57 +34593,27 @@ 1 2 -16 +5 2 3 -25 +1 3 4 -8 +1 4 5 -12 - - -5 -6 -6 - - -6 -7 -9 +2 7 -11 -10 - - -11 -19 -9 - - -19 -39 -9 - - -42 -130 -9 - - -132 -980 -6 +8 +1 @@ -34974,27 +34629,12 @@ 1 2 -52 +8 2 3 -31 - - -3 -4 -15 - - -4 -5 -12 - - -5 -8 -9 +2 @@ -35010,57 +34650,27 @@ 1 2 -16 +5 2 3 -25 +1 3 4 -8 +1 4 5 -12 - - -5 -6 -6 - - -6 -7 -9 +2 7 -11 -10 - - -11 -19 -9 - - -19 -39 -9 - - -42 -130 -9 - - -132 -980 -6 +8 +1 @@ -35076,7 +34686,7 @@ 1 2 -3666 +25 @@ -35092,7 +34702,7 @@ 1 2 -3666 +25 @@ -35108,7 +34718,7 @@ 1 2 -3666 +25 @@ -35118,15 +34728,15 @@ asp_tag_name -1920 +28 tag -1920 +28 name -110 +15 @@ -35140,7 +34750,7 @@ 1 2 -1920 +28 @@ -35156,57 +34766,27 @@ 1 2 -15 +10 2 3 -20 +2 3 4 -3 - - -4 -5 -10 +1 5 -8 -9 - - -8 -11 -9 - - -11 -14 -9 - - -14 -21 -10 - - -24 -38 -10 - - -50 -71 -9 +6 +1 -76 -130 -6 +6 +7 +1 @@ -35216,22 +34796,22 @@ asp_tag_isempty -363 +1 tag -363 +1 cil_instruction -17762677 +17762709 id -17762677 +17762709 opcode @@ -35243,7 +34823,7 @@ impl -1075745 +1075749 @@ -35257,7 +34837,7 @@ 1 2 -17762677 +17762709 @@ -35273,7 +34853,7 @@ 1 2 -17762677 +17762709 @@ -35289,7 +34869,7 @@ 1 2 -17762677 +17762709 @@ -35358,13 +34938,13 @@ 16 -153187 -397705 +153188 +397706 16 421486 -1761436 +1761440 13 @@ -35511,12 +35091,12 @@ 72210 -156029 +156030 16 176525 -758788 +758792 13 @@ -35597,7 +35177,7 @@ 94672 -1075746 +1075750 43 @@ -35754,7 +35334,7 @@ 94672 -1075746 +1075750 43 @@ -35781,7 +35361,7 @@ 3 4 -178628 +178631 4 @@ -35796,17 +35376,17 @@ 7 10 -93902 +93903 10 15 -83468 +83467 15 26 -84044 +84045 26 @@ -35842,7 +35422,7 @@ 3 4 -190914 +190917 4 @@ -35862,17 +35442,17 @@ 7 9 -90930 +90931 9 13 -98471 +98470 13 20 -84244 +84245 20 @@ -35908,7 +35488,7 @@ 3 4 -178628 +178631 4 @@ -35923,17 +35503,17 @@ 7 10 -93902 +93903 10 15 -83468 +83467 15 26 -84044 +84045 26 @@ -35953,15 +35533,15 @@ cil_jump -1461276 +1461279 instruction -1461276 +1461279 target -1171285 +1171286 @@ -35975,7 +35555,7 @@ 1 2 -1461276 +1461279 @@ -36001,7 +35581,7 @@ 3 256 -51975 +51976 @@ -36011,15 +35591,15 @@ cil_access -6097501 +6097515 instruction -6097501 +6097515 target -1342773 +1342781 @@ -36033,7 +35613,7 @@ 1 2 -6097501 +6097515 @@ -36049,7 +35629,7 @@ 1 2 -400905 +400912 2 @@ -36059,7 +35639,7 @@ 3 4 -149466 +149467 4 @@ -36078,7 +35658,7 @@ 30 -47893 +47894 16948 @@ -36089,15 +35669,15 @@ cil_value -556329 +556330 instruction -556329 +556330 value -86381 +86382 @@ -36111,7 +35691,7 @@ 1 2 -556329 +556330 @@ -36127,7 +35707,7 @@ 1 2 -37537 +37538 2 @@ -36540,11 +36120,11 @@ cil_type_location -212852 +212853 id -118809 +118810 loc @@ -36562,7 +36142,7 @@ 1 2 -52292 +52293 2 @@ -36658,11 +36238,11 @@ cil_method_location -1622420 +1622426 id -939512 +939518 loc @@ -36680,7 +36260,7 @@ 1 2 -474427 +474433 2 @@ -36791,15 +36371,15 @@ cil_type -310744 +310746 id -310744 +310746 name -69903 +69904 kind @@ -36811,7 +36391,7 @@ sourceDecl -189847 +189848 @@ -36825,7 +36405,7 @@ 1 2 -310744 +310746 @@ -36841,7 +36421,7 @@ 1 2 -310744 +310746 @@ -36857,7 +36437,7 @@ 1 2 -310744 +310746 @@ -36873,7 +36453,7 @@ 1 2 -310744 +310746 @@ -36889,7 +36469,7 @@ 1 2 -41024 +41025 2 @@ -36920,7 +36500,7 @@ 1 2 -69903 +69904 @@ -36936,7 +36516,7 @@ 1 2 -60864 +60865 2 @@ -36962,7 +36542,7 @@ 1 2 -42608 +42609 2 @@ -37006,8 +36586,8 @@ 1 -249378 -249379 +249380 +249381 1 @@ -37037,8 +36617,8 @@ 1 -67304 -67305 +67305 +67306 1 @@ -37099,8 +36679,8 @@ 1 -129439 -129440 +129440 +129441 1 @@ -37231,7 +36811,7 @@ 1 2 -181709 +181710 2 @@ -37252,7 +36832,7 @@ 1 2 -189847 +189848 @@ -37268,7 +36848,7 @@ 1 2 -189847 +189848 @@ -37284,7 +36864,7 @@ 1 2 -186967 +186968 2 @@ -37493,19 +37073,19 @@ cil_method -1164170 +1164177 id -1164170 +1164177 name -196164 +196167 parent -166238 +166239 return_type @@ -37523,7 +37103,7 @@ 1 2 -1164170 +1164177 @@ -37539,7 +37119,7 @@ 1 2 -1164170 +1164177 @@ -37555,7 +37135,7 @@ 1 2 -1164170 +1164177 @@ -37571,7 +37151,7 @@ 1 2 -91448 +91451 2 @@ -37595,7 +37175,7 @@ 13 -131916 +131917 8052 @@ -37612,7 +37192,7 @@ 1 2 -96428 +96431 2 @@ -37636,7 +37216,7 @@ 15 -103427 +103428 5615 @@ -37653,7 +37233,7 @@ 1 2 -162790 +162793 2 @@ -37689,7 +37269,7 @@ 3 4 -20193 +20194 4 @@ -37745,7 +37325,7 @@ 3 4 -20980 +20981 4 @@ -37796,7 +37376,7 @@ 2 3 -40692 +40693 3 @@ -37861,7 +37441,7 @@ 31 -402822 +402825 1661 @@ -37933,7 +37513,7 @@ 8 -123711 +123712 4236 @@ -37944,15 +37524,15 @@ cil_method_source_declaration -1075007 +1075014 method -1075007 +1075014 source -976101 +976107 @@ -37966,7 +37546,7 @@ 1 2 -1075007 +1075014 @@ -37982,7 +37562,7 @@ 1 2 -933517 +933523 2 @@ -37997,15 +37577,15 @@ cil_method_implementation -1351436 +1351440 id -1351436 +1351440 method -788230 +788234 location @@ -38023,7 +37603,7 @@ 1 2 -1351436 +1351440 @@ -38039,7 +37619,7 @@ 1 2 -1351436 +1351440 @@ -38055,7 +37635,7 @@ 1 2 -419065 +419069 2 @@ -38091,7 +37671,7 @@ 1 2 -419085 +419089 2 @@ -38351,23 +37931,23 @@ cil_field -459117 +459120 id -459117 +459120 parent -78097 +78098 name -163874 +163877 field_type -66956 +66957 @@ -38381,7 +37961,7 @@ 1 2 -459117 +459120 @@ -38397,7 +37977,7 @@ 1 2 -459117 +459120 @@ -38413,7 +37993,7 @@ 1 2 -459117 +459120 @@ -38429,7 +38009,7 @@ 1 2 -18670 +18671 2 @@ -38485,7 +38065,7 @@ 1 2 -18670 +18671 2 @@ -38541,7 +38121,7 @@ 1 2 -22569 +22570 2 @@ -38587,7 +38167,7 @@ 1 2 -105589 +105592 2 @@ -38618,7 +38198,7 @@ 1 2 -105589 +105592 2 @@ -38649,7 +38229,7 @@ 1 2 -125364 +125367 2 @@ -38680,7 +38260,7 @@ 1 2 -32076 +32077 2 @@ -38709,7 +38289,7 @@ 161 -63270 +63271 174 @@ -38726,7 +38306,7 @@ 1 2 -41592 +41593 2 @@ -38757,7 +38337,7 @@ 1 2 -43052 +43053 2 @@ -38781,7 +38361,7 @@ 90 -25354 +25355 196 @@ -38792,15 +38372,15 @@ cil_parameter -2241273 +2241281 id -2241273 +2241281 method -1091090 +1091095 index @@ -38808,7 +38388,7 @@ param_type -227413 +227415 @@ -38822,7 +38402,7 @@ 1 2 -2241273 +2241281 @@ -38838,7 +38418,7 @@ 1 2 -2241273 +2241281 @@ -38854,7 +38434,7 @@ 1 2 -2241273 +2241281 @@ -38870,17 +38450,17 @@ 1 2 -457241 +457244 2 3 -371753 +371754 3 4 -150895 +150896 4 @@ -38906,17 +38486,17 @@ 1 2 -457241 +457244 2 3 -371753 +371754 3 4 -150895 +150896 4 @@ -38942,12 +38522,12 @@ 1 2 -478810 +478813 2 3 -381799 +381801 3 @@ -39032,12 +38612,12 @@ 33136 -262097 +262098 4 -633849 -1091091 +633851 +1091096 2 @@ -39108,12 +38688,12 @@ 33136 -262097 +262098 4 -633849 -1091091 +633851 +1091096 2 @@ -39184,7 +38764,7 @@ 35950 -179765 +179767 3 @@ -39201,22 +38781,22 @@ 1 2 -67477 +67478 2 3 -53744 +53745 3 4 -22720 +22719 4 5 -15429 +15430 5 @@ -39252,22 +38832,22 @@ 1 2 -68945 +68946 2 3 -53403 +53404 3 4 -22604 +22603 4 5 -15196 +15197 5 @@ -39303,17 +38883,17 @@ 1 2 -161358 +161360 2 3 -44633 +44632 3 5 -17710 +17711 5 @@ -39398,15 +38978,15 @@ cil_getter -232515 +232516 prop -232515 +232516 method -232515 +232516 @@ -39420,7 +39000,7 @@ 1 2 -232515 +232516 @@ -39436,7 +39016,7 @@ 1 2 -232515 +232516 @@ -39590,11 +39170,11 @@ cil_property -232995 +232996 id -232995 +232996 parent @@ -39602,7 +39182,7 @@ name -60870 +60871 property_type @@ -39620,7 +39200,7 @@ 1 2 -232995 +232996 @@ -39636,7 +39216,7 @@ 1 2 -232995 +232996 @@ -39652,7 +39232,7 @@ 1 2 -232995 +232996 @@ -39811,7 +39391,7 @@ 1 2 -31483 +31484 2 @@ -39847,7 +39427,7 @@ 1 2 -31483 +31484 2 @@ -39883,7 +39463,7 @@ 1 2 -51983 +51984 2 @@ -40412,15 +39992,15 @@ cil_local_variable -989635 +989637 id -989635 +989637 impl -292891 +292892 index @@ -40442,7 +40022,7 @@ 1 2 -989635 +989637 @@ -40458,7 +40038,7 @@ 1 2 -989635 +989637 @@ -40474,7 +40054,7 @@ 1 2 -989635 +989637 @@ -40495,7 +40075,7 @@ 2 3 -49612 +49613 3 @@ -40541,7 +40121,7 @@ 2 3 -49612 +49613 3 @@ -40587,7 +40167,7 @@ 2 3 -63289 +63290 3 @@ -40672,7 +40252,7 @@ 3102 -292892 +292893 22 @@ -40738,7 +40318,7 @@ 3102 -292892 +292893 22 @@ -42262,11 +41842,11 @@ cil_method_stack_size -1351436 +1351440 method -1351436 +1351440 size @@ -42284,7 +41864,7 @@ 1 2 -1351436 +1351440 @@ -42349,7 +41929,7 @@ 74163 -1041565 +1041568 3 @@ -42360,77 +41940,77 @@ cil_public -883904 +883908 id -883904 +883908 cil_private -508798 +508804 id -508798 +508804 cil_protected -856296 +856299 id -856296 +856299 cil_internal -51633 +51635 id -51633 +51635 cil_static -459535 +459542 id -459535 +459542 cil_sealed -184038 +184039 id -184038 +184039 cil_virtual -375107 +375108 id -375107 +375108 @@ -42448,11 +42028,11 @@ cil_class -103798 +103799 id -103798 +103799 @@ -42492,33 +42072,33 @@ cil_specialname -415805 +415808 id -415805 +415808 cil_newslot -243445 +243446 id -243445 +243446 cil_base_class -108602 +108603 id -108602 +108603 base @@ -42536,7 +42116,7 @@ 1 2 -108602 +108603 @@ -42576,7 +42156,7 @@ 20 -45957 +45958 219 @@ -42587,15 +42167,15 @@ cil_base_interface -52126 +52127 id -25869 +25870 base -16465 +16466 @@ -42609,7 +42189,7 @@ 1 2 -16163 +16164 2 @@ -42650,7 +42230,7 @@ 1 2 -12889 +12890 2 @@ -42891,11 +42471,11 @@ cil_type_argument -242722 +242724 bound -171457 +171459 index @@ -42917,7 +42497,7 @@ 1 2 -120678 +120680 2 @@ -42943,7 +42523,7 @@ 1 2 -122717 +122719 2 @@ -43008,7 +42588,7 @@ 7664 -171458 +171460 3 @@ -43991,15 +43571,15 @@ metadata_handle -5245589 +5188835 entity -2712144 +3004043 location -1806 +1703 handle @@ -44017,27 +43597,27 @@ 1 2 -1333886 +1502534 2 3 -920872 +1109759 3 4 -171626 +156365 4 6 -221369 +226414 6 -591 -64391 +16 +8971 @@ -44053,27 +43633,22 @@ 1 2 -1843036 +2108097 2 3 -491566 +607938 3 4 -162465 +139145 4 -10 -206601 - - -10 -39 -8476 +13 +148863 @@ -44087,64 +43662,59 @@ 12 -1 -2 -22 - - 2 3 464 -3 +4 13 -146 +141 14 -88 -136 +93 +128 -88 -208 -136 +93 +213 +128 -208 -409 -137 +213 +418 +130 -410 -658 -137 +418 +666 +128 -663 -1103 -136 +666 +1113 +128 -1105 -1792 -136 +1115 +1811 +128 -1795 -3903 -136 +1825 +4029 +128 -3999 -13105 -137 +4055 +15302 +128 -13241 +15445 110459 -83 +72 @@ -44160,57 +43730,57 @@ 1 2 -486 +464 2 7 -142 +140 7 -46 -136 +48 +129 -46 -113 -137 +48 +114 +129 -113 -222 -136 +114 +225 +130 -223 -355 -136 +225 +360 +129 -359 +360 579 -137 +128 583 -1038 -137 +1033 +128 -1039 -2262 -136 +1037 +2272 +128 -2268 -7743 -136 +2297 +8607 +129 -7800 +8727 110459 -87 +69 @@ -44231,47 +43801,47 @@ 2 3 -53204 +52480 3 7 -9098 +9134 7 15 -8859 +9762 15 -26 -9051 +28 +9288 -26 -39 -8919 +28 +42 +8952 -39 -63 -9148 +42 +65 +8905 -63 -104 -8882 +65 +105 +8954 -104 -539 -8794 +105 +652 +8790 -539 -1544 -878 +652 +1533 +568 @@ -44292,42 +43862,42 @@ 4 5 -55971 +55970 5 -12 -9795 +11 +8999 -12 -20 -8862 +11 +18 +9170 -20 -28 -9240 +18 +26 +9007 -28 -43 -8804 +26 +40 +9508 -43 -63 -8904 +40 +61 +8955 -63 -200 -8803 +61 +185 +8830 -200 -1807 -2555 +185 +1704 +2495 From e990bea248d280239b99c240acf3284d6b9e14a4 Mon Sep 17 00:00:00 2001 From: Calum Grant Date: Tue, 12 Nov 2019 11:50:06 +0000 Subject: [PATCH 0358/2538] C#: Update upgrade script --- .../semmlecode.csharp.dbscheme | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme index e55d8c990309..df0118d2d283 100644 --- a/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme +++ b/csharp/upgrades/f93793ee5f6b7bec615eaa1af0a1a4dea19472bb/semmlecode.csharp.dbscheme @@ -480,8 +480,8 @@ case @nullability.kind of | 2 = @annotated ; -#keyset[nullability, index] -nullability_member(int nullability: @nullability ref, int index: int ref, int child: @nullability ref) +#keyset[parent, index] +nullability_parent(int nullability: @nullability ref, int index: int ref, int parent: @nullability ref) type_nullability(int id: @has_type_annotation ref, int nullability: @nullability ref) From f50dd84c490f257118f389c3f6869de534f77576 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Nov 2019 14:09:54 +0000 Subject: [PATCH 0359/2538] CPP: Rename good and bad example files. --- .../{NtohlArrayBad.cpp => NtohlArrayNoBound-bad.cpp} | 0 .../{NtohlArrayGood.cpp => NtohlArrayNoBound-good.cpp} | 0 .../src/Likely Bugs/Memory Management/NtohlArrayNoBound.qhelp | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) rename cpp/ql/src/Likely Bugs/Memory Management/{NtohlArrayBad.cpp => NtohlArrayNoBound-bad.cpp} (100%) rename cpp/ql/src/Likely Bugs/Memory Management/{NtohlArrayGood.cpp => NtohlArrayNoBound-good.cpp} (100%) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayBad.cpp b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound-bad.cpp similarity index 100% rename from cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayBad.cpp rename to cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound-bad.cpp diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayGood.cpp b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound-good.cpp similarity index 100% rename from cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayGood.cpp rename to cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound-good.cpp diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qhelp index fc8f309f73a0..3556df38c58e 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qhelp +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qhelp @@ -31,10 +31,10 @@ it to host byte order. The data is then used as an index in an array access expr there is no validation that the data returned by ntohl is within the bounds of the array, which could lead to reading outside the bounds of the buffer.

    - +

    In the corrected example, the returned data is validated against the known size of the buffer, before being used as an array index.

    - + From 0343bd6b9ca51035919ae7a01c74cb6867093707 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Nov 2019 14:37:56 +0000 Subject: [PATCH 0360/2538] CPP: Inline BufferAccess into NtohlArrayNoBound.qll (we'd prefer other queries to be written with the models library or Security.BufferAccess). --- .../Memory Management/BufferAccess.qll | 174 ------------------ .../Memory Management/NtohlArrayNoBound.qll | 174 +++++++++++++++++- 2 files changed, 173 insertions(+), 175 deletions(-) delete mode 100644 cpp/ql/src/Likely Bugs/Memory Management/BufferAccess.qll diff --git a/cpp/ql/src/Likely Bugs/Memory Management/BufferAccess.qll b/cpp/ql/src/Likely Bugs/Memory Management/BufferAccess.qll deleted file mode 100644 index 286db31020fb..000000000000 --- a/cpp/ql/src/Likely Bugs/Memory Management/BufferAccess.qll +++ /dev/null @@ -1,174 +0,0 @@ -import cpp -import semmle.code.cpp.dataflow.TaintTracking -private import semmle.code.cpp.dataflow.RecursionPrevention - -/** - * A buffer which includes an allocation size. - */ -abstract class BufferWithSize extends DataFlow::Node { - abstract Expr getSizeExpr(); - - BufferAccess getAnAccess() { - any(BufferWithSizeConfig bsc).hasFlow(this, DataFlow::exprNode(result.getPointer())) - } -} - -/** An allocation function. */ -abstract class Alloc extends Function { } - -/** - * Allocation functions identified by the QL for C/C++ standard library. - */ -class DefaultAlloc extends Alloc { - DefaultAlloc() { allocationFunction(this) } -} - -/** A buffer created through a call to an allocation function. */ -class AllocBuffer extends BufferWithSize { - FunctionCall call; - - AllocBuffer() { - asExpr() = call and - call.getTarget() instanceof Alloc - } - - override Expr getSizeExpr() { result = call.getArgument(0) } -} - -/** - * Find accesses of buffers for which we have a size expression. - */ -private class BufferWithSizeConfig extends TaintTracking::Configuration { - BufferWithSizeConfig() { this = "BufferWithSize" } - - override predicate isSource(DataFlow::Node n) { n = any(BufferWithSize b) } - - override predicate isSink(DataFlow::Node n) { n.asExpr() = any(BufferAccess ae).getPointer() } - - override predicate isSanitizer(DataFlow::Node s) { - s = any(BufferWithSize b) and - s.asExpr().getControlFlowScope() instanceof Alloc - } -} - -/** - * An access (read or write) to a buffer, provided as a pair of - * a pointer to the buffer and the length of data to be read or written. - * Extend this class to support different kinds of buffer access. - */ -abstract class BufferAccess extends Locatable { - /** Gets the pointer to the buffer being accessed. */ - abstract Expr getPointer(); - - /** Gets the length of the data being read or written by this buffer access. */ - abstract Expr getAccessedLength(); -} - -/** - * A buffer access through an array expression. - */ -class ArrayBufferAccess extends BufferAccess, ArrayExpr { - override Expr getPointer() { result = this.getArrayBase() } - - override Expr getAccessedLength() { result = this.getArrayOffset() } -} - -/** - * A buffer access through an overloaded array expression. - */ -class OverloadedArrayBufferAccess extends BufferAccess, OverloadedArrayExpr { - override Expr getPointer() { result = this.getQualifier() } - - override Expr getAccessedLength() { result = this.getAnArgument() } -} - -/** - * A buffer access through pointer arithmetic. - */ -class PointerArithmeticAccess extends BufferAccess, Expr { - PointerArithmeticOperation p; - - PointerArithmeticAccess() { - this = p and - p.getAnOperand().getType().getUnspecifiedType() instanceof IntegralType and - not p.getParent() instanceof ComparisonOperation - } - - override Expr getPointer() { - result = p.getAnOperand() and - result.getType().getUnspecifiedType() instanceof PointerType - } - - override Expr getAccessedLength() { - result = p.getAnOperand() and - result.getType().getUnspecifiedType() instanceof IntegralType - } -} - -/** - * A pair of buffer accesses through a call to memcpy. - */ -class MemCpy extends BufferAccess, FunctionCall { - MemCpy() { getTarget().hasName("memcpy") } - - override Expr getPointer() { - result = getArgument(0) or - result = getArgument(1) - } - - override Expr getAccessedLength() { result = getArgument(2) } -} - -class StrncpySizeExpr extends BufferAccess, FunctionCall { - StrncpySizeExpr() { getTarget().hasName("strncpy") } - - override Expr getPointer() { - result = getArgument(0) or - result = getArgument(1) - } - - override Expr getAccessedLength() { result = getArgument(2) } -} - -class RecvSizeExpr extends BufferAccess, FunctionCall { - RecvSizeExpr() { getTarget().hasName("recv") } - - override Expr getPointer() { result = getArgument(1) } - - override Expr getAccessedLength() { result = getArgument(2) } -} - -class SendSizeExpr extends BufferAccess, FunctionCall { - SendSizeExpr() { getTarget().hasName("send") } - - override Expr getPointer() { result = getArgument(1) } - - override Expr getAccessedLength() { result = getArgument(2) } -} - -class SnprintfSizeExpr extends BufferAccess, FunctionCall { - SnprintfSizeExpr() { getTarget().hasName("snprintf") } - - override Expr getPointer() { result = getArgument(0) } - - override Expr getAccessedLength() { result = getArgument(1) } -} - -class MemcmpSizeExpr extends BufferAccess, FunctionCall { - MemcmpSizeExpr() { getTarget().hasName("Memcmp") } - - override Expr getPointer() { - result = getArgument(0) or - result = getArgument(1) - } - - override Expr getAccessedLength() { result = getArgument(2) } -} - -class MallocSizeExpr extends BufferAccess, FunctionCall { - MallocSizeExpr() { getTarget().hasName("malloc") } - - override Expr getPointer() { none() } - - override Expr getAccessedLength() { result = getArgument(1) } -} diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll index 3e1f74bfbed0..306c72516674 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll @@ -1,8 +1,180 @@ import cpp import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Guards -import BufferAccess import semmle.code.cpp.valuenumbering.GlobalValueNumbering +import semmle.code.cpp.dataflow.TaintTracking +private import semmle.code.cpp.dataflow.RecursionPrevention + +/** + * A buffer which includes an allocation size. + */ +abstract class BufferWithSize extends DataFlow::Node { + abstract Expr getSizeExpr(); + + BufferAccess getAnAccess() { + any(BufferWithSizeConfig bsc).hasFlow(this, DataFlow::exprNode(result.getPointer())) + } +} + +/** An allocation function. */ +abstract class Alloc extends Function { } + +/** + * Allocation functions identified by the QL for C/C++ standard library. + */ +class DefaultAlloc extends Alloc { + DefaultAlloc() { allocationFunction(this) } +} + +/** A buffer created through a call to an allocation function. */ +class AllocBuffer extends BufferWithSize { + FunctionCall call; + + AllocBuffer() { + asExpr() = call and + call.getTarget() instanceof Alloc + } + + override Expr getSizeExpr() { result = call.getArgument(0) } +} + +/** + * Find accesses of buffers for which we have a size expression. + */ +private class BufferWithSizeConfig extends TaintTracking::Configuration { + BufferWithSizeConfig() { this = "BufferWithSize" } + + override predicate isSource(DataFlow::Node n) { n = any(BufferWithSize b) } + + override predicate isSink(DataFlow::Node n) { n.asExpr() = any(BufferAccess ae).getPointer() } + + override predicate isSanitizer(DataFlow::Node s) { + s = any(BufferWithSize b) and + s.asExpr().getControlFlowScope() instanceof Alloc + } +} + +/** + * An access (read or write) to a buffer, provided as a pair of + * a pointer to the buffer and the length of data to be read or written. + * Extend this class to support different kinds of buffer access. + */ +abstract class BufferAccess extends Locatable { + /** Gets the pointer to the buffer being accessed. */ + abstract Expr getPointer(); + + /** Gets the length of the data being read or written by this buffer access. */ + abstract Expr getAccessedLength(); +} + +/** + * A buffer access through an array expression. + */ +class ArrayBufferAccess extends BufferAccess, ArrayExpr { + override Expr getPointer() { result = this.getArrayBase() } + + override Expr getAccessedLength() { result = this.getArrayOffset() } +} + +/** + * A buffer access through an overloaded array expression. + */ +class OverloadedArrayBufferAccess extends BufferAccess, OverloadedArrayExpr { + override Expr getPointer() { result = this.getQualifier() } + + override Expr getAccessedLength() { result = this.getAnArgument() } +} + +/** + * A buffer access through pointer arithmetic. + */ +class PointerArithmeticAccess extends BufferAccess, Expr { + PointerArithmeticOperation p; + + PointerArithmeticAccess() { + this = p and + p.getAnOperand().getType().getUnspecifiedType() instanceof IntegralType and + not p.getParent() instanceof ComparisonOperation + } + + override Expr getPointer() { + result = p.getAnOperand() and + result.getType().getUnspecifiedType() instanceof PointerType + } + + override Expr getAccessedLength() { + result = p.getAnOperand() and + result.getType().getUnspecifiedType() instanceof IntegralType + } +} + +/** + * A pair of buffer accesses through a call to memcpy. + */ +class MemCpy extends BufferAccess, FunctionCall { + MemCpy() { getTarget().hasName("memcpy") } + + override Expr getPointer() { + result = getArgument(0) or + result = getArgument(1) + } + + override Expr getAccessedLength() { result = getArgument(2) } +} + +class StrncpySizeExpr extends BufferAccess, FunctionCall { + StrncpySizeExpr() { getTarget().hasName("strncpy") } + + override Expr getPointer() { + result = getArgument(0) or + result = getArgument(1) + } + + override Expr getAccessedLength() { result = getArgument(2) } +} + +class RecvSizeExpr extends BufferAccess, FunctionCall { + RecvSizeExpr() { getTarget().hasName("recv") } + + override Expr getPointer() { result = getArgument(1) } + + override Expr getAccessedLength() { result = getArgument(2) } +} + +class SendSizeExpr extends BufferAccess, FunctionCall { + SendSizeExpr() { getTarget().hasName("send") } + + override Expr getPointer() { result = getArgument(1) } + + override Expr getAccessedLength() { result = getArgument(2) } +} + +class SnprintfSizeExpr extends BufferAccess, FunctionCall { + SnprintfSizeExpr() { getTarget().hasName("snprintf") } + + override Expr getPointer() { result = getArgument(0) } + + override Expr getAccessedLength() { result = getArgument(1) } +} + +class MemcmpSizeExpr extends BufferAccess, FunctionCall { + MemcmpSizeExpr() { getTarget().hasName("Memcmp") } + + override Expr getPointer() { + result = getArgument(0) or + result = getArgument(1) + } + + override Expr getAccessedLength() { result = getArgument(2) } +} + +class MallocSizeExpr extends BufferAccess, FunctionCall { + MallocSizeExpr() { getTarget().hasName("malloc") } + + override Expr getPointer() { none() } + + override Expr getAccessedLength() { result = getArgument(1) } +} class NetworkFunctionCall extends FunctionCall { NetworkFunctionCall() { From 5c87ed5ab27afbf8004be654615cb709cceb37ec Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Nov 2019 14:43:08 +0000 Subject: [PATCH 0361/2538] CPP: Remove unused code. --- .../Memory Management/NtohlArrayNoBound.qll | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll index 306c72516674..0871da2f92e4 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll +++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll @@ -2,57 +2,6 @@ import cpp import semmle.code.cpp.dataflow.DataFlow import semmle.code.cpp.controlflow.Guards import semmle.code.cpp.valuenumbering.GlobalValueNumbering -import semmle.code.cpp.dataflow.TaintTracking -private import semmle.code.cpp.dataflow.RecursionPrevention - -/** - * A buffer which includes an allocation size. - */ -abstract class BufferWithSize extends DataFlow::Node { - abstract Expr getSizeExpr(); - - BufferAccess getAnAccess() { - any(BufferWithSizeConfig bsc).hasFlow(this, DataFlow::exprNode(result.getPointer())) - } -} - -/** An allocation function. */ -abstract class Alloc extends Function { } - -/** - * Allocation functions identified by the QL for C/C++ standard library. - */ -class DefaultAlloc extends Alloc { - DefaultAlloc() { allocationFunction(this) } -} - -/** A buffer created through a call to an allocation function. */ -class AllocBuffer extends BufferWithSize { - FunctionCall call; - - AllocBuffer() { - asExpr() = call and - call.getTarget() instanceof Alloc - } - - override Expr getSizeExpr() { result = call.getArgument(0) } -} - -/** - * Find accesses of buffers for which we have a size expression. - */ -private class BufferWithSizeConfig extends TaintTracking::Configuration { - BufferWithSizeConfig() { this = "BufferWithSize" } - - override predicate isSource(DataFlow::Node n) { n = any(BufferWithSize b) } - - override predicate isSink(DataFlow::Node n) { n.asExpr() = any(BufferAccess ae).getPointer() } - - override predicate isSanitizer(DataFlow::Node s) { - s = any(BufferWithSize b) and - s.asExpr().getControlFlowScope() instanceof Alloc - } -} /** * An access (read or write) to a buffer, provided as a pair of From 5b2e32b0513463d4c5f29fcea133e6f761555ba6 Mon Sep 17 00:00:00 2001 From: Max Schaefer Date: Tue, 12 Nov 2019 15:03:02 +0000 Subject: [PATCH 0362/2538] Add `qlpack.yml` files for test folders. --- cpp/ql/test/qlpack.yml | 3 +++ csharp/ql/test/qlpack.yml | 3 +++ java/ql/test/qlpack.yml | 3 +++ javascript/ql/test/qlpack.yml | 3 +++ python/ql/test/qlpack.yml | 3 +++ 5 files changed, 15 insertions(+) create mode 100644 cpp/ql/test/qlpack.yml create mode 100644 csharp/ql/test/qlpack.yml create mode 100644 java/ql/test/qlpack.yml create mode 100644 javascript/ql/test/qlpack.yml create mode 100644 python/ql/test/qlpack.yml diff --git a/cpp/ql/test/qlpack.yml b/cpp/ql/test/qlpack.yml new file mode 100644 index 000000000000..36dcb70d4efc --- /dev/null +++ b/cpp/ql/test/qlpack.yml @@ -0,0 +1,3 @@ +name: codeql-cpp-tests +version: 0.0.0 +libraryPathDependencies: codeql-cpp diff --git a/csharp/ql/test/qlpack.yml b/csharp/ql/test/qlpack.yml new file mode 100644 index 000000000000..20f6e83ee305 --- /dev/null +++ b/csharp/ql/test/qlpack.yml @@ -0,0 +1,3 @@ +name: codeql-csharp-tests +version: 0.0.0 +libraryPathDependencies: codeql-csharp diff --git a/java/ql/test/qlpack.yml b/java/ql/test/qlpack.yml new file mode 100644 index 000000000000..d4b46d7d2b01 --- /dev/null +++ b/java/ql/test/qlpack.yml @@ -0,0 +1,3 @@ +name: codeql-java-tests +version: 0.0.0 +libraryPathDependencies: codeql-java diff --git a/javascript/ql/test/qlpack.yml b/javascript/ql/test/qlpack.yml new file mode 100644 index 000000000000..d40472ed653c --- /dev/null +++ b/javascript/ql/test/qlpack.yml @@ -0,0 +1,3 @@ +name: codeql-javascript-tests +version: 0.0.0 +libraryPathDependencies: codeql-javascript diff --git a/python/ql/test/qlpack.yml b/python/ql/test/qlpack.yml new file mode 100644 index 000000000000..eed82a82aec8 --- /dev/null +++ b/python/ql/test/qlpack.yml @@ -0,0 +1,3 @@ +name: codeql-python-tests +version: 0.0.0 +libraryPathDependencies: codeql-python From ea9e3bb1a89d22ebad7f8ca81c6d2bd353226cf0 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Tue, 12 Nov 2019 16:17:03 +0000 Subject: [PATCH 0363/2538] CPP: Rename VirtualDispatch again. --- cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll | 2 +- .../VirtualDispatchPrototype.qll} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename cpp/ql/src/semmle/code/cpp/{controlflow/VirtualDispatch.qll => dispatch/VirtualDispatchPrototype.qll} (100%) diff --git a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll index 0d7b9083846e..8f2950c91239 100644 --- a/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll +++ b/cpp/ql/src/Security/CWE/CWE-457/InitializationFunctions.qll @@ -4,7 +4,7 @@ import cpp import external.ExternalArtifact -private import semmle.code.cpp.controlflow.VirtualDispatch +private import semmle.code.cpp.dispatch.VirtualDispatchPrototype import semmle.code.cpp.NestedFields import Microsoft.SAL import semmle.code.cpp.controlflow.Guards diff --git a/cpp/ql/src/semmle/code/cpp/controlflow/VirtualDispatch.qll b/cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatchPrototype.qll similarity index 100% rename from cpp/ql/src/semmle/code/cpp/controlflow/VirtualDispatch.qll rename to cpp/ql/src/semmle/code/cpp/dispatch/VirtualDispatchPrototype.qll From 8cd6b5176316d00e06a59f27f01fbf7d6c909de9 Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 12 Nov 2019 17:27:18 +0100 Subject: [PATCH 0364/2538] Java: Add ConditionalExpr to overflow candidate pattern. --- java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql | 5 +++++ java/ql/test/query-tests/UselessComparisonTest/A.java | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql index e28b190b4650..af37df936e04 100644 --- a/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql +++ b/java/ql/src/Likely Bugs/Comparison/UselessComparisonTest.ql @@ -132,6 +132,11 @@ Expr overFlowCand() { result.(AssignExpr).getRhs() = overFlowCand() or result.(LocalVariableDeclExpr).getInit() = overFlowCand() + or + exists(ConditionalExpr c | c = result | + c.getTrueExpr() = overFlowCand() and + c.getFalseExpr() = overFlowCand() + ) } predicate positiveOrNegative(Expr e) { positive(e) or negative(e) } diff --git a/java/ql/test/query-tests/UselessComparisonTest/A.java b/java/ql/test/query-tests/UselessComparisonTest/A.java index f2b473c2ee32..abc525ff20dc 100644 --- a/java/ql/test/query-tests/UselessComparisonTest/A.java +++ b/java/ql/test/query-tests/UselessComparisonTest/A.java @@ -121,6 +121,11 @@ void overflowTests(int x, int y) { } } + void overflowTests2(int[] a, boolean b) { + int newlen = b ? (a.length + 1) << 1 : (a.length >> 1) + a.length; + if (newlen < 0) overflow(); + } + static final long VAL = 100L; long overflowAwareIncrease(long x) { From 7619275c8bcf21db7e46faf5c4799be564ea3bbf Mon Sep 17 00:00:00 2001 From: Anders Schack-Mulligen Date: Tue, 12 Nov 2019 15:59:59 +0100 Subject: [PATCH 0365/2538] Java: Fix range analysis bug in integral inequality bounds. --- .../semmle/code/java/dataflow/RangeAnalysis.qll | 15 +++++++++------ .../test/query-tests/UselessComparisonTest/C.java | 6 ++++++ 2 files changed, 15 insertions(+), 6 deletions(-) create mode 100644 java/ql/test/query-tests/UselessComparisonTest/C.java diff --git a/java/ql/src/semmle/code/java/dataflow/RangeAnalysis.qll b/java/ql/src/semmle/code/java/dataflow/RangeAnalysis.qll index 41ed735b7520..f8384245073e 100644 --- a/java/ql/src/semmle/code/java/dataflow/RangeAnalysis.qll +++ b/java/ql/src/semmle/code/java/dataflow/RangeAnalysis.qll @@ -298,10 +298,11 @@ private predicate boundFlowStepSsa( ) } -/** Holds if `v != e + delta` at `pos`. */ -private predicate unequalFlowStepSsa( +/** Holds if `v != e + delta` at `pos` and `v` is of integral type. */ +private predicate unequalFlowStepIntegralSsa( SsaVariable v, SsaReadPosition pos, Expr e, int delta, Reason reason ) { + v.getSourceVariable().getType() instanceof IntegralType and exists(Guard guard, boolean testIsTrue | pos.hasReadOfVar(v) and guard = eqFlowCond(v, e, delta, false, testIsTrue) and @@ -555,7 +556,7 @@ private predicate boundedSsa( boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2) | - unequalSsa(v, pos, b, d, r1) and + unequalIntegralSsa(v, pos, b, d, r1) and ( upper = true and delta = d - 1 or @@ -570,11 +571,13 @@ private predicate boundedSsa( } /** - * Holds if `v != b + delta` at `pos`. + * Holds if `v != b + delta` at `pos` and `v` is of integral type. */ -private predicate unequalSsa(SsaVariable v, SsaReadPosition pos, Bound b, int delta, Reason reason) { +private predicate unequalIntegralSsa( + SsaVariable v, SsaReadPosition pos, Bound b, int delta, Reason reason +) { exists(Expr e, int d1, int d2 | - unequalFlowStepSsa(v, pos, e, d1, reason) and + unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and bounded(e, b, d2, true, _, _, _) and bounded(e, b, d2, false, _, _, _) and delta = d2 + d1 diff --git a/java/ql/test/query-tests/UselessComparisonTest/C.java b/java/ql/test/query-tests/UselessComparisonTest/C.java new file mode 100644 index 000000000000..c1ca8261eb2a --- /dev/null +++ b/java/ql/test/query-tests/UselessComparisonTest/C.java @@ -0,0 +1,6 @@ +public class C { + double m1(double x) { + return (x < 0 || x > 1 || Double.isNaN(x)) ? Double.NaN : + x == 0 ? 0 : x == 1 ? 1 : 0.5; + } +} From f54e0d0d07425b269f7e5269059c8b7bd7c774fe Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 26 Aug 2019 11:04:42 -0700 Subject: [PATCH 0366/2538] [CPP-418] Initial modifications to Type.qll. To be continued. --- cpp/ql/src/semmle/code/cpp/Type.qll | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index ea1e7fd50268..a838a09eebf4 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -5,6 +5,8 @@ private import semmle.code.cpp.internal.ResolveClass /** * A C/C++ type. + * + * This QL class represents the root of the C/C++ type hierarchy. */ class Type extends Locatable, @type { Type() { isType(underlyingElement(this)) } @@ -289,6 +291,13 @@ class Type extends Locatable, @type { /** * A C/C++ built-in primitive type (int, float, void, and so on). See 4.1.1. + * In the following example, `unsigned int` and `double` denote primitive + * built-in types: + * ``` + * double a; + * unsigned int ua[40]; + * typedef double LargeFloat; + * ``` */ class BuiltInType extends Type, @builtintype { override string toString() { result = this.getName() } From 1f35f4bb522ad1ca258dea3c242df5889b682440 Mon Sep 17 00:00:00 2001 From: Ziemowit Laski Date: Mon, 2 Sep 2019 15:45:38 -0700 Subject: [PATCH 0367/2538] [CPP-418] Add descriptions for QL classes in Type.qll. (Still need to figure out how to describe unknown and erroneous types.) --- cpp/ql/src/semmle/code/cpp/Type.qll | 302 +++++++++++++++++++++++----- 1 file changed, 252 insertions(+), 50 deletions(-) diff --git a/cpp/ql/src/semmle/code/cpp/Type.qll b/cpp/ql/src/semmle/code/cpp/Type.qll index a838a09eebf4..a90b87bc7ac7 100644 --- a/cpp/ql/src/semmle/code/cpp/Type.qll +++ b/cpp/ql/src/semmle/code/cpp/Type.qll @@ -310,7 +310,7 @@ class BuiltInType extends Type, @builtintype { } /** - * An erroneous type. + * An erroneous type. This type has no corresponding C/C++ syntax. */ class ErroneousType extends BuiltInType { ErroneousType() { builtintypes(underlyingElement(this), _, 1, _, _, _) } @@ -319,7 +319,7 @@ class ErroneousType extends BuiltInType { } /** - * The unknown type. + * The unknown type. This type has no corresponding C/C++ syntax. */ class UnknownType extends BuiltInType { UnknownType() { builtintypes(underlyingElement(this), _, 2, _, _, _) } @@ -335,6 +335,10 @@ private predicate isArithmeticType(@builtintype type, int kind) { /** * The C/C++ arithmetic types. See 4.1.1. + * + * This includes primitive types on which arithmetic, bitwise or logical + * operations may be performed. Examples of arithmetic types include + * `char`, `int`, `float` and `bool`. */ class ArithmeticType extends BuiltInType { ArithmeticType() { isArithmeticType(underlyingElement(this), _) } @@ -359,10 +363,19 @@ private predicate isIntegralType(@builtintype type, int kind) { /** * A C/C++ integral or enum type. - * The definition of "integral type" in the C++ Standard excludes enum types, - * but because an enum type holds a value of its underlying integral type, + * + * The definition of "integral type" in the C++ Standard excludes `enum` types, + * but because an `enum` type holds a value of its underlying integral type, * it is often useful to have a common category that includes both integral - * and enum types. + * and `enum` types. + * + * In the following example, `a`, `b` and `c` are all declared with an + * integral or `enum` type: + * ``` + * unsigned long a; + * enum e1 { val1, val2 } b; + * enum class e2: short { val3, val4 } c; + * ``` */ class IntegralOrEnumType extends Type { IntegralOrEnumType() { @@ -435,7 +448,17 @@ private predicate integralTypeMapping(int original, int canonical, int unsigned, } /** - * The C/C++ integral types. See 4.1.1. + * The C/C++ integral types. See 4.1.1. These are types that are represented + * as integers of varying sizes. Both `enum` types and floating-point types + * are excluded. + * + * In the following examples, `a`, `b` and `c` are declared using integral + * types: + * ``` + * unsigned int a; + * long long b; + * char c; + * ``` */ class IntegralType extends ArithmeticType, IntegralOrEnumType { int kind; @@ -506,7 +529,12 @@ class IntegralType extends ArithmeticType, IntegralOrEnumType { } /** - * The C/C++ boolean type. See 4.2. + * The C/C++ boolean type. See 4.2. This is the C `_Bool` type + * or the C++ `bool` type. For example, + * ``` + * extern bool a, b; // C++ + * _Bool c, d; // C + * ``` */ class BoolType extends IntegralType { BoolType() { builtintypes(underlyingElement(this), _, 4, _, _, _) } @@ -515,12 +543,23 @@ class BoolType extends IntegralType { } /** - * The C/C++ character types. See 4.3. + * The C/C++ character types. See 4.3. This includes the `char`, + * `signed char` and `unsigned char` types, all of which are + * distinct from one another. For example, + * ``` + * char a, b; + * signed char c, d; + * unsigned char e, f; + * ``` */ abstract class CharType extends IntegralType { } /** - * The C/C++ char type (which is different to signed char and unsigned char). + * The C/C++ `char` type (which is distinct from `signed char` and + * `unsigned char`). For example, + * ``` + * char a, b; + * ``` */ class PlainCharType extends CharType { PlainCharType() { builtintypes(underlyingElement(this), _, 5, _, _, _) } @@ -529,7 +568,11 @@ class PlainCharType extends CharType { } /** - * The C/C++ unsigned char type (which is different to plain char, even when chars are unsigned by default). + * The C/C++ `unsigned char` type (which is distinct from plain `char` + * even when `char` is unsigned by default). + * ``` + * unsigned char e, f; + * ``` */ class UnsignedCharType extends CharType { UnsignedCharType() { builtintypes(underlyingElement(this), _, 6, _, _, _) } @@ -538,7 +581,11 @@ class UnsignedCharType extends CharType { } /** - * The C/C++ signed char type (which is different to plain char, even when chars are signed by default). + * The C/C++ `signed char` type (which is distinct from plain `char` + * even when `char` is signed by default). + * ``` + * signed char c, d; + * ``` */ class SignedCharType extends CharType { SignedCharType() { builtintypes(underlyingElement(this), _, 7, _, _, _) } @@ -547,7 +594,11 @@ class SignedCharType extends CharType { } /** - * The C/C++ short types. See 4.3. + * The C/C++ short types. See 4.3. This includes `short`, `signed short` + * and `unsigned short`; `short` and `signed short` are equivalent. + * ``` + * signed short ss; + * ``` */ class ShortType extends IntegralType { ShortType() { @@ -560,7 +611,11 @@ class ShortType extends IntegralType { } /** - * The C/C++ integer types. See 4.4. + * The C/C++ integer types. See 4.4. This includes `int`, `signed int` + * and `unsigned int`; `int` and `signed int` are equivalent. + * ``` + * unsigned int ui; + * ``` */ class IntType extends IntegralType { IntType() { @@ -573,7 +628,11 @@ class IntType extends IntegralType { } /** - * The C/C++ long types. See 4.4. + * The C/C++ long types. See 4.4. This includes `long`, `signed long` + * and `unsigned long`; `long` and `signed long` are equivalent. + * ``` + * long l; + * ``` */ class LongType extends IntegralType { LongType() { @@ -586,7 +645,11 @@ class LongType extends IntegralType { } /** - * The C/C++ long long types. See 4.4. + * The C/C++ long long types. See 4.4. This includes `long long`, `signed long long` + * and `unsigned long long`; `long long` and `signed long long` are equivalent. + * ``` + * signed long long sll; + * ``` */ class LongLongType extends IntegralType { LongLongType() { @@ -599,7 +662,13 @@ class LongLongType extends IntegralType { } /** - * The GNU C __int128 types. + * The GNU C __int128 primitive types. They are not part of standard C/C++. + * + * This includes `__int128`, `signed __int128` + * and `unsigned __int128`; `__int128` and `signed __int128` are equivalent. + * ``` + * unsigned __int128 ui128; + * ``` */ class Int128Type extends IntegralType { Int128Type() { @@ -607,10 +676,18 @@ class Int128Type extends IntegralType { builtintypes(underlyingElement(this), _, 36, _, _, _) or builtintypes(underlyingElement(this), _, 37, _, _, _) } + + override string getCanonicalQLClass() { result = "Int128Type" } } /** - * The C/C++ floating point types. See 4.5. + * The C/C++ floating point types. See 4.5. This includes `float`, + * `double` and `long double` types. + * ``` + * float f; + * double d; + * long double ld; + * ``` */ class FloatingPointType extends ArithmeticType { FloatingPointType() { @@ -628,7 +705,10 @@ class FloatingPointType extends ArithmeticType { } /** - * The C/C++ float type. + * The C/C++ `float` type. + * ``` + * float f; + * ``` */ class FloatType extends FloatingPointType { FloatType() { builtintypes(underlyingElement(this), _, 24, _, _, _) } @@ -637,7 +717,10 @@ class FloatType extends FloatingPointType { } /** - * The C/C++ double type. + * The C/C++ `double` type. + * ``` + * double d; + * ``` */ class DoubleType extends FloatingPointType { DoubleType() { builtintypes(underlyingElement(this), _, 25, _, _, _) } @@ -646,7 +729,10 @@ class DoubleType extends FloatingPointType { } /** - * The C/C++ long double type. + * The C/C++ `long double` type. + * ``` + * long double ld; + * ``` */ class LongDoubleType extends FloatingPointType { LongDoubleType() { builtintypes(underlyingElement(this), _, 26, _, _, _) } @@ -655,35 +741,58 @@ class LongDoubleType extends FloatingPointType { } /** - * The GNU C __float128 type. + * The GNU C `__float128` primitive type. This is not standard C/C++. + * ``` + * __float128 f128; + * ``` */ class Float128Type extends FloatingPointType { Float128Type() { builtintypes(underlyingElement(this), _, 38, _, _, _) } + + override string getCanonicalQLClass() { result = "Float128Type" } } /** - * The GNU C _Decimal32 type. + * The GNU C `_Decimal32` primitive type. This is not standard C/C++. + * ``` + * _Decimal32 d32; + * ``` */ class Decimal32Type extends FloatingPointType { Decimal32Type() { builtintypes(underlyingElement(this), _, 40, _, _, _) } + + override string getCanonicalQLClass() { result = "Decimal32Type" } } /** - * The GNU C _Decimal64 type. + * The GNU C `_Decimal64` primitive type. This is not standard C/C++. + * ``` + * _Decimal64 d64; + * ``` */ class Decimal64Type extends FloatingPointType { Decimal64Type() { builtintypes(underlyingElement(this), _, 41, _, _, _) } + + override string getCanonicalQLClass() { result = "Decimal64Type" } } /** - * The GNU C _Decimal128 type. + * The GNU C `_Decimal128` primitive type. This is not standard C/C++. + * ``` + * _Decimal128 d128; + * ``` */ class Decimal128Type extends FloatingPointType { Decimal128Type() { builtintypes(underlyingElement(this), _, 42, _, _, _) } + + override string getCanonicalQLClass() { result = "Decimal128Type" } } /** - * The C/C++ void type. See 4.7. + * The C/C++ `void` type. See 4.7. + * ``` + * const void *cvp; + * ``` */ class VoidType extends BuiltInType { VoidType() { builtintypes(underlyingElement(this), _, 3, _, _, _) } @@ -697,6 +806,9 @@ class VoidType extends BuiltInType { * Note that on some platforms `wchar_t` doesn't exist as a built-in * type but a typedef is provided. Consider using the `Wchar_t` QL * class to include these types. + * ``` + * wchar_t wc; + * ``` */ class WideCharType extends IntegralType { WideCharType() { builtintypes(underlyingElement(this), _, 33, _, _, _) } @@ -705,7 +817,10 @@ class WideCharType extends IntegralType { } /** - * The C/C++ `char16_t` type. + * The C/C++ `char16_t` type. This is available starting with C11 and C++11. + * ``` + * char16_t c16; + * ``` */ class Char16Type extends IntegralType { Char16Type() { builtintypes(underlyingElement(this), _, 43, _, _, _) } @@ -714,7 +829,10 @@ class Char16Type extends IntegralType { } /** - * The C/C++ `char32_t` type. + * The C/C++ `char32_t` type. This is available starting with C11 and C++11. + * ``` + * char32_t c32; + * ``` */ class Char32Type extends IntegralType { Char32Type() { builtintypes(underlyingElement(this), _, 44, _, _, _) } @@ -723,13 +841,11 @@ class Char32Type extends IntegralType { } /** - * The type of the C++11 nullptr constant. - * - * Note that this is not `nullptr_t`, as `nullptr_t` is defined as: + * The (primitive) type of the C++11 `nullptr` constant. It is the + * unspeakable type given by `decltype(nullptr)`. * ``` - * typedef decltype(nullptr) nullptr_t; + * typedef decltype(nullptr) nullptr_t; * ``` - * Instead, this is the unspeakable type given by `decltype(nullptr)`. */ class NullPointerType extends BuiltInType { NullPointerType() { builtintypes(underlyingElement(this), _, 34, _, _, _) } @@ -740,8 +856,14 @@ class NullPointerType extends BuiltInType { /** * A C/C++ derived type. * - * These are pointer and reference types, array and vector types, and const and volatile types. - * In all cases, the type is formed from a single base type. + * These are pointer and reference types, array and GNU vector types, and `const` and `volatile` types. + * In all cases, the type is formed from a single base type. For example, + * ``` + * int *pi; + * int &ri = *pi; + * const float fa[40]; + * decltype(pi) dpi; + * ``` */ class DerivedType extends Type, @derivedtype { override string toString() { result = this.getName() } @@ -786,9 +908,16 @@ class DerivedType extends Type, @derivedtype { } /** - * An instance of the C++11 decltype operator. + * An instance of the C++11 `decltype` operator. For example, + * ``` + * int a; + * decltype(a) b; + * ``` */ class Decltype extends Type, @decltype { + + override string getCanonicalQLClass() { result = "Decltype" } + /** * The expression whose type is being obtained by this decltype. */ @@ -852,6 +981,10 @@ class Decltype extends Type, @decltype { /** * A C/C++ pointer type. See 4.9.1. + * ``` + * void *ptr; + * void **ptr2 = &ptr; + * ``` */ class PointerType extends DerivedType { PointerType() { derivedtypes(underlyingElement(this), _, 1, _) } @@ -874,7 +1007,7 @@ class PointerType extends DerivedType { /** * A C++ reference type. See 4.9.1. * - * For C++11 code bases, this includes both lvalue references (&) and rvalue references (&&). + * For C++11 code bases, this includes both _lvalue_ references (&) and _rvalue_ references (&&). * To distinguish between them, use the LValueReferenceType and RValueReferenceType classes. */ class ReferenceType extends DerivedType { @@ -900,7 +1033,11 @@ class ReferenceType extends DerivedType { } /** - * A C++11 lvalue reference type (e.g. int&). + * A C++11 lvalue reference type (e.g. `int&`). + * ``` + * int a; + * int& b = a; + * ``` */ class LValueReferenceType extends ReferenceType { LValueReferenceType() { derivedtypes(underlyingElement(this), _, 2, _) } @@ -909,7 +1046,14 @@ class LValueReferenceType extends ReferenceType { } /** - * A C++11 rvalue reference type (e.g. int&&). + * A C++11 rvalue reference type (e.g. `int&&`). It is used to + * implement "move" semantics for object construction and assignments. + * ``` + * class C { + * E e; + * C(C&& from): e(from.e) { } + * }; + * ``` */ class RValueReferenceType extends ReferenceType { RValueReferenceType() { derivedtypes(underlyingElement(this), _, 8, _) } @@ -921,6 +1065,10 @@ class RValueReferenceType extends ReferenceType { /** * A type with specifiers. + * ``` + * const int a; + * volatile char v; + * ``` */ class SpecifiedType extends DerivedType { SpecifiedType() { derivedtypes(underlyingElement(this), _, 3, _) } @@ -966,6 +1114,9 @@ class SpecifiedType extends DerivedType { /** * A C/C++ array type. See 4.9.1. + * ``` + * char table[32]; + * ``` */ class ArrayType extends DerivedType { ArrayType() { derivedtypes(underlyingElement(this), _, 4, _) } @@ -1012,10 +1163,16 @@ class ArrayType extends DerivedType { * A GNU/Clang vector type. * * In both Clang and GNU compilers, vector types can be introduced using the - * __attribute__((vector_size(byte_size))) syntax. The Clang compiler also - * allows vector types to be introduced using the ext_vector_type, - * neon_vector_type, and neon_polyvector_type attributes (all of which take + * `__attribute__((vector_size(byte_size)))` syntax. The Clang compiler also + * allows vector types to be introduced using the `ext_vector_type`, + * `neon_vector_type`, and `neon_polyvector_typ`e attributes (all of which take * an element type rather than a byte size). + * ``` + * typedef int v4si __attribute__ (( vector_size(4*sizeof(int)) )); + * v4si v = { 1, 2, 3, 4 }; + * typedef float float4 __attribute__((ext_vector_type(4))); + * float4 vf = (float4)(1.0f, 2.0f, 3.0f, 4.0f); + * ``` */ class GNUVectorType extends DerivedType { GNUVectorType() { derivedtypes(underlyingElement(this), _, 5, _) } @@ -1054,7 +1211,10 @@ class GNUVectorType extends DerivedType { } /** - * A C/C++ pointer to function. See 7.7. + * A C/C++ pointer to a function. See 7.7. + * ``` + * int(* pointer)(const void *element1, const void *element2); + * ``` */ class FunctionPointerType extends FunctionPointerIshType { FunctionPointerType() { derivedtypes(underlyingElement(this), _, 6, _) } @@ -1069,13 +1229,20 @@ class FunctionPointerType extends FunctionPointerIshType { } /** - * A C/C++ reference to function. + * A C++ reference to a function. + * ``` + * int(& reference)(const void *element1, const void *element2); + * ``` */ class FunctionReferenceType extends FunctionPointerIshType { FunctionReferenceType() { derivedtypes(underlyingElement(this), _, 7, _) } override string getCanonicalQLClass() { result = "FunctionReferenceType" } + override int getPointerIndirectionLevel() { + result = getBaseType().getPointerIndirectionLevel() + } + override int getPointerIndirectionLevel() { result = getBaseType().getPointerIndirectionLevel() } override string explain() { @@ -1088,6 +1255,10 @@ class FunctionReferenceType extends FunctionPointerIshType { * * Block types (along with blocks themselves) are a language extension * supported by Clang, and by Apple's branch of GCC. + * ``` + * int(^ block)(const char *element1, const char *element2) + * = ^int (const char *element1, const char *element2) { return element1 - element 2; } + * ``` */ class BlockType extends FunctionPointerIshType { BlockType() { derivedtypes(underlyingElement(this), _, 10, _) } @@ -1100,7 +1271,9 @@ class BlockType extends FunctionPointerIshType { } /** - * A C/C++ pointer to function, or a block. + * A C/C++ pointer to a function, a C++ function reference, or a clang/Apple block. + * + * See FunctionPointerType, FunctionReferenceType and BlockType for more information. */ class FunctionPointerIshType extends DerivedType { FunctionPointerIshType() { @@ -1145,7 +1318,14 @@ class FunctionPointerIshType extends DerivedType { } /** - * A C++ pointer to member. See 15.5. + * A C++ pointer to data member. See 15.5. + * ``` + * class C { int m; }; + * int C::* p = &C::m; // pointer to data member m of class C + * class C *; + * int val = c.*p; // access data member + * + * ``` */ class PointerToMemberType extends Type, @ptrtomember { /** a printable representation of this named element */ @@ -1182,7 +1362,9 @@ class PointerToMemberType extends Type, @ptrtomember { } /** - * A C/C++ routine type. This is what results from stripping away the pointer from a function pointer type. + * A C/C++ routine type. Conceptually, this is what results from stripping away the pointer from a function pointer type. + * It has no corresponding syntax in C/C++. + * */ class RoutineType extends Type, @routinetype { /** a printable representation of this named element */ @@ -1243,6 +1425,12 @@ class RoutineType extends Type, @routinetype { /** * A C++ typename template parameter. + * + * In the example below, `T` is a template parameter: + * ``` + * template + * class C { }; + * ``` */ class TemplateParameter extends UserType { TemplateParameter() { @@ -1254,15 +1442,29 @@ class TemplateParameter extends UserType { override predicate involvesTemplateParameter() { any() } } -/** A C++ template template parameter, e.g. template <template <typename,typename> class T>. */ -class TemplateTemplateParameter extends TemplateParameter { - TemplateTemplateParameter() { usertypes(underlyingElement(this), _, 8) } +/** A C++ template template parameter. + * + * In the example below, `T` is a template template parameter (although its name + * may be omitted): + * ``` + * template