From e2fdfbb71f7eedb0ea32c1c7b12c0df11b1677fd Mon Sep 17 00:00:00 2001 From: Gulshan Singh Date: Wed, 18 Jan 2023 00:40:25 -0800 Subject: [PATCH 001/141] Add RangeNode class --- .../rangeanalysis/extensions/RangeNode.qll | 111 ++++++++++++++++++ 1 file changed, 111 insertions(+) create mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll new file mode 100644 index 00000000000..d06389e0c74 --- /dev/null +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll @@ -0,0 +1,111 @@ +private import cpp +private import semmle.code.cpp.dataflow.DataFlow +private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis + +string getExprBoundAsString(Expr e) { + if exists(lowerBound(e)) and exists(upperBound(e)) + then result = "[" + lowerBound(e) + ", " + upperBound(e) + "]" + else result = "[unknown range]" +} + +/** + * Holds for any integer type after resolving typedefs and stripping `const` + * specifiers, such as for `const size_t` + */ +predicate isIntegralType(Type t) { + // We use `getUnspecifiedType` here because without it things like + // `const size_t` aren't considered to be integral + t.getUnspecifiedType() instanceof IntegralType +} + +/** + * Holds for any reference to an integer type after resolving typedefs and + * stripping `const` specifiers, such as for `const size_t&` + */ +predicate isIntegralReferenceType(Type t) { isIntegralType(t.(ReferenceType).stripType()) } + +/** + * Holds for any pointer to an integer type after resolving typedefs and + * stripping `const` specifiers, such as for `const size_t*`. This predicate + * holds for any pointer depth, such as for `const size_t**`. + */ +predicate isIntegralPointerType(Type t) { isIntegralType(t.(PointerType).stripType()) } + +predicate hasIntegralOrReferenceIntegralType(Locatable e) { + exists(Type t | + ( + t = e.(Expr).getUnspecifiedType() + or + // This will cover variables, parameters, type declarations, etc. + t = e.(DeclarationEntry).getUnspecifiedType() + ) and + isIntegralType(t) + or + isIntegralReferenceType(t) + ) +} + +Expr getLOp(Operation o) { + result = o.(BinaryOperation).getLeftOperand() or + result = o.(Assignment).getLValue() +} + +Expr getROp(Operation o) { + result = o.(BinaryOperation).getRightOperand() or + result = o.(Assignment).getRValue() +} + +/** + * Display the ranges of expressions in the path view + */ +private class ExprRangeNode extends DataFlow::ExprNode { + pragma[inline] + private string getIntegralBounds(Expr arg) { + if hasIntegralOrReferenceIntegralType(arg) + then result = getExprBoundAsString(arg) + else result = "" + } + + private string getOperationBounds(Operation e) { + result = + getExprBoundAsString(e) + " = " + getExprBoundAsString(getLOp(e)) + + e.(Operation).getOperator() + getExprBoundAsString(getROp(e)) + } + + private string getCallBounds(Call e) { + result = + getExprBoundAsString(e) + "(" + + concat(Expr arg, int i | + arg = e.(Call).getArgument(i) + | + getIntegralBounds(arg) order by i, "," + ) + ")" + } + + override string toString() { + exists(Expr e | e = getExpr() | + if hasIntegralOrReferenceIntegralType(e) + then + exists(getOperationBounds(e)) and result = super.toString() + ": " + getOperationBounds(e) + or + exists(getCallBounds(e)) and result = super.toString() + ": " + getCallBounds(e) + or + not exists(getOperationBounds(e)) and + not exists(getCallBounds(e)) and + result = super.toString() + ": " + getExprBoundAsString(e) + else result = super.toString() + ) + } +} + +/** + * Display the ranges of expressions in the path view + */ +private class ReferenceArgumentRangeNode extends DataFlow::DefinitionByReferenceNode { + override string toString() { + if hasIntegralOrReferenceIntegralType(asDefiningArgument()) + then result = super.toString() + ": " + getExprBoundAsString(getArgument()) + else result = super.toString() + } +} +// TODO: Show ranges for DataFlow::ExplicitParameterNode From bae1dfebb20473b097caabae18c65f1d2c7a43a5 Mon Sep 17 00:00:00 2001 From: Gulshan Singh Date: Mon, 20 Mar 2023 09:36:13 -0700 Subject: [PATCH 002/141] Address some review comments on RangeNode class --- .../rangeanalysis/extensions/RangeNode.qll | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll index d06389e0c74..d24d754a4ac 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/extensions/RangeNode.qll @@ -1,3 +1,13 @@ +/** + * This module implements subclasses for various DataFlow nodes that extends + * their `toString()` predicates with range information, if applicable. By + * including this module in a `path-problem` query, this range information + * will be displayed at each step in the query results. + * + * This is currently implemented for `DataFlow::ExprNode` and `DataFlow::DefinitionByReferenceNode`, + * but it is not yet implemented for `DataFlow::ParameterNode`. + */ + private import cpp private import semmle.code.cpp.dataflow.DataFlow private import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis @@ -39,9 +49,7 @@ predicate hasIntegralOrReferenceIntegralType(Locatable e) { // This will cover variables, parameters, type declarations, etc. t = e.(DeclarationEntry).getUnspecifiedType() ) and - isIntegralType(t) - or - isIntegralReferenceType(t) + (isIntegralType(t) or isIntegralReferenceType(t)) ) } @@ -68,27 +76,24 @@ private class ExprRangeNode extends DataFlow::ExprNode { private string getOperationBounds(Operation e) { result = - getExprBoundAsString(e) + " = " + getExprBoundAsString(getLOp(e)) + - e.(Operation).getOperator() + getExprBoundAsString(getROp(e)) + getExprBoundAsString(e) + " = " + getExprBoundAsString(getLOp(e)) + e.getOperator() + + getExprBoundAsString(getROp(e)) } private string getCallBounds(Call e) { result = getExprBoundAsString(e) + "(" + - concat(Expr arg, int i | - arg = e.(Call).getArgument(i) - | - getIntegralBounds(arg) order by i, "," - ) + ")" + concat(Expr arg, int i | arg = e.getArgument(i) | getIntegralBounds(arg) order by i, ",") + + ")" } override string toString() { exists(Expr e | e = getExpr() | if hasIntegralOrReferenceIntegralType(e) then - exists(getOperationBounds(e)) and result = super.toString() + ": " + getOperationBounds(e) + result = super.toString() + ": " + getOperationBounds(e) or - exists(getCallBounds(e)) and result = super.toString() + ": " + getCallBounds(e) + result = super.toString() + ": " + getCallBounds(e) or not exists(getOperationBounds(e)) and not exists(getCallBounds(e)) and @@ -108,4 +113,3 @@ private class ReferenceArgumentRangeNode extends DataFlow::DefinitionByReference else result = super.toString() } } -// TODO: Show ranges for DataFlow::ExplicitParameterNode From ccf152df0054087bb77e4152f87e9e4eb06f18b8 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Sun, 26 Mar 2023 21:29:55 -0400 Subject: [PATCH 003/141] Added support for progressive hashing in crypto-js module --- .../javascript/frameworks/CryptoLibraries.qll | 56 ++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 21d23f517f3..9426163d303 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -274,6 +274,34 @@ private module NodeJSCrypto { * A model of the crypto-js library. */ private module CryptoJS { + private class InstantiatedAlgorithm extends DataFlow::CallNode { + CryptographicAlgorithm algorithm; // non-functional + + InstantiatedAlgorithm() { + /* + * ``` + * const crypto = require("crypto-js"); + * const cipher = crypto.algo.SHA256.create(); + * ``` + * matched as: + * ``` + * const crypto = require("crypto-js"); + * const cipher = crypto.algo..create(); + * ``` + */ + + exists(DataFlow::SourceNode mod, DataFlow::PropRead propRead | + mod = DataFlow::moduleImport("crypto-js") and + propRead = mod.getAPropertyRead("algo").getAPropertyRead() and + this = propRead.getAMemberCall("create") and + not isStrongPasswordHashingAlgorithm(propRead.getPropertyName()) + ) + } + + CryptographicAlgorithm getAlgorithm() { result = algorithm } + } + + /** * Matches `CryptoJS.` and `require("crypto-js/")` */ @@ -325,13 +353,39 @@ private module CryptoJS { input = result.getParameter(0) } + private DataFlow::CallNode getUpdatedApplication (DataFlow::Node input, InstantiatedAlgorithm instantiation) { + /* + * ``` + * var CryptoJS = require("crypto-js"); + * var hash = CryptoJS.algo.SHA256.create(); + * hash.update('message'); + * hash.update('password'); + * var hashInHex = hash.finalize(); + * ``` + * Matched as: + * ``` + * var CryptoJS = require("crypto-js"); + * var hash = CryptoJS.algo..create(); + * hash.update(); + * hash.update(); + * var hashInHex = hash.finalize(); + * ``` + * Also matches where `CryptoJS.algo.` has been + * replaced by `require("crypto-js/")` + */ + + result = instantiation.getAMemberCall("update") and + input = result.getArgument(0) + } + private class Apply extends CryptographicOperation::Range instanceof API::CallNode { API::Node input; CryptographicAlgorithm algorithm; // non-functional Apply() { this = getEncryptionApplication(input, algorithm) or - this = getDirectApplication(input, algorithm) + this = getDirectApplication(input, algorithm) or + this = getUpdatedApplication(input, instantiation) } override DataFlow::Node getAnInput() { result = input.asSink() } From ad527b8f690da610f34f2a6613c3066dffb5c231 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Sun, 26 Mar 2023 21:53:22 -0400 Subject: [PATCH 004/141] Added new example files and renamed existing ones --- .../CWE-916/examples/InsufficientPasswordHash_CryptoJS.js | 8 ++++++++ .../examples/InsufficientPasswordHash_CryptoJS_fixed | 8 ++++++++ ...PasswordHash.js => InsufficientPasswordHash_NodeJS.js} | 0 ..._fixed.js => InsufficientPasswordHash_NodeJS_fixed.js} | 0 4 files changed, 16 insertions(+) create mode 100644 javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js create mode 100644 javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS_fixed rename javascript/ql/src/Security/CWE-916/examples/{InsufficientPasswordHash.js => InsufficientPasswordHash_NodeJS.js} (100%) rename javascript/ql/src/Security/CWE-916/examples/{InsufficientPasswordHash_fixed.js => InsufficientPasswordHash_NodeJS_fixed.js} (100%) diff --git a/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js new file mode 100644 index 00000000000..68064a6cd9f --- /dev/null +++ b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js @@ -0,0 +1,8 @@ +const crypto = require('crypto-js') +function hashPassword(email, password) { + var algo = crypto.algo.SHA512.create() + algo.update(password, 'utf-8') // BAD + algo.update(email.toLowerCase(), 'utf-8') + var hash = algo.finalize() + return hash.toString(crypto.enc.Base64) +} \ No newline at end of file diff --git a/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS_fixed b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS_fixed new file mode 100644 index 00000000000..909f09f8f4e --- /dev/null +++ b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS_fixed @@ -0,0 +1,8 @@ +const crypto = require('crypto-js') +function hashPassword(email, password) { + var algo = crypto.algo.PBKDF2.create() + algo.update(password, 'utf-8') // GOOD + algo.update(email.toLowerCase(), 'utf-8') + var hash = algo.finalize() + return hash.toString(crypto.enc.Base64) +} \ No newline at end of file diff --git a/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash.js b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_NodeJS.js similarity index 100% rename from javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash.js rename to javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_NodeJS.js diff --git a/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_fixed.js b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_NodeJS_fixed.js similarity index 100% rename from javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_fixed.js rename to javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_NodeJS_fixed.js From cef6b95b15d7f74e8569ac1ff7b286cd4a17042b Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Sun, 26 Mar 2023 22:32:34 -0400 Subject: [PATCH 005/141] Fixed Conflicts due to recent changes to file --- .../javascript/frameworks/CryptoLibraries.qll | 6 ++++-- .../examples/InsufficientPasswordHash_CryptoJS.js | 14 +++++++------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 9426163d303..2e193029386 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -4,6 +4,7 @@ import javascript import semmle.javascript.Concepts::Cryptography +private import semmle.javascript.security.internal.CryptoAlgorithmNames /** * A key used in a cryptographic algorithm. @@ -353,7 +354,7 @@ private module CryptoJS { input = result.getParameter(0) } - private DataFlow::CallNode getUpdatedApplication (DataFlow::Node input, InstantiatedAlgorithm instantiation) { + private API::CallNode getUpdatedApplication (API::Node input, InstantiatedAlgorithm instantiation) { /* * ``` * var CryptoJS = require("crypto-js"); @@ -375,12 +376,13 @@ private module CryptoJS { */ result = instantiation.getAMemberCall("update") and - input = result.getArgument(0) + input = result.getParameter(0) } private class Apply extends CryptographicOperation::Range instanceof API::CallNode { API::Node input; CryptographicAlgorithm algorithm; // non-functional + InstantiatedAlgorithm instantiation; Apply() { this = getEncryptionApplication(input, algorithm) or diff --git a/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js index 68064a6cd9f..c0a621f85b1 100644 --- a/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js +++ b/javascript/ql/src/Security/CWE-916/examples/InsufficientPasswordHash_CryptoJS.js @@ -1,8 +1,8 @@ -const crypto = require('crypto-js') -function hashPassword(email, password) { - var algo = crypto.algo.SHA512.create() - algo.update(password, 'utf-8') // BAD - algo.update(email.toLowerCase(), 'utf-8') - var hash = algo.finalize() - return hash.toString(crypto.enc.Base64) +const crypto = require('crypto-js') +function hashPassword(email, password) { + var algo = crypto.algo.SHA512.create() + algo.update(password, 'utf-8') // BAD + algo.update(email.toLowerCase(), 'utf-8') + var hash = algo.finalize() + return hash.toString(crypto.enc.Base64) } \ No newline at end of file From 4980948613c644bf943a43d25d157c801a7a8f3e Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Sun, 26 Mar 2023 23:07:32 -0400 Subject: [PATCH 006/141] changenote --- .../change-notes/2023-03-26-CryptoJS-progressive-hashing.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 javascript/ql/lib/change-notes/2023-03-26-CryptoJS-progressive-hashing.md diff --git a/javascript/ql/lib/change-notes/2023-03-26-CryptoJS-progressive-hashing.md b/javascript/ql/lib/change-notes/2023-03-26-CryptoJS-progressive-hashing.md new file mode 100644 index 00000000000..7b76ab10298 --- /dev/null +++ b/javascript/ql/lib/change-notes/2023-03-26-CryptoJS-progressive-hashing.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The crypto-js module in `CryptoLibraries.qll` now supports progressive hashing with algo.update(). From 0aceedac78ad58836884196c94c07062dc7c4a35 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 27 Mar 2023 13:38:23 +0200 Subject: [PATCH 007/141] QL: Make Class.getType() only return ClassType Previously this would return both the ClassCharType and ClassType --- ql/ql/src/codeql_ql/ast/Ast.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ql/ql/src/codeql_ql/ast/Ast.qll b/ql/ql/src/codeql_ql/ast/Ast.qll index 4264cdf24db..818828d44fe 100644 --- a/ql/ql/src/codeql_ql/ast/Ast.qll +++ b/ql/ql/src/codeql_ql/ast/Ast.qll @@ -972,7 +972,7 @@ class Class extends TClass, TypeDeclaration, ModuleDeclaration { } /** Gets the class type defined by this class declaration. */ - Type getType() { result.getDeclaration() = this } + ClassType getType() { result.getDeclaration() = this } override AstNode getAChild(string pred) { result = super.getAChild(pred) From 7b4951005b1f9a647f7add1d7b388cdbf1b6eff6 Mon Sep 17 00:00:00 2001 From: Asger F Date: Mon, 27 Mar 2023 13:47:29 +0200 Subject: [PATCH 008/141] QL: Update test expectations --- ql/ql/test/type/type.expected | 8 -------- 1 file changed, 8 deletions(-) diff --git a/ql/ql/test/type/type.expected b/ql/ql/test/type/type.expected index fd3a34c27f6..7089676858d 100644 --- a/ql/ql/test/type/type.expected +++ b/ql/ql/test/type/type.expected @@ -1,6 +1,4 @@ | Test.qll:4:15:4:18 | this | Test.qll:3:7:3:13 | Strings | -| Test.qll:4:15:4:18 | this | Test.qll:3:7:3:13 | Strings.Strings | -| Test.qll:4:15:4:18 | this | Test.qll:3:7:3:13 | Strings.extends | | Test.qll:4:22:4:76 | Set | file://:0:0:0:0 | string | | Test.qll:4:23:4:24 | String | file://:0:0:0:0 | string | | Test.qll:4:27:4:29 | String | file://:0:0:0:0 | string | @@ -13,8 +11,6 @@ | Test.qll:4:66:4:69 | String | file://:0:0:0:0 | string | | Test.qll:4:72:4:75 | String | file://:0:0:0:0 | string | | Test.qll:8:14:8:17 | this | Test.qll:7:7:7:12 | Floats | -| Test.qll:8:14:8:17 | this | Test.qll:7:7:7:12 | Floats.Floats | -| Test.qll:8:14:8:17 | this | Test.qll:7:7:7:12 | Floats.extends | | Test.qll:8:21:8:70 | Set | file://:0:0:0:0 | float | | Test.qll:8:22:8:24 | Float | file://:0:0:0:0 | float | | Test.qll:8:27:8:29 | Float | file://:0:0:0:0 | float | @@ -35,14 +31,10 @@ | Test.qll:13:45:13:49 | AddExpr | file://:0:0:0:0 | float | | Test.qll:13:49:13:49 | b | Test.qll:7:7:7:12 | Floats | | Test.qll:16:12:16:15 | this | Test.qll:15:7:15:10 | Base | -| Test.qll:16:12:16:15 | this | Test.qll:15:7:15:10 | Base.Base | -| Test.qll:16:12:16:15 | this | Test.qll:15:7:15:10 | Base.extends | | Test.qll:16:19:16:23 | String | file://:0:0:0:0 | string | | Test.qll:18:15:18:20 | result | file://:0:0:0:0 | int | | Test.qll:18:24:18:24 | Integer | file://:0:0:0:0 | int | | Test.qll:22:11:22:14 | this | Test.qll:21:7:21:9 | Sub | -| Test.qll:22:11:22:14 | this | Test.qll:21:7:21:9 | Sub.Sub | -| Test.qll:22:11:22:14 | this | Test.qll:21:7:21:9 | Sub.extends | | Test.qll:22:18:22:22 | String | file://:0:0:0:0 | string | | Test.qll:24:15:24:20 | result | file://:0:0:0:0 | int | | Test.qll:24:24:24:33 | Super | Test.qll:15:7:15:10 | Base | From 3ef5f3070fdeac563c4b3a04e4b4b048b886b118 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Mon, 27 Mar 2023 12:02:35 -0400 Subject: [PATCH 009/141] small change --- .../javascript/frameworks/CryptoLibraries.qll | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 2e193029386..61178566401 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -276,7 +276,7 @@ private module NodeJSCrypto { */ private module CryptoJS { private class InstantiatedAlgorithm extends DataFlow::CallNode { - CryptographicAlgorithm algorithm; // non-functional + private string algorithmName; InstantiatedAlgorithm() { /* @@ -295,11 +295,25 @@ private module CryptoJS { mod = DataFlow::moduleImport("crypto-js") and propRead = mod.getAPropertyRead("algo").getAPropertyRead() and this = propRead.getAMemberCall("create") and - not isStrongPasswordHashingAlgorithm(propRead.getPropertyName()) + algorithmName = propRead.getPropertyName() and + not isStrongPasswordHashingAlgorithm(algorithmName) ) } - CryptographicAlgorithm getAlgorithm() { result = algorithm } + CryptographicAlgorithm getAlgorithm() { result.matchesName(algorithmName) } + + private BlockMode getExplicitBlockMode() { result.matchesString(algorithmName) } + + BlockMode getBlockMode() { + isBlockEncryptionAlgorithm(this.getAlgorithm()) and + ( + if exists(this.getExplicitBlockMode()) + then result = this.getExplicitBlockMode() + else + // CBC is the default if not explicitly specified + result = "CBC" + ) + } } From 6bf94e800be5b0b2165c3ecab93c681714b915ab Mon Sep 17 00:00:00 2001 From: Chris Bellanti Date: Mon, 27 Mar 2023 12:16:20 -0400 Subject: [PATCH 010/141] Added check to disabling certificate validation query --- .../ql/src/Security/CWE-295/DisablingCertificateValidation.ql | 2 ++ .../2023-03-27-disabling-certificate-validation.md | 4 ++++ 2 files changed, 6 insertions(+) create mode 100644 javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md diff --git a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql index 7fd76a635ec..d9f7267d425 100644 --- a/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql +++ b/javascript/ql/src/Security/CWE-295/DisablingCertificateValidation.ql @@ -19,6 +19,8 @@ DataFlow::InvokeNode tlsInvocation() { or result = DataFlow::moduleMember("https", "Agent").getAnInstantiation() or + result = DataFlow::moduleMember("https", "createServer").getACall() + or exists(DataFlow::NewNode new | new = DataFlow::moduleMember("tls", "TLSSocket").getAnInstantiation() | diff --git a/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md b/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md new file mode 100644 index 00000000000..85966642c48 --- /dev/null +++ b/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md @@ -0,0 +1,4 @@ +--- +category: majorAnalysis +--- +* The `DisablingCertificateValidation.ql` query has been updated to check `createServer` from `https` for disabled certificate validation. From 57ab5a06ae479e3e4bcb5df58b2a3bb5dac7f2e4 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Mon, 27 Mar 2023 15:20:08 -0400 Subject: [PATCH 011/141] autoformatted --- .../ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 61178566401..9809bb14bc6 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -316,7 +316,6 @@ private module CryptoJS { } } - /** * Matches `CryptoJS.` and `require("crypto-js/")` */ @@ -368,7 +367,7 @@ private module CryptoJS { input = result.getParameter(0) } - private API::CallNode getUpdatedApplication (API::Node input, InstantiatedAlgorithm instantiation) { + private API::CallNode getUpdatedApplication(API::Node input, InstantiatedAlgorithm instantiation) { /* * ``` * var CryptoJS = require("crypto-js"); @@ -391,7 +390,7 @@ private module CryptoJS { result = instantiation.getAMemberCall("update") and input = result.getParameter(0) - } + } private class Apply extends CryptographicOperation::Range instanceof API::CallNode { API::Node input; From e5e20ab42c7baeb196390bb730cbb9cb7102815c Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Tue, 28 Mar 2023 10:57:13 +0200 Subject: [PATCH 012/141] add backticks around the concrete parse error --- .../extractor/src/com/semmle/js/extractor/AutoBuild.java | 4 ++-- .../diagnostics/syntax-error/diagnostics.expected | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index 3b86ed15f8e..a2da051451a 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -1236,8 +1236,8 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set if (!extractor.getConfig().isExterns()) seenFiles = true; List errors = loc == null ? Collections.emptyList() : loc.getParseErrors(); for (ParseError err : errors) { - String msg = "A parse error occurred: " + StringUtil.escapeMarkdown(err.getMessage()) - + ". Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis."; + String msg = "A parse error occurred: `" + StringUtil.escapeMarkdown(err.getMessage()).trim() + + "`. Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis."; // file, relative to the source root String relativeFilePath = null; if (file.startsWith(LGTM_SRC)) { diff --git a/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/diagnostics.expected b/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/diagnostics.expected index 0c4405ea92b..c1ee7485218 100644 --- a/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/diagnostics.expected +++ b/javascript/ql/integration-tests/all-platforms/diagnostics/syntax-error/diagnostics.expected @@ -6,7 +6,7 @@ "startColumn": 4, "startLine": 1 }, - "markdownMessage": "A parse error occurred: Unexpected token. Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis.", + "markdownMessage": "A parse error occurred: `Unexpected token`. Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis.", "severity": "warning", "source": { "extractorName": "javascript", From 70dfa6e15cc9092c2350b097b45ba0a4684b618a Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Tue, 28 Mar 2023 12:34:44 +0200 Subject: [PATCH 013/141] use StringUtil.quoteWithBackticks instead of manually quoting with a single backtick --- .../extractor/src/com/semmle/js/extractor/AutoBuild.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java index a2da051451a..2874d510512 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -1236,8 +1236,8 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set if (!extractor.getConfig().isExterns()) seenFiles = true; List errors = loc == null ? Collections.emptyList() : loc.getParseErrors(); for (ParseError err : errors) { - String msg = "A parse error occurred: `" + StringUtil.escapeMarkdown(err.getMessage()).trim() - + "`. Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis."; + String msg = "A parse error occurred: " + StringUtil.quoteWithBackticks(StringUtil.escapeMarkdown(err.getMessage()).trim()) + + ". Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis."; // file, relative to the source root String relativeFilePath = null; if (file.startsWith(LGTM_SRC)) { From 50c3c159a979b542f11533a5a68fab40377220c3 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 28 Mar 2023 14:34:46 +0200 Subject: [PATCH 014/141] C#: Make checked and unchecked as a local flow step. --- .../code/csharp/dataflow/internal/DataFlowPrivate.qll | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll index 9bcddf7c6c2..a380330ae8b 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowPrivate.qll @@ -239,6 +239,14 @@ module LocalFlow { scope = e2 and isSuccessor = true or + e1 = e2.(CheckedExpr).getExpr() and + scope = e2 and + isSuccessor = true + or + e1 = e2.(UncheckedExpr).getExpr() and + scope = e2 and + isSuccessor = true + or exists(WithExpr we | scope = we and isSuccessor = true From 9966e09fd78618911e74c9a6c82b6ac8af9a8863 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Tue, 28 Mar 2023 15:05:48 +0200 Subject: [PATCH 015/141] C#: Add operator dataflow test case with checked and unchecked examples. --- .../dataflow/operators/Operator.cs | 38 +++++++++ .../dataflow/operators/operatorFlow.expected | 80 +++++++++++++++++++ .../dataflow/operators/operatorFlow.ql | 11 +++ 3 files changed, 129 insertions(+) create mode 100644 csharp/ql/test/library-tests/dataflow/operators/Operator.cs create mode 100644 csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected create mode 100644 csharp/ql/test/library-tests/dataflow/operators/operatorFlow.ql diff --git a/csharp/ql/test/library-tests/dataflow/operators/Operator.cs b/csharp/ql/test/library-tests/dataflow/operators/Operator.cs new file mode 100644 index 00000000000..164b1e84525 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/operators/Operator.cs @@ -0,0 +1,38 @@ +public class Operators +{ + + static void Sink(object o) { } + static T Source(object source) => throw null; + + public class C + { + public static C operator +(C x, C y) => x; + + public static C operator checked -(C x, C y) => y; + public static C operator -(C x, C y) => x; + } + + public void M1() + { + var x = Source(1); + var y = Source(2); + var z = x + y; + Sink(z); // $ hasValueFlow=1 + } + + public void M2() + { + var x = Source(3); + var y = Source(4); + var z = unchecked(x - y); + Sink(z); // $ hasValueFlow=3 + } + + public void M3() + { + var x = Source(5); + var y = Source(6); + var z = checked(x - y); + Sink(z); // $ hasValueFlow=6 + } +} \ No newline at end of file diff --git a/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected new file mode 100644 index 00000000000..33f8c4a03e6 --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected @@ -0,0 +1,80 @@ +failures +edges +| Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | +| Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | +| Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | +| Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | +| Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | +| Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | +| Operator.cs:17:17:17:28 | call to method Source : C | Operator.cs:19:17:19:17 | access to local variable x : C | +| Operator.cs:17:17:17:28 | call to method Source : C | Operator.cs:19:17:19:17 | access to local variable x : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:19:17:19:21 | call to operator + : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:19:17:19:21 | call to operator + : C | +| Operator.cs:19:17:19:21 | call to operator + : C | Operator.cs:20:14:20:14 | access to local variable z | +| Operator.cs:19:17:19:21 | call to operator + : C | Operator.cs:20:14:20:14 | access to local variable z | +| Operator.cs:25:17:25:28 | call to method Source : C | Operator.cs:27:27:27:27 | access to local variable x : C | +| Operator.cs:25:17:25:28 | call to method Source : C | Operator.cs:27:27:27:27 | access to local variable x : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:27:27:27:31 | call to operator - : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:27:27:27:31 | call to operator - : C | +| Operator.cs:27:27:27:31 | call to operator - : C | Operator.cs:28:14:28:14 | access to local variable z | +| Operator.cs:27:27:27:31 | call to operator - : C | Operator.cs:28:14:28:14 | access to local variable z | +| Operator.cs:34:17:34:28 | call to method Source : C | Operator.cs:35:29:35:29 | access to local variable y : C | +| Operator.cs:34:17:34:28 | call to method Source : C | Operator.cs:35:29:35:29 | access to local variable y : C | +| Operator.cs:35:25:35:29 | call to operator checked - : C | Operator.cs:36:14:36:14 | access to local variable z | +| Operator.cs:35:25:35:29 | call to operator checked - : C | Operator.cs:36:14:36:14 | access to local variable z | +| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | +nodes +| Operator.cs:9:38:9:38 | x : C | semmle.label | x : C | +| Operator.cs:9:38:9:38 | x : C | semmle.label | x : C | +| Operator.cs:9:49:9:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:9:49:9:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:11:51:11:51 | y : C | semmle.label | y : C | +| Operator.cs:11:51:11:51 | y : C | semmle.label | y : C | +| Operator.cs:11:57:11:57 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:11:57:11:57 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:12:38:12:38 | x : C | semmle.label | x : C | +| Operator.cs:12:38:12:38 | x : C | semmle.label | x : C | +| Operator.cs:12:49:12:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:12:49:12:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:17:17:17:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:17:17:17:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:19:17:19:21 | call to operator + : C | semmle.label | call to operator + : C | +| Operator.cs:19:17:19:21 | call to operator + : C | semmle.label | call to operator + : C | +| Operator.cs:20:14:20:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:20:14:20:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:25:17:25:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:25:17:25:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:27:27:27:31 | call to operator - : C | semmle.label | call to operator - : C | +| Operator.cs:27:27:27:31 | call to operator - : C | semmle.label | call to operator - : C | +| Operator.cs:28:14:28:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:28:14:28:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:34:17:34:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:34:17:34:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:35:25:35:29 | call to operator checked - : C | semmle.label | call to operator checked - : C | +| Operator.cs:35:25:35:29 | call to operator checked - : C | semmle.label | call to operator checked - : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:36:14:36:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:36:14:36:14 | access to local variable z | semmle.label | access to local variable z | +subpaths +| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | Operator.cs:19:17:19:21 | call to operator + : C | +| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | Operator.cs:19:17:19:21 | call to operator + : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | Operator.cs:27:27:27:31 | call to operator - : C | +| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | Operator.cs:27:27:27:31 | call to operator - : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | +| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | +#select +| Operator.cs:20:14:20:14 | access to local variable z | Operator.cs:17:17:17:28 | call to method Source : C | Operator.cs:20:14:20:14 | access to local variable z | $@ | Operator.cs:17:17:17:28 | call to method Source : C | call to method Source : C | +| Operator.cs:28:14:28:14 | access to local variable z | Operator.cs:25:17:25:28 | call to method Source : C | Operator.cs:28:14:28:14 | access to local variable z | $@ | Operator.cs:25:17:25:28 | call to method Source : C | call to method Source : C | +| Operator.cs:36:14:36:14 | access to local variable z | Operator.cs:34:17:34:28 | call to method Source : C | Operator.cs:36:14:36:14 | access to local variable z | $@ | Operator.cs:34:17:34:28 | call to method Source : C | call to method Source : C | diff --git a/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.ql b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.ql new file mode 100644 index 00000000000..55578cf970c --- /dev/null +++ b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.ql @@ -0,0 +1,11 @@ +/** + * @kind path-problem + */ + +import csharp +import DataFlow::PathGraph +import TestUtilities.InlineFlowTest + +from DataFlow::PathNode source, DataFlow::PathNode sink, DefaultValueFlowConf conf +where conf.hasFlowPath(source, sink) +select sink, source, sink, "$@", source, source.toString() From 4b3a4195094b950f587f53993fc95e3417642649 Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Tue, 28 Mar 2023 15:23:15 +0200 Subject: [PATCH 016/141] just use quoteWithBackticks --- 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 2874d510512..346d31231df 100644 --- a/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java +++ b/javascript/extractor/src/com/semmle/js/extractor/AutoBuild.java @@ -1236,7 +1236,7 @@ protected DependencyInstallationResult preparePackagesAndDependencies(Set if (!extractor.getConfig().isExterns()) seenFiles = true; List errors = loc == null ? Collections.emptyList() : loc.getParseErrors(); for (ParseError err : errors) { - String msg = "A parse error occurred: " + StringUtil.quoteWithBackticks(StringUtil.escapeMarkdown(err.getMessage()).trim()) + String msg = "A parse error occurred: " + StringUtil.quoteWithBackticks(err.getMessage().trim()) + ". Check the syntax of the file. If the file is invalid, correct the error or [exclude](https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/customizing-code-scanning) the file from analysis."; // file, relative to the source root String relativeFilePath = null; From 13c0effbd276cd6fd7b93d6335a0f126aff10eca Mon Sep 17 00:00:00 2001 From: Erik Krogh Kristensen Date: Tue, 28 Mar 2023 15:27:16 +0200 Subject: [PATCH 017/141] change to minor change --- .../change-notes/2023-03-27-disabling-certificate-validation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md b/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md index 85966642c48..7e7f93e8b7d 100644 --- a/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md +++ b/javascript/ql/src/change-notes/2023-03-27-disabling-certificate-validation.md @@ -1,4 +1,4 @@ --- -category: majorAnalysis +category: minorAnalysis --- * The `DisablingCertificateValidation.ql` query has been updated to check `createServer` from `https` for disabled certificate validation. From 123eb1e57b9d73426a048f6ae1fc30c8f4036cd2 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Tue, 28 Mar 2023 11:14:28 -0400 Subject: [PATCH 018/141] Update javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll Co-authored-by: Asger F --- .../ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 9809bb14bc6..af3b31986ce 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -400,7 +400,10 @@ private module CryptoJS { Apply() { this = getEncryptionApplication(input, algorithm) or this = getDirectApplication(input, algorithm) or - this = getUpdatedApplication(input, instantiation) + exists(InstantiatedAlgorithm instantiation | + this = getUpdatedApplication(input, instantiation) and + algorithm = instantiation.getAlgorithm() + ) } override DataFlow::Node getAnInput() { result = input.asSink() } From fe3b0a56cae71d03956284e3cfd8f4c501c43a4e Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Tue, 28 Mar 2023 11:27:23 -0400 Subject: [PATCH 019/141] Removed unnecessary field --- .../ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll | 1 - 1 file changed, 1 deletion(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index af3b31986ce..af179f765da 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -395,7 +395,6 @@ private module CryptoJS { private class Apply extends CryptographicOperation::Range instanceof API::CallNode { API::Node input; CryptographicAlgorithm algorithm; // non-functional - InstantiatedAlgorithm instantiation; Apply() { this = getEncryptionApplication(input, algorithm) or From 0eb61d39d303d09e9f2100d79695112ff6b4ece0 Mon Sep 17 00:00:00 2001 From: smiddy007 <70818821+smiddy007@users.noreply.github.com> Date: Tue, 28 Mar 2023 11:28:32 -0400 Subject: [PATCH 020/141] formatting --- .../ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index af179f765da..8e788151f97 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -397,8 +397,10 @@ private module CryptoJS { CryptographicAlgorithm algorithm; // non-functional Apply() { - this = getEncryptionApplication(input, algorithm) or - this = getDirectApplication(input, algorithm) or + this = getEncryptionApplication(input, algorithm) + or + this = getDirectApplication(input, algorithm) + or exists(InstantiatedAlgorithm instantiation | this = getUpdatedApplication(input, instantiation) and algorithm = instantiation.getAlgorithm() From f8e76b534781bd415f7cb198eb579c1c8d029082 Mon Sep 17 00:00:00 2001 From: Asger F Date: Wed, 29 Mar 2023 10:31:42 +0200 Subject: [PATCH 021/141] Ruby: do not depend on trackDefNode in isDef --- ruby/ql/lib/codeql/ruby/ApiGraphs.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll index 7f69f71d17f..35bdf1c25d3 100644 --- a/ruby/ql/lib/codeql/ruby/ApiGraphs.qll +++ b/ruby/ql/lib/codeql/ruby/ApiGraphs.qll @@ -584,7 +584,7 @@ module API { // If a call node is relevant as a use-node, treat its arguments as def-nodes argumentStep(_, useCandFwd(), rhs) or - defStep(_, trackDefNode(_), rhs) + defStep(_, defCand(), rhs) or rhs = any(EntryPoint entry).getASink() } From f3f17791c37c526c2d9f509e62327339a3a62626 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 10:17:21 +0200 Subject: [PATCH 022/141] Swift: extract all source files in WMO mode WMO stands for whole module optimization. It's a compilation mode where all sources of a module are compiled together, e.g. ``` swift-frontend -emit-module A.swift B.swift -o Module.swiftmodule ``` This is opposed to incremental mode, where one would do something like ``` swift-frontend -emit-module -primary-file A.swift B.swift -module-name Module -o Module~A.swiftmodule swift-frontend -emit-module A.swift -primary-file B.swift -module-name Module -o Module~B.swiftmodule swift-frontend -merge-modules Module~A.swiftmodule Module~B.swiftmodule -o Module.swiftmodule ``` In WMO mode we were skipping extraction of all files after the first one, because we were filtering in only files with an associated output, and internally swift only assigns the output to the first input file in WMO mode (which is just an implementation detail). This patch refines that filter, by getting all input source files in case there are no primary inputs. --- swift/extractor/SwiftExtractor.cpp | 13 +++++++++---- .../posix-only/frontend-invocations/Files.expected | 1 + 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/swift/extractor/SwiftExtractor.cpp b/swift/extractor/SwiftExtractor.cpp index 9638ac2949b..8982c36c1c9 100644 --- a/swift/extractor/SwiftExtractor.cpp +++ b/swift/extractor/SwiftExtractor.cpp @@ -161,11 +161,12 @@ static std::unordered_set extractDeclarations( static std::unordered_set collectInputFilenames(swift::CompilerInstance& compiler) { // The frontend can be called in many different ways. // At each invocation we only extract system and builtin modules and any input source files that - // have an output associated with them. + // are primary inputs, or all of them if there are no primary inputs (whole module optimization) std::unordered_set sourceFiles; - auto inputFiles = compiler.getInvocation().getFrontendOptions().InputsAndOutputs.getAllInputs(); - for (auto& input : inputFiles) { - if (input.getType() == swift::file_types::TY_Swift && !input.outputFilename().empty()) { + const auto& inOuts = compiler.getInvocation().getFrontendOptions().InputsAndOutputs; + for (auto& input : inOuts.getAllInputs()) { + if (input.getType() == swift::file_types::TY_Swift && + (!inOuts.hasPrimaryInputs() || input.isPrimary())) { sourceFiles.insert(input.getFileName()); } } @@ -191,11 +192,15 @@ void codeql::extractSwiftFiles(SwiftExtractorState& state, swift::CompilerInstan todo.pop_back(); bool isFromSourceFile = false; std::unordered_set encounteredModules; + llvm::errs() << "MODULE: " << module->getRealName() << '\n'; for (auto file : module->getFiles()) { + llvm::errs() << " FILE: kind=" << static_cast(file->getKind()); auto sourceFile = llvm::dyn_cast(file); if (!sourceFile) { + llvm::errs() << '\n'; continue; } + llvm::errs() << " name=" << sourceFile->getFilename() << '\n'; isFromSourceFile = true; if (inputFiles.count(sourceFile->getFilename().str()) == 0) { continue; diff --git a/swift/integration-tests/posix-only/frontend-invocations/Files.expected b/swift/integration-tests/posix-only/frontend-invocations/Files.expected index 1e97daa9ab4..296a5d16513 100644 --- a/swift/integration-tests/posix-only/frontend-invocations/Files.expected +++ b/swift/integration-tests/posix-only/frontend-invocations/Files.expected @@ -6,6 +6,7 @@ | F1.swift:0:0:0:0 | F1.swift | | F2.swift:0:0:0:0 | F2.swift | | F3.swift:0:0:0:0 | F3.swift | +| F4.swift:0:0:0:0 | F4.swift | | F5.swift:0:0:0:0 | F5.swift | | G.swift:0:0:0:0 | G.swift | | H1.swift:0:0:0:0 | H1.swift | From 2cfecac54561dfdf7afbeace573327e2c7ab665d Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 13:14:44 +0200 Subject: [PATCH 023/141] Swift: remove debug prints --- swift/extractor/SwiftExtractor.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/swift/extractor/SwiftExtractor.cpp b/swift/extractor/SwiftExtractor.cpp index 8982c36c1c9..c331dcbc3c1 100644 --- a/swift/extractor/SwiftExtractor.cpp +++ b/swift/extractor/SwiftExtractor.cpp @@ -192,15 +192,11 @@ void codeql::extractSwiftFiles(SwiftExtractorState& state, swift::CompilerInstan todo.pop_back(); bool isFromSourceFile = false; std::unordered_set encounteredModules; - llvm::errs() << "MODULE: " << module->getRealName() << '\n'; for (auto file : module->getFiles()) { - llvm::errs() << " FILE: kind=" << static_cast(file->getKind()); auto sourceFile = llvm::dyn_cast(file); if (!sourceFile) { - llvm::errs() << '\n'; continue; } - llvm::errs() << " name=" << sourceFile->getFilename() << '\n'; isFromSourceFile = true; if (inputFiles.count(sourceFile->getFilename().str()) == 0) { continue; From bba5d9dbd64cc8dbfd3a7452e7b4d10e7ad6c477 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 14:03:07 +0200 Subject: [PATCH 024/141] Codegen: add `set` to schema definitions --- misc/codegen/lib/schema.py | 8 +- misc/codegen/lib/schemadefs.py | 12 +- misc/codegen/schemadefs.py | 149 ------------------------- misc/codegen/test/test_schemaloader.py | 6 + 4 files changed, 23 insertions(+), 152 deletions(-) delete mode 100644 misc/codegen/schemadefs.py diff --git a/misc/codegen/lib/schema.py b/misc/codegen/lib/schema.py index 5e2974ae87d..64a4720093b 100644 --- a/misc/codegen/lib/schema.py +++ b/misc/codegen/lib/schema.py @@ -25,6 +25,7 @@ class Property: OPTIONAL = auto() REPEATED_OPTIONAL = auto() PREDICATE = auto() + REPEATED_UNORDERED = auto() kind: Kind name: Optional[str] = None @@ -44,7 +45,11 @@ class Property: @property def is_repeated(self) -> bool: - return self.kind in (self.Kind.REPEATED, self.Kind.REPEATED_OPTIONAL) + return self.kind in (self.Kind.REPEATED, self.Kind.REPEATED_OPTIONAL, self.Kind.REPEATED_UNORDERED) + + @property + def is_unordered(self) -> bool: + return self.kind == self.Kind.REPEATED_UNORDERED @property def is_predicate(self) -> bool: @@ -65,6 +70,7 @@ RepeatedProperty = functools.partial(Property, Property.Kind.REPEATED) RepeatedOptionalProperty = functools.partial( Property, Property.Kind.REPEATED_OPTIONAL) PredicateProperty = functools.partial(Property, Property.Kind.PREDICATE) +RepeatedUnorderedProperty = functools.partial(Property, Property.Kind.REPEATED_UNORDERED) @dataclass diff --git a/misc/codegen/lib/schemadefs.py b/misc/codegen/lib/schemadefs.py index 6c9457490e7..15d0294ab77 100644 --- a/misc/codegen/lib/schemadefs.py +++ b/misc/codegen/lib/schemadefs.py @@ -77,7 +77,7 @@ class _Optionalizer(_schema.PropertyModifier): K = _schema.Property.Kind if prop.kind != K.SINGLE: raise _schema.Error( - "Optional should only be applied to simple property types") + "optional should only be applied to simple property types") prop.kind = K.OPTIONAL @@ -90,7 +90,14 @@ class _Listifier(_schema.PropertyModifier): prop.kind = K.REPEATED_OPTIONAL else: raise _schema.Error( - "Repeated should only be applied to simple or optional property types") + "list should only be applied to simple or optional property types") + +class _Setifier(_schema.PropertyModifier): + def modify(self, prop: _schema.Property): + K = _schema.Property.Kind + if prop.kind != K.SINGLE: + raise _schema.Error("set should only be applied to simple property types") + prop.kind = K.REPEATED_UNORDERED class _TypeModifier: @@ -122,6 +129,7 @@ string = "string" predicate = _schema.predicate_marker optional = _TypeModifier(_Optionalizer()) list = _TypeModifier(_Listifier()) +set = _TypeModifier(_Setifier()) child = _ChildModifier() doc = _DocModifier diff --git a/misc/codegen/schemadefs.py b/misc/codegen/schemadefs.py deleted file mode 100644 index 6c9457490e7..00000000000 --- a/misc/codegen/schemadefs.py +++ /dev/null @@ -1,149 +0,0 @@ -from typing import Callable as _Callable -from misc.codegen.lib import schema as _schema -import inspect as _inspect -from dataclasses import dataclass as _dataclass - - -class _ChildModifier(_schema.PropertyModifier): - def modify(self, prop: _schema.Property): - if prop.type is None or prop.type[0].islower(): - raise _schema.Error("Non-class properties cannot be children") - prop.is_child = True - - -@_dataclass -class _DocModifier(_schema.PropertyModifier): - doc: str - - def modify(self, prop: _schema.Property): - if "\n" in self.doc or self.doc[-1] == ".": - raise _schema.Error("No newlines or trailing dots are allowed in doc, did you intend to use desc?") - prop.doc = self.doc - - -@_dataclass -class _DescModifier(_schema.PropertyModifier): - description: str - - def modify(self, prop: _schema.Property): - prop.description = _schema.split_doc(self.description) - - -def include(source: str): - # add to `includes` variable in calling context - _inspect.currentframe().f_back.f_locals.setdefault( - "__includes", []).append(source) - - -class _Namespace: - """ simple namespacing mechanism """ - - def __init__(self, **kwargs): - self.__dict__.update(kwargs) - - -qltest = _Namespace() -ql = _Namespace() -cpp = _Namespace() -synth = _Namespace() - - -@_dataclass -class _Pragma(_schema.PropertyModifier): - """ A class or property pragma. - For properties, it functions similarly to a `_PropertyModifier` with `|`, adding the pragma. - For schema classes it acts as a python decorator with `@`. - """ - pragma: str - - def __post_init__(self): - namespace, _, name = self.pragma.partition('_') - setattr(globals()[namespace], name, self) - - def modify(self, prop: _schema.Property): - prop.pragmas.append(self.pragma) - - def __call__(self, cls: type) -> type: - """ use this pragma as a decorator on classes """ - if "_pragmas" in cls.__dict__: # not using hasattr as we don't want to land on inherited pragmas - cls._pragmas.append(self.pragma) - else: - cls._pragmas = [self.pragma] - return cls - - -class _Optionalizer(_schema.PropertyModifier): - def modify(self, prop: _schema.Property): - K = _schema.Property.Kind - if prop.kind != K.SINGLE: - raise _schema.Error( - "Optional should only be applied to simple property types") - prop.kind = K.OPTIONAL - - -class _Listifier(_schema.PropertyModifier): - def modify(self, prop: _schema.Property): - K = _schema.Property.Kind - if prop.kind == K.SINGLE: - prop.kind = K.REPEATED - elif prop.kind == K.OPTIONAL: - prop.kind = K.REPEATED_OPTIONAL - else: - raise _schema.Error( - "Repeated should only be applied to simple or optional property types") - - -class _TypeModifier: - """ Modifies types using get item notation """ - - def __init__(self, modifier: _schema.PropertyModifier): - self.modifier = modifier - - def __getitem__(self, item): - return item | self.modifier - - -_ClassDecorator = _Callable[[type], type] - - -def _annotate(**kwargs) -> _ClassDecorator: - def f(cls: type) -> type: - for k, v in kwargs.items(): - setattr(cls, f"_{k}", v) - return cls - - return f - - -boolean = "boolean" -int = "int" -string = "string" - -predicate = _schema.predicate_marker -optional = _TypeModifier(_Optionalizer()) -list = _TypeModifier(_Listifier()) - -child = _ChildModifier() -doc = _DocModifier -desc = _DescModifier - -use_for_null = _annotate(null=True) - -_Pragma("qltest_skip") -_Pragma("qltest_collapse_hierarchy") -_Pragma("qltest_uncollapse_hierarchy") - -ql.default_doc_name = lambda doc: _annotate(doc_name=doc) -_Pragma("ql_internal") - -_Pragma("cpp_skip") - - -def group(name: str = "") -> _ClassDecorator: - return _annotate(group=name) - - -synth.from_class = lambda ref: _annotate(ipa=_schema.IpaInfo( - from_class=_schema.get_type_name(ref))) -synth.on_arguments = lambda **kwargs: _annotate( - ipa=_schema.IpaInfo(on_arguments={k: _schema.get_type_name(t) for k, t in kwargs.items()})) diff --git a/misc/codegen/test/test_schemaloader.py b/misc/codegen/test/test_schemaloader.py index 9724a82da8f..458c517ce02 100644 --- a/misc/codegen/test/test_schemaloader.py +++ b/misc/codegen/test/test_schemaloader.py @@ -167,6 +167,7 @@ def test_properties(): three: defs.list[defs.boolean] four: defs.list[defs.optional[defs.string]] five: defs.predicate + six: defs.set[defs.string] assert data.classes == { 'A': schema.Class('A', properties=[ @@ -175,6 +176,7 @@ def test_properties(): schema.RepeatedProperty('three', 'boolean'), schema.RepeatedOptionalProperty('four', 'string'), schema.PredicateProperty('five'), + schema.RepeatedUnorderedProperty('six', 'string'), ]), } @@ -193,6 +195,7 @@ def test_class_properties(): two: defs.optional[A] three: defs.list[A] four: defs.list[defs.optional[A]] + five: defs.set[A] assert data.classes == { 'A': schema.Class('A', derived={'B'}), @@ -201,6 +204,7 @@ def test_class_properties(): schema.OptionalProperty('two', 'A'), schema.RepeatedProperty('three', 'A'), schema.RepeatedOptionalProperty('four', 'A'), + schema.RepeatedUnorderedProperty('five', 'A'), ]), } @@ -213,6 +217,7 @@ def test_string_reference_class_properties(): two: defs.optional["A"] three: defs.list["A"] four: defs.list[defs.optional["A"]] + five: defs.set["A"] assert data.classes == { 'A': schema.Class('A', properties=[ @@ -220,6 +225,7 @@ def test_string_reference_class_properties(): schema.OptionalProperty('two', 'A'), schema.RepeatedProperty('three', 'A'), schema.RepeatedOptionalProperty('four', 'A'), + schema.RepeatedUnorderedProperty('five', 'A'), ]), } From eef140c3fcbfcc021e2352d9f9f34d7029785de9 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 14:11:06 +0200 Subject: [PATCH 025/141] Codegen: implement `set` in dbschemegen --- misc/codegen/generators/dbschemegen.py | 11 ++++++++++- misc/codegen/test/test_dbschemegen.py | 26 ++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/misc/codegen/generators/dbschemegen.py b/misc/codegen/generators/dbschemegen.py index 05483748db5..8441b6fd61d 100755 --- a/misc/codegen/generators/dbschemegen.py +++ b/misc/codegen/generators/dbschemegen.py @@ -64,7 +64,16 @@ def cls_to_dbscheme(cls: schema.Class, lookup: typing.Dict[str, schema.Class], a ) # use property-specific tables for 1-to-many and 1-to-at-most-1 properties for f in cls.properties: - if f.is_repeated: + if f.is_unordered: + yield Table( + name=inflection.tableize(f"{cls.name}_{f.name}"), + columns=[ + Column("id", type=dbtype(cls.name)), + Column(inflection.singularize(f.name), dbtype(f.type, add_or_none_except)), + ], + dir=dir, + ) + elif f.is_repeated: yield Table( keyset=KeySet(["id", "index"]), name=inflection.tableize(f"{cls.name}_{f.name}"), diff --git a/misc/codegen/test/test_dbschemegen.py b/misc/codegen/test/test_dbschemegen.py index 7a986538b06..86b9dd2fc84 100644 --- a/misc/codegen/test/test_dbschemegen.py +++ b/misc/codegen/test/test_dbschemegen.py @@ -168,6 +168,32 @@ def test_final_class_with_repeated_field(generate, property_cls, dir_param): ) +def test_final_class_with_repeated_unordered_field(generate, dir_param): + assert generate([ + schema.Class("Object", group=dir_param.input, properties=[ + schema.RepeatedUnorderedProperty("foo", "bar"), + ]), + ]) == dbscheme.Scheme( + src=schema_file.name, + includes=[], + declarations=[ + dbscheme.Table( + name="objects", + columns=[ + dbscheme.Column('id', '@object', binding=True), + ], dir=dir_param.expected, + ), + dbscheme.Table( + name="object_foos", + columns=[ + dbscheme.Column('id', '@object'), + dbscheme.Column('foo', 'bar'), + ], dir=dir_param.expected, + ), + ], + ) + + def test_final_class_with_predicate_field(generate, dir_param): assert generate([ schema.Class("Object", group=dir_param.input, properties=[ From 442e85099b83c7faacb7d91db39f70da1d5e69c3 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 14:25:41 +0200 Subject: [PATCH 026/141] Codegen: implement `set` in cppgen --- misc/codegen/generators/cppgen.py | 1 + misc/codegen/lib/cpp.py | 1 + .../templates/cpp_classes_cpp.mustache | 2 +- misc/codegen/test/test_cppgen.py | 113 +++++++++--------- 4 files changed, 60 insertions(+), 57 deletions(-) diff --git a/misc/codegen/generators/cppgen.py b/misc/codegen/generators/cppgen.py index f6a7f8d792c..1cd6cc36450 100644 --- a/misc/codegen/generators/cppgen.py +++ b/misc/codegen/generators/cppgen.py @@ -49,6 +49,7 @@ def _get_field(cls: schema.Class, p: schema.Property, add_or_none_except: typing is_optional=p.is_optional, is_repeated=p.is_repeated, is_predicate=p.is_predicate, + is_unordered=p.is_unordered, trap_name=trap_name, ) args.update(cpp.get_field_override(p.name)) diff --git a/misc/codegen/lib/cpp.py b/misc/codegen/lib/cpp.py index 9ca2d8e2ebc..eed7aba045c 100644 --- a/misc/codegen/lib/cpp.py +++ b/misc/codegen/lib/cpp.py @@ -36,6 +36,7 @@ class Field: base_type: str is_optional: bool = False is_repeated: bool = False + is_unordered: bool = False is_predicate: bool = False trap_name: str = None first: bool = False diff --git a/misc/codegen/templates/cpp_classes_cpp.mustache b/misc/codegen/templates/cpp_classes_cpp.mustache index d78c89fc3c7..725fc10c6ef 100644 --- a/misc/codegen/templates/cpp_classes_cpp.mustache +++ b/misc/codegen/templates/cpp_classes_cpp.mustache @@ -24,7 +24,7 @@ void {{name}}::emit({{^final}}TrapLabel<{{name}}Tag> id, {{/final}}std::ostream& {{#is_repeated}} for (auto i = 0u; i < {{field_name}}.size(); ++i) { {{^is_optional}} - out << {{trap_name}}Trap{id, i, {{field_name}}[i]} << '\n'; + out << {{trap_name}}Trap{id, {{^is_unordered}}i, {{/is_unordered}}{{field_name}}[i]} << '\n'; {{/is_optional}} {{#is_optional}} if ({{field_name}}[i]) out << {{trap_name}}Trap{id, i, *{{field_name}}[i]} << '\n'; diff --git a/misc/codegen/test/test_cppgen.py b/misc/codegen/test/test_cppgen.py index 278f184fcbc..840a163995c 100644 --- a/misc/codegen/test/test_cppgen.py +++ b/misc/codegen/test/test_cppgen.py @@ -41,8 +41,8 @@ def test_empty_class(generate): assert generate([ schema.Class(name="MyClass"), ]) == [ - cpp.Class(name="MyClass", final=True, trap_name="MyClasses") - ] + cpp.Class(name="MyClass", final=True, trap_name="MyClasses") + ] def test_two_class_hierarchy(generate): @@ -51,9 +51,9 @@ def test_two_class_hierarchy(generate): schema.Class(name="A", derived={"B"}), schema.Class(name="B", bases=["A"]), ]) == [ - base, - cpp.Class(name="B", bases=[base], final=True, trap_name="Bs"), - ] + base, + cpp.Class(name="B", bases=[base], final=True, trap_name="Bs"), + ] @pytest.mark.parametrize("type,expected", [ @@ -62,22 +62,23 @@ def test_two_class_hierarchy(generate): ("boolean", "bool"), ("MyClass", "TrapLabel"), ]) -@pytest.mark.parametrize("property_cls,optional,repeated,trap_name", [ - (schema.SingleProperty, False, False, None), - (schema.OptionalProperty, True, False, "MyClassProps"), - (schema.RepeatedProperty, False, True, "MyClassProps"), - (schema.RepeatedOptionalProperty, True, True, "MyClassProps"), +@pytest.mark.parametrize("property_cls,optional,repeated,unordered,trap_name", [ + (schema.SingleProperty, False, False, False, None), + (schema.OptionalProperty, True, False, False, "MyClassProps"), + (schema.RepeatedProperty, False, True, False, "MyClassProps"), + (schema.RepeatedOptionalProperty, True, True, False, "MyClassProps"), + (schema.RepeatedUnorderedProperty, False, True, True, "MyClassProps"), ]) -def test_class_with_field(generate, type, expected, property_cls, optional, repeated, trap_name): +def test_class_with_field(generate, type, expected, property_cls, optional, repeated, unordered, trap_name): assert generate([ schema.Class(name="MyClass", properties=[property_cls("prop", type)]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field("prop", expected, is_optional=optional, - is_repeated=repeated, trap_name=trap_name)], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field("prop", expected, is_optional=optional, + is_repeated=repeated, is_unordered=unordered, trap_name=trap_name)], + trap_name="MyClasses", + final=True) + ] def test_class_field_with_null(generate, input): @@ -90,13 +91,13 @@ def test_class_field_with_null(generate, input): schema.SingleProperty("y", "B"), ]) ]) == [ - a, - cpp.Class(name="B", bases=[a], final=True, trap_name="Bs", - fields=[ - cpp.Field("x", "TrapLabel"), - cpp.Field("y", "TrapLabel"), - ]), - ] + a, + cpp.Class(name="B", bases=[a], final=True, trap_name="Bs", + fields=[ + cpp.Field("x", "TrapLabel"), + cpp.Field("y", "TrapLabel"), + ]), + ] def test_class_with_predicate(generate): @@ -104,12 +105,12 @@ def test_class_with_predicate(generate): schema.Class(name="MyClass", properties=[ schema.PredicateProperty("prop")]), ]) == [ - cpp.Class(name="MyClass", - fields=[ - cpp.Field("prop", "bool", trap_name="MyClassProp", is_predicate=True)], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[ + cpp.Field("prop", "bool", trap_name="MyClassProp", is_predicate=True)], + trap_name="MyClasses", + final=True) + ] @pytest.mark.parametrize("name", @@ -119,11 +120,11 @@ def test_class_with_overridden_unsigned_field(generate, name): schema.Class(name="MyClass", properties=[ schema.SingleProperty(name, "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field(name, "unsigned")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field(name, "unsigned")], + trap_name="MyClasses", + final=True) + ] def test_class_with_overridden_underscore_field(generate): @@ -131,11 +132,11 @@ def test_class_with_overridden_underscore_field(generate): schema.Class(name="MyClass", properties=[ schema.SingleProperty("something_", "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field("something", "bar")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field("something", "bar")], + trap_name="MyClasses", + final=True) + ] @pytest.mark.parametrize("name", cpp.cpp_keywords) @@ -144,11 +145,11 @@ def test_class_with_keyword_field(generate, name): schema.Class(name="MyClass", properties=[ schema.SingleProperty(name, "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field(name + "_", "bar")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field(name + "_", "bar")], + trap_name="MyClasses", + final=True) + ] def test_classes_with_dirs(generate_grouped): @@ -160,11 +161,11 @@ def test_classes_with_dirs(generate_grouped): schema.Class(name="C", bases=["CBase"], group="bar"), schema.Class(name="D", group="foo/bar/baz"), ]) == { - ".": [cpp.Class(name="A", trap_name="As", final=True)], - "foo": [cpp.Class(name="B", trap_name="Bs", final=True)], - "bar": [cbase, cpp.Class(name="C", bases=[cbase], trap_name="Cs", final=True)], - "foo/bar/baz": [cpp.Class(name="D", trap_name="Ds", final=True)], - } + ".": [cpp.Class(name="A", trap_name="As", final=True)], + "foo": [cpp.Class(name="B", trap_name="Bs", final=True)], + "bar": [cbase, cpp.Class(name="C", bases=[cbase], trap_name="Cs", final=True)], + "foo/bar/baz": [cpp.Class(name="D", trap_name="Ds", final=True)], + } def test_cpp_skip_pragma(generate): @@ -174,10 +175,10 @@ def test_cpp_skip_pragma(generate): schema.SingleProperty("y", "bar", pragmas=["x", "cpp_skip", "y"]), ]) ]) == [ - cpp.Class(name="A", final=True, trap_name="As", fields=[ - cpp.Field("x", "foo"), - ]), - ] + cpp.Class(name="A", final=True, trap_name="As", fields=[ + cpp.Field("x", "foo"), + ]), + ] def test_ipa_classes_ignored(generate): @@ -198,8 +199,8 @@ def test_ipa_classes_ignored(generate): name="Z", ), ]) == [ - cpp.Class(name="Z", final=True, trap_name="Zs"), - ] + cpp.Class(name="Z", final=True, trap_name="Zs"), + ] if __name__ == '__main__': From 00b59f83f2d6bf19bcf02d9814f5449a76eeaf08 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 14:34:11 +0200 Subject: [PATCH 027/141] Codegen: disallow `child` on `set` properties --- misc/codegen/lib/schemadefs.py | 2 ++ misc/codegen/test/test_schemaloader.py | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/misc/codegen/lib/schemadefs.py b/misc/codegen/lib/schemadefs.py index 15d0294ab77..e84d4e2a9d8 100644 --- a/misc/codegen/lib/schemadefs.py +++ b/misc/codegen/lib/schemadefs.py @@ -8,6 +8,8 @@ class _ChildModifier(_schema.PropertyModifier): def modify(self, prop: _schema.Property): if prop.type is None or prop.type[0].islower(): raise _schema.Error("Non-class properties cannot be children") + if prop.is_unordered: + raise _schema.Error("Set properties cannot be children") prop.is_child = True diff --git a/misc/codegen/test/test_schemaloader.py b/misc/codegen/test/test_schemaloader.py index 458c517ce02..9c9750818ea 100644 --- a/misc/codegen/test/test_schemaloader.py +++ b/misc/codegen/test/test_schemaloader.py @@ -259,8 +259,8 @@ def test_children(): } -@pytest.mark.parametrize("spec", [defs.string, defs.int, defs.boolean, defs.predicate]) -def test_builtin_and_predicate_children_not_allowed(spec): +@pytest.mark.parametrize("spec", [defs.string, defs.int, defs.boolean, defs.predicate, defs.set["A"]]) +def test_builtin_predicate_and_set_children_not_allowed(spec): with pytest.raises(schema.Error): @load class data: From d5ee7286570389e7709d916994743712bb56fb6e Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 15:03:00 +0200 Subject: [PATCH 028/141] Codegen: implement `set` in qlgen (excluding QL tests) --- misc/codegen/generators/qlgen.py | 3 ++- misc/codegen/lib/ql.py | 11 ++++++++- misc/codegen/templates/ql_class.mustache | 24 ++++++++++++------- misc/codegen/templates/ql_db.mustache | 2 +- .../templates/ql_property_doc.mustache | 5 ++++ misc/codegen/test/test_ql.py | 21 ++++++++++++++-- misc/codegen/test/test_qlgen.py | 16 +++++++++++++ 7 files changed, 69 insertions(+), 13 deletions(-) diff --git a/misc/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py index 68b3a6d7ef3..1f400b6e069 100755 --- a/misc/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -109,6 +109,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str = prev_child=prev_child if prop.is_child else None, is_optional=prop.is_optional, is_predicate=prop.is_predicate, + is_unordered=prop.is_unordered, description=prop.description ) if prop.is_single: @@ -123,7 +124,7 @@ def get_ql_property(cls: schema.Class, prop: schema.Property, prev_child: str = singular=inflection.singularize(inflection.camelize(prop.name)), plural=inflection.pluralize(inflection.camelize(prop.name)), tablename=inflection.tableize(f"{cls.name}_{prop.name}"), - tableparams=["this", "index", "result"], + tableparams=["this", "index", "result"] if not prop.is_unordered else ["this", "result"], doc=_get_doc(cls, prop, plural=False), doc_plural=_get_doc(cls, prop, plural=True), ) diff --git a/misc/codegen/lib/ql.py b/misc/codegen/lib/ql.py index ace39a61e0e..2b887e6ab7d 100644 --- a/misc/codegen/lib/ql.py +++ b/misc/codegen/lib/ql.py @@ -36,6 +36,7 @@ class Property: first: bool = False is_optional: bool = False is_predicate: bool = False + is_unordered: bool = False prev_child: Optional[str] = None qltest_skip: bool = False description: List[str] = field(default_factory=list) @@ -49,7 +50,11 @@ class Property: @property def getter(self): - return f"get{self.singular}" if not self.is_predicate else self.singular + if self.is_predicate: + return self.singular + if self.is_unordered: + return self.indefinite_getter + return f"get{self.singular}" @property def indefinite_getter(self): @@ -77,6 +82,10 @@ class Property: def has_description(self) -> bool: return bool(self.description) + @property + def is_indexed(self) -> bool: + return self.is_repeated and not self.is_unordered + @dataclass class Base: diff --git a/misc/codegen/templates/ql_class.mustache b/misc/codegen/templates/ql_class.mustache index 173df3a75b9..862b46067c4 100644 --- a/misc/codegen/templates/ql_class.mustache +++ b/misc/codegen/templates/ql_class.mustache @@ -66,9 +66,9 @@ module Generated { * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - {{type}} getImmediate{{singular}}({{#is_repeated}}int index{{/is_repeated}}) { + {{type}} get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}int index{{/is_indexed}}) { {{^ipa}} - result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}})) + result = Synth::convert{{type}}FromRaw(Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}})) {{/ipa}} {{#ipa}} none() @@ -83,8 +83,8 @@ module Generated { {{/description}} {{/has_description}} */ - final {{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) { - result = getImmediate{{singular}}({{#is_repeated}}index{{/is_repeated}}).resolve() + final {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { + result = get{{#is_unordered}}An{{/is_unordered}}Immediate{{singular}}({{#is_indexed}}index{{/is_indexed}}).resolve() } {{/type_is_class}} @@ -97,9 +97,9 @@ module Generated { {{/description}} {{/has_description}} */ - {{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) { + {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { {{^ipa}} - {{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_repeated}}index{{/is_repeated}}) + {{^is_predicate}}result = {{/is_predicate}}Synth::convert{{name}}ToRaw(this){{^root}}.(Raw::{{name}}){{/root}}.{{getter}}({{#is_indexed}}index{{/is_indexed}}) {{/ipa}} {{#ipa}} none() @@ -115,7 +115,7 @@ module Generated { exists({{getter}}({{#is_repeated}}index{{/is_repeated}})) } {{/is_optional}} - {{#is_repeated}} + {{#is_indexed}} /** * Gets any of the {{doc_plural}}. @@ -132,7 +132,15 @@ module Generated { result = count(int i | exists({{getter}}(i))) } {{/is_optional}} - {{/is_repeated}} + {{/is_indexed}} + {{#is_unordered}} + /** + * Gets the number of {{doc_plural}}. + */ + final int getNumberOf{{plural}}() { + result = count({{getter}}()) + } + {{/is_unordered}} {{/properties}} } } diff --git a/misc/codegen/templates/ql_db.mustache b/misc/codegen/templates/ql_db.mustache index 750cdb008a8..55a83514d6e 100644 --- a/misc/codegen/templates/ql_db.mustache +++ b/misc/codegen/templates/ql_db.mustache @@ -13,7 +13,7 @@ module Raw { {{/description}} {{/has_description}} */ - {{type}} {{getter}}({{#is_repeated}}int index{{/is_repeated}}) { + {{type}} {{getter}}({{#is_indexed}}int index{{/is_indexed}}) { {{tablename}}({{#tableparams}}{{^first}}, {{/first}}{{param}}{{/tableparams}}) } {{/properties}} diff --git a/misc/codegen/templates/ql_property_doc.mustache b/misc/codegen/templates/ql_property_doc.mustache index 483772d14f6..7f21c6461c9 100644 --- a/misc/codegen/templates/ql_property_doc.mustache +++ b/misc/codegen/templates/ql_property_doc.mustache @@ -1,6 +1,11 @@ {{^is_predicate}} +{{^is_unoredered}} Gets the {{#is_repeated}}`index`th {{/is_repeated}}{{doc}}{{#is_repeated}} (0-based){{/is_repeated}}{{#is_optional}}, if it exists{{/is_optional}}. +{{/is_unoredered}} {{/is_predicate}} {{#is_predicate}} Holds if {{doc}}. {{/is_predicate}} +{{#is_unordered}} +Gets any of the {{doc_plural}}. +{{/is_unordered}} diff --git a/misc/codegen/test/test_ql.py b/misc/codegen/test/test_ql.py index 0006bbb96e4..0149f299667 100644 --- a/misc/codegen/test/test_ql.py +++ b/misc/codegen/test/test_ql.py @@ -27,19 +27,26 @@ def test_property_is_a_class(type, expected): assert [p.param for p in prop.tableparams] == expected_tableparams -@pytest.mark.parametrize("name,expected_getter", [ +indefinite_getters = [ ("Argument", "getAnArgument"), ("Element", "getAnElement"), ("Integer", "getAnInteger"), ("Operator", "getAnOperator"), ("Unit", "getAUnit"), ("Whatever", "getAWhatever"), -]) +] + +@pytest.mark.parametrize("name,expected_getter", indefinite_getters) def test_property_indefinite_article(name, expected_getter): prop = ql.Property(name, plural="X") assert prop.indefinite_getter == expected_getter +@pytest.mark.parametrize("name,expected_getter", indefinite_getters) +def test_property_unordered_getter(name, expected_getter): + prop = ql.Property(name, plural="X", is_unordered=True) + assert prop.getter == expected_getter + @pytest.mark.parametrize("plural,expected", [ (None, False), ("", False), @@ -49,6 +56,16 @@ def test_property_is_repeated(plural, expected): prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural) assert prop.is_repeated is expected +@pytest.mark.parametrize("plural,unordered,expected", [ + (None, False, False), + ("", False, False), + ("X", False, True), + ("X", True, False), +]) +def test_property_is_indexed(plural, unordered, expected): + prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural, is_unordered=unordered) + assert prop.is_indexed is expected + @pytest.mark.parametrize("is_optional,is_predicate,plural,expected", [ (False, False, None, True), diff --git a/misc/codegen/test/test_qlgen.py b/misc/codegen/test/test_qlgen.py index f16b1404c2e..5db9a99d706 100644 --- a/misc/codegen/test/test_qlgen.py +++ b/misc/codegen/test/test_qlgen.py @@ -337,6 +337,22 @@ def test_repeated_property(generate_classes, is_child, prev_child): ])), } +def test_repeated_unordered_property(generate_classes): + assert generate_classes([ + schema.Class("FakeRoot"), + schema.Class("MyObject", properties=[ + schema.RepeatedUnorderedProperty("foo", "bar")]), + ]) == { + "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), + a_ql_class(name="FakeRoot", final=True)), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, properties=[ + ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", + tableparams=["this", "result"], is_unordered=True, + doc="foo of this my object", doc_plural="foos of this my object"), + ])), + } + @pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")]) def test_repeated_optional_property(generate_classes, is_child, prev_child): From d7a3cb2d01c16cfff79ce98bdec33abd6c7b0e72 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 15:12:39 +0200 Subject: [PATCH 029/141] Codegen: implement `set` in ql test generation --- misc/codegen/generators/qlgen.py | 2 +- misc/codegen/lib/ql.py | 2 +- misc/codegen/templates/ql_test_property.mustache | 4 ++-- misc/codegen/test/test_qlgen.py | 13 +++++++++---- 4 files changed, 13 insertions(+), 8 deletions(-) diff --git a/misc/codegen/generators/qlgen.py b/misc/codegen/generators/qlgen.py index 1f400b6e069..7affea51828 100755 --- a/misc/codegen/generators/qlgen.py +++ b/misc/codegen/generators/qlgen.py @@ -256,7 +256,7 @@ def _get_all_properties_to_be_tested(cls: schema.Class, lookup: typing.Dict[str, # TODO here operations are duplicated, but should be better if we split ql and qltest generation p = get_ql_property(c, p) yield ql.PropertyForTest(p.getter, is_total=p.is_single or p.is_predicate, - type=p.type if not p.is_predicate else None, is_repeated=p.is_repeated) + type=p.type if not p.is_predicate else None, is_indexed=p.is_indexed) if p.is_repeated and not p.is_optional: yield ql.PropertyForTest(f"getNumberOf{p.plural}", type="int") elif p.is_optional and not p.is_repeated: diff --git a/misc/codegen/lib/ql.py b/misc/codegen/lib/ql.py index 2b887e6ab7d..97165053fd0 100644 --- a/misc/codegen/lib/ql.py +++ b/misc/codegen/lib/ql.py @@ -197,7 +197,7 @@ class PropertyForTest: getter: str is_total: bool = True type: Optional[str] = None - is_repeated: bool = False + is_indexed: bool = False @dataclass diff --git a/misc/codegen/templates/ql_test_property.mustache b/misc/codegen/templates/ql_test_property.mustache index 5e81298089d..a0ba0a52d69 100644 --- a/misc/codegen/templates/ql_test_property.mustache +++ b/misc/codegen/templates/ql_test_property.mustache @@ -4,7 +4,7 @@ import {{elements_module}} import TestUtils {{#property}} -from {{class_name}} x{{#is_repeated}}, int index{{/is_repeated}} +from {{class_name}} x{{#is_indexed}}, int index{{/is_indexed}} where toBeTested(x) and not x.isUnknown() -select x, {{#is_repeated}}index, {{/is_repeated}}x.{{getter}}({{#is_repeated}}index{{/is_repeated}}) +select x, {{#is_indexed}}index, {{/is_indexed}}x.{{getter}}({{#is_indexed}}index{{/is_indexed}}) {{/property}} diff --git a/misc/codegen/test/test_qlgen.py b/misc/codegen/test/test_qlgen.py index 5db9a99d706..3c5738d6196 100644 --- a/misc/codegen/test/test_qlgen.py +++ b/misc/codegen/test/test_qlgen.py @@ -568,23 +568,28 @@ def test_test_partial_properties(opts, generate_tests): schema.Class("B", bases=["A"], properties=[ schema.RepeatedProperty("y", "bool"), schema.RepeatedOptionalProperty("z", "int"), + schema.RepeatedUnorderedProperty("w", "string"), ]), ]) == { "B/B.ql": a_ql_class_tester(class_name="B", properties=[ ql.PropertyForTest(getter="hasX"), ql.PropertyForTest(getter="getNumberOfYs", type="int"), + ql.PropertyForTest(getter="getNumberOfWs", type="int"), ]), "B/B_getX.ql": a_ql_property_tester(class_name="B", property=ql.PropertyForTest(getter="getX", is_total=False, type="string")), "B/B_getY.ql": a_ql_property_tester(class_name="B", property=ql.PropertyForTest(getter="getY", is_total=False, - is_repeated=True, + is_indexed=True, type="bool")), "B/B_getZ.ql": a_ql_property_tester(class_name="B", property=ql.PropertyForTest(getter="getZ", is_total=False, - is_repeated=True, - type="int")), + is_indexed=True, + type="int")), + "B/B_getAW.ql": a_ql_property_tester(class_name="B", + property=ql.PropertyForTest(getter="getAW", is_total=False, + type="string")), } @@ -605,7 +610,7 @@ def test_test_properties_deduplicated(opts, generate_tests): ]), "Final/Final_getY.ql": a_ql_property_tester(class_name="Final", property=ql.PropertyForTest(getter="getY", is_total=False, - is_repeated=True, + is_indexed=True, type="bool")), } From 20128adee493a65f9a7c89eb47fe35783cc2b546 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 15:17:57 +0200 Subject: [PATCH 030/141] Swift: make imported and exported modules a set --- swift/ql/.generated.list | 8 ++--- swift/ql/lib/codeql/swift/generated/Raw.qll | 6 ++-- .../swift/generated/decl/ModuleDecl.qll | 34 +++++++------------ swift/ql/lib/swift.dbscheme | 4 --- .../ModuleDecl_getAnExportedModule.expected | 1 + ...e.ql => ModuleDecl_getAnExportedModule.ql} | 4 +-- .../ModuleDecl_getAnImportedModule.expected | 9 +++++ ...e.ql => ModuleDecl_getAnImportedModule.ql} | 4 +-- .../ModuleDecl_getExportedModule.expected | 1 - .../ModuleDecl_getImportedModule.expected | 9 ----- swift/schema.py | 4 +-- 11 files changed, 36 insertions(+), 48 deletions(-) create mode 100644 swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.expected rename swift/ql/test/extractor-tests/generated/decl/ModuleDecl/{ModuleDecl_getExportedModule.ql => ModuleDecl_getAnExportedModule.ql} (62%) create mode 100644 swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.expected rename swift/ql/test/extractor-tests/generated/decl/ModuleDecl/{ModuleDecl_getImportedModule.ql => ModuleDecl_getAnImportedModule.ql} (62%) delete mode 100644 swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected delete mode 100644 swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected diff --git a/swift/ql/.generated.list b/swift/ql/.generated.list index 5c6b0ce34c7..76f44e6e85c 100644 --- a/swift/ql/.generated.list +++ b/swift/ql/.generated.list @@ -384,7 +384,7 @@ ql/lib/codeql/swift/generated/OtherAvailabilitySpec.qll 0e26a203b26ff0581b7396b0 ql/lib/codeql/swift/generated/ParentChild.qll 0ac2139b8b2e172858262d80950a0212b21fe46bf6af7259d9058fb7193f8242 6f7464ecd8ca04b6aa261139b36a162e5b0636237d514b8431ef4f97a1c603dc ql/lib/codeql/swift/generated/PlatformVersionAvailabilitySpec.qll f82d9ca416fe8bd59b5531b65b1c74c9f317b3297a6101544a11339a1cffce38 7f5c6d3309e66c134107afe55bae76dfc9a72cb7cdd6d4c3706b6b34cee09fa0 ql/lib/codeql/swift/generated/PureSynthConstructors.qll 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 173c0dd59396a1de26fe870e3bc2766c46de689da2a4d8807cb62023bbce1a98 -ql/lib/codeql/swift/generated/Raw.qll efe60f045f8a4aecedd7bfe8110c0c10539bcdcb9f17f342cf560c8d065e6aff 261825907250bb4ddeba8ccce0df29b45f13c6fb338eb41a06ea6b43e7aa9788 +ql/lib/codeql/swift/generated/Raw.qll 02e54c90cb3ee38fe39b2c17fd4720b5a78fa617edb530a1627a2853798a272f 91f4d685e0e3ebec70566bbab89754b12af0be434445856c39a9b19e5d5e7041 ql/lib/codeql/swift/generated/Synth.qll af02e0b49fe7b488592687996cc74d9525d4e3fbc9d324820b310b356f4d2612 5c740a660721173e9e4e45eb701d373ca19ff14d61cdaea309b65871e0deea90 ql/lib/codeql/swift/generated/SynthConstructors.qll a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 a1b3ca33017f82124286ccad317a05484fee144fb9c3cdd2e500ce38e5efcec4 ql/lib/codeql/swift/generated/UnknownFile.qll 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 0fcf9beb8de79440bcdfff4bb6ab3dd139bd273e6c32754e05e6a632651e85f6 @@ -414,7 +414,7 @@ ql/lib/codeql/swift/generated/decl/IfConfigDecl.qll 58c1a02a3867105c61d29e2d9bc6 ql/lib/codeql/swift/generated/decl/ImportDecl.qll 8892cd34d182c6747e266e213f0239fd3402004370a9be6e52b9747d91a7b61b 2c07217ab1b7ebc39dc2cb20d45a2b1b899150cabd3b1a15cd8b1479bab64578 ql/lib/codeql/swift/generated/decl/InfixOperatorDecl.qll d98168fdf180f28582bae8ec0242c1220559235230a9c94e9f479708c561ea21 aad805aa74d63116b19f435983d6df6df31cef6a5bbd30d7c2944280b470dee6 ql/lib/codeql/swift/generated/decl/MissingMemberDecl.qll eaf8989eda461ec886a2e25c1e5e80fc4a409f079c8d28671e6e2127e3167479 d74b31b5dfa54ca5411cd5d41c58f1f76cfccc1e12b4f1fdeed398b4faae5355 -ql/lib/codeql/swift/generated/decl/ModuleDecl.qll 675135d140d273cd83e290cf433bcaebc48065d433e2cf8e570612b686d2fb53 d8cd5418205e05598800bf13e8aa01e6018b5c6727075381afd4c83136c29366 +ql/lib/codeql/swift/generated/decl/ModuleDecl.qll 0b809c371dae40cfdc7bf869c654158dc154e1551d8466c339742c7fdc26a5db 3d7efb0ccfd752d9f01624d21eba79067824b3910b11185c81f0b513b69e8c51 ql/lib/codeql/swift/generated/decl/NominalTypeDecl.qll 7e8980cd646e9dee91e429f738d6682b18c8f8974c9561c7b936fca01b56fdb2 513e55dd6a68d83a8e884c9a373ecd70eca8e3957e0f5f6c2b06696e4f56df88 ql/lib/codeql/swift/generated/decl/OpaqueTypeDecl.qll f2cdbc238b9ea67d5bc2defd8ec0455efafd7fdaeca5b2f72d0bbb16a8006d17 041724a6ec61b60291d2a68d228d5f106c02e1ba6bf3c1d3d0a6dda25777a0e5 ql/lib/codeql/swift/generated/decl/OperatorDecl.qll 3ffdc7ab780ee94a975f0ce3ae4252b52762ca8dbea6f0eb95f951e404c36a5b 25e39ccd868fa2d1fbce0eb7cbf8e9c2aca67d6fd42f76e247fb0fa74a51b230 @@ -720,9 +720,9 @@ ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getImportedModule.q ql/test/extractor-tests/generated/decl/ImportDecl/ImportDecl_getMember.ql 6d48d3a93bc96dba3bda71ec9d9d6282615c2228a58da6167c169fafaedb3e17 8560b23d0f52b845c81727ce09c0b2f9647965c83d7de165e8cd3d91be5bdd42 ql/test/extractor-tests/generated/decl/InfixOperatorDecl/MISSING_SOURCE.txt 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 66846d526b0bc4328735c3c4dd9c390a9325da5b5dfd42ec07622f9c7108a7d7 ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl.ql f9216e83077ebc0cb5a5bf2d7368af86167a1bfd378f9cd5592fd484a1bbc5dd 1c2de61cb064474340db10de4399c49f15eb0a5669e6dc9587d8b4f656b0134f +ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql 321619519c5cffefda78f11f2c85a199af76fccbfcc51126c7a558ba12fdfd80 30e48eb820ba9d7f3ec30bf4536c0f84280c5f2ca8c63427f6b77d74a092e68b +ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql 65fae5b1a7db3a11fd837ed78c663e8907306c36695ae73e4e29559755276fbe 3ddef1a7af7a636e66674fadb3e727ad18655a9ecb4c73fd3d6aca202f1191fb ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getBaseType.ql 54a4bd2cfa666271ae9092285bb7217b082c88483d614066cfb599fc8ab84305 8b24ab8e93efe3922cb192eb5de5f517763058782e83e8732153421adddd68e1 -ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql cfca012f0951c86560d892ea5eae182d5eda661c9484a0df71ef9c905123e8f6 dfebda4fcad0e2f2a2c944782a7355b3caeac569e5a45621c582bc1bb243b2cc -ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql 44018a788205592c59cd10072f8b8d0558100bb15fff4b3e490176e86193e5b1 cc9fe6571713af8a0e844ac5da682c24feb1a2be4535e3feeb4cbbafba91a414 ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getMember.ql a4663d47cf0a16a07167b9a64d56f8ba8e504a78142c7e216d1df69879df9130 3f6a4080e33bddd1e34fa25519d855811c256182055db4989be8150fcddd541b ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl.ql 16ccca5a90cc3133ab085ccb843416abc103f2fcf3423a84fbd7f5c15a5c7f17 242d7ea07842ee3fb0f9905b5cbc0ea744f1116c4591c5f133025260991bfdeb ql/test/extractor-tests/generated/decl/OpaqueTypeDecl/OpaqueTypeDecl_getBaseType.ql d030fd55ea5a5443c03e8ba1a024c03e3c68c96c948c850131f59fbac6409402 46816c1a75a4cf11db95884733382e46d5573b6c1116d5de0bfe5ae91fed4c3d diff --git a/swift/ql/lib/codeql/swift/generated/Raw.qll b/swift/ql/lib/codeql/swift/generated/Raw.qll index 3dad5a302fc..29005f07fb1 100644 --- a/swift/ql/lib/codeql/swift/generated/Raw.qll +++ b/swift/ql/lib/codeql/swift/generated/Raw.qll @@ -419,13 +419,15 @@ module Raw { /** * Gets the `index`th imported module of this module declaration (0-based). + *Gets any of the imported modules of this module declaration. */ - ModuleDecl getImportedModule(int index) { module_decl_imported_modules(this, index, result) } + ModuleDecl getAnImportedModule() { module_decl_imported_modules(this, result) } /** * Gets the `index`th exported module of this module declaration (0-based). + *Gets any of the exported modules of this module declaration. */ - ModuleDecl getExportedModule(int index) { module_decl_exported_modules(this, index, result) } + ModuleDecl getAnExportedModule() { module_decl_exported_modules(this, result) } } class SubscriptDecl extends @subscript_decl, AbstractStorageDecl, GenericContext { diff --git a/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll b/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll index 4b10570ef7b..7f11f4a1cbd 100644 --- a/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll +++ b/swift/ql/lib/codeql/swift/generated/decl/ModuleDecl.qll @@ -23,62 +23,52 @@ module Generated { /** * Gets the `index`th imported module of this module declaration (0-based). + *Gets any of the imported modules of this module declaration. * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - ModuleDecl getImmediateImportedModule(int index) { + ModuleDecl getAnImmediateImportedModule() { result = Synth::convertModuleDeclFromRaw(Synth::convertModuleDeclToRaw(this) .(Raw::ModuleDecl) - .getImportedModule(index)) + .getAnImportedModule()) } /** * Gets the `index`th imported module of this module declaration (0-based). + *Gets any of the imported modules of this module declaration. */ - final ModuleDecl getImportedModule(int index) { - result = getImmediateImportedModule(index).resolve() - } - - /** - * Gets any of the imported modules of this module declaration. - */ - final ModuleDecl getAnImportedModule() { result = getImportedModule(_) } + final ModuleDecl getAnImportedModule() { result = getAnImmediateImportedModule().resolve() } /** * Gets the number of imported modules of this module declaration. */ - final int getNumberOfImportedModules() { result = count(int i | exists(getImportedModule(i))) } + final int getNumberOfImportedModules() { result = count(getAnImportedModule()) } /** * Gets the `index`th exported module of this module declaration (0-based). + *Gets any of the exported modules of this module declaration. * * This includes nodes from the "hidden" AST. It can be overridden in subclasses to change the * behavior of both the `Immediate` and non-`Immediate` versions. */ - ModuleDecl getImmediateExportedModule(int index) { + ModuleDecl getAnImmediateExportedModule() { result = Synth::convertModuleDeclFromRaw(Synth::convertModuleDeclToRaw(this) .(Raw::ModuleDecl) - .getExportedModule(index)) + .getAnExportedModule()) } /** * Gets the `index`th exported module of this module declaration (0-based). + *Gets any of the exported modules of this module declaration. */ - final ModuleDecl getExportedModule(int index) { - result = getImmediateExportedModule(index).resolve() - } - - /** - * Gets any of the exported modules of this module declaration. - */ - final ModuleDecl getAnExportedModule() { result = getExportedModule(_) } + final ModuleDecl getAnExportedModule() { result = getAnImmediateExportedModule().resolve() } /** * Gets the number of exported modules of this module declaration. */ - final int getNumberOfExportedModules() { result = count(int i | exists(getExportedModule(i))) } + final int getNumberOfExportedModules() { result = count(getAnExportedModule()) } } } diff --git a/swift/ql/lib/swift.dbscheme b/swift/ql/lib/swift.dbscheme index c2f01f2beb6..db22947f6ae 100644 --- a/swift/ql/lib/swift.dbscheme +++ b/swift/ql/lib/swift.dbscheme @@ -482,17 +482,13 @@ module_decl_is_system_module( //dir=decl int id: @module_decl ref ); -#keyset[id, index] module_decl_imported_modules( //dir=decl int id: @module_decl ref, - int index: int ref, int imported_module: @module_decl_or_none ref ); -#keyset[id, index] module_decl_exported_modules( //dir=decl int id: @module_decl ref, - int index: int ref, int exported_module: @module_decl_or_none ref ); diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.expected new file mode 100644 index 00000000000..271c68f34fd --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.expected @@ -0,0 +1 @@ +| file://:0:0:0:0 | Foo | file://:0:0:0:0 | Swift | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql similarity index 62% rename from swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql rename to swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql index 012f1501665..649b56793c8 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.ql +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnExportedModule.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ModuleDecl x, int index +from ModuleDecl x where toBeTested(x) and not x.isUnknown() -select x, index, x.getExportedModule(index) +select x, x.getAnExportedModule() diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.expected new file mode 100644 index 00000000000..c711cd8b913 --- /dev/null +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.expected @@ -0,0 +1,9 @@ +| file://:0:0:0:0 | Foo | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | Foo | file://:0:0:0:0 | SwiftOnoneSupport | +| file://:0:0:0:0 | Foo | file://:0:0:0:0 | _Concurrency | +| file://:0:0:0:0 | Foo | file://:0:0:0:0 | _StringProcessing | +| file://:0:0:0:0 | __ObjC | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | default_module_name | file://:0:0:0:0 | Swift | +| file://:0:0:0:0 | default_module_name | file://:0:0:0:0 | SwiftOnoneSupport | +| file://:0:0:0:0 | default_module_name | file://:0:0:0:0 | _Concurrency | +| file://:0:0:0:0 | default_module_name | file://:0:0:0:0 | _StringProcessing | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql similarity index 62% rename from swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql rename to swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql index c5c8e83e23b..d7c95b74e73 100644 --- a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.ql +++ b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getAnImportedModule.ql @@ -2,6 +2,6 @@ import codeql.swift.elements import TestUtils -from ModuleDecl x, int index +from ModuleDecl x where toBeTested(x) and not x.isUnknown() -select x, index, x.getImportedModule(index) +select x, x.getAnImportedModule() diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected deleted file mode 100644 index a0865f2c40a..00000000000 --- a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getExportedModule.expected +++ /dev/null @@ -1 +0,0 @@ -| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift | diff --git a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected b/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected deleted file mode 100644 index ca1793b95ef..00000000000 --- a/swift/ql/test/extractor-tests/generated/decl/ModuleDecl/ModuleDecl_getImportedModule.expected +++ /dev/null @@ -1,9 +0,0 @@ -| file://:0:0:0:0 | Foo | 0 | file://:0:0:0:0 | Swift | -| file://:0:0:0:0 | Foo | 1 | file://:0:0:0:0 | _StringProcessing | -| file://:0:0:0:0 | Foo | 2 | file://:0:0:0:0 | _Concurrency | -| file://:0:0:0:0 | Foo | 3 | file://:0:0:0:0 | SwiftOnoneSupport | -| file://:0:0:0:0 | __ObjC | 0 | file://:0:0:0:0 | Swift | -| file://:0:0:0:0 | default_module_name | 0 | file://:0:0:0:0 | Swift | -| file://:0:0:0:0 | default_module_name | 1 | file://:0:0:0:0 | _StringProcessing | -| file://:0:0:0:0 | default_module_name | 2 | file://:0:0:0:0 | _Concurrency | -| file://:0:0:0:0 | default_module_name | 3 | file://:0:0:0:0 | SwiftOnoneSupport | diff --git a/swift/schema.py b/swift/schema.py index a9b075cd933..a63053bed14 100644 --- a/swift/schema.py +++ b/swift/schema.py @@ -272,8 +272,8 @@ class GenericTypeDecl(GenericContext, TypeDecl): class ModuleDecl(TypeDecl): is_builtin_module: predicate | doc("this module is the built-in one") is_system_module: predicate | doc("this module is a system one") - imported_modules: list["ModuleDecl"] - exported_modules: list["ModuleDecl"] + imported_modules: set["ModuleDecl"] + exported_modules: set["ModuleDecl"] class SubscriptDecl(AbstractStorageDecl, GenericContext): params: list[ParamDecl] | child From 48c23033918a5ebac9ab8d543f9b1c0f13008a52 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 15:33:46 +0200 Subject: [PATCH 031/141] Swift: add upgrade/downgrade scripts --- .../module_decl_exported_modules.ql | 15 + .../module_decl_imported_modules.ql | 15 + .../old.dbscheme | 2597 ++++++++++++++++ .../swift.dbscheme | 2601 +++++++++++++++++ .../upgrade.properties | 4 + .../old.dbscheme | 2601 +++++++++++++++++ .../swift.dbscheme | 2597 ++++++++++++++++ .../upgrade.properties | 4 + 8 files changed, 10434 insertions(+) create mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql create mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql create mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme create mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme create mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties create mode 100644 swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme create mode 100644 swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme create mode 100644 swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql new file mode 100644 index 00000000000..6f2f7125742 --- /dev/null +++ b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql @@ -0,0 +1,15 @@ +class Element extends @element { + string toString() { none() } +} + +int getExportedModuleIndex(Element m, Element i) { + i = + rank[result + 1](Element j, string name | + module_decl_exported_modules(m, j) and type_decls(j, name) + | + j order by name + ) +} + +from Element m, Element i +select m, getExportedModuleIndex(m, i), i diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql new file mode 100644 index 00000000000..88093d6e5e5 --- /dev/null +++ b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql @@ -0,0 +1,15 @@ +class Element extends @element { + string toString() { none() } +} + +int getImportedModuleIndex(Element m, Element i) { + i = + rank[result + 1](Element j, string name | + module_decl_imported_modules(m, j) and type_decls(j, name) + | + j order by name + ) +} + +from Element m, Element i +select m, getImportedModuleIndex(m, i), i diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme new file mode 100644 index 00000000000..db22947f6ae --- /dev/null +++ b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme @@ -0,0 +1,2597 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme new file mode 100644 index 00000000000..c2f01f2beb6 --- /dev/null +++ b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme @@ -0,0 +1,2601 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties new file mode 100644 index 00000000000..160d55476c9 --- /dev/null +++ b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties @@ -0,0 +1,4 @@ +description: Revert turning exported and imported modules into unindexed sets +compatibility: full +module_decl_imported_modules.rel: run module_decl_imported_modules.ql +module_decl_exported_modules.rel: run module_decl_exported_modules.ql diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme new file mode 100644 index 00000000000..c2f01f2beb6 --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme @@ -0,0 +1,2601 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme new file mode 100644 index 00000000000..db22947f6ae --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme @@ -0,0 +1,2597 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties new file mode 100644 index 00000000000..def634ba268 --- /dev/null +++ b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties @@ -0,0 +1,4 @@ +description: Turn exported and imported modules into unindexed sets +compatibility: full +module_decl_imported_modules.rel: reorder module_decl_imported_modules(int id, int index, int imported) id imported +module_decl_exported_modules.rel: reorder module_decl_exported_modules(int id, int index, int exported) id exported From 92197bf9f2aa3a4e19c46088364820389a582ab8 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Wed, 29 Mar 2023 15:57:45 +0200 Subject: [PATCH 032/141] Codegen: fix autopep8 pre-commit hook --- .pre-commit-config.yaml | 2 +- misc/codegen/lib/schemadefs.py | 1 + misc/codegen/test/test_cppgen.py | 100 +++++++++++++++---------------- misc/codegen/test/test_ql.py | 3 + misc/codegen/test/test_qlgen.py | 17 +++--- 5 files changed, 64 insertions(+), 59 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e612a423462..bb25a64ebfb 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -19,7 +19,7 @@ repos: rev: v1.6.0 hooks: - id: autopep8 - files: ^swift/.*\.py + files: ^misc/codegen/.*\.py - repo: local hooks: diff --git a/misc/codegen/lib/schemadefs.py b/misc/codegen/lib/schemadefs.py index e84d4e2a9d8..f3bfd9840dc 100644 --- a/misc/codegen/lib/schemadefs.py +++ b/misc/codegen/lib/schemadefs.py @@ -94,6 +94,7 @@ class _Listifier(_schema.PropertyModifier): raise _schema.Error( "list should only be applied to simple or optional property types") + class _Setifier(_schema.PropertyModifier): def modify(self, prop: _schema.Property): K = _schema.Property.Kind diff --git a/misc/codegen/test/test_cppgen.py b/misc/codegen/test/test_cppgen.py index 840a163995c..1bc7d150b2e 100644 --- a/misc/codegen/test/test_cppgen.py +++ b/misc/codegen/test/test_cppgen.py @@ -41,8 +41,8 @@ def test_empty_class(generate): assert generate([ schema.Class(name="MyClass"), ]) == [ - cpp.Class(name="MyClass", final=True, trap_name="MyClasses") - ] + cpp.Class(name="MyClass", final=True, trap_name="MyClasses") + ] def test_two_class_hierarchy(generate): @@ -51,9 +51,9 @@ def test_two_class_hierarchy(generate): schema.Class(name="A", derived={"B"}), schema.Class(name="B", bases=["A"]), ]) == [ - base, - cpp.Class(name="B", bases=[base], final=True, trap_name="Bs"), - ] + base, + cpp.Class(name="B", bases=[base], final=True, trap_name="Bs"), + ] @pytest.mark.parametrize("type,expected", [ @@ -73,12 +73,12 @@ def test_class_with_field(generate, type, expected, property_cls, optional, repe assert generate([ schema.Class(name="MyClass", properties=[property_cls("prop", type)]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field("prop", expected, is_optional=optional, - is_repeated=repeated, is_unordered=unordered, trap_name=trap_name)], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field("prop", expected, is_optional=optional, + is_repeated=repeated, is_unordered=unordered, trap_name=trap_name)], + trap_name="MyClasses", + final=True) + ] def test_class_field_with_null(generate, input): @@ -91,13 +91,13 @@ def test_class_field_with_null(generate, input): schema.SingleProperty("y", "B"), ]) ]) == [ - a, - cpp.Class(name="B", bases=[a], final=True, trap_name="Bs", - fields=[ - cpp.Field("x", "TrapLabel"), - cpp.Field("y", "TrapLabel"), - ]), - ] + a, + cpp.Class(name="B", bases=[a], final=True, trap_name="Bs", + fields=[ + cpp.Field("x", "TrapLabel"), + cpp.Field("y", "TrapLabel"), + ]), + ] def test_class_with_predicate(generate): @@ -105,12 +105,12 @@ def test_class_with_predicate(generate): schema.Class(name="MyClass", properties=[ schema.PredicateProperty("prop")]), ]) == [ - cpp.Class(name="MyClass", - fields=[ - cpp.Field("prop", "bool", trap_name="MyClassProp", is_predicate=True)], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[ + cpp.Field("prop", "bool", trap_name="MyClassProp", is_predicate=True)], + trap_name="MyClasses", + final=True) + ] @pytest.mark.parametrize("name", @@ -120,11 +120,11 @@ def test_class_with_overridden_unsigned_field(generate, name): schema.Class(name="MyClass", properties=[ schema.SingleProperty(name, "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field(name, "unsigned")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field(name, "unsigned")], + trap_name="MyClasses", + final=True) + ] def test_class_with_overridden_underscore_field(generate): @@ -132,11 +132,11 @@ def test_class_with_overridden_underscore_field(generate): schema.Class(name="MyClass", properties=[ schema.SingleProperty("something_", "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field("something", "bar")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field("something", "bar")], + trap_name="MyClasses", + final=True) + ] @pytest.mark.parametrize("name", cpp.cpp_keywords) @@ -145,11 +145,11 @@ def test_class_with_keyword_field(generate, name): schema.Class(name="MyClass", properties=[ schema.SingleProperty(name, "bar")]), ]) == [ - cpp.Class(name="MyClass", - fields=[cpp.Field(name + "_", "bar")], - trap_name="MyClasses", - final=True) - ] + cpp.Class(name="MyClass", + fields=[cpp.Field(name + "_", "bar")], + trap_name="MyClasses", + final=True) + ] def test_classes_with_dirs(generate_grouped): @@ -161,11 +161,11 @@ def test_classes_with_dirs(generate_grouped): schema.Class(name="C", bases=["CBase"], group="bar"), schema.Class(name="D", group="foo/bar/baz"), ]) == { - ".": [cpp.Class(name="A", trap_name="As", final=True)], - "foo": [cpp.Class(name="B", trap_name="Bs", final=True)], - "bar": [cbase, cpp.Class(name="C", bases=[cbase], trap_name="Cs", final=True)], - "foo/bar/baz": [cpp.Class(name="D", trap_name="Ds", final=True)], - } + ".": [cpp.Class(name="A", trap_name="As", final=True)], + "foo": [cpp.Class(name="B", trap_name="Bs", final=True)], + "bar": [cbase, cpp.Class(name="C", bases=[cbase], trap_name="Cs", final=True)], + "foo/bar/baz": [cpp.Class(name="D", trap_name="Ds", final=True)], + } def test_cpp_skip_pragma(generate): @@ -175,10 +175,10 @@ def test_cpp_skip_pragma(generate): schema.SingleProperty("y", "bar", pragmas=["x", "cpp_skip", "y"]), ]) ]) == [ - cpp.Class(name="A", final=True, trap_name="As", fields=[ - cpp.Field("x", "foo"), - ]), - ] + cpp.Class(name="A", final=True, trap_name="As", fields=[ + cpp.Field("x", "foo"), + ]), + ] def test_ipa_classes_ignored(generate): @@ -199,8 +199,8 @@ def test_ipa_classes_ignored(generate): name="Z", ), ]) == [ - cpp.Class(name="Z", final=True, trap_name="Zs"), - ] + cpp.Class(name="Z", final=True, trap_name="Zs"), + ] if __name__ == '__main__': diff --git a/misc/codegen/test/test_ql.py b/misc/codegen/test/test_ql.py index 0149f299667..6d1e2181194 100644 --- a/misc/codegen/test/test_ql.py +++ b/misc/codegen/test/test_ql.py @@ -36,6 +36,7 @@ indefinite_getters = [ ("Whatever", "getAWhatever"), ] + @pytest.mark.parametrize("name,expected_getter", indefinite_getters) def test_property_indefinite_article(name, expected_getter): prop = ql.Property(name, plural="X") @@ -47,6 +48,7 @@ def test_property_unordered_getter(name, expected_getter): prop = ql.Property(name, plural="X", is_unordered=True) assert prop.getter == expected_getter + @pytest.mark.parametrize("plural,expected", [ (None, False), ("", False), @@ -56,6 +58,7 @@ def test_property_is_repeated(plural, expected): prop = ql.Property("foo", "Foo", "props", ["result"], plural=plural) assert prop.is_repeated is expected + @pytest.mark.parametrize("plural,unordered,expected", [ (None, False, False), ("", False, False), diff --git a/misc/codegen/test/test_qlgen.py b/misc/codegen/test/test_qlgen.py index 3c5738d6196..e6dd8d452cb 100644 --- a/misc/codegen/test/test_qlgen.py +++ b/misc/codegen/test/test_qlgen.py @@ -337,21 +337,22 @@ def test_repeated_property(generate_classes, is_child, prev_child): ])), } + def test_repeated_unordered_property(generate_classes): assert generate_classes([ schema.Class("FakeRoot"), schema.Class("MyObject", properties=[ schema.RepeatedUnorderedProperty("foo", "bar")]), ]) == { - "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), - a_ql_class(name="FakeRoot", final=True)), - "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), - a_ql_class(name="MyObject", final=True, properties=[ + "FakeRoot.qll": (a_ql_stub(name="FakeRoot", base_import=gen_import_prefix + "FakeRoot"), + a_ql_class(name="FakeRoot", final=True)), + "MyObject.qll": (a_ql_stub(name="MyObject", base_import=gen_import_prefix + "MyObject"), + a_ql_class(name="MyObject", final=True, properties=[ ql.Property(singular="Foo", plural="Foos", type="bar", tablename="my_object_foos", tableparams=["this", "result"], is_unordered=True, doc="foo of this my object", doc_plural="foos of this my object"), - ])), - } + ])), + } @pytest.mark.parametrize("is_child,prev_child", [(False, None), (True, "")]) @@ -588,8 +589,8 @@ def test_test_partial_properties(opts, generate_tests): is_indexed=True, type="int")), "B/B_getAW.ql": a_ql_property_tester(class_name="B", - property=ql.PropertyForTest(getter="getAW", is_total=False, - type="string")), + property=ql.PropertyForTest(getter="getAW", is_total=False, + type="string")), } From ce2cab0d2e5eef5d13f8344b4b1fc98861b2b50e Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 27 Mar 2023 15:40:42 -0400 Subject: [PATCH 033/141] Move TaintedPath configurations to Query.qll --- .../code/java/security/TaintedPathQuery.qll | 104 ++++++++++++++++++ .../src/Security/CWE/CWE-022/TaintedPath.ql | 38 +------ .../CWE/CWE-022/TaintedPathCommon.qll | 48 -------- .../Security/CWE/CWE-022/TaintedPathLocal.ql | 30 +---- 4 files changed, 110 insertions(+), 110 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll delete mode 100644 java/ql/src/Security/CWE/CWE-022/TaintedPathCommon.qll diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll new file mode 100644 index 00000000000..8ce1bbdc886 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -0,0 +1,104 @@ +/** Provides dataflow configurations for tainted path queries. */ + +import java +import semmle.code.java.frameworks.Networking +import semmle.code.java.dataflow.DataFlow +import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.dataflow.ExternalFlow +import semmle.code.java.security.PathCreation +import semmle.code.java.security.PathSanitizer + +/** + * A unit class for adding additional taint steps. + * + * Extend this class to add additional taint steps that should apply to tainted path flow configurations. + */ +class TaintedPathAdditionalTaintStep extends Unit { + abstract predicate step(DataFlow::Node n1, DataFlow::Node n2); +} + +private class DefaultTaintedPathAdditionalTaintStep extends TaintedPathAdditionalTaintStep { + override predicate step(DataFlow::Node n1, DataFlow::Node n2) { + exists(Argument a | + a = n1.asExpr() and + a.getCall() = n2.asExpr() and + a = any(TaintPreservingUriCtorParam tpp).getAnArgument() + ) + } +} + +private class TaintPreservingUriCtorParam extends Parameter { + TaintPreservingUriCtorParam() { + exists(Constructor ctor, int idx, int nParams | + ctor.getDeclaringType() instanceof TypeUri and + this = ctor.getParameter(idx) and + nParams = ctor.getNumberOfParameters() + | + // URI(String scheme, String ssp, String fragment) + idx = 1 and nParams = 3 + or + // URI(String scheme, String host, String path, String fragment) + idx = [1, 2] and nParams = 4 + or + // URI(String scheme, String authority, String path, String query, String fragment) + idx = 2 and nParams = 5 + or + // URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment) + idx = 4 and nParams = 7 + ) + } +} + +/** + * A taint-tracking configuration for tracking flow from remote sources to the creation of a path. + */ +module TaintedPathConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { + sink.asExpr() = any(PathCreation p).getAnInput() + or + sinkNode(sink, ["create-file", "read-file"]) + } + + predicate isBarrier(DataFlow::Node sanitizer) { + sanitizer.getType() instanceof BoxedType or + sanitizer.getType() instanceof PrimitiveType or + sanitizer.getType() instanceof NumberType or + sanitizer instanceof PathInjectionSanitizer + } + + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + any(TaintedPathAdditionalTaintStep s).step(n1, n2) + } +} + +/** Tracks flow from remote sources to the creation of a path. */ +module TaintedPathFlow = TaintTracking::Global; + +/** + * A taint-tracking configuration for tracking flow from user input to the creation of a path. + */ +module TaintedPathLocalConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } + + predicate isSink(DataFlow::Node sink) { + sink.asExpr() = any(PathCreation p).getAnInput() + or + sinkNode(sink, "create-file") + } + + predicate isBarrier(DataFlow::Node sanitizer) { + sanitizer.getType() instanceof BoxedType or + sanitizer.getType() instanceof PrimitiveType or + sanitizer.getType() instanceof NumberType or + sanitizer instanceof PathInjectionSanitizer + } + + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + any(TaintedPathAdditionalTaintStep s).step(n1, n2) + } +} + +/** Tracks flow from user input to the creation of a path. */ +module TaintedPathLocalFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql index 4058978f29a..2d73514d97b 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPath.ql @@ -14,36 +14,8 @@ */ import java -import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.dataflow.ExternalFlow -import semmle.code.java.security.PathCreation -import semmle.code.java.security.PathSanitizer -import TaintedPathCommon - -module TaintedPathConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(PathCreation p).getAnInput() - or - sinkNode(sink, ["create-file", "read-file"]) - } - - predicate isBarrier(DataFlow::Node sanitizer) { - sanitizer.getType() instanceof BoxedType or - sanitizer.getType() instanceof PrimitiveType or - sanitizer.getType() instanceof NumberType or - sanitizer instanceof PathInjectionSanitizer - } - - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - any(TaintedPathAdditionalTaintStep s).step(n1, n2) - } -} - -module TaintedPath = TaintTracking::Global; - -import TaintedPath::PathGraph +import semmle.code.java.security.TaintedPathQuery +import TaintedPathFlow::PathGraph /** * Gets the data-flow node at which to report a path ending at `sink`. @@ -53,13 +25,13 @@ import TaintedPath::PathGraph * continue to report there; otherwise we report directly at `sink`. */ DataFlow::Node getReportingNode(DataFlow::Node sink) { - TaintedPath::flowTo(sink) and + TaintedPathFlow::flowTo(sink) and if exists(PathCreation pc | pc.getAnInput() = sink.asExpr()) then result.asExpr() = any(PathCreation pc | pc.getAnInput() = sink.asExpr()) else result = sink } -from TaintedPath::PathNode source, TaintedPath::PathNode sink -where TaintedPath::flowPath(source, sink) +from TaintedPathFlow::PathNode source, TaintedPathFlow::PathNode sink +where TaintedPathFlow::flowPath(source, sink) select getReportingNode(sink.getNode()), source, sink, "This path depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPathCommon.qll b/java/ql/src/Security/CWE/CWE-022/TaintedPathCommon.qll deleted file mode 100644 index 418931d9a0d..00000000000 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPathCommon.qll +++ /dev/null @@ -1,48 +0,0 @@ -/** - * Models a very basic guard for the tainted path queries. - */ - -import java -import semmle.code.java.frameworks.Networking -import semmle.code.java.dataflow.DataFlow - -/** - * A unit class for adding additional taint steps. - * - * Extend this class to add additional taint steps that should apply to tainted path flow configurations. - */ -class TaintedPathAdditionalTaintStep extends Unit { - abstract predicate step(DataFlow::Node n1, DataFlow::Node n2); -} - -private class DefaultTaintedPathAdditionalTaintStep extends TaintedPathAdditionalTaintStep { - override predicate step(DataFlow::Node n1, DataFlow::Node n2) { - exists(Argument a | - a = n1.asExpr() and - a.getCall() = n2.asExpr() and - a = any(TaintPreservingUriCtorParam tpp).getAnArgument() - ) - } -} - -private class TaintPreservingUriCtorParam extends Parameter { - TaintPreservingUriCtorParam() { - exists(Constructor ctor, int idx, int nParams | - ctor.getDeclaringType() instanceof TypeUri and - this = ctor.getParameter(idx) and - nParams = ctor.getNumberOfParameters() - | - // URI(String scheme, String ssp, String fragment) - idx = 1 and nParams = 3 - or - // URI(String scheme, String host, String path, String fragment) - idx = [1, 2] and nParams = 4 - or - // URI(String scheme, String authority, String path, String query, String fragment) - idx = 2 and nParams = 5 - or - // URI(String scheme, String userInfo, String host, int port, String path, String query, String fragment) - idx = 4 and nParams = 7 - ) - } -} diff --git a/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql b/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql index 94c2b0e68a0..c017b8a3aa9 100644 --- a/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql +++ b/java/ql/src/Security/CWE/CWE-022/TaintedPathLocal.ql @@ -14,35 +14,7 @@ */ import java -import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.dataflow.ExternalFlow -import semmle.code.java.security.PathCreation -import semmle.code.java.security.PathSanitizer -import TaintedPathCommon - -module TaintedPathLocalConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } - - predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(PathCreation p).getAnInput() - or - sinkNode(sink, "create-file") - } - - predicate isBarrier(DataFlow::Node sanitizer) { - sanitizer.getType() instanceof BoxedType or - sanitizer.getType() instanceof PrimitiveType or - sanitizer.getType() instanceof NumberType or - sanitizer instanceof PathInjectionSanitizer - } - - predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { - any(TaintedPathAdditionalTaintStep s).step(n1, n2) - } -} - -module TaintedPathLocalFlow = TaintTracking::Global; - +import semmle.code.java.security.TaintedPathQuery import TaintedPathLocalFlow::PathGraph /** From 367042bcff501995381181ea425b64a884297cbf Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 27 Mar 2023 15:44:33 -0400 Subject: [PATCH 034/141] Move ZipSlip configurations to Query.qll library --- .../code/java/security/ZipSlipQuery.qll | 46 +++++++++++++++++++ java/ql/src/Security/CWE/CWE-022/ZipSlip.ql | 41 +---------------- 2 files changed, 47 insertions(+), 40 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll b/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll new file mode 100644 index 00000000000..61323e034d6 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll @@ -0,0 +1,46 @@ +/** Provides dataflow configurations to be used in ZipSlip queries. */ + +import java +import semmle.code.java.controlflow.Guards +import semmle.code.java.dataflow.SSA +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.security.PathSanitizer +private import semmle.code.java.dataflow.ExternalFlow + +/** + * A method that returns the name of an archive entry. + */ +class ArchiveEntryNameMethod extends Method { + ArchiveEntryNameMethod() { + exists(RefType archiveEntry | + archiveEntry.hasQualifiedName("java.util.zip", "ZipEntry") or + archiveEntry.hasQualifiedName("org.apache.commons.compress.archivers", "ArchiveEntry") + | + this.getDeclaringType().getAnAncestor() = archiveEntry and + this.hasName("getName") + ) + } +} + +/** + * A taint-tracking configuration for reasoning about unsafe zip file extraction. + */ +module ZipSlipConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source.asExpr().(MethodAccess).getMethod() instanceof ArchiveEntryNameMethod + } + + predicate isSink(DataFlow::Node sink) { sink instanceof FileCreationSink } + + predicate isBarrier(DataFlow::Node node) { node instanceof PathInjectionSanitizer } +} + +/** Tracks flow from archive entries to file creation. */ +module ZipSlipFlow = TaintTracking::Global; + +/** + * A sink that represents a file creation, such as a file write, copy or move operation. + */ +private class FileCreationSink extends DataFlow::Node { + FileCreationSink() { sinkNode(this, "create-file") } +} diff --git a/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql b/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql index b1afdfe65a4..3488c97c057 100644 --- a/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql +++ b/java/ql/src/Security/CWE/CWE-022/ZipSlip.ql @@ -13,48 +13,9 @@ */ import java -import semmle.code.java.controlflow.Guards -import semmle.code.java.dataflow.SSA -import semmle.code.java.dataflow.TaintTracking -import semmle.code.java.security.PathSanitizer -private import semmle.code.java.dataflow.ExternalFlow - -/** - * A method that returns the name of an archive entry. - */ -class ArchiveEntryNameMethod extends Method { - ArchiveEntryNameMethod() { - exists(RefType archiveEntry | - archiveEntry.hasQualifiedName("java.util.zip", "ZipEntry") or - archiveEntry.hasQualifiedName("org.apache.commons.compress.archivers", "ArchiveEntry") - | - this.getDeclaringType().getAnAncestor() = archiveEntry and - this.hasName("getName") - ) - } -} - -module ZipSlipConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source.asExpr().(MethodAccess).getMethod() instanceof ArchiveEntryNameMethod - } - - predicate isSink(DataFlow::Node sink) { sink instanceof FileCreationSink } - - predicate isBarrier(DataFlow::Node node) { node instanceof PathInjectionSanitizer } -} - -module ZipSlipFlow = TaintTracking::Global; - +import semmle.code.java.security.ZipSlipQuery import ZipSlipFlow::PathGraph -/** - * A sink that represents a file creation, such as a file write, copy or move operation. - */ -private class FileCreationSink extends DataFlow::Node { - FileCreationSink() { sinkNode(this, "create-file") } -} - from ZipSlipFlow::PathNode source, ZipSlipFlow::PathNode sink where ZipSlipFlow::flowPath(source, sink) select source.getNode(), source, sink, From 19a94a5c1354d5f59b1d6b2c9ce2c68216decfbf Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 27 Mar 2023 17:05:14 -0400 Subject: [PATCH 035/141] Move InsecureBeanValidation configuration to Query.qll --- .../security/InsecureBeanValidationQuery.qll | 63 +++++++++++++++++++ .../CWE/CWE-094/InsecureBeanValidation.ql | 61 +----------------- 2 files changed, 64 insertions(+), 60 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll new file mode 100644 index 00000000000..198cf7fb57c --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll @@ -0,0 +1,63 @@ +/** Provides classes and a taint tracking configuration to reason about insecure bean validation. */ + +import java +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.dataflow.ExternalFlow + +/** + * A message interpolator Type that perform Expression Language (EL) evaluations + */ +class ELMessageInterpolatorType extends RefType { + ELMessageInterpolatorType() { + this.getASourceSupertype*() + .hasQualifiedName("org.hibernate.validator.messageinterpolation", + ["ResourceBundleMessageInterpolator", "ValueFormatterMessageInterpolator"]) + } +} + +/** + * A method call that sets the application's default message interpolator. + */ +class SetMessageInterpolatorCall extends MethodAccess { + SetMessageInterpolatorCall() { + exists(Method m, RefType t | + this.getMethod() = m and + m.getDeclaringType().getASourceSupertype*() = t and + ( + t.hasQualifiedName("javax.validation", ["Configuration", "ValidatorContext"]) and + m.getName() = "messageInterpolator" + or + t.hasQualifiedName("org.springframework.validation.beanvalidation", + ["CustomValidatorBean", "LocalValidatorFactoryBean"]) and + m.getName() = "setMessageInterpolator" + ) + ) + } + + /** + * Holds if the message interpolator is likely to be safe, because it does not process Java Expression Language expressions. + */ + predicate isSafe() { not this.getAnArgument().getType() instanceof ELMessageInterpolatorType } +} + +/** + * Taint tracking BeanValidationConfiguration describing the flow of data from user input + * to the argument of a method that builds constraint error messages. + */ +module BeanValidationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof BeanValidationSink } +} + +/** Tracks flow from user input to the argument of a method that builds constraint error messages. */ +module BeanValidationFlow = TaintTracking::Global; + +/** + * A bean validation sink, such as method `buildConstraintViolationWithTemplate` + * declared on a subtype of `javax.validation.ConstraintValidatorContext`. + */ +private class BeanValidationSink extends DataFlow::Node { + BeanValidationSink() { sinkNode(this, "bean-validation") } +} diff --git a/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql b/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql index 5e957f23793..2dd0bf617ba 100644 --- a/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql +++ b/java/ql/src/Security/CWE/CWE-094/InsecureBeanValidation.ql @@ -11,68 +11,9 @@ */ import java -import semmle.code.java.dataflow.TaintTracking -import semmle.code.java.dataflow.FlowSources -private import semmle.code.java.dataflow.ExternalFlow - -/** - * A message interpolator Type that perform Expression Language (EL) evaluations - */ -class ELMessageInterpolatorType extends RefType { - ELMessageInterpolatorType() { - this.getASourceSupertype*() - .hasQualifiedName("org.hibernate.validator.messageinterpolation", - ["ResourceBundleMessageInterpolator", "ValueFormatterMessageInterpolator"]) - } -} - -/** - * A method call that sets the application's default message interpolator. - */ -class SetMessageInterpolatorCall extends MethodAccess { - SetMessageInterpolatorCall() { - exists(Method m, RefType t | - this.getMethod() = m and - m.getDeclaringType().getASourceSupertype*() = t and - ( - t.hasQualifiedName("javax.validation", ["Configuration", "ValidatorContext"]) and - m.getName() = "messageInterpolator" - or - t.hasQualifiedName("org.springframework.validation.beanvalidation", - ["CustomValidatorBean", "LocalValidatorFactoryBean"]) and - m.getName() = "setMessageInterpolator" - ) - ) - } - - /** - * The message interpolator is likely to be safe, because it does not process Java Expression Language expressions. - */ - predicate isSafe() { not this.getAnArgument().getType() instanceof ELMessageInterpolatorType } -} - -/** - * Taint tracking BeanValidationConfiguration describing the flow of data from user input - * to the argument of a method that builds constraint error messages. - */ -module BeanValidationConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - predicate isSink(DataFlow::Node sink) { sink instanceof BeanValidationSink } -} - -module BeanValidationFlow = TaintTracking::Global; - +import semmle.code.java.security.InsecureBeanValidationQuery import BeanValidationFlow::PathGraph -/** - * A bean validation sink, such as method `buildConstraintViolationWithTemplate` - * declared on a subtype of `javax.validation.ConstraintValidatorContext`. - */ -private class BeanValidationSink extends DataFlow::Node { - BeanValidationSink() { sinkNode(this, "bean-validation") } -} - from BeanValidationFlow::PathNode source, BeanValidationFlow::PathNode sink where ( From 1add6926430fb0f2be035090a0932a775163b0ab Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 28 Mar 2023 16:29:02 -0400 Subject: [PATCH 036/141] Move XssConfig to XssQuery.qll --- .../semmle/code/java/security/XssQuery.qll | 26 +++++++++++++++++++ java/ql/src/Security/CWE/CWE-079/XSS.ql | 20 +------------- 2 files changed, 27 insertions(+), 19 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/XssQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/XssQuery.qll b/java/ql/lib/semmle/code/java/security/XssQuery.qll new file mode 100644 index 00000000000..5accb2ca585 --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/XssQuery.qll @@ -0,0 +1,26 @@ +/** Provides a taint tracking configuration to track cross site scripting. */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.dataflow.TaintTracking +import semmle.code.java.security.XSS + +/** + * A taint-tracking configuration for cross site scripting vulnerabilities. + */ +module XssConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof XssSink } + + predicate isBarrier(DataFlow::Node node) { node instanceof XssSanitizer } + + predicate isBarrierOut(DataFlow::Node node) { node instanceof XssSinkBarrier } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(XssAdditionalTaintStep s).step(node1, node2) + } +} + +/** Tracks flow from remote sources to cross site scripting vulnerabilities. */ +module XssFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-079/XSS.ql b/java/ql/src/Security/CWE/CWE-079/XSS.ql index dbec746eaf6..9ae92a7e362 100644 --- a/java/ql/src/Security/CWE/CWE-079/XSS.ql +++ b/java/ql/src/Security/CWE/CWE-079/XSS.ql @@ -12,25 +12,7 @@ */ import java -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.security.XSS - -module XssConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - predicate isSink(DataFlow::Node sink) { sink instanceof XssSink } - - predicate isBarrier(DataFlow::Node node) { node instanceof XssSanitizer } - - predicate isBarrierOut(DataFlow::Node node) { node instanceof XssSinkBarrier } - - predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - any(XssAdditionalTaintStep s).step(node1, node2) - } -} - -module XssFlow = TaintTracking::Global; - +import semmle.code.java.security.XssQuery import XssFlow::PathGraph from XssFlow::PathNode source, XssFlow::PathNode sink From e3af8b2c7fda552304264b3b03379d088526e48f Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 28 Mar 2023 16:35:35 -0400 Subject: [PATCH 037/141] Move LdapInjectionLib to LdapInjectionQuery.qll --- .../semmle/code/java/security/LdapInjectionQuery.qll} | 3 +++ java/ql/src/Security/CWE/CWE-090/LdapInjection.ql | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) rename java/ql/{src/Security/CWE/CWE-090/LdapInjectionLib.qll => lib/semmle/code/java/security/LdapInjectionQuery.qll} (78%) diff --git a/java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll b/java/ql/lib/semmle/code/java/security/LdapInjectionQuery.qll similarity index 78% rename from java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll rename to java/ql/lib/semmle/code/java/security/LdapInjectionQuery.qll index d6ca8b1169d..c0f52cdf659 100644 --- a/java/ql/src/Security/CWE/CWE-090/LdapInjectionLib.qll +++ b/java/ql/lib/semmle/code/java/security/LdapInjectionQuery.qll @@ -1,3 +1,5 @@ +/** Provides a taint tracking configuration to reason about unvalidated user input that is used to construct LDAP queries. */ + import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.LdapInjection @@ -17,4 +19,5 @@ module LdapInjectionFlowConfig implements DataFlow::ConfigSig { } } +/** Tracks flow from remote sources to LDAP injection vulnerabilities. */ module LdapInjectionFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql b/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql index e879a33051d..e511cb8819c 100644 --- a/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql +++ b/java/ql/src/Security/CWE/CWE-090/LdapInjection.ql @@ -13,7 +13,7 @@ import java import semmle.code.java.dataflow.FlowSources -import LdapInjectionLib +import semmle.code.java.security.LdapInjectionQuery import LdapInjectionFlow::PathGraph from LdapInjectionFlow::PathNode source, LdapInjectionFlow::PathNode sink From 3eaa94a5d2d250ab189a5c02c633ea32e70fbcc8 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 28 Mar 2023 16:53:28 -0400 Subject: [PATCH 038/141] Move ResponseSplitting configuration to ResponseSplittingQuery.qll --- .../java/security/ResponseSplittingQuery.qll | 40 +++++++++++++++++++ .../Security/CWE/CWE-113/ResponseSplitting.ql | 39 ++---------------- 2 files changed, 44 insertions(+), 35 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll b/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll new file mode 100644 index 00000000000..95eaab22e0d --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll @@ -0,0 +1,40 @@ +/** Provides a taint tracking configuration to reason about response splitting vulnerabilities. */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.security.ResponseSplitting + +/** + * A taint-tracking configuration for response splitting vulnerabilities. + */ +module ResponseSplittingConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { + source instanceof RemoteFlowSource and + not source instanceof SafeHeaderSplittingSource + } + + predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType + or + node.getType() instanceof BoxedType + or + exists(MethodAccess ma, string methodName, CompileTimeConstantExpr target | + node.asExpr() = ma and + ma.getMethod().hasQualifiedName("java.lang", "String", methodName) and + target = ma.getArgument(0) and + ( + methodName = "replace" and target.getIntValue() = [10, 13] // 10 == "\n", 13 == "\r" + or + methodName = "replaceAll" and + target.getStringValue().regexpMatch(".*([\n\r]|\\[\\^[^\\]\r\n]*\\]).*") + ) + ) + } +} + +/** + * Tracks flow from remote sources to response splitting vulnerabilities. + */ +module ResponseSplittingFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql b/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql index 4fef0a620cd..2138d9187a1 100644 --- a/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql +++ b/java/ql/src/Security/CWE/CWE-113/ResponseSplitting.ql @@ -12,42 +12,11 @@ */ import java -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.security.ResponseSplitting +import semmle.code.java.security.ResponseSplittingQuery +import ResponseSplittingFlow::PathGraph -module ResponseSplittingConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { - source instanceof RemoteFlowSource and - not source instanceof SafeHeaderSplittingSource - } - - predicate isSink(DataFlow::Node sink) { sink instanceof HeaderSplittingSink } - - predicate isBarrier(DataFlow::Node node) { - node.getType() instanceof PrimitiveType - or - node.getType() instanceof BoxedType - or - exists(MethodAccess ma, string methodName, CompileTimeConstantExpr target | - node.asExpr() = ma and - ma.getMethod().hasQualifiedName("java.lang", "String", methodName) and - target = ma.getArgument(0) and - ( - methodName = "replace" and target.getIntValue() = [10, 13] // 10 == "\n", 13 == "\r" - or - methodName = "replaceAll" and - target.getStringValue().regexpMatch(".*([\n\r]|\\[\\^[^\\]\r\n]*\\]).*") - ) - ) - } -} - -module ResponseSplitting = TaintTracking::Global; - -import ResponseSplitting::PathGraph - -from ResponseSplitting::PathNode source, ResponseSplitting::PathNode sink -where ResponseSplitting::flowPath(source, sink) +from ResponseSplittingFlow::PathNode source, ResponseSplittingFlow::PathNode sink +where ResponseSplittingFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This header depends on a $@, which may cause a response-splitting vulnerability.", source.getNode(), "user-provided value" From 7d9fad5733f33d2463904c16795cf5938a577456 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 14:42:17 -0400 Subject: [PATCH 039/141] Add change note --- .../2023-03-29-moved-configurations-for-queries.md | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md diff --git a/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md b/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md new file mode 100644 index 00000000000..b99d43364fa --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md @@ -0,0 +1,9 @@ +--- +category: minorAnalysis +--- +* Added the `TaintedPathQuery.qll` library to provide the `TaintedPathFlow` and `TaintedPathLocalFlow` taint-tracking modules to reason about tainted path vulnerabilities. +* Added the `ZipSlipQuery.qll` library to provide the `ZipSlipFlow` taint-tracking module to reason about zip-slip vulnerabilities. +* Added the `InsecureBeanValidationQuery.qll` library to provide the `BeanValidationFlow` taint-tracking module to reason about bean validation vulnerabilities. +* Added the `XssQuery.qll` library to provide the `XssFlow` taint-tracking module to reason about cross site scripting vulnerabilities. +* Added the `LdapInjectionQuery.qll` library to provide the `LdapInjectionFlow` taint-tracking module to reason about LDAP injection vulnerabilities. +* Added the `ResponseSplittingQuery.qll` library to provide the `ResponseSplittingFlow` taint-tracking module to reason about response splitting vulnerabilities. From 9afa0516218248ac630cd05dd8dc87a96dfa414f Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 14:51:27 -0400 Subject: [PATCH 040/141] Move ExternallyControlledFormatStringFlow to Query.qll --- .../ExternallyControlledFormatStringQuery.qll | 26 +++++++++++++++++++ .../ExternallyControlledFormatString.ql | 19 +------------- 2 files changed, 27 insertions(+), 18 deletions(-) create mode 100644 java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll diff --git a/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll b/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll new file mode 100644 index 00000000000..64448b9012a --- /dev/null +++ b/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll @@ -0,0 +1,26 @@ +/** Provides a taint-tracking configuration to reason about externally controlled format string vulnerabilities. */ + +import java +import semmle.code.java.dataflow.FlowSources +import semmle.code.java.StringFormat + +/** + * A taint-tracking configuration for externally controlled format string vulnerabilities. + */ +module ExternallyControlledFormatStringConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { + sink.asExpr() = any(StringFormat formatCall).getFormatArgument() + } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof NumericType or node.getType() instanceof BooleanType + } +} + +/** + * Taint-tracking flow for externally controlled format string vulnerabilities. + */ +module ExternallyControlledFormatStringFlow = + TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql index a2d2e9005ef..1b6adf1ade7 100644 --- a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql +++ b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql @@ -11,24 +11,7 @@ */ import java -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.StringFormat - -module ExternallyControlledFormatStringConfig implements DataFlow::ConfigSig { - predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(StringFormat formatCall).getFormatArgument() - } - - predicate isBarrier(DataFlow::Node node) { - node.getType() instanceof NumericType or node.getType() instanceof BooleanType - } -} - -module ExternallyControlledFormatStringFlow = - TaintTracking::Global; - +import semmle.code.java.security.ExternallyControlledFormatStringQuery import ExternallyControlledFormatStringFlow::PathGraph from From e5f11d00a76414f821913e62dde810535b0fe627 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 16 Mar 2023 15:41:24 -0400 Subject: [PATCH 041/141] Refactor CWE-502/UnsafeDeserialization --- .../semmle/code/java/frameworks/JsonIo.qll | 35 +- .../security/UnsafeDeserializationQuery.qll | 347 ++++++++++++------ .../CWE/CWE-502/UnsafeDeserialization.ql | 6 +- .../security/CWE-502/UnsafeDeserialization.ql | 2 +- 4 files changed, 265 insertions(+), 125 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/JsonIo.qll b/java/ql/lib/semmle/code/java/frameworks/JsonIo.qll index ab4c1b115d9..aa332bd78ed 100644 --- a/java/ql/lib/semmle/code/java/frameworks/JsonIo.qll +++ b/java/ql/lib/semmle/code/java/frameworks/JsonIo.qll @@ -42,8 +42,12 @@ class JsonIoUseMapsSetter extends MethodAccess { } } -/** A data flow configuration tracing flow from JsonIo safe settings. */ -class SafeJsonIoConfig extends DataFlow2::Configuration { +/** + * DEPRECATED: Use `SafeJsonIoFlow` instead. + * + * A data flow configuration tracing flow from JsonIo safe settings. + */ +deprecated class SafeJsonIoConfig extends DataFlow2::Configuration { SafeJsonIoConfig() { this = "UnsafeDeserialization::SafeJsonIoConfig" } override predicate isSource(DataFlow::Node src) { @@ -65,3 +69,30 @@ class SafeJsonIoConfig extends DataFlow2::Configuration { ) } } + +/** + * A data flow configuration tracing flow from JsonIo safe settings. + */ +module SafeJsonIoConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + exists(MethodAccess ma | + ma instanceof JsonIoUseMapsSetter and + src.asExpr() = ma.getQualifier() + ) + } + + predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | + ma.getMethod() instanceof JsonIoJsonToJavaMethod and + sink.asExpr() = ma.getArgument(1) + ) + or + exists(ClassInstanceExpr cie | + cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and + sink.asExpr() = cie.getArgument(1) + ) + } +} + +/** Tracks flow from JsonIo safe settings. */ +module SafeJsonIoFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 6d0ff888d82..352c3b481a6 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -35,15 +35,13 @@ private class XmlDecoderReadObjectMethod extends Method { } } -private class SafeXStream extends DataFlow2::Configuration { - SafeXStream() { this = "UnsafeDeserialization::SafeXStream" } - - override predicate isSource(DataFlow::Node src) { +private module SafeXStreamConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { any(XStreamEnableWhiteListing ma).getQualifier().(VarAccess).getVariable().getAnAccess() = src.asExpr() } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getQualifier() and ma.getMethod() instanceof XStreamReadObjectMethod @@ -51,33 +49,33 @@ private class SafeXStream extends DataFlow2::Configuration { } } -private class SafeKryo extends DataFlow2::Configuration { - SafeKryo() { this = "UnsafeDeserialization::SafeKryo" } +private module SafeXStreamFlow = DataFlow::Global; - override predicate isSource(DataFlow::Node src) { +private module SafeKryoConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { any(KryoEnableWhiteListing ma).getQualifier().(VarAccess).getVariable().getAnAccess() = src.asExpr() } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getQualifier() and ma.getMethod() instanceof KryoReadObjectMethod ) } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { - this.stepKryoPoolBuilderFactoryArgToConstructor(node1, node2) or - this.stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(node1, node2) or - this.stepKryoPoolBuilderChainMethod(node1, node2) or - this.stepKryoPoolBorrowMethod(node1, node2) + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + stepKryoPoolBuilderFactoryArgToConstructor(node1, node2) or + stepKryoPoolRunMethodAccessQualifierToFunctionalArgument(node1, node2) or + stepKryoPoolBuilderChainMethod(node1, node2) or + stepKryoPoolBorrowMethod(node1, node2) } /** * Holds when a functional expression is used to create a `KryoPool.Builder`. * Eg. `new KryoPool.Builder(() -> new Kryo())` */ - private predicate stepKryoPoolBuilderFactoryArgToConstructor( + additional predicate stepKryoPoolBuilderFactoryArgToConstructor( DataFlow::Node node1, DataFlow::Node node2 ) { exists(ConstructorCall cc, FunctionalExpr fe | @@ -92,7 +90,7 @@ private class SafeKryo extends DataFlow2::Configuration { * Holds when a `KryoPool.run` is called to use a `Kryo` instance. * Eg. `pool.run(kryo -> ...)` */ - private predicate stepKryoPoolRunMethodAccessQualifierToFunctionalArgument( + additional predicate stepKryoPoolRunMethodAccessQualifierToFunctionalArgument( DataFlow::Node node1, DataFlow::Node node2 ) { exists(MethodAccess ma | @@ -105,7 +103,7 @@ private class SafeKryo extends DataFlow2::Configuration { /** * Holds when a `KryoPool.Builder` method is called fluently. */ - private predicate stepKryoPoolBuilderChainMethod(DataFlow::Node node1, DataFlow::Node node2) { + additional predicate stepKryoPoolBuilderChainMethod(DataFlow::Node node1, DataFlow::Node node2) { exists(MethodAccess ma | ma.getMethod() instanceof KryoPoolBuilderMethod and ma = node2.asExpr() and @@ -116,7 +114,7 @@ private class SafeKryo extends DataFlow2::Configuration { /** * Holds when a `KryoPool.borrow` method is called. */ - private predicate stepKryoPoolBorrowMethod(DataFlow::Node node1, DataFlow::Node node2) { + additional predicate stepKryoPoolBorrowMethod(DataFlow::Node node1, DataFlow::Node node2) { exists(MethodAccess ma | ma.getMethod() = any(Method m | m.getDeclaringType() instanceof KryoPool and m.hasName("borrow")) and @@ -126,6 +124,8 @@ private class SafeKryo extends DataFlow2::Configuration { } } +private module SafeKryoFlow = DataFlow::Global; + /** * Holds if `ma` is a call that deserializes data from `sink`. */ @@ -145,11 +145,11 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) { or m instanceof XStreamReadObjectMethod and sink = ma.getAnArgument() and - not exists(SafeXStream sxs | sxs.hasFlowToExpr(ma.getQualifier())) + not SafeXStreamFlow::flowToExpr(ma.getQualifier()) or m instanceof KryoReadObjectMethod and sink = ma.getAnArgument() and - not exists(SafeKryo sk | sk.hasFlowToExpr(ma.getQualifier())) + not SafeKryoFlow::flowToExpr(ma.getQualifier()) or m instanceof MethodApacheSerializationUtilsDeserialize and sink = ma.getArgument(0) @@ -181,17 +181,17 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) { ma.getMethod() instanceof ObjectMapperReadMethod and sink = ma.getArgument(0) and ( - exists(UnsafeTypeConfig config | config.hasFlowToExpr(ma.getAnArgument())) + UnsafeTypeFlow::flowToExpr(ma.getAnArgument()) or - exists(EnableJacksonDefaultTypingConfig config | config.hasFlowToExpr(ma.getQualifier())) + EnableJacksonDefaultTypingFlow::flowToExpr(ma.getQualifier()) or hasArgumentWithUnsafeJacksonAnnotation(ma) ) and - not exists(SafeObjectMapperConfig config | config.hasFlowToExpr(ma.getQualifier())) + not SafeObjectMapperFlow::flowToExpr(ma.getQualifier()) or m instanceof JabsorbUnmarshallMethod and sink = ma.getArgument(2) and - any(UnsafeTypeConfig config).hasFlowToExpr(ma.getArgument(1)) + UnsafeTypeFlow::flowToExpr(ma.getArgument(1)) or m instanceof JabsorbFromJsonMethod and sink = ma.getArgument(0) @@ -200,7 +200,7 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) { sink = ma.getArgument(0) and ( // User controls the target type for deserialization - any(UnsafeTypeConfig c).hasFlowToExpr(ma.getArgument(1)) + UnsafeTypeFlow::flowToExpr(ma.getArgument(1)) or // jodd.json.JsonParser may be configured for unrestricted deserialization to user-specified types joddJsonParserConfiguredUnsafely(ma.getQualifier()) @@ -211,7 +211,7 @@ predicate unsafeDeserialization(MethodAccess ma, Expr sink) { or m instanceof GsonDeserializeMethod and sink = ma.getArgument(0) and - any(UnsafeTypeConfig config).hasFlowToExpr(ma.getArgument(1)) + UnsafeTypeFlow::flowToExpr(ma.getArgument(1)) ) } @@ -223,17 +223,53 @@ class UnsafeDeserializationSink extends DataFlow::ExprNode { MethodAccess getMethodAccess() { unsafeDeserialization(result, this.getExpr()) } } -/** - * Tracks flows from remote user input to a deserialization sink. - */ -class UnsafeDeserializationConfig extends TaintTracking::Configuration { - UnsafeDeserializationConfig() { this = "UnsafeDeserializationConfig" } +/** A sanitizer for unsafe deserialization */ +private class UnsafeDeserializationSanitizer extends DataFlow::Node { + UnsafeDeserializationSanitizer() { + exists(ClassInstanceExpr cie | + cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and + cie = this.asExpr() and + SafeJsonIoFlow::flowToExpr(cie.getArgument(1)) + ) + or + exists(MethodAccess ma | + ma.getMethod() instanceof JsonIoJsonToJavaMethod and + ma.getArgument(0) = this.asExpr() and + SafeJsonIoFlow::flowToExpr(ma.getArgument(1)) + ) + or + exists(MethodAccess ma | + // Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears + // to be called with an explicit class argument limiting those types that can + // be instantiated during deserialization. + ma.getMethod() instanceof JoddJsonParseMethod and + ma.getArgument(1).getType() instanceof TypeClass and + not ma.getArgument(1) instanceof NullLiteral and + not ma.getArgument(1).getType().getName() = ["Class", "Class"] and + this.asExpr() = ma.getAnArgument() + ) + or + exists(MethodAccess ma | + // Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears + // to be called with an explicit class argument limiting those types that can + // be instantiated during deserialization, or if the deserializer has already been + // configured to use a specified root class. + ma.getMethod() instanceof FlexjsonDeserializeMethod and + this.asExpr() = ma.getAnArgument() and + ( + ma.getArgument(1).getType() instanceof TypeClass and + not ma.getArgument(1) instanceof NullLiteral and + not ma.getArgument(1).getType().getName() = ["Class", "Class"] + or + isSafeFlexjsonDeserializer(ma.getQualifier()) + ) + ) + } +} - override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink } - - override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { +/** Taint step for Unsafe deserialization */ +private class UnsafeDeserializationAdditionalTaintStep extends Unit { + predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { exists(ClassInstanceExpr cie | cie.getArgument(0) = pred.asExpr() and cie = succ.asExpr() and @@ -257,49 +293,44 @@ class UnsafeDeserializationConfig extends TaintTracking::Configuration { or intentFlowsToParcel(pred, succ) } +} + +/** + * DEPRECATED: Use `UnsafeDeserializationFlow` instead. + * + * Tracks flows from remote user input to a deserialization sink. + */ +deprecated class UnsafeDeserializationConfig extends TaintTracking::Configuration { + UnsafeDeserializationConfig() { this = "UnsafeDeserializationConfig" } + + override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink } + + override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + any(UnsafeDeserializationAdditionalTaintStep s).isAdditionalTaintStep(pred, succ) + } override predicate isSanitizer(DataFlow::Node node) { - exists(ClassInstanceExpr cie | - cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and - cie = node.asExpr() and - exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(cie.getArgument(1))) - ) - or - exists(MethodAccess ma | - ma.getMethod() instanceof JsonIoJsonToJavaMethod and - ma.getArgument(0) = node.asExpr() and - exists(SafeJsonIoConfig sji | sji.hasFlowToExpr(ma.getArgument(1))) - ) - or - exists(MethodAccess ma | - // Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears - // to be called with an explicit class argument limiting those types that can - // be instantiated during deserialization. - ma.getMethod() instanceof JoddJsonParseMethod and - ma.getArgument(1).getType() instanceof TypeClass and - not ma.getArgument(1) instanceof NullLiteral and - not ma.getArgument(1).getType().getName() = ["Class", "Class"] and - node.asExpr() = ma.getAnArgument() - ) - or - exists(MethodAccess ma | - // Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears - // to be called with an explicit class argument limiting those types that can - // be instantiated during deserialization, or if the deserializer has already been - // configured to use a specified root class. - ma.getMethod() instanceof FlexjsonDeserializeMethod and - node.asExpr() = ma.getAnArgument() and - ( - ma.getArgument(1).getType() instanceof TypeClass and - not ma.getArgument(1) instanceof NullLiteral and - not ma.getArgument(1).getType().getName() = ["Class", "Class"] - or - isSafeFlexjsonDeserializer(ma.getQualifier()) - ) - ) + node instanceof UnsafeDeserializationSanitizer } } +/** Tracks flows from remote user input to a deserialization sink. */ +private module UnsafeDeserializationConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink } + + predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { + any(UnsafeDeserializationAdditionalTaintStep s).isAdditionalTaintStep(pred, succ) + } + + predicate isBarrier(DataFlow::Node node) { node instanceof UnsafeDeserializationSanitizer } +} + +module UnsafeDeserializationFlow = TaintTracking::Global; + /** * Gets a safe usage of the `use` method of Flexjson, which could be: * use(String, ...) where the path is null or @@ -350,18 +381,9 @@ predicate looksLikeResolveClassStep(DataFlow::Node fromNode, DataFlow::Node toNo ) } -/** - * Tracks flow from a remote source to a type descriptor (e.g. a `java.lang.Class` instance) - * passed to a deserialization method. - * - * If this is user-controlled, arbitrary code could be executed while instantiating the user-specified type. - */ -class UnsafeTypeConfig extends TaintTracking2::Configuration { - UnsafeTypeConfig() { this = "UnsafeTypeConfig" } - - override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } - - override predicate isSink(DataFlow::Node sink) { +/** A sink representing an argument of a deserialization method */ +private class UnsafeTypeSink extends DataFlow::Node { + UnsafeTypeSink() { exists(MethodAccess ma, int i, Expr arg | i > 0 and ma.getArgument(i) = arg | ( ma.getMethod() instanceof ObjectMapperReadMethod @@ -378,15 +400,13 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration { or arg.getType().(RefType).hasQualifiedName("java.lang.reflect", "Type") ) and - arg = sink.asExpr() + arg = this.asExpr() ) } +} - /** - * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class - * or at least looks like resolving a class. - */ - override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { +private class UnsafeTypeAdditionalTaintStep extends Unit { + predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { resolveClassStep(fromNode, toNode) or looksLikeResolveClassStep(fromNode, toNode) or intentFlowsToParcel(fromNode, toNode) @@ -394,9 +414,57 @@ class UnsafeTypeConfig extends TaintTracking2::Configuration { } /** + * DEPRECATED: Use `UnsafeTypeFlow` instead. + * + * Tracks flow from a remote source to a type descriptor (e.g. a `java.lang.Class` instance) + * passed to a deserialization method. + * + * If this is user-controlled, arbitrary code could be executed while instantiating the user-specified type. + */ +deprecated class UnsafeTypeConfig extends TaintTracking2::Configuration { + UnsafeTypeConfig() { this = "UnsafeTypeConfig" } + + override predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } + + override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeTypeSink } + + /** + * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class + * or at least looks like resolving a class. + */ + override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + any(UnsafeTypeAdditionalTaintStep s).isAdditionalTaintStep(fromNode, toNode) + } +} + +private module UnsafeTypeConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeTypeSink } + + /** + * Holds if `fromNode` to `toNode` is a dataflow step that resolves a class + * or at least looks like resolving a class. + */ + predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + any(UnsafeTypeAdditionalTaintStep s).isAdditionalTaintStep(fromNode, toNode) + } +} + +/** + * Tracks flow from a remote source to a type descriptor (e.g. a `java.lang.Class` instance) + * passed to a deserialization method. + * + * If this is user-controlled, arbitrary code could be executed while instantiating the user-specified type. + */ +module UnsafeTypeFlow = TaintTracking::Global; + +/** + * DEPRECATED: Use `EnableJacksonDefaultTypingFlow` instead. + * * Tracks flow from `enableDefaultTyping` calls to a subsequent Jackson deserialization method call. */ -class EnableJacksonDefaultTypingConfig extends DataFlow2::Configuration { +deprecated class EnableJacksonDefaultTypingConfig extends DataFlow2::Configuration { EnableJacksonDefaultTypingConfig() { this = "EnableJacksonDefaultTypingConfig" } override predicate isSource(DataFlow::Node src) { @@ -406,13 +474,43 @@ class EnableJacksonDefaultTypingConfig extends DataFlow2::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof ObjectMapperReadQualifier } } +private module EnableJacksonDefaultTypingConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { + any(EnableJacksonDefaultTyping ma).getQualifier() = src.asExpr() + } + + predicate isSink(DataFlow::Node sink) { sink instanceof ObjectMapperReadQualifier } +} + /** + * Tracks flow from `enableDefaultTyping` calls to a subsequent Jackson deserialization method call. + */ +module EnableJacksonDefaultTypingFlow = DataFlow::Global; + +/** Dataflow step that creates an `ObjectMapper` via a builder. */ +private class ObjectMapperBuilderAdditionalFlowStep extends Unit { + predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + exists(MethodAccess ma, Method m | m = ma.getMethod() | + m.getDeclaringType() instanceof MapperBuilder and + m.getReturnType() + .(RefType) + .hasQualifiedName("com.fasterxml.jackson.databind.json", + ["JsonMapper$Builder", "JsonMapper"]) and + fromNode.asExpr() = ma.getQualifier() and + ma = toNode.asExpr() + ) + } +} + +/** + * DEPRECATED: Use `SafeObjectMapperFlow` instead. + * * Tracks flow from calls that set a type validator to a subsequent Jackson deserialization method call, * including across builder method calls. * * Such a Jackson deserialization method call is safe because validation will likely prevent instantiating unexpected types. */ -class SafeObjectMapperConfig extends DataFlow2::Configuration { +deprecated class SafeObjectMapperConfig extends DataFlow2::Configuration { SafeObjectMapperConfig() { this = "SafeObjectMapperConfig" } override predicate isSource(DataFlow::Node src) { @@ -426,18 +524,32 @@ class SafeObjectMapperConfig extends DataFlow2::Configuration { * that configures or creates an `ObjectMapper` via a builder. */ override predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - exists(MethodAccess ma, Method m | m = ma.getMethod() | - m.getDeclaringType() instanceof MapperBuilder and - m.getReturnType() - .(RefType) - .hasQualifiedName("com.fasterxml.jackson.databind.json", - ["JsonMapper$Builder", "JsonMapper"]) and - fromNode.asExpr() = ma.getQualifier() and - ma = toNode.asExpr() - ) + any(ObjectMapperBuilderAdditionalFlowStep s).isAdditionalFlowStep(fromNode, toNode) } } +private module SafeObjectMapperConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof SetPolymorphicTypeValidatorSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof ObjectMapperReadQualifier } + + /** + * Holds if `fromNode` to `toNode` is a dataflow step + * that configures or creates an `ObjectMapper` via a builder. + */ + predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + any(ObjectMapperBuilderAdditionalFlowStep s).isAdditionalFlowStep(fromNode, toNode) + } +} + +/** + * Tracks flow from calls that set a type validator to a subsequent Jackson deserialization method call, + * including across builder method calls. + * + * Such a Jackson deserialization method call is safe because validation will likely prevent instantiating unexpected types. + */ +module SafeObjectMapperFlow = DataFlow::Global; + /** * A method that configures Jodd's JsonParser, either enabling dangerous deserialization to * arbitrary Java types or restricting the types that can be instantiated. @@ -454,20 +566,12 @@ private class JoddJsonParserConfigurationMethodQualifier extends DataFlow::ExprN } } -/** - * Configuration tracking flow from methods that configure `jodd.json.JsonParser`'s class - * instantiation feature to a `.parse` call on the same parser. - */ -private class JoddJsonParserConfigurationMethodConfig extends DataFlow2::Configuration { - JoddJsonParserConfigurationMethodConfig() { - this = "UnsafeDeserialization::JoddJsonParserConfigurationMethodConfig" - } - - override predicate isSource(DataFlow::Node src) { +private module JoddJsonParserConfigurationMethodConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof JoddJsonParserConfigurationMethodQualifier } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | ma.getMethod() instanceof JoddJsonParseMethod and sink.asExpr() = ma.getQualifier() // The class type argument @@ -475,6 +579,13 @@ private class JoddJsonParserConfigurationMethodConfig extends DataFlow2::Configu } } +/** + * Configuration tracking flow from methods that configure `jodd.json.JsonParser`'s class + * instantiation feature to a `.parse` call on the same parser. + */ +private module JoddJsonParserConfigurationMethodFlow = + DataFlow::Global; + /** * Gets the qualifier to a method call that configures a `jodd.json.JsonParser` instance unsafely. * @@ -512,10 +623,8 @@ private DataFlow::Node getASafelyConfiguredParser() { * and which never appears to be configured safely. */ private predicate joddJsonParserConfiguredUnsafely(Expr parserExpr) { - exists(DataFlow::Node parser, JoddJsonParserConfigurationMethodConfig config | - parser.asExpr() = parserExpr - | - config.hasFlow(getAnUnsafelyConfiguredParser(), parser) and - not config.hasFlow(getASafelyConfiguredParser(), parser) + exists(DataFlow::Node parser | parser.asExpr() = parserExpr | + JoddJsonParserConfigurationMethodFlow::flow(getAnUnsafelyConfiguredParser(), parser) and + not JoddJsonParserConfigurationMethodFlow::flow(getASafelyConfiguredParser(), parser) ) } diff --git a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql index d494d92e657..1c5660653a6 100644 --- a/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql +++ b/java/ql/src/Security/CWE/CWE-502/UnsafeDeserialization.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.UnsafeDeserializationQuery -import DataFlow::PathGraph +import UnsafeDeserializationFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, UnsafeDeserializationConfig conf -where conf.hasFlowPath(source, sink) +from UnsafeDeserializationFlow::PathNode source, UnsafeDeserializationFlow::PathNode sink +where UnsafeDeserializationFlow::flowPath(source, sink) select sink.getNode().(UnsafeDeserializationSink).getMethodAccess(), source, sink, "Unsafe deserialization depends on a $@.", source.getNode(), "user-provided value" diff --git a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ql b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ql index a2ba654a540..4d10c798e33 100644 --- a/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ql +++ b/java/ql/test/query-tests/security/CWE-502/UnsafeDeserialization.ql @@ -9,7 +9,7 @@ class UnsafeDeserializationTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "unsafeDeserialization" and - exists(DataFlow::Node sink, UnsafeDeserializationConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | UnsafeDeserializationFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From 6681c1a3a858d9d4313218743b5c3c0ec45f065c Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 16 Mar 2023 15:54:07 -0400 Subject: [PATCH 042/141] Refactor SnakeYaml.qll --- .../semmle/code/java/frameworks/SnakeYaml.qll | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll b/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll index 3ea5d79c138..f0ade403bfc 100644 --- a/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll +++ b/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll @@ -4,8 +4,6 @@ import java import semmle.code.java.dataflow.DataFlow -import semmle.code.java.dataflow.DataFlow2 -import semmle.code.java.dataflow.DataFlow3 /** * The class `org.yaml.snakeyaml.constructor.SafeConstructor`. @@ -30,28 +28,28 @@ class Yaml extends RefType { Yaml() { this.getAnAncestor().hasQualifiedName("org.yaml.snakeyaml", "Yaml") } } -private class SafeYamlConstructionFlowConfig extends DataFlow3::Configuration { - SafeYamlConstructionFlowConfig() { this = "SnakeYaml::SafeYamlConstructionFlowConfig" } +private module SafeYamlConstructionFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSnakeYamlConstruction } - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof SafeSnakeYamlConstruction - } + predicate isSink(DataFlow::Node sink) { sink = yamlClassInstanceExprArgument(_) } - override predicate isSink(DataFlow::Node sink) { sink = this.yamlClassInstanceExprArgument(_) } - - private DataFlow::ExprNode yamlClassInstanceExprArgument(ClassInstanceExpr cie) { + additional DataFlow::ExprNode yamlClassInstanceExprArgument(ClassInstanceExpr cie) { cie.getConstructedType() instanceof Yaml and result.getExpr() = cie.getArgument(0) } - ClassInstanceExpr getSafeYaml() { this.hasFlowTo(this.yamlClassInstanceExprArgument(result)) } + additional ClassInstanceExpr getSafeYaml() { + SafeYamlConstructionFlow::flowTo(yamlClassInstanceExprArgument(result)) + } } +private module SafeYamlConstructionFlow = DataFlow::Global; + /** * An instance of `Yaml` that does not allow arbitrary constructor to be called. */ private class SafeYaml extends ClassInstanceExpr { - SafeYaml() { exists(SafeYamlConstructionFlowConfig conf | conf.getSafeYaml() = this) } + SafeYaml() { SafeYamlConstructionFlowConfig::getSafeYaml() = this } } /** A call to a parse method of `Yaml`. */ @@ -65,23 +63,25 @@ private class SnakeYamlParse extends MethodAccess { } } -private class SafeYamlFlowConfig extends DataFlow2::Configuration { - SafeYamlFlowConfig() { this = "SnakeYaml::SafeYamlFlowConfig" } +private module SafeYamlFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeYaml } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeYaml } + predicate isSink(DataFlow::Node sink) { sink = yamlParseQualifier(_) } - override predicate isSink(DataFlow::Node sink) { sink = this.yamlParseQualifier(_) } - - private DataFlow::ExprNode yamlParseQualifier(SnakeYamlParse syp) { + additional DataFlow::ExprNode yamlParseQualifier(SnakeYamlParse syp) { result.getExpr() = syp.getQualifier() } - SnakeYamlParse getASafeSnakeYamlParse() { this.hasFlowTo(this.yamlParseQualifier(result)) } + additional SnakeYamlParse getASafeSnakeYamlParse() { + SafeYamlFlow::flowTo(yamlParseQualifier(result)) + } } +private module SafeYamlFlow = DataFlow::Global; + /** * A call to a parse method of `Yaml` that allows arbitrary constructor to be called. */ class UnsafeSnakeYamlParse extends SnakeYamlParse { - UnsafeSnakeYamlParse() { not exists(SafeYamlFlowConfig sy | sy.getASafeSnakeYamlParse() = this) } + UnsafeSnakeYamlParse() { not SafeYamlFlowConfig::getASafeSnakeYamlParse() = this } } From b4130e650dba3cdc6cf845403118bcbd76433e46 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 16 Mar 2023 21:46:55 -0400 Subject: [PATCH 043/141] Refactor RegexFlowConfigs.qll --- .../code/java/regex/RegexFlowConfigs.qll | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/regex/RegexFlowConfigs.qll b/java/ql/lib/semmle/code/java/regex/RegexFlowConfigs.qll index 5a913ccdef8..f517d6dec64 100644 --- a/java/ql/lib/semmle/code/java/regex/RegexFlowConfigs.qll +++ b/java/ql/lib/semmle/code/java/regex/RegexFlowConfigs.qll @@ -136,24 +136,22 @@ private class GuavaRegexFlowStep extends RegexAdditionalFlowStep { } } -private class RegexFlowConf extends DataFlow2::Configuration { - RegexFlowConf() { this = "RegexFlowConfig" } +private module RegexFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node.asExpr() instanceof ExploitableStringLiteral } - override predicate isSource(DataFlow::Node node) { - node.asExpr() instanceof ExploitableStringLiteral - } + predicate isSink(DataFlow::Node node) { node instanceof RegexFlowSink } - override predicate isSink(DataFlow::Node node) { node instanceof RegexFlowSink } - - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { any(RegexAdditionalFlowStep s).step(node1, node2) } - override predicate isBarrier(DataFlow::Node node) { + predicate isBarrier(DataFlow::Node node) { node.getEnclosingCallable().getDeclaringType() instanceof NonSecurityTestClass } } +private module RegexFlow = DataFlow::Global; + /** * Holds if `regex` is used as a regex, with the mode `mode` (if known). * If regex mode is not known, `mode` will be `"None"`. @@ -162,7 +160,7 @@ private class RegexFlowConf extends DataFlow2::Configuration { * and therefore may be relevant for ReDoS queries are considered. */ predicate usedAsRegex(StringLiteral regex, string mode, boolean match_full_string) { - any(RegexFlowConf c).hasFlow(DataFlow2::exprNode(regex), _) and + RegexFlow::flow(DataFlow::exprNode(regex), _) and mode = "None" and // TODO: proper mode detection (if matchesFullString(regex) then match_full_string = true else match_full_string = false) } @@ -172,9 +170,9 @@ predicate usedAsRegex(StringLiteral regex, string mode, boolean match_full_strin * as though it was implicitly surrounded by ^ and $. */ private predicate matchesFullString(StringLiteral regex) { - exists(RegexFlowConf c, RegexFlowSink sink | + exists(RegexFlowSink sink | sink.matchesFullString() and - c.hasFlow(DataFlow2::exprNode(regex), sink) + RegexFlow::flow(DataFlow::exprNode(regex), sink) ) } @@ -185,8 +183,8 @@ private predicate matchesFullString(StringLiteral regex) { * and therefore may be relevant for ReDoS queries are considered. */ predicate regexMatchedAgainst(StringLiteral regex, Expr str) { - exists(RegexFlowConf c, RegexFlowSink sink | + exists(RegexFlowSink sink | str = sink.getStringArgument() and - c.hasFlow(DataFlow2::exprNode(regex), sink) + RegexFlow::flow(DataFlow::exprNode(regex), sink) ) } From aa7934161aacf31869d6ecfa6e17ac6dc0b774e8 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Sun, 19 Mar 2023 23:24:35 -0400 Subject: [PATCH 044/141] Refactor CleartextStorage libraries --- .../CleartextStorageAndroidDatabaseQuery.qll | 20 +++++------ ...CleartextStorageAndroidFilesystemQuery.qll | 20 +++++------ .../security/CleartextStorageClassQuery.qll | 24 ++++++------- .../security/CleartextStorageCookieQuery.qll | 14 ++++---- .../CleartextStoragePropertiesQuery.qll | 18 +++++----- .../java/security/CleartextStorageQuery.qll | 34 ++++++++----------- .../CleartextStorageSharedPrefsQuery.qll | 18 +++++----- 7 files changed, 71 insertions(+), 77 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidDatabaseQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidDatabaseQuery.qll index 7edd9e74c50..d995d11ce5b 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidDatabaseQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidDatabaseQuery.qll @@ -29,16 +29,16 @@ class LocalDatabaseOpenMethodAccess extends Storable, Call { } override Expr getAnInput() { - exists(LocalDatabaseFlowConfig config, DataFlow::Node database | + exists(DataFlow::Node database | localDatabaseInput(database, result) and - config.hasFlow(DataFlow::exprNode(this), database) + LocalDatabaseFlow::flow(DataFlow::exprNode(this), database) ) } override Expr getAStore() { - exists(LocalDatabaseFlowConfig config, DataFlow::Node database | + exists(DataFlow::Node database | localDatabaseStore(database, result) and - config.hasFlow(DataFlow::exprNode(this), database) + LocalDatabaseFlow::flow(DataFlow::exprNode(this), database) ) } } @@ -93,19 +93,17 @@ private predicate localDatabaseStore(DataFlow::Node database, MethodAccess store ) } -private class LocalDatabaseFlowConfig extends DataFlow::Configuration { - LocalDatabaseFlowConfig() { this = "LocalDatabaseFlowConfig" } - - override predicate isSource(DataFlow::Node source) { +private module LocalDatabaseFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof LocalDatabaseOpenMethodAccess } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { localDatabaseInput(sink, _) or localDatabaseStore(sink, _) } - override predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { // Adds a step for tracking databases through field flow, that is, a database is opened and // assigned to a field, and then an input or store method is called on that field elsewhere. exists(Field f | @@ -115,3 +113,5 @@ private class LocalDatabaseFlowConfig extends DataFlow::Configuration { ) } } + +private module LocalDatabaseFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidFilesystemQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidFilesystemQuery.qll index 89cc7ac021b..2641a3ab0df 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidFilesystemQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageAndroidFilesystemQuery.qll @@ -24,16 +24,16 @@ class LocalFileOpenCall extends Storable { } override Expr getAnInput() { - exists(FilesystemFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | filesystemInput(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + FilesystemFlow::flow(DataFlow::exprNode(this), n) ) } override Expr getAStore() { - exists(FilesystemFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | closesFile(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + FilesystemFlow::flow(DataFlow::exprNode(this), n) ) } } @@ -79,17 +79,15 @@ private class CloseFileMethod extends Method { } } -private class FilesystemFlowConfig extends DataFlow::Configuration { - FilesystemFlowConfig() { this = "FilesystemFlowConfig" } +private module FilesystemFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof LocalFileOpenCall } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { filesystemInput(sink, _) or closesFile(sink, _) } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { // Add nested Writer constructors as extra data flow steps exists(ClassInstanceExpr cie | cie.getConstructedType().getAnAncestor().hasQualifiedName("java.io", "Writer") and @@ -98,3 +96,5 @@ private class FilesystemFlowConfig extends DataFlow::Configuration { ) } } + +private module FilesystemFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll index 3fe06a2de08..41e5c060816 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageClassQuery.qll @@ -14,8 +14,8 @@ private class ClassCleartextStorageSink extends CleartextStorageSink { abstract class ClassStore extends Storable, ClassInstanceExpr { /** Gets an input, for example `input` in `instance.password = input`. */ override Expr getAnInput() { - exists(ClassStoreFlowConfig conf, DataFlow::Node instance | - conf.hasFlow(DataFlow::exprNode(this), instance) and + exists(DataFlow::Node instance | + ClassStoreFlow::flow(DataFlow::exprNode(this), instance) and result = getInstanceInput(instance, this.getConstructor().getDeclaringType()) ) } @@ -40,9 +40,9 @@ private class Serializable extends ClassStore { /** Gets a store, for example `outputStream.writeObject(instance)`. */ override Expr getAStore() { - exists(ClassStoreFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | serializableStore(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + ClassStoreFlow::flow(DataFlow::exprNode(this), n) ) } } @@ -53,9 +53,9 @@ private class Marshallable extends ClassStore { /** Gets a store, for example `marshaller.marshal(instance)`. */ override Expr getAStore() { - exists(ClassStoreFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | marshallableStore(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + ClassStoreFlow::flow(DataFlow::exprNode(this), n) ) } } @@ -73,20 +73,20 @@ private Expr getInstanceInput(DataFlow::Node instance, RefType t) { ) } -private class ClassStoreFlowConfig extends DataFlow::Configuration { - ClassStoreFlowConfig() { this = "ClassStoreFlowConfig" } +private module ClassStoreFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ClassStore } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ClassStore } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(getInstanceInput(sink, _)) or serializableStore(sink, _) or marshallableStore(sink, _) } - override int fieldFlowBranchLimit() { result = 1 } + int fieldFlowBranchLimit() { result = 1 } } +private module ClassStoreFlow = DataFlow::Global; + private predicate serializableStore(DataFlow::Node instance, Expr store) { exists(MethodAccess m | store = m and diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll index bd071e7fef6..59c098281f1 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageCookieQuery.qll @@ -20,9 +20,9 @@ class Cookie extends Storable, ClassInstanceExpr { /** Gets a store, for example `response.addCookie(cookie);`. */ override Expr getAStore() { - exists(CookieToStoreFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | cookieStore(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + CookieToStoreFlow::flow(DataFlow::exprNode(this), n) ) } } @@ -37,12 +37,12 @@ private predicate cookieStore(DataFlow::Node cookie, Expr store) { ) } -private class CookieToStoreFlowConfig extends DataFlow3::Configuration { - CookieToStoreFlowConfig() { this = "CookieToStoreFlowConfig" } +private module CookieToStoreFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Cookie } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Cookie } - - override predicate isSink(DataFlow::Node sink) { cookieStore(sink, _) } + predicate isSink(DataFlow::Node sink) { cookieStore(sink, _) } } +private module CookieToStoreFlow = DataFlow::Global; + private Expr cookieInput(Cookie c) { result = c.getArgument(1) } diff --git a/java/ql/lib/semmle/code/java/security/CleartextStoragePropertiesQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStoragePropertiesQuery.qll index c75689c1fd2..f262104078e 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStoragePropertiesQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStoragePropertiesQuery.qll @@ -19,17 +19,17 @@ class Properties extends Storable, ClassInstanceExpr { /** Gets an input, for example `input` in `props.setProperty("password", input);`. */ override Expr getAnInput() { - exists(PropertiesFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | propertiesInput(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + PropertiesFlow::flow(DataFlow::exprNode(this), n) ) } /** Gets a store, for example `props.store(outputStream, "...")`. */ override Expr getAStore() { - exists(PropertiesFlowConfig conf, DataFlow::Node n | + exists(DataFlow::Node n | propertiesStore(n, result) and - conf.hasFlow(DataFlow::exprNode(this), n) + PropertiesFlow::flow(DataFlow::exprNode(this), n) ) } } @@ -50,13 +50,13 @@ private predicate propertiesStore(DataFlow::Node prop, Expr store) { ) } -private class PropertiesFlowConfig extends DataFlow::Configuration { - PropertiesFlowConfig() { this = "PropertiesFlowConfig" } +private module PropertiesFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Properties } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof Properties } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { propertiesInput(sink, _) or propertiesStore(sink, _) } } + +private module PropertiesFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll index 8bd14b63ea6..fa19a25f110 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll @@ -21,9 +21,7 @@ class CleartextStorageAdditionalTaintStep extends Unit { class SensitiveSource extends Expr instanceof SensitiveExpr { /** Holds if this source flows to the `sink`. */ predicate flowsTo(Expr sink) { - exists(SensitiveSourceFlowConfig conf | - conf.hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) - ) + SensitiveSourceFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) } } @@ -40,27 +38,25 @@ abstract class Storable extends Call { abstract Expr getAStore(); } -private class SensitiveSourceFlowConfig extends TaintTracking2::Configuration { - SensitiveSourceFlowConfig() { this = "SensitiveSourceFlowConfig" } +private module SensitiveSourceFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SensitiveExpr } + predicate isSink(DataFlow::Node sink) { sink instanceof CleartextStorageSink } - override predicate isSink(DataFlow::Node sink) { sink instanceof CleartextStorageSink } + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof CleartextStorageSanitizer } - override predicate isSanitizer(DataFlow::Node sanitizer) { - sanitizer instanceof CleartextStorageSanitizer - } - - override predicate isAdditionalTaintStep(DataFlow::Node n1, DataFlow::Node n2) { + predicate isAdditionalFlowStep(DataFlow::Node n1, DataFlow::Node n2) { any(CleartextStorageAdditionalTaintStep c).step(n1, n2) } } +private module SensitiveSourceFlow = TaintTracking::Global; + private class DefaultCleartextStorageSanitizer extends CleartextStorageSanitizer { DefaultCleartextStorageSanitizer() { this.getType() instanceof NumericType or this.getType() instanceof BooleanType or - exists(EncryptedValueFlowConfig conf | conf.hasFlow(_, this)) + EncryptedValueFlow::flow(_, this) } } @@ -76,12 +72,10 @@ private class EncryptedSensitiveMethodAccess extends MethodAccess { } /** Flow configuration for encryption methods flowing to inputs of persistent storage. */ -private class EncryptedValueFlowConfig extends DataFlow4::Configuration { - EncryptedValueFlowConfig() { this = "EncryptedValueFlowConfig" } +private module EncryptedValueFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof EncryptedSensitiveMethodAccess } - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof EncryptedSensitiveMethodAccess - } - - override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SensitiveExpr } + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SensitiveExpr } } + +private module EncryptedValueFlow = DataFlow::Global; diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageSharedPrefsQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageSharedPrefsQuery.qll index e67a2d1aa21..07764a251f7 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageSharedPrefsQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageSharedPrefsQuery.qll @@ -28,17 +28,17 @@ class SharedPreferencesEditorMethodAccess extends Storable, MethodAccess { /** Gets an input, for example `password` in `editor.putString("password", password);`. */ override Expr getAnInput() { - exists(SharedPreferencesFlowConfig conf, DataFlow::Node editor | + exists(DataFlow::Node editor | sharedPreferencesInput(editor, result) and - conf.hasFlow(DataFlow::exprNode(this), editor) + SharedPreferencesFlow::flow(DataFlow::exprNode(this), editor) ) } /** Gets a store, for example `editor.commit();`. */ override Expr getAStore() { - exists(SharedPreferencesFlowConfig conf, DataFlow::Node editor | + exists(DataFlow::Node editor | sharedPreferencesStore(editor, result) and - conf.hasFlow(DataFlow::exprNode(this), editor) + SharedPreferencesFlow::flow(DataFlow::exprNode(this), editor) ) } } @@ -65,15 +65,15 @@ private predicate sharedPreferencesStore(DataFlow::Node editor, MethodAccess m) } /** Flow from `SharedPreferences.Editor` to either a setter or a store method. */ -private class SharedPreferencesFlowConfig extends DataFlow::Configuration { - SharedPreferencesFlowConfig() { this = "SharedPreferencesFlowConfig" } - - override predicate isSource(DataFlow::Node src) { +private module SharedPreferencesFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SharedPreferencesEditorMethodAccess } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sharedPreferencesInput(sink, _) or sharedPreferencesStore(sink, _) } } + +private module SharedPreferencesFlow = DataFlow::Global; From a040ff699789cae7bde15f73ef6d98a427608b89 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Sun, 19 Mar 2023 23:41:21 -0400 Subject: [PATCH 045/141] Refactor ConditionalBypass --- .../java/security/ConditionalBypassQuery.qll | 19 ++++++++++++++++++- .../Security/CWE/CWE-807/ConditionalBypass.ql | 8 ++++---- .../semmle/tests/ConditionalBypassTest.ql | 2 +- 3 files changed, 23 insertions(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll b/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll index 9bff32eac02..eb5d6672ae3 100644 --- a/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll @@ -37,9 +37,11 @@ private predicate endsWithStep(DataFlow::Node node1, DataFlow::Node node2) { } /** + * DEPRECATED: Use `ConditionalBypassFlow` instead. + * * A taint tracking configuration for untrusted data flowing to sensitive conditions. */ -class ConditionalBypassFlowConfig extends TaintTracking::Configuration { +deprecated class ConditionalBypassFlowConfig extends TaintTracking::Configuration { ConditionalBypassFlowConfig() { this = "ConditionalBypassFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -50,3 +52,18 @@ class ConditionalBypassFlowConfig extends TaintTracking::Configuration { endsWithStep(node1, node2) } } + +module ConditionalBypassFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { conditionControlsMethod(_, sink.asExpr()) } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + endsWithStep(node1, node2) + } +} + +/** + * A taint tracking configuration for untrusted data flowing to sensitive conditions. + */ +module ConditionalBypassFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql b/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql index 3cfa2079685..d012ae33810 100644 --- a/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql +++ b/java/ql/src/Security/CWE/CWE-807/ConditionalBypass.ql @@ -15,15 +15,15 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.security.ConditionalBypassQuery -import DataFlow::PathGraph +import ConditionalBypassFlow::PathGraph from - DataFlow::PathNode source, DataFlow::PathNode sink, MethodAccess m, Expr e, - ConditionalBypassFlowConfig conf + ConditionalBypassFlow::PathNode source, ConditionalBypassFlow::PathNode sink, MethodAccess m, + Expr e where conditionControlsMethod(m, e) and sink.getNode().asExpr() = e and - conf.hasFlowPath(source, sink) + ConditionalBypassFlow::flowPath(source, sink) select m, source, sink, "Sensitive method may not be executed depending on a $@, which flows from $@.", e, "this condition", source.getNode(), "user-controlled value" diff --git a/java/ql/test/query-tests/security/CWE-807/semmle/tests/ConditionalBypassTest.ql b/java/ql/test/query-tests/security/CWE-807/semmle/tests/ConditionalBypassTest.ql index ef676d4a8f0..20ca408f1b2 100644 --- a/java/ql/test/query-tests/security/CWE-807/semmle/tests/ConditionalBypassTest.ql +++ b/java/ql/test/query-tests/security/CWE-807/semmle/tests/ConditionalBypassTest.ql @@ -9,7 +9,7 @@ class ConditionalBypassTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasConditionalBypassTest" and - exists(DataFlow::Node sink, ConditionalBypassFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | ConditionalBypassFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From ac8dec740a38a5c2502337652f0c109d37d06fd9 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 20 Mar 2023 07:35:20 -0400 Subject: [PATCH 046/141] Refactor UnsafeCertTrustQuery --- .../java/security/UnsafeCertTrustQuery.qll | 28 +++++++++++++------ .../Security/CWE/CWE-273/UnsafeCertTrust.ql | 4 +-- .../security/CWE-273/UnsafeCertTrustTest.ql | 4 +-- 3 files changed, 22 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll index ee87fdc64ee..979c0c9c149 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -6,9 +6,11 @@ import semmle.code.java.security.UnsafeCertTrust import semmle.code.java.security.Encryption /** + * DEPRECATED: Use `SslEndpointIdentificationFlow` instead. + * * A taint flow configuration for SSL connections created without a proper certificate trust configuration. */ -class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { +deprecated class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { SslEndpointIdentificationFlowConfig() { this = "SslEndpointIdentificationFlowConfig" } override predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } @@ -20,30 +22,38 @@ class SslEndpointIdentificationFlowConfig extends TaintTracking::Configuration { } } +private module SslEndpointIdentificationFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } + + predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SslUnsafeCertTrustSanitizer } +} + +module SslEndpointIdentificationFlow = TaintTracking::Global; + /** * An SSL object that was assigned a safe `SSLParameters` object and can be considered safe. */ private class SslConnectionWithSafeSslParameters extends SslUnsafeCertTrustSanitizer { SslConnectionWithSafeSslParameters() { - exists(SafeSslParametersFlowConfig config, DataFlow::Node safe, DataFlow::Node sanitizer | - config.hasFlowTo(safe) and + exists(DataFlow::Node safe, DataFlow::Node sanitizer | + SafeSslParametersFlow::flowTo(safe) and sanitizer = DataFlow::exprNode(safe.asExpr().(Argument).getCall().getQualifier()) and DataFlow::localFlow(sanitizer, this) ) } } -private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { - SafeSslParametersFlowConfig() { this = "SafeSslParametersFlowConfig" } - - override predicate isSource(DataFlow::Node source) { +private module SafeSslParametersFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { exists(MethodAccess ma | ma instanceof SafeSetEndpointIdentificationAlgorithm and DataFlow::getInstanceArgument(ma) = source.(DataFlow::PostUpdateNode).getPreUpdateNode() ) } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma, RefType t | t instanceof SslSocket or t instanceof SslEngine | ma.getMethod().hasName("setSSLParameters") and ma.getMethod().getDeclaringType().getAnAncestor() = t and @@ -52,6 +62,8 @@ private class SafeSslParametersFlowConfig extends DataFlow2::Configuration { } } +private module SafeSslParametersFlow = DataFlow::Global; + /** * A call to `SSLParameters.setEndpointIdentificationAlgorithm` with a non-null and non-empty parameter. */ diff --git a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql index 2925d588c74..eb5241ac87a 100644 --- a/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql +++ b/java/ql/src/Security/CWE/CWE-273/UnsafeCertTrust.ql @@ -18,7 +18,5 @@ import semmle.code.java.security.UnsafeCertTrustQuery from Expr unsafeTrust where unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet or - exists(SslEndpointIdentificationFlowConfig config | - config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) - ) + SslEndpointIdentificationFlow::flowTo(DataFlow::exprNode(unsafeTrust)) select unsafeTrust, "Unsafe configuration of trusted certificates." diff --git a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql index 344faa7f86b..fd18ccc27eb 100644 --- a/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql +++ b/java/ql/test/query-tests/security/CWE-273/UnsafeCertTrustTest.ql @@ -12,9 +12,7 @@ class UnsafeCertTrustTest extends InlineExpectationsTest { exists(Expr unsafeTrust | unsafeTrust instanceof RabbitMQEnableHostnameVerificationNotSet or - exists(SslEndpointIdentificationFlowConfig config | - config.hasFlowTo(DataFlow::exprNode(unsafeTrust)) - ) + SslEndpointIdentificationFlow::flowTo(DataFlow::exprNode(unsafeTrust)) | unsafeTrust.getLocation() = location and element = unsafeTrust.toString() and From e8f7e3fcf1ab9c1ede76d22089f6d271a64900be Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 20 Mar 2023 14:38:24 -0400 Subject: [PATCH 047/141] Refactor ExternalAPIs.qll --- .../code/java/security/ExternalAPIs.qll | 25 ++++++++++++++----- .../CWE/CWE-020/UntrustedDataToExternalAPI.ql | 6 ++--- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll index ef23d28a076..9ba1b9c7e87 100644 --- a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll @@ -98,8 +98,12 @@ class ExternalApiDataNode extends DataFlow::Node { /** DEPRECATED: Alias for ExternalApiDataNode */ deprecated class ExternalAPIDataNode = ExternalApiDataNode; -/** A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. */ -class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { +/** + * DEPRECATED: Use `UntrustedDataToExternalApiFlow` instead. + * + * A configuration for tracking flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. + */ +deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { UntrustedDataToExternalApiConfig() { this = "UntrustedDataToExternalAPIConfig" } override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -107,17 +111,26 @@ class UntrustedDataToExternalApiConfig extends TaintTracking::Configuration { override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } } +private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } +} + +/** + * Tracks flow from untrusted data to external APIs. + */ +module UntrustedDataToExternalApiFlow = TaintTracking::Global; + /** DEPRECATED: Alias for UntrustedDataToExternalApiConfig */ deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiConfig; /** A node representing untrusted data being passed to an external API. */ class UntrustedExternalApiDataNode extends ExternalApiDataNode { - UntrustedExternalApiDataNode() { any(UntrustedDataToExternalApiConfig c).hasFlow(_, this) } + UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) } /** Gets a source of untrusted data which is passed to this external API data node. */ - DataFlow::Node getAnUntrustedSource() { - any(UntrustedDataToExternalApiConfig c).hasFlow(result, this) - } + DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) } } /** DEPRECATED: Alias for UntrustedExternalApiDataNode */ diff --git a/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql b/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql index b4a2e209513..fdbb34b2247 100644 --- a/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql +++ b/java/ql/src/Security/CWE/CWE-020/UntrustedDataToExternalAPI.ql @@ -13,10 +13,10 @@ import java import semmle.code.java.dataflow.FlowSources import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.ExternalAPIs -import DataFlow::PathGraph +import UntrustedDataToExternalApiFlow::PathGraph -from UntrustedDataToExternalApiConfig config, DataFlow::PathNode source, DataFlow::PathNode sink -where config.hasFlowPath(source, sink) +from UntrustedDataToExternalApiFlow::PathNode source, UntrustedDataToExternalApiFlow::PathNode sink +where UntrustedDataToExternalApiFlow::flowPath(source, sink) select sink, source, sink, "Call to " + sink.getNode().(ExternalApiDataNode).getMethodDescription() + " with untrusted data from $@.", source, source.toString() From 2698b61514b4ab77f91447aff08d96b9f3974f4d Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 20 Mar 2023 14:52:48 -0400 Subject: [PATCH 048/141] Refactor HardcodedCredentialsApiCall.qll --- .../HardcodedCredentialsApiCallQuery.qll | 54 ++++++++++++++++++- .../CWE-798/HardcodedCredentialsApiCall.ql | 7 ++- .../tests/HardcodedCredentialsApiCall.ql | 4 +- 3 files changed, 57 insertions(+), 8 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll b/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll index fb786710d66..1d942cc1b97 100644 --- a/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll +++ b/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll @@ -7,9 +7,11 @@ import semmle.code.java.dataflow.DataFlow import HardcodedCredentials /** + * DEPRECATED: Use `HardcodedCredentialApiCallFlow` instead. + * * A data-flow configuration that tracks flow from a hard-coded credential in a call to a sensitive Java API which may compromise security. */ -class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration { +deprecated class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration { HardcodedCredentialApiCallConfiguration() { this = "HardcodedCredentialApiCallConfiguration" } override predicate isSource(DataFlow::Node n) { @@ -52,3 +54,53 @@ class HardcodedCredentialApiCallConfiguration extends DataFlow::Configuration { n.asExpr().(MethodAccess).getMethod() instanceof MethodSystemGetenv } } + +/** + * A data-flow configuration that tracks flow from a hard-coded credential in a call to a sensitive Java API which may compromise security. + */ +private module HardcodedCredentialApiCallConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node n) { + n.asExpr() instanceof HardcodedExpr and + not n.asExpr().getEnclosingCallable() instanceof ToStringMethod + } + + predicate isSink(DataFlow::Node n) { n.asExpr() instanceof CredentialsApiSink } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + node1.asExpr().getType() instanceof TypeString and + ( + exists(MethodAccess ma | ma.getMethod().hasName(["getBytes", "toCharArray"]) | + node2.asExpr() = ma and + ma.getQualifier() = node1.asExpr() + ) + or + // These base64 routines are usually taint propagators, and this is not a general + // TaintTracking::Configuration, so we must specifically include them here + // as a common transform applied to a constant before passing to a remote API. + exists(MethodAccess ma | + ma.getMethod() + .hasQualifiedName([ + "java.util", "cn.hutool.core.codec", "org.apache.shiro.codec", + "apache.commons.codec.binary", "org.springframework.util" + ], ["Base64$Encoder", "Base64$Decoder", "Base64", "Base64Utils"], + [ + "encode", "encodeToString", "decode", "decodeBase64", "encodeBase64", + "encodeBase64Chunked", "encodeBase64String", "encodeBase64URLSafe", + "encodeBase64URLSafeString" + ]) + | + node1.asExpr() = ma.getArgument(0) and + node2.asExpr() = ma + ) + ) + } + + predicate isBarrier(DataFlow::Node n) { + n.asExpr().(MethodAccess).getMethod() instanceof MethodSystemGetenv + } +} + +/** + * Tracks flow from a hard-coded credential in a call to a sensitive Java API which may compromise security. + */ +module HardcodedCredentialApiCallFlow = DataFlow::Global; diff --git a/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql b/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql index 2b84f4b8065..410cea0ed03 100644 --- a/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql +++ b/java/ql/src/Security/CWE/CWE-798/HardcodedCredentialsApiCall.ql @@ -11,10 +11,9 @@ */ import semmle.code.java.security.HardcodedCredentialsApiCallQuery -import DataFlow::PathGraph +import HardcodedCredentialApiCallFlow::PathGraph -from - DataFlow::PathNode source, DataFlow::PathNode sink, HardcodedCredentialApiCallConfiguration conf -where conf.hasFlowPath(source, sink) +from HardcodedCredentialApiCallFlow::PathNode source, HardcodedCredentialApiCallFlow::PathNode sink +where HardcodedCredentialApiCallFlow::flowPath(source, sink) select source.getNode(), source, sink, "Hard-coded value flows to $@.", sink.getNode(), "sensitive API call" diff --git a/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql b/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql index 79ce1738f38..621d2a0105c 100644 --- a/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql +++ b/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql @@ -9,9 +9,7 @@ class HardcodedCredentialsApiCallTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "HardcodedCredentialsApiCall" and - exists(DataFlow::Node sink, HardcodedCredentialApiCallConfiguration conf | - conf.hasFlow(_, sink) - | + exists(DataFlow::Node sink | HardcodedCredentialApiCallFlow::flow(_, sink) | sink.getLocation() = location and element = sink.toString() and value = "" From c67b984fff0ff235cb76d8cf95700b79ceefaadf Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 20 Mar 2023 16:53:31 -0400 Subject: [PATCH 049/141] Refactor RandomQuery.qll --- .../semmle/code/java/security/RandomQuery.qll | 22 ++++++++----------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/RandomQuery.qll b/java/ql/lib/semmle/code/java/security/RandomQuery.qll index 1674cefdb70..b14191f4dd4 100644 --- a/java/ql/lib/semmle/code/java/security/RandomQuery.qll +++ b/java/ql/lib/semmle/code/java/security/RandomQuery.qll @@ -2,7 +2,7 @@ import java import semmle.code.java.dataflow.DefUse -import semmle.code.java.dataflow.DataFlow6 +import semmle.code.java.dataflow.DataFlow import RandomDataSource /** @@ -29,20 +29,18 @@ private predicate isSeeded(RValue use) { ) } -private class PredictableSeedFlowConfiguration extends DataFlow6::Configuration { - PredictableSeedFlowConfiguration() { this = "Random::PredictableSeedFlowConfiguration" } +private module PredictableSeedFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof PredictableSeedExpr } - override predicate isSource(DataFlow6::Node source) { - source.asExpr() instanceof PredictableSeedExpr - } + predicate isSink(DataFlow::Node sink) { isSeeding(sink.asExpr(), _) } - override predicate isSink(DataFlow6::Node sink) { isSeeding(sink.asExpr(), _) } - - override predicate isAdditionalFlowStep(DataFlow6::Node node1, DataFlow6::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { predictableCalcStep(node1.asExpr(), node2.asExpr()) } } +private module PredictableSeedFlow = DataFlow::Global; + private predicate predictableCalcStep(Expr e1, Expr e2) { e2.(BinaryExpr).hasOperands(e1, any(PredictableSeedExpr p)) or @@ -81,7 +79,7 @@ private predicate predictableCalcStep(Expr e1, Expr e2) { private predicate safelySeeded(RValue use) { exists(Expr arg | isSeeding(arg, use) and - not exists(PredictableSeedFlowConfiguration conf | conf.hasFlowToExpr(arg)) + not PredictableSeedFlow::flowToExpr(arg) ) or exists(GetRandomData da, RValue seeduse | @@ -118,9 +116,7 @@ private predicate isSeeding(Expr arg, RValue use) { private predicate isSeedingSource(Expr arg, RValue use, Expr source) { isSeeding(arg, use) and - exists(PredictableSeedFlowConfiguration conf | - conf.hasFlow(DataFlow6::exprNode(source), DataFlow6::exprNode(arg)) - ) + PredictableSeedFlow::flow(DataFlow::exprNode(source), DataFlow::exprNode(arg)) } private predicate isRandomSeeding(MethodAccess m, Expr arg) { From da718610e83a33f66a688744a1af2717a36280bc Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Mon, 20 Mar 2023 16:54:21 -0400 Subject: [PATCH 050/141] Refactor HttpsUrlsQuery.qll --- .../code/java/security/HttpsUrlsQuery.qll | 26 ++++++++++++++++++- java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql | 6 ++--- 2 files changed, 28 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll b/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll index 50c76cefbca..ca46ba8cba0 100644 --- a/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll +++ b/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll @@ -6,9 +6,11 @@ import semmle.code.java.frameworks.Networking import semmle.code.java.security.HttpsUrls /** + * DEPRECATED: Use `HttpsStringToUrlOpenMethodFlow` instead. + * * A taint tracking configuration for HTTP connections. */ -class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration { +deprecated class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration { HttpStringToUrlOpenMethodFlowConfig() { this = "HttpStringToUrlOpenMethodFlowConfig" } override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpStringLiteral } @@ -23,3 +25,25 @@ class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Configuration { node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType } } + +/** + * A taint tracking configuration for HTTP connections. + */ +private module HttpStringToUrlOpenMethodFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpStringLiteral } + + predicate isSink(DataFlow::Node sink) { sink instanceof UrlOpenSink } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(HttpUrlsAdditionalTaintStep c).step(node1, node2) + } + + predicate isBarrier(DataFlow::Node node) { + node.getType() instanceof PrimitiveType or node.getType() instanceof BoxedType + } +} + +/** + * Detect taint flow of HTTP connections. + */ +module HttpStringToUrlOpenMethodFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql index 745a2d6dfad..4bcf99fd4b6 100644 --- a/java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql +++ b/java/ql/src/Security/CWE/CWE-319/HttpsUrls.ql @@ -12,9 +12,9 @@ import java import semmle.code.java.security.HttpsUrlsQuery -import DataFlow::PathGraph +import HttpStringToUrlOpenMethodFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink -where any(HttpStringToUrlOpenMethodFlowConfig c).hasFlowPath(source, sink) +from HttpStringToUrlOpenMethodFlow::PathNode source, HttpStringToUrlOpenMethodFlow::PathNode sink +where HttpStringToUrlOpenMethodFlow::flowPath(source, sink) select sink.getNode(), source, sink, "URL may have been constructed with HTTP protocol, using $@.", source.getNode(), "this HTTP URL" From 7262c6a097631a0101c008c07e225f0853a8f04a Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 12:57:14 -0400 Subject: [PATCH 051/141] Refactor XmlParsers.qll --- .../semmle/code/java/security/XmlParsers.qll | 263 +++++++++--------- .../Security/CWE/CWE-611/XXELib.qll | 4 +- 2 files changed, 125 insertions(+), 142 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/XmlParsers.qll b/java/ql/lib/semmle/code/java/security/XmlParsers.qll index 8cdf962584d..c02587b7f26 100644 --- a/java/ql/lib/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/lib/semmle/code/java/security/XmlParsers.qll @@ -81,24 +81,18 @@ class DocumentBuilderParse extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } override predicate isSafe() { - exists(SafeDocumentBuilderToDocumentBuilderParseFlowConfig conf | - conf.hasFlowToExpr(this.getQualifier()) - ) + SafeDocumentBuilderToDocumentBuilderParseFlow::flowToExpr(this.getQualifier()) } } -private class SafeDocumentBuilderToDocumentBuilderParseFlowConfig extends DataFlow2::Configuration { - SafeDocumentBuilderToDocumentBuilderParseFlowConfig() { - this = "XmlParsers::SafeDocumentBuilderToDocumentBuilderParseFlowConfig" - } +private module SafeDocumentBuilderToDocumentBuilderParseFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDocumentBuilder } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDocumentBuilder } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(DocumentBuilderParse dbp).getQualifier() } - override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { exists(RefType t, ReturnStmt ret, Method m | node2.asExpr().(ClassInstanceExpr).getConstructedType().getSourceDeclaration() = t and t.getASourceSupertype+().hasQualifiedName("java.lang", "ThreadLocal") and @@ -117,9 +111,12 @@ private class SafeDocumentBuilderToDocumentBuilderParseFlowConfig extends DataFl ) } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeDocumentBuilderToDocumentBuilderParseFlow = + DataFlow::Global; + /** * A `ParserConfig` specific to `DocumentBuilderFactory`. */ @@ -198,31 +195,27 @@ private class DocumentBuilderConstruction extends MethodAccess { } } -private class SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig extends DataFlow3::Configuration +private module SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig implements + DataFlow::ConfigSig { - SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig() { - this = "XmlParsers::SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig" - } + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDocumentBuilderFactory } - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof SafeDocumentBuilderFactory - } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(DocumentBuilderConstruction dbc).getQualifier() } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlow = + DataFlow::Global; + /** * A `DocumentBuilder` created from a safely configured `DocumentBuilderFactory`. */ class SafeDocumentBuilder extends DocumentBuilderConstruction { SafeDocumentBuilder() { - exists(SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlowConfig conf | - conf.hasFlowToExpr(this.getQualifier()) - ) + SafeDocumentBuilderFactoryToDocumentBuilderConstructionFlow::flowToExpr(this.getQualifier()) } } @@ -252,27 +245,24 @@ class XmlInputFactoryStreamReader extends XmlParserCall { } override predicate isSafe() { - exists(SafeXmlInputFactoryToXmlInputFactoryReaderFlowConfig conf | - conf.hasFlowToExpr(this.getQualifier()) - ) + SafeXmlInputFactoryToXmlInputFactoryReaderFlow::flowToExpr(this.getQualifier()) } } -private class SafeXmlInputFactoryToXmlInputFactoryReaderFlowConfig extends DataFlow2::Configuration { - SafeXmlInputFactoryToXmlInputFactoryReaderFlowConfig() { - this = "XmlParsers::SafeXmlInputFactoryToXmlInputFactoryReaderFlowConfig" - } +private module SafeXmlInputFactoryToXmlInputFactoryReaderFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeXmlInputFactory } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeXmlInputFactory } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(XmlInputFactoryStreamReader xifsr).getQualifier() or sink.asExpr() = any(XmlInputFactoryEventReader xifer).getQualifier() } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeXmlInputFactoryToXmlInputFactoryReaderFlow = + DataFlow::Global; + /** A call to `XMLInputFactory.createEventReader`. */ class XmlInputFactoryEventReader extends XmlParserCall { XmlInputFactoryEventReader() { @@ -290,9 +280,7 @@ class XmlInputFactoryEventReader extends XmlParserCall { } override predicate isSafe() { - exists(SafeXmlInputFactoryToXmlInputFactoryReaderFlowConfig conf | - conf.hasFlowToExpr(this.getQualifier()) - ) + SafeXmlInputFactoryToXmlInputFactoryReaderFlow::flowToExpr(this.getQualifier()) } } @@ -387,27 +375,24 @@ class SaxBuilderParse extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } override predicate isSafe() { - exists(SafeSaxBuilderToSaxBuilderParseFlowConfig conf | conf.hasFlowToExpr(this.getQualifier())) + SafeSaxBuilderToSaxBuilderParseFlow::flowToExpr(this.getQualifier()) } } /** DEPRECATED: Alias for SaxBuilderParse */ deprecated class SAXBuilderParse = SaxBuilderParse; -private class SafeSaxBuilderToSaxBuilderParseFlowConfig extends DataFlow2::Configuration { - SafeSaxBuilderToSaxBuilderParseFlowConfig() { - this = "XmlParsers::SafeSAXBuilderToSAXBuilderParseFlowConfig" - } +private module SafeSaxBuilderToSaxBuilderParseFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxBuilder } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxBuilder } + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(SaxBuilderParse sax).getQualifier() } - override predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(SaxBuilderParse sax).getQualifier() - } - - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeSaxBuilderToSaxBuilderParseFlow = + DataFlow::Global; + /** * A `ParserConfig` specific to `SAXBuilder`. */ @@ -478,9 +463,7 @@ class SaxParserParse extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } - override predicate isSafe() { - exists(SafeSaxParserFlowConfig sp | sp.hasFlowToExpr(this.getQualifier())) - } + override predicate isSafe() { SafeSaxParserFlow::flowToExpr(this.getQualifier()) } } /** DEPRECATED: Alias for SaxParserParse */ @@ -536,14 +519,10 @@ class SafeSaxParserFactory extends VarAccess { /** DEPRECATED: Alias for SafeSaxParserFactory */ deprecated class SafeSAXParserFactory = SafeSaxParserFactory; -private class SafeSaxParserFactoryToNewSaxParserFlowConfig extends DataFlow5::Configuration { - SafeSaxParserFactoryToNewSaxParserFlowConfig() { - this = "XmlParsers::SafeSAXParserFactoryToNewSAXParserFlowConfig" - } +private module SafeSaxParserFactoryToNewSaxParserFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxParserFactory } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxParserFactory } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma, Method m | sink.asExpr() = ma.getQualifier() and ma.getMethod() = m and @@ -552,31 +531,32 @@ private class SafeSaxParserFactoryToNewSaxParserFlowConfig extends DataFlow5::Co ) } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } -private class SafeSaxParserFlowConfig extends DataFlow4::Configuration { - SafeSaxParserFlowConfig() { this = "XmlParsers::SafeSAXParserFlowConfig" } +private module SafeSaxParserFactoryToNewSaxParserFlow = + DataFlow::Global; - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxParser } +private module SafeSaxParserFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxParser } - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof SaxParser ) } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeSaxParserFlow = DataFlow::Global; + /** A `SaxParser` created from a safely configured `SaxParserFactory`. */ class SafeSaxParser extends MethodAccess { SafeSaxParser() { - exists(SafeSaxParserFactoryToNewSaxParserFlowConfig sdf | - this.getMethod().getDeclaringType() instanceof SaxParserFactory and - this.getMethod().hasName("newSAXParser") and - sdf.hasFlowToExpr(this.getQualifier()) - ) + this.getMethod().getDeclaringType() instanceof SaxParserFactory and + this.getMethod().hasName("newSAXParser") and + SafeSaxParserFactoryToNewSaxParserFlow::flowToExpr(this.getQualifier()) } } @@ -606,9 +586,7 @@ class SaxReaderRead extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } - override predicate isSafe() { - exists(SafeSaxReaderFlowConfig sr | sr.hasFlowToExpr(this.getQualifier())) - } + override predicate isSafe() { SafeSaxReaderFlow::flowToExpr(this.getQualifier()) } } /** DEPRECATED: Alias for SaxReaderRead */ @@ -628,20 +606,20 @@ class SaxReaderConfig extends ParserConfig { /** DEPRECATED: Alias for SaxReaderConfig */ deprecated class SAXReaderConfig = SaxReaderConfig; -private class SafeSaxReaderFlowConfig extends DataFlow4::Configuration { - SafeSaxReaderFlowConfig() { this = "XmlParsers::SafeSAXReaderFlowConfig" } +private module SafeSaxReaderFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxReader } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxReader } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { exists(MethodAccess ma | sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof SaxReader ) } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeSaxReaderFlow = DataFlow::Global; + /** A safely configured `SaxReader`. */ class SafeSaxReader extends VarAccess { SafeSaxReader() { @@ -715,18 +693,16 @@ class XmlReaderConfig extends ParserConfig { /** DEPRECATED: Alias for XmlReaderConfig */ deprecated class XMLReaderConfig = XmlReaderConfig; -private class ExplicitlySafeXmlReaderFlowConfig extends DataFlow3::Configuration { - ExplicitlySafeXmlReaderFlowConfig() { this = "XmlParsers::ExplicitlySafeXMLReaderFlowConfig" } +private module ExplicitlySafeXmlReaderFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof ExplicitlySafeXmlReader } - override predicate isSource(DataFlow::Node src) { - src.asExpr() instanceof ExplicitlySafeXmlReader - } + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SafeXmlReaderFlowSink } - override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SafeXmlReaderFlowSink } - - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module ExplicitlySafeXmlReaderFlow = DataFlow::Global; + /** An argument to a safe XML reader. */ class SafeXmlReaderFlowSink extends Expr { SafeXmlReaderFlowSink() { @@ -774,40 +750,35 @@ class ExplicitlySafeXmlReader extends VarAccess { /** Holds if `SafeXmlReaderFlowSink` detects flow from this to `sink` */ predicate flowsTo(SafeXmlReaderFlowSink sink) { - any(ExplicitlySafeXmlReaderFlowConfig conf) - .hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) + ExplicitlySafeXmlReaderFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) } } /** DEPRECATED: Alias for ExplicitlySafeXmlReader */ deprecated class ExplicitlySafeXMLReader = ExplicitlySafeXmlReader; -private class CreatedSafeXmlReaderFlowConfig extends DataFlow3::Configuration { - CreatedSafeXmlReaderFlowConfig() { this = "XmlParsers::CreatedSafeXMLReaderFlowConfig" } +private module CreatedSafeXmlReaderFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CreatedSafeXmlReader } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof CreatedSafeXmlReader } + predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SafeXmlReaderFlowSink } - override predicate isSink(DataFlow::Node sink) { sink.asExpr() instanceof SafeXmlReaderFlowSink } - - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module CreatedSafeXmlReaderFlow = DataFlow::Global; + /** An `XmlReader` that is obtained from a safe source. */ class CreatedSafeXmlReader extends Call { CreatedSafeXmlReader() { //Obtained from SAXParser - exists(SafeSaxParserFlowConfig safeParser | - this.(MethodAccess).getMethod().getDeclaringType() instanceof SaxParser and - this.(MethodAccess).getMethod().hasName("getXMLReader") and - safeParser.hasFlowToExpr(this.getQualifier()) - ) + this.(MethodAccess).getMethod().getDeclaringType() instanceof SaxParser and + this.(MethodAccess).getMethod().hasName("getXMLReader") and + SafeSaxParserFlow::flowToExpr(this.getQualifier()) or //Obtained from SAXReader - exists(SafeSaxReaderFlowConfig safeReader | - this.(MethodAccess).getMethod().getDeclaringType() instanceof SaxReader and - this.(MethodAccess).getMethod().hasName("getXMLReader") and - safeReader.hasFlowToExpr(this.getQualifier()) - ) + this.(MethodAccess).getMethod().getDeclaringType() instanceof SaxReader and + this.(MethodAccess).getMethod().hasName("getXMLReader") and + SafeSaxReaderFlow::flowToExpr(this.getQualifier()) or exists(RefType secureReader, string package | this.(ClassInstanceExpr).getConstructedType() = secureReader and @@ -818,8 +789,7 @@ class CreatedSafeXmlReader extends Call { /** Holds if `CreatedSafeXmlReaderFlowConfig` detects flow from this to `sink` */ predicate flowsTo(SafeXmlReaderFlowSink sink) { - any(CreatedSafeXmlReaderFlowConfig conf) - .hasFlow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) + CreatedSafeXmlReaderFlow::flow(DataFlow::exprNode(this), DataFlow::exprNode(sink)) } } @@ -975,26 +945,23 @@ class TransformerTransform extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } override predicate isSafe() { - exists(SafeTransformerToTransformerTransformFlowConfig st | - st.hasFlowToExpr(this.getQualifier()) - ) + SafeTransformerToTransformerTransformFlow::flowToExpr(this.getQualifier()) } } -private class SafeTransformerToTransformerTransformFlowConfig extends DataFlow2::Configuration { - SafeTransformerToTransformerTransformFlowConfig() { - this = "XmlParsers::SafeTransformerToTransformerTransformFlowConfig" - } +private module SafeTransformerToTransformerTransformFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeTransformer } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeTransformer } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(TransformerTransform tt).getQualifier() } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeTransformerToTransformerTransformFlow = + DataFlow::Global; + /** A call to `Transformer.newTransformer` with source. */ class TransformerFactorySource extends XmlParserCall { TransformerFactorySource() { @@ -1007,9 +974,7 @@ class TransformerFactorySource extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } - override predicate isSafe() { - exists(SafeTransformerFactoryFlowConfig stf | stf.hasFlowToExpr(this.getQualifier())) - } + override predicate isSafe() { SafeTransformerFactoryFlow::flowToExpr(this.getQualifier()) } } /** A `ParserConfig` specific to `TransformerFactory`. */ @@ -1024,10 +989,12 @@ class TransformerFactoryConfig extends TransformerConfig { } /** + * DEPRECATED: Use `SafeTransformerFactoryFlow` instead. + * * A dataflow configuration that identifies `TransformerFactory` and `SAXTransformerFactory` * instances that have been safely configured. */ -class SafeTransformerFactoryFlowConfig extends DataFlow3::Configuration { +deprecated class SafeTransformerFactoryFlowConfig extends DataFlow3::Configuration { SafeTransformerFactoryFlowConfig() { this = "XmlParsers::SafeTransformerFactoryFlowConfig" } override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeTransformerFactory } @@ -1042,6 +1009,29 @@ class SafeTransformerFactoryFlowConfig extends DataFlow3::Configuration { override int fieldFlowBranchLimit() { result = 0 } } +/** + * A dataflow configuration that identifies `TransformerFactory` and `SAXTransformerFactory` + * instances that have been safely configured. + */ +private module SafeTransformerFactoryFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeTransformerFactory } + + predicate isSink(DataFlow::Node sink) { + exists(MethodAccess ma | + sink.asExpr() = ma.getQualifier() and + ma.getMethod().getDeclaringType() instanceof TransformerFactory + ) + } + + int fieldFlowBranchLimit() { result = 0 } +} + +/** + * Identifies `TransformerFactory` and `SAXTransformerFactory` + * instances that have been safely configured. + */ +module SafeTransformerFactoryFlow = DataFlow::Global; + /** A safely configured `TransformerFactory`. */ class SafeTransformerFactory extends VarAccess { SafeTransformerFactory() { @@ -1059,11 +1049,11 @@ class SafeTransformerFactory extends VarAccess { /** A `Transformer` created from a safely configured `TransformerFactory`. */ class SafeTransformer extends MethodAccess { SafeTransformer() { - exists(SafeTransformerFactoryFlowConfig stf, Method m | + exists(Method m | this.getMethod() = m and m.getDeclaringType() instanceof TransformerFactory and m.hasName("newTransformer") and - stf.hasFlowToExpr(this.getQualifier()) + SafeTransformerFactoryFlow::flowToExpr(this.getQualifier()) ) } } @@ -1085,9 +1075,7 @@ class SaxTransformerFactoryNewXmlFilter extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } - override predicate isSafe() { - exists(SafeTransformerFactoryFlowConfig stf | stf.hasFlowToExpr(this.getQualifier())) - } + override predicate isSafe() { SafeTransformerFactoryFlow::flowToExpr(this.getQualifier()) } } /** DEPRECATED: Alias for SaxTransformerFactoryNewXmlFilter */ @@ -1123,26 +1111,23 @@ class SchemaFactoryNewSchema extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } override predicate isSafe() { - exists(SafeSchemaFactoryToSchemaFactoryNewSchemaFlowConfig ssf | - ssf.hasFlowToExpr(this.getQualifier()) - ) + SafeSchemaFactoryToSchemaFactoryNewSchemaFlow::flowToExpr(this.getQualifier()) } } -private class SafeSchemaFactoryToSchemaFactoryNewSchemaFlowConfig extends DataFlow2::Configuration { - SafeSchemaFactoryToSchemaFactoryNewSchemaFlowConfig() { - this = "XmlParsers::SafeSchemaFactoryToSchemaFactoryNewSchemaFlowConfig" - } +private module SafeSchemaFactoryToSchemaFactoryNewSchemaFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSchemaFactory } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSchemaFactory } - - override predicate isSink(DataFlow::Node sink) { + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(SchemaFactoryNewSchema sfns).getQualifier() } - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } +private module SafeSchemaFactoryToSchemaFactoryNewSchemaFlow = + DataFlow::Global; + /** A safely configured `SchemaFactory`. */ class SafeSchemaFactory extends VarAccess { SafeSchemaFactory() { diff --git a/java/ql/src/experimental/Security/CWE/CWE-611/XXELib.qll b/java/ql/src/experimental/Security/CWE/CWE-611/XXELib.qll index 3f44faa54d0..61008ae63aa 100644 --- a/java/ql/src/experimental/Security/CWE/CWE-611/XXELib.qll +++ b/java/ql/src/experimental/Security/CWE/CWE-611/XXELib.qll @@ -232,9 +232,7 @@ class SaxTransformerFactoryNewTransformerHandler extends XmlParserCall { override Expr getSink() { result = this.getArgument(0) } - override predicate isSafe() { - exists(SafeTransformerFactoryFlowConfig stf | stf.hasFlowToExpr(this.getQualifier())) - } + override predicate isSafe() { SafeTransformerFactoryFlow::flowToExpr(this.getQualifier()) } } /** DEPRECATED: Alias for SaxTransformerFactoryNewTransformerHandler */ From 3b2eea2d4483fa0ce540fe906f80b654455d967e Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 20:05:03 -0400 Subject: [PATCH 052/141] Refactor XxeQuery --- .../lib/semmle/code/java/security/XxeQuery.qll | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/XxeQuery.qll b/java/ql/lib/semmle/code/java/security/XxeQuery.qll index e1df8a1e601..18f7dd9e357 100644 --- a/java/ql/lib/semmle/code/java/security/XxeQuery.qll +++ b/java/ql/lib/semmle/code/java/security/XxeQuery.qll @@ -1,7 +1,7 @@ /** Provides default definitions to be used in XXE queries. */ import java -private import semmle.code.java.dataflow.TaintTracking2 +private import semmle.code.java.dataflow.TaintTracking private import semmle.code.java.security.XmlParsers import semmle.code.java.security.Xxe @@ -11,7 +11,7 @@ import semmle.code.java.security.Xxe */ private class DefaultXxeSink extends XxeSink { DefaultXxeSink() { - not exists(SafeSaxSourceFlowConfig safeSource | safeSource.hasFlowTo(this)) and + not SafeSaxSourceFlow::flowTo(this) and exists(XmlParserCall parse | parse.getSink() = this.asExpr() and not parse.isSafe() @@ -22,14 +22,12 @@ private class DefaultXxeSink extends XxeSink { /** * A taint-tracking configuration for safe XML readers used to parse XML documents. */ -private class SafeSaxSourceFlowConfig extends TaintTracking2::Configuration { - SafeSaxSourceFlowConfig() { this = "SafeSaxSourceFlowConfig" } +private module SafeSaxSourceFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxSource } - override predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSaxSource } + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(XmlParserCall parse).getSink() } - override predicate isSink(DataFlow::Node sink) { - sink.asExpr() = any(XmlParserCall parse).getSink() - } - - override int fieldFlowBranchLimit() { result = 0 } + int fieldFlowBranchLimit() { result = 0 } } + +private module SafeSaxSourceFlow = TaintTracking::Global; From dcd46c2236b9a1de9f166f04653d98922f1aa51e Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 17:14:48 -0400 Subject: [PATCH 053/141] Refactor InsecureTrustManager --- .../security/InsecureTrustManagerQuery.qll | 22 ++++++++++++++++++- .../CWE/CWE-295/InsecureTrustManager.ql | 6 ++--- .../InsecureTrustManagerTest.ql | 19 ++++++++++------ 3 files changed, 36 insertions(+), 11 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll index 22ab9bbcbc9..d54653e3046 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll @@ -5,10 +5,12 @@ import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.InsecureTrustManager /** + * DEPRECATED: Use `InsecureTrustManagerFlow` instead. + * * A configuration to model the flow of an insecure `TrustManager` * to the initialization of an SSL context. */ -class InsecureTrustManagerConfiguration extends DataFlow::Configuration { +deprecated class InsecureTrustManagerConfiguration extends DataFlow::Configuration { InsecureTrustManagerConfiguration() { this = "InsecureTrustManagerConfiguration" } override predicate isSource(DataFlow::Node source) { @@ -23,3 +25,21 @@ class InsecureTrustManagerConfiguration extends DataFlow::Configuration { c instanceof DataFlow::ArrayContent } } + +/** + * A configuration to model the flow of an insecure `TrustManager` + * to the initialization of an SSL context. + */ +private module InsecureTrustManagerConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof InsecureTrustManagerSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof InsecureTrustManagerSink } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + (isSink(node) or isAdditionalFlowStep(node, _)) and + node.getType() instanceof Array and + c instanceof DataFlow::ArrayContent + } +} + +module InsecureTrustManagerFlow = DataFlow::Global; diff --git a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql index 755f2b5a4a7..4904c08b195 100644 --- a/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql +++ b/java/ql/src/Security/CWE/CWE-295/InsecureTrustManager.ql @@ -13,10 +13,10 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.security.InsecureTrustManagerQuery -import DataFlow::PathGraph +import InsecureTrustManagerFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink -where any(InsecureTrustManagerConfiguration cfg).hasFlowPath(source, sink) +from InsecureTrustManagerFlow::PathNode source, InsecureTrustManagerFlow::PathNode sink +where InsecureTrustManagerFlow::flowPath(source, sink) select sink, source, sink, "This uses $@, which is defined in $@ and trusts any certificate.", source, "TrustManager", source.getNode().asExpr().(ClassInstanceExpr).getConstructedType() as type, type.nestedName() diff --git a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql index fb00ff33b34..0f068d04679 100644 --- a/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql +++ b/java/ql/test/query-tests/security/CWE-295/InsecureTrustManager/InsecureTrustManagerTest.ql @@ -1,13 +1,18 @@ import java import semmle.code.java.security.InsecureTrustManagerQuery -import TestUtilities.InlineFlowTest +import TestUtilities.InlineExpectationsTest -class EnableLegacy extends EnableLegacyConfiguration { - EnableLegacy() { exists(this) } -} +class InsecureTrustManagerTest extends InlineExpectationsTest { + InsecureTrustManagerTest() { this = "InsecureTrustManagerTest" } -class InsecureTrustManagerTest extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { - result = any(InsecureTrustManagerConfiguration c) + override string getARelevantTag() { result = "hasValueFlow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasValueFlow" and + exists(DataFlow::Node sink | InsecureTrustManagerFlow::flowTo(sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) } } From fa2f0dbc3b51739c65dcabe443b47e7e8706f731 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 17:15:08 -0400 Subject: [PATCH 054/141] Refactor InsecureBasicAuth --- .../java/security/InsecureBasicAuthQuery.qll | 23 ++++++++++++++++++- .../Security/CWE/CWE-522/InsecureBasicAuth.ql | 6 ++--- .../security/CWE-522/InsecureBasicAuthTest.ql | 2 +- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll index 941aaafe580..83e653bbe18 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll @@ -6,10 +6,12 @@ import semmle.code.java.security.InsecureBasicAuth import semmle.code.java.dataflow.TaintTracking /** + * DEPRECATED: Use `InsecureBasicAuthFlow` instead. + * * A taint tracking configuration for the Basic authentication scheme * being used in HTTP connections. */ -class BasicAuthFlowConfig extends TaintTracking::Configuration { +deprecated class BasicAuthFlowConfig extends TaintTracking::Configuration { BasicAuthFlowConfig() { this = "InsecureBasicAuth::BasicAuthFlowConfig" } override predicate isSource(DataFlow::Node src) { src instanceof InsecureBasicAuthSource } @@ -20,3 +22,22 @@ class BasicAuthFlowConfig extends TaintTracking::Configuration { any(HttpUrlsAdditionalTaintStep c).step(node1, node2) } } + +/** + * A taint tracking configuration for the Basic authentication scheme + * being used in HTTP connections. + */ +private module BasicAuthFlowConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node src) { src instanceof InsecureBasicAuthSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof InsecureBasicAuthSink } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(HttpUrlsAdditionalTaintStep c).step(node1, node2) + } +} + +/** + * Tracks flow for the Basic authentication scheme being used in HTTP connections. + */ +module InsecureBasicAuthFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql b/java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql index 069245b4a3e..ae74b355e5f 100644 --- a/java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql +++ b/java/ql/src/Security/CWE/CWE-522/InsecureBasicAuth.ql @@ -16,9 +16,9 @@ import java import semmle.code.java.security.InsecureBasicAuthQuery -import DataFlow::PathGraph +import InsecureBasicAuthFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, BasicAuthFlowConfig config -where config.hasFlowPath(source, sink) +from InsecureBasicAuthFlow::PathNode source, InsecureBasicAuthFlow::PathNode sink +where InsecureBasicAuthFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Insecure basic authentication from a $@.", source.getNode(), "HTTP URL" diff --git a/java/ql/test/query-tests/security/CWE-522/InsecureBasicAuthTest.ql b/java/ql/test/query-tests/security/CWE-522/InsecureBasicAuthTest.ql index b593c5476ef..29057edce71 100644 --- a/java/ql/test/query-tests/security/CWE-522/InsecureBasicAuthTest.ql +++ b/java/ql/test/query-tests/security/CWE-522/InsecureBasicAuthTest.ql @@ -9,7 +9,7 @@ class HasInsecureBasicAuthTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasInsecureBasicAuth" and - exists(DataFlow::Node sink, BasicAuthFlowConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | InsecureBasicAuthFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From cae5637d8d64c1e9b7b27977cbc75e1d9b603ced Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 17:23:33 -0400 Subject: [PATCH 055/141] Refactor InsufficientKeySize --- .../security/InsufficientKeySizeQuery.qll | 35 +++++++++++++++++-- .../CWE/CWE-326/InsufficientKeySize.ql | 6 ++-- .../CWE-326/InsufficientKeySizeTest.ql | 2 +- 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll b/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll index eb416d9647b..6b54031e4d3 100644 --- a/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll @@ -3,8 +3,12 @@ import semmle.code.java.dataflow.DataFlow import semmle.code.java.security.InsufficientKeySize -/** A data flow configuration for tracking key sizes used in cryptographic algorithms. */ -class KeySizeConfiguration extends DataFlow::Configuration { +/** + * DEPRECATED: Use `KeySizeFlow` instead. + * + * A data flow configuration for tracking key sizes used in cryptographic algorithms. + */ +deprecated class KeySizeConfiguration extends DataFlow::Configuration { KeySizeConfiguration() { this = "KeySizeConfiguration" } override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { @@ -15,3 +19,30 @@ class KeySizeConfiguration extends DataFlow::Configuration { sink.(InsufficientKeySizeSink).hasState(state) } } + +/** + * A data flow configuration for tracking key sizes used in cryptographic algorithms. + */ +private module KeySizeConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { + source.(InsufficientKeySizeSource).hasState(state) + } + + predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { + sink.(InsufficientKeySizeSink).hasState(state) + } + + predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) { none() } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2, + DataFlow::FlowState state2 + ) { + none() + } +} + +/** Tracks key sizes used in cryptographic algorithms. */ +module KeySizeFlow = DataFlow::GlobalWithState; diff --git a/java/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql b/java/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql index 2cf3d9115b3..39e4c3e64e5 100644 --- a/java/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql +++ b/java/ql/src/Security/CWE/CWE-326/InsufficientKeySize.ql @@ -13,10 +13,10 @@ import java import semmle.code.java.security.InsufficientKeySizeQuery -import DataFlow::PathGraph +import KeySizeFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, KeySizeConfiguration cfg -where cfg.hasFlowPath(source, sink) +from KeySizeFlow::PathNode source, KeySizeFlow::PathNode sink +where KeySizeFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This $@ is less than the recommended key size of " + source.getState() + " bits.", source.getNode(), "key size" diff --git a/java/ql/test/query-tests/security/CWE-326/InsufficientKeySizeTest.ql b/java/ql/test/query-tests/security/CWE-326/InsufficientKeySizeTest.ql index 12f667a67f3..1384a36e4ce 100644 --- a/java/ql/test/query-tests/security/CWE-326/InsufficientKeySizeTest.ql +++ b/java/ql/test/query-tests/security/CWE-326/InsufficientKeySizeTest.ql @@ -9,7 +9,7 @@ class InsufficientKeySizeTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasInsufficientKeySize" and - exists(DataFlow::PathNode sink | exists(KeySizeConfiguration cfg | cfg.hasFlowPath(_, sink)) | + exists(KeySizeFlow::PathNode sink | KeySizeFlow::flowPath(_, sink) | sink.getNode().getLocation() = location and element = sink.getNode().toString() and value = "" From f8e26f15719d77d94dbde83953d07bece23dcce5 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 17:46:28 -0400 Subject: [PATCH 056/141] Refactor MissingJWTSignatureCheck --- .../MissingJWTSignatureCheckQuery.qll | 20 ++++++++++++++++++- .../CWE/CWE-347/MissingJWTSignatureCheck.ql | 6 +++--- .../CWE-347/MissingJWTSignatureCheckTest.ql | 2 +- 3 files changed, 23 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll b/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll index 818a4c664fe..38d80b43996 100644 --- a/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll +++ b/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll @@ -5,10 +5,12 @@ import semmle.code.java.dataflow.DataFlow import semmle.code.java.security.JWT /** + * DEPRECATED: Use `MissingJwtSignatureCheckFlow` instead. + * * Models flow from signing keys assignments to qualifiers of JWT insecure parsers. * This is used to determine whether a `JwtParser` performing unsafe parsing has a signing key set. */ -class MissingJwtSignatureCheckConf extends DataFlow::Configuration { +deprecated class MissingJwtSignatureCheckConf extends DataFlow::Configuration { MissingJwtSignatureCheckConf() { this = "SigningToExprDataFlow" } override predicate isSource(DataFlow::Node source) { @@ -21,3 +23,19 @@ class MissingJwtSignatureCheckConf extends DataFlow::Configuration { any(JwtParserWithInsecureParseAdditionalFlowStep c).step(node1, node2) } } + +/** + * Models flow from signing keys assignments to qualifiers of JWT insecure parsers. + * This is used to determine whether a `JwtParser` performing unsafe parsing has a signing key set. + */ +private module MissingJwtSignatureCheckConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof JwtParserWithInsecureParseSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof JwtParserWithInsecureParseSink } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(JwtParserWithInsecureParseAdditionalFlowStep c).step(node1, node2) + } +} + +module MissingJwtSignatureCheckFlow = DataFlow::Global; diff --git a/java/ql/src/Security/CWE/CWE-347/MissingJWTSignatureCheck.ql b/java/ql/src/Security/CWE/CWE-347/MissingJWTSignatureCheck.ql index 648321ec3ab..077d7a67370 100644 --- a/java/ql/src/Security/CWE/CWE-347/MissingJWTSignatureCheck.ql +++ b/java/ql/src/Security/CWE/CWE-347/MissingJWTSignatureCheck.ql @@ -12,9 +12,9 @@ import java import semmle.code.java.security.MissingJWTSignatureCheckQuery -import DataFlow::PathGraph +import MissingJwtSignatureCheckFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, MissingJwtSignatureCheckConf conf -where conf.hasFlowPath(source, sink) +from MissingJwtSignatureCheckFlow::PathNode source, MissingJwtSignatureCheckFlow::PathNode sink +where MissingJwtSignatureCheckFlow::flowPath(source, sink) select sink.getNode(), source, sink, "This parses a $@, but the signature is not verified.", source.getNode(), "JWT signing key" diff --git a/java/ql/test/query-tests/security/CWE-347/MissingJWTSignatureCheckTest.ql b/java/ql/test/query-tests/security/CWE-347/MissingJWTSignatureCheckTest.ql index b4f4c1c445e..df6867bbefe 100644 --- a/java/ql/test/query-tests/security/CWE-347/MissingJWTSignatureCheckTest.ql +++ b/java/ql/test/query-tests/security/CWE-347/MissingJWTSignatureCheckTest.ql @@ -9,7 +9,7 @@ class HasMissingJwtSignatureCheckTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasMissingJwtSignatureCheck" and - exists(DataFlow::Node sink, MissingJwtSignatureCheckConf conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | MissingJwtSignatureCheckFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From 469ac80d40855f64d35156a7fc2cea79ef85436f Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 18:01:57 -0400 Subject: [PATCH 057/141] Refactor PartialPathTraversal --- .../security/PartialPathTraversalQuery.qll | 21 ++++++++++++++++++- .../CWE-023/PartialPathTraversalFromRemote.ql | 8 ++++--- .../PartialPathTraversalFromRemoteTest.ql | 21 +++++++++++-------- 3 files changed, 37 insertions(+), 13 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll b/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll index a43f90ae10d..613b9844459 100644 --- a/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll @@ -7,11 +7,13 @@ import semmle.code.java.dataflow.TaintTracking import semmle.code.java.dataflow.FlowSources /** + * DEPRECATED: Use `PartialPathTraversalFromRemoteFlow` instead. + * * A taint-tracking configuration for unsafe user input * that is used to validate against path traversal, but is insufficient * and remains vulnerable to Partial Path Traversal. */ -class PartialPathTraversalFromRemoteConfig extends TaintTracking::Configuration { +deprecated class PartialPathTraversalFromRemoteConfig extends TaintTracking::Configuration { PartialPathTraversalFromRemoteConfig() { this = "PartialPathTraversalFromRemoteConfig" } override predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource } @@ -20,3 +22,20 @@ class PartialPathTraversalFromRemoteConfig extends TaintTracking::Configuration any(PartialPathTraversalMethodAccess ma).getQualifier() = node.asExpr() } } + +/** + * A taint-tracking configuration for unsafe user input + * that is used to validate against path traversal, but is insufficient + * and remains vulnerable to Partial Path Traversal. + */ +private module PartialPathTraversalFromRemoteConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource } + + predicate isSink(DataFlow::Node node) { + any(PartialPathTraversalMethodAccess ma).getQualifier() = node.asExpr() + } +} + +/** Tracks flow of unsafe user input that is used to validate against path traversal, but is insufficient and remains vulnerable to Partial Path Traversal. */ +module PartialPathTraversalFromRemoteFlow = + TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalFromRemote.ql b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalFromRemote.ql index 8ef4ab45853..ef62f433ae6 100644 --- a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalFromRemote.ql +++ b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalFromRemote.ql @@ -11,10 +11,12 @@ */ import semmle.code.java.security.PartialPathTraversalQuery -import DataFlow::PathGraph +import PartialPathTraversalFromRemoteFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink -where any(PartialPathTraversalFromRemoteConfig config).hasFlowPath(source, sink) +from + PartialPathTraversalFromRemoteFlow::PathNode source, + PartialPathTraversalFromRemoteFlow::PathNode sink +where PartialPathTraversalFromRemoteFlow::flowPath(source, sink) select sink.getNode(), source, sink, "Partial Path Traversal Vulnerability due to insufficient guard against path traversal from $@.", source, "user-supplied data" diff --git a/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql b/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql index 7f441e62d4e..a07eb6892c3 100644 --- a/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql +++ b/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalFromRemoteTest.ql @@ -1,21 +1,24 @@ import java -import TestUtilities.InlineFlowTest +import TestUtilities.InlineExpectationsTest import semmle.code.java.security.PartialPathTraversalQuery -class EnableLegacy extends EnableLegacyConfiguration { - EnableLegacy() { exists(this) } -} - class TestRemoteSource extends RemoteFlowSource { TestRemoteSource() { this.asParameter().hasName(["dir", "path"]) } override string getSourceType() { result = "TestSource" } } -class Test extends InlineFlowTest { - override DataFlow::Configuration getValueFlowConfig() { none() } +class Test extends InlineExpectationsTest { + Test() { this = "PartialPathTraversalFromRemoteTest" } - override TaintTracking::Configuration getTaintFlowConfig() { - result instanceof PartialPathTraversalFromRemoteConfig + override string getARelevantTag() { result = "hasTaintFlow" } + + override predicate hasActualResult(Location location, string element, string tag, string value) { + tag = "hasTaintFlow" and + exists(DataFlow::Node sink | PartialPathTraversalFromRemoteFlow::flowTo(sink) | + sink.getLocation() = location and + element = sink.toString() and + value = "" + ) } } From 42b582da2ff6b3b867cd5059e6ec0a973d9df37f Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 21 Mar 2023 20:01:35 -0400 Subject: [PATCH 058/141] Refactor StaticInitializationVector --- .../StaticInitializationVectorQuery.qll | 36 +++++++++++++------ .../CWE-1204/StaticInitializationVector.ql | 6 ++-- .../StaticInitializationVectorTest.ql | 2 +- 3 files changed, 30 insertions(+), 14 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll index 64dee88b7fd..6a9a524e11a 100644 --- a/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -83,25 +83,23 @@ private class ArrayUpdate extends Expr { /** * A config that tracks dataflow from creating an array to an operation that updates it. */ -private class ArrayUpdateConfig extends DataFlow2::Configuration { - ArrayUpdateConfig() { this = "ArrayUpdateConfig" } +private module ArrayUpdateConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source.asExpr() instanceof StaticByteArrayCreation } - override predicate isSource(DataFlow::Node source) { - source.asExpr() instanceof StaticByteArrayCreation - } + predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(ArrayUpdate upd).getArray() } - override predicate isSink(DataFlow::Node sink) { sink.asExpr() = any(ArrayUpdate upd).getArray() } - - override predicate isBarrierOut(DataFlow::Node node) { this.isSink(node) } + predicate isBarrierOut(DataFlow::Node node) { isSink(node) } } +private module ArrayUpdateFlow = DataFlow::Global; + /** * A source that defines an array that doesn't get updated. */ private class StaticInitializationVectorSource extends DataFlow::Node { StaticInitializationVectorSource() { exists(StaticByteArrayCreation array | array = this.asExpr() | - not exists(ArrayUpdateConfig config | config.hasFlow(DataFlow2::exprNode(array), _)) and + not ArrayUpdateFlow::flow(DataFlow2::exprNode(array), _) and // Reduce FPs from utility methods that return an empty array in an exceptional case not exists(ReturnStmt ret | array.getADimension().(CompileTimeConstantExpr).getIntValue() = 0 and @@ -146,9 +144,11 @@ private predicate createInitializationVectorSpecStep(DataFlow::Node fromNode, Da } /** + * DEPRECATED: Use `StaticInitializationVectorFlow` instead. + * * A config that tracks dataflow to initializing a cipher with a static initialization vector. */ -class StaticInitializationVectorConfig extends TaintTracking::Configuration { +deprecated class StaticInitializationVectorConfig extends TaintTracking::Configuration { StaticInitializationVectorConfig() { this = "StaticInitializationVectorConfig" } override predicate isSource(DataFlow::Node source) { @@ -161,3 +161,19 @@ class StaticInitializationVectorConfig extends TaintTracking::Configuration { createInitializationVectorSpecStep(fromNode, toNode) } } + +/** + * A config that tracks dataflow to initializing a cipher with a static initialization vector. + */ +private module StaticInitializationVectorConfig implements DataFlow::ConfigSig { + predicate isSource(DataFlow::Node source) { source instanceof StaticInitializationVectorSource } + + predicate isSink(DataFlow::Node sink) { sink instanceof EncryptionInitializationSink } + + predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + createInitializationVectorSpecStep(fromNode, toNode) + } +} + +/** Tracks the flow from a static initialization vector to the initialization of a cipher */ +module StaticInitializationVectorFlow = TaintTracking::Global; diff --git a/java/ql/src/Security/CWE/CWE-1204/StaticInitializationVector.ql b/java/ql/src/Security/CWE/CWE-1204/StaticInitializationVector.ql index 669c4e6f946..258e0f87112 100644 --- a/java/ql/src/Security/CWE/CWE-1204/StaticInitializationVector.ql +++ b/java/ql/src/Security/CWE/CWE-1204/StaticInitializationVector.ql @@ -13,9 +13,9 @@ import java import semmle.code.java.security.StaticInitializationVectorQuery -import DataFlow::PathGraph +import StaticInitializationVectorFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink, StaticInitializationVectorConfig conf -where conf.hasFlowPath(source, sink) +from StaticInitializationVectorFlow::PathNode source, StaticInitializationVectorFlow::PathNode sink +where StaticInitializationVectorFlow::flowPath(source, sink) select sink.getNode(), source, sink, "A $@ should not be used for encryption.", source.getNode(), "static initialization vector" diff --git a/java/ql/test/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql b/java/ql/test/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql index 653a3cefa7a..ceaf8e11a4f 100644 --- a/java/ql/test/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql +++ b/java/ql/test/query-tests/security/CWE-1204/StaticInitializationVectorTest.ql @@ -9,7 +9,7 @@ class StaticInitializationVectorTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "staticInitializationVector" and - exists(DataFlow::Node sink, StaticInitializationVectorConfig conf | conf.hasFlowTo(sink) | + exists(DataFlow::Node sink | StaticInitializationVectorFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From 8621a496451cb623bfdb1e41cff3a47015b73d7c Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 28 Mar 2023 23:19:07 -0400 Subject: [PATCH 059/141] Remove unnecessary `private` markers --- .../security/AndroidSensitiveCommunicationQuery.qll | 2 +- .../java/security/ArbitraryApkInstallationQuery.qll | 2 +- java/ql/lib/semmle/code/java/security/ExternalAPIs.qll | 2 +- .../code/java/security/FragmentInjectionQuery.qll | 2 +- .../java/security/HardcodedCredentialsApiCallQuery.qll | 2 +- .../lib/semmle/code/java/security/HttpsUrlsQuery.qll | 2 +- .../code/java/security/InsecureBasicAuthQuery.qll | 2 +- .../code/java/security/InsecureTrustManagerQuery.qll | 2 +- .../code/java/security/InsufficientKeySizeQuery.qll | 2 +- .../security/IntentUriPermissionManipulationQuery.qll | 2 +- .../semmle/code/java/security/LogInjectionQuery.qll | 2 +- .../java/security/MissingJWTSignatureCheckQuery.qll | 2 +- .../code/java/security/PartialPathTraversalQuery.qll | 2 +- .../semmle/code/java/security/RsaWithoutOaepQuery.qll | 2 +- .../code/java/security/SensitiveLoggingQuery.qll | 2 +- .../java/security/StaticInitializationVectorQuery.qll | 2 +- .../semmle/code/java/security/UnsafeCertTrustQuery.qll | 2 +- .../java/security/UnsafeContentUriResolutionQuery.qll | 2 +- .../code/java/security/UnsafeDeserializationQuery.qll | 10 ++++++++-- java/ql/lib/semmle/code/java/security/XmlParsers.qll | 2 +- .../code/java/security/regexp/PolynomialReDoSQuery.qll | 2 +- 21 files changed, 28 insertions(+), 22 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll index e0c9fbff800..3c9c2b920cb 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll @@ -151,7 +151,7 @@ deprecated class SensitiveCommunicationConfig extends TaintTracking::Configurati } } -private module SensitiveCommunicationConfig implements DataFlow::ConfigSig { +module SensitiveCommunicationConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveInfoExpr } predicate isSink(DataFlow::Node sink) { diff --git a/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll index d066f4974a1..9df15067be9 100644 --- a/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ArbitraryApkInstallationQuery.qll @@ -9,7 +9,7 @@ private import semmle.code.java.security.ArbitraryApkInstallation * A dataflow configuration for flow from an external source of an APK to the * `setData[AndType][AndNormalize]` method of an intent. */ -private module ApkInstallationConfig implements DataFlow::ConfigSig { +module ApkInstallationConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node node) { node instanceof ExternalApkSource } predicate isSink(DataFlow::Node node) { diff --git a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll index 9ba1b9c7e87..2590a3c3652 100644 --- a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll @@ -111,7 +111,7 @@ deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configu override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } } -private module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { +module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } diff --git a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll index 94b1877a4a3..844b53b05fd 100644 --- a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll @@ -23,7 +23,7 @@ deprecated class FragmentInjectionTaintConf extends TaintTracking::Configuration } } -private module FragmentInjectionTaintConfig implements DataFlow::ConfigSig { +module FragmentInjectionTaintConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof FragmentInjectionSink } diff --git a/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll b/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll index 1d942cc1b97..6080cd188b3 100644 --- a/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll +++ b/java/ql/lib/semmle/code/java/security/HardcodedCredentialsApiCallQuery.qll @@ -58,7 +58,7 @@ deprecated class HardcodedCredentialApiCallConfiguration extends DataFlow::Confi /** * A data-flow configuration that tracks flow from a hard-coded credential in a call to a sensitive Java API which may compromise security. */ -private module HardcodedCredentialApiCallConfig implements DataFlow::ConfigSig { +module HardcodedCredentialApiCallConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node n) { n.asExpr() instanceof HardcodedExpr and not n.asExpr().getEnclosingCallable() instanceof ToStringMethod diff --git a/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll b/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll index ca46ba8cba0..cc827d34d46 100644 --- a/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll +++ b/java/ql/lib/semmle/code/java/security/HttpsUrlsQuery.qll @@ -29,7 +29,7 @@ deprecated class HttpStringToUrlOpenMethodFlowConfig extends TaintTracking::Conf /** * A taint tracking configuration for HTTP connections. */ -private module HttpStringToUrlOpenMethodFlowConfig implements DataFlow::ConfigSig { +module HttpStringToUrlOpenMethodFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof HttpStringLiteral } predicate isSink(DataFlow::Node sink) { sink instanceof UrlOpenSink } diff --git a/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll index 83e653bbe18..60e16662d9a 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureBasicAuthQuery.qll @@ -27,7 +27,7 @@ deprecated class BasicAuthFlowConfig extends TaintTracking::Configuration { * A taint tracking configuration for the Basic authentication scheme * being used in HTTP connections. */ -private module BasicAuthFlowConfig implements DataFlow::ConfigSig { +module BasicAuthFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof InsecureBasicAuthSource } predicate isSink(DataFlow::Node sink) { sink instanceof InsecureBasicAuthSink } diff --git a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll index d54653e3046..a7514ceff96 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureTrustManagerQuery.qll @@ -30,7 +30,7 @@ deprecated class InsecureTrustManagerConfiguration extends DataFlow::Configurati * A configuration to model the flow of an insecure `TrustManager` * to the initialization of an SSL context. */ -private module InsecureTrustManagerConfig implements DataFlow::ConfigSig { +module InsecureTrustManagerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof InsecureTrustManagerSource } predicate isSink(DataFlow::Node sink) { sink instanceof InsecureTrustManagerSink } diff --git a/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll b/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll index 6b54031e4d3..d0d51ffbf08 100644 --- a/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsufficientKeySizeQuery.qll @@ -23,7 +23,7 @@ deprecated class KeySizeConfiguration extends DataFlow::Configuration { /** * A data flow configuration for tracking key sizes used in cryptographic algorithms. */ -private module KeySizeConfig implements DataFlow::StateConfigSig { +module KeySizeConfig implements DataFlow::StateConfigSig { class FlowState = DataFlow::FlowState; predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll index 970cb4867fd..1a7a8502ddb 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -35,7 +35,7 @@ deprecated class IntentUriPermissionManipulationConf extends TaintTracking::Conf } } -private module IntentUriPermissionManipulationConfig implements DataFlow::ConfigSig { +module IntentUriPermissionManipulationConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof IntentUriPermissionManipulationSink } diff --git a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll index a26e08d3edc..c5696448a0b 100644 --- a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll @@ -23,7 +23,7 @@ deprecated class LogInjectionConfiguration extends TaintTracking::Configuration } } -private module LogInjectionConfig implements DataFlow::ConfigSig { +module LogInjectionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof LogInjectionSink } diff --git a/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll b/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll index 38d80b43996..c316da2f965 100644 --- a/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll +++ b/java/ql/lib/semmle/code/java/security/MissingJWTSignatureCheckQuery.qll @@ -28,7 +28,7 @@ deprecated class MissingJwtSignatureCheckConf extends DataFlow::Configuration { * Models flow from signing keys assignments to qualifiers of JWT insecure parsers. * This is used to determine whether a `JwtParser` performing unsafe parsing has a signing key set. */ -private module MissingJwtSignatureCheckConfig implements DataFlow::ConfigSig { +module MissingJwtSignatureCheckConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof JwtParserWithInsecureParseSource } predicate isSink(DataFlow::Node sink) { sink instanceof JwtParserWithInsecureParseSink } diff --git a/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll b/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll index 613b9844459..1fd25df25aa 100644 --- a/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll +++ b/java/ql/lib/semmle/code/java/security/PartialPathTraversalQuery.qll @@ -28,7 +28,7 @@ deprecated class PartialPathTraversalFromRemoteConfig extends TaintTracking::Con * that is used to validate against path traversal, but is insufficient * and remains vulnerable to Partial Path Traversal. */ -private module PartialPathTraversalFromRemoteConfig implements DataFlow::ConfigSig { +module PartialPathTraversalFromRemoteConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node node) { node instanceof RemoteFlowSource } predicate isSink(DataFlow::Node node) { diff --git a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll index 0d9df09bb74..87affb3b457 100644 --- a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll +++ b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll @@ -26,7 +26,7 @@ deprecated class RsaWithoutOaepConfig extends DataFlow::Configuration { } } -private module RsaWithoutOaepConfig implements DataFlow::ConfigSig { +module RsaWithoutOaepConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { exists(CompileTimeConstantExpr specExpr, string spec | specExpr.getStringValue() = spec and diff --git a/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll b/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll index ea687d32a0a..d9ed2b970b0 100644 --- a/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll +++ b/java/ql/lib/semmle/code/java/security/SensitiveLoggingQuery.qll @@ -49,7 +49,7 @@ deprecated class SensitiveLoggerConfiguration extends TaintTracking::Configurati } /** A data-flow configuration for identifying potentially-sensitive data flowing to a log output. */ -private module SensitiveLoggerConfig implements DataFlow::ConfigSig { +module SensitiveLoggerConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source.asExpr() instanceof CredentialExpr } predicate isSink(DataFlow::Node sink) { sinkNode(sink, "logging") } diff --git a/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll b/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll index 6a9a524e11a..38d426adc5a 100644 --- a/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll +++ b/java/ql/lib/semmle/code/java/security/StaticInitializationVectorQuery.qll @@ -165,7 +165,7 @@ deprecated class StaticInitializationVectorConfig extends TaintTracking::Configu /** * A config that tracks dataflow to initializing a cipher with a static initialization vector. */ -private module StaticInitializationVectorConfig implements DataFlow::ConfigSig { +module StaticInitializationVectorConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof StaticInitializationVectorSource } predicate isSink(DataFlow::Node sink) { sink instanceof EncryptionInitializationSink } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll index 979c0c9c149..83658be36ad 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -22,7 +22,7 @@ deprecated class SslEndpointIdentificationFlowConfig extends TaintTracking::Conf } } -private module SslEndpointIdentificationFlowConfig implements DataFlow::ConfigSig { +module SslEndpointIdentificationFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } predicate isSink(DataFlow::Node sink) { sink instanceof SslConnectionCreation } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll index b59c4b79655..1a5f6c6b37b 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll @@ -26,7 +26,7 @@ deprecated class UnsafeContentResolutionConf extends TaintTracking::Configuratio } } -private module UnsafeContentResolutionConfig implements DataFlow::ConfigSig { +module UnsafeContentResolutionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof ContentUriResolutionSink } diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 352c3b481a6..f76edbc80a4 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -437,7 +437,13 @@ deprecated class UnsafeTypeConfig extends TaintTracking2::Configuration { } } -private module UnsafeTypeConfig implements DataFlow::ConfigSig { +/** + * Tracks flow from a remote source to a type descriptor (e.g. a `java.lang.Class` instance) + * passed to a deserialization method. + * + * If this is user-controlled, arbitrary code could be executed while instantiating the user-specified type. + */ +module UnsafeTypeConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeTypeSink } @@ -528,7 +534,7 @@ deprecated class SafeObjectMapperConfig extends DataFlow2::Configuration { } } -private module SafeObjectMapperConfig implements DataFlow::ConfigSig { +module SafeObjectMapperConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof SetPolymorphicTypeValidatorSource } predicate isSink(DataFlow::Node sink) { sink instanceof ObjectMapperReadQualifier } diff --git a/java/ql/lib/semmle/code/java/security/XmlParsers.qll b/java/ql/lib/semmle/code/java/security/XmlParsers.qll index c02587b7f26..dd28d8b0117 100644 --- a/java/ql/lib/semmle/code/java/security/XmlParsers.qll +++ b/java/ql/lib/semmle/code/java/security/XmlParsers.qll @@ -1013,7 +1013,7 @@ deprecated class SafeTransformerFactoryFlowConfig extends DataFlow3::Configurati * A dataflow configuration that identifies `TransformerFactory` and `SAXTransformerFactory` * instances that have been safely configured. */ -private module SafeTransformerFactoryFlowConfig implements DataFlow::ConfigSig { +module SafeTransformerFactoryFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeTransformerFactory } predicate isSink(DataFlow::Node sink) { diff --git a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll index e85e130e381..4d7f963e968 100644 --- a/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll +++ b/java/ql/lib/semmle/code/java/security/regexp/PolynomialReDoSQuery.qll @@ -65,7 +65,7 @@ deprecated predicate hasPolynomialReDoSResult( } /** A configuration for Polynomial ReDoS queries. */ -private module PolynomialRedosConfig implements DataFlow::ConfigSig { +module PolynomialRedosConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } predicate isSink(DataFlow::Node sink) { From 6a3eadf6cb573bae5f9c24ed882d7104ffca7f71 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 22 Mar 2023 23:38:03 -0400 Subject: [PATCH 060/141] Refactor ImplicitPendingIntents --- .../security/ImplicitPendingIntentsQuery.qll | 51 ++++++++++++++++++- .../CWE/CWE-927/ImplicitPendingIntents.ql | 6 +-- .../CWE-927/ImplicitPendingIntentsTest.ql | 2 +- 3 files changed, 54 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/ImplicitPendingIntentsQuery.qll b/java/ql/lib/semmle/code/java/security/ImplicitPendingIntentsQuery.qll index 814dc93f8d0..c02abb4de81 100644 --- a/java/ql/lib/semmle/code/java/security/ImplicitPendingIntentsQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ImplicitPendingIntentsQuery.qll @@ -7,10 +7,12 @@ import semmle.code.java.frameworks.android.PendingIntent import semmle.code.java.security.ImplicitPendingIntents /** + * DEPRECATED: Use `ImplicitPendingIntentStartFlow` instead. + * * A taint tracking configuration for implicit `PendingIntent`s * being wrapped in another implicit `Intent` that gets started. */ -class ImplicitPendingIntentStartConf extends TaintTracking::Configuration { +deprecated class ImplicitPendingIntentStartConf extends TaintTracking::Configuration { ImplicitPendingIntentStartConf() { this = "ImplicitPendingIntentStartConf" } override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { @@ -52,3 +54,50 @@ class ImplicitPendingIntentStartConf extends TaintTracking::Configuration { c instanceof DataFlow::ArrayContent } } + +/** + * A taint tracking configuration for implicit `PendingIntent`s + * being wrapped in another implicit `Intent` that gets started. + */ +module ImplicitPendingIntentStartConfig implements DataFlow::StateConfigSig { + class FlowState = DataFlow::FlowState; + + predicate isSource(DataFlow::Node source, FlowState state) { + source.(ImplicitPendingIntentSource).hasState(state) + } + + predicate isSink(DataFlow::Node sink, FlowState state) { + sink.(ImplicitPendingIntentSink).hasState(state) + } + + predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof ExplicitIntentSanitizer } + + predicate isBarrier(DataFlow::Node node, FlowState state) { none() } + + predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { + any(ImplicitPendingIntentAdditionalTaintStep c).step(node1, node2) + } + + predicate isAdditionalFlowStep( + DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2 + ) { + any(ImplicitPendingIntentAdditionalTaintStep c).step(node1, state1, node2, state2) + } + + predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) { + isSink(node, _) and + allowIntentExtrasImplicitRead(node, c) + or + isAdditionalFlowStep(node, _) and + c.(DataFlow::FieldContent).getType() instanceof PendingIntent + or + // Allow implicit reads of Intent arrays for steps like getActivities + // or sinks like startActivities + (isSink(node, _) or isAdditionalFlowStep(node, _, _, _)) and + node.getType().(Array).getElementType() instanceof TypeIntent and + c instanceof DataFlow::ArrayContent + } +} + +module ImplicitPendingIntentStartFlow = + TaintTracking::GlobalWithState; diff --git a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql index 58eb6300868..f4065ceeae6 100644 --- a/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql +++ b/java/ql/src/Security/CWE/CWE-927/ImplicitPendingIntents.ql @@ -15,10 +15,10 @@ import java import semmle.code.java.dataflow.DataFlow import semmle.code.java.security.ImplicitPendingIntentsQuery -import DataFlow::PathGraph +import ImplicitPendingIntentStartFlow::PathGraph -from DataFlow::PathNode source, DataFlow::PathNode sink -where any(ImplicitPendingIntentStartConf conf).hasFlowPath(source, sink) +from ImplicitPendingIntentStartFlow::PathNode source, ImplicitPendingIntentStartFlow::PathNode sink +where ImplicitPendingIntentStartFlow::flowPath(source, sink) select sink.getNode(), source, sink, "$@ and sent to an unspecified third party through a PendingIntent.", source.getNode(), "An implicit Intent is created" diff --git a/java/ql/test/query-tests/security/CWE-927/ImplicitPendingIntentsTest.ql b/java/ql/test/query-tests/security/CWE-927/ImplicitPendingIntentsTest.ql index 871dcd2cef2..972653380aa 100644 --- a/java/ql/test/query-tests/security/CWE-927/ImplicitPendingIntentsTest.ql +++ b/java/ql/test/query-tests/security/CWE-927/ImplicitPendingIntentsTest.ql @@ -9,7 +9,7 @@ class ImplicitPendingIntentsTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "hasImplicitPendingIntent" and - exists(DataFlow::Node sink | any(ImplicitPendingIntentStartConf c).hasFlowTo(sink) | + exists(DataFlow::Node sink | ImplicitPendingIntentStartFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From a119b99f929108084fb18ec7f7b1fd836f6f6dc6 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 28 Mar 2023 23:48:18 -0400 Subject: [PATCH 061/141] Documentation additions --- .../lib/semmle/code/java/security/FragmentInjectionQuery.qll | 4 ++++ java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll | 3 +++ 2 files changed, 7 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll index 844b53b05fd..6164a6663a0 100644 --- a/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/FragmentInjectionQuery.qll @@ -23,6 +23,10 @@ deprecated class FragmentInjectionTaintConf extends TaintTracking::Configuration } } +/** + * A taint-tracking configuration for unsafe user input + * that is used to create Android fragments dynamically. + */ module FragmentInjectionTaintConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } diff --git a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll index c5696448a0b..2610870b383 100644 --- a/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/LogInjectionQuery.qll @@ -23,6 +23,9 @@ deprecated class LogInjectionConfiguration extends TaintTracking::Configuration } } +/** + * A taint-tracking configuration for tracking untrusted user input used in log entries. + */ module LogInjectionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } From d24c5071d864504c41123340feb9848be869f418 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Tue, 28 Mar 2023 23:48:31 -0400 Subject: [PATCH 062/141] Move private helper method out of module --- java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll b/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll index f0ade403bfc..f21b9552061 100644 --- a/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll +++ b/java/ql/lib/semmle/code/java/frameworks/SnakeYaml.qll @@ -28,16 +28,16 @@ class Yaml extends RefType { Yaml() { this.getAnAncestor().hasQualifiedName("org.yaml.snakeyaml", "Yaml") } } +private DataFlow::ExprNode yamlClassInstanceExprArgument(ClassInstanceExpr cie) { + cie.getConstructedType() instanceof Yaml and + result.getExpr() = cie.getArgument(0) +} + private module SafeYamlConstructionFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeSnakeYamlConstruction } predicate isSink(DataFlow::Node sink) { sink = yamlClassInstanceExprArgument(_) } - additional DataFlow::ExprNode yamlClassInstanceExprArgument(ClassInstanceExpr cie) { - cie.getConstructedType() instanceof Yaml and - result.getExpr() = cie.getArgument(0) - } - additional ClassInstanceExpr getSafeYaml() { SafeYamlConstructionFlow::flowTo(yamlClassInstanceExprArgument(result)) } From a798b1959fc081632560b87bf928b4590eae43a1 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 09:24:52 -0400 Subject: [PATCH 063/141] Replace `flow(_, sink)` with `flowTo(sink)` --- java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll | 2 +- java/ql/lib/semmle/code/java/security/ExternalAPIs.qll | 2 +- .../CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll b/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll index fa19a25f110..0fdf69eb8a3 100644 --- a/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll +++ b/java/ql/lib/semmle/code/java/security/CleartextStorageQuery.qll @@ -56,7 +56,7 @@ private class DefaultCleartextStorageSanitizer extends CleartextStorageSanitizer DefaultCleartextStorageSanitizer() { this.getType() instanceof NumericType or this.getType() instanceof BooleanType or - EncryptedValueFlow::flow(_, this) + EncryptedValueFlow::flowTo(this) } } diff --git a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll index 2590a3c3652..6e534b89c1d 100644 --- a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll @@ -127,7 +127,7 @@ deprecated class UntrustedDataToExternalAPIConfig = UntrustedDataToExternalApiCo /** A node representing untrusted data being passed to an external API. */ class UntrustedExternalApiDataNode extends ExternalApiDataNode { - UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flow(_, this) } + UntrustedExternalApiDataNode() { UntrustedDataToExternalApiFlow::flowTo(this) } /** Gets a source of untrusted data which is passed to this external API data node. */ DataFlow::Node getAnUntrustedSource() { UntrustedDataToExternalApiFlow::flow(result, this) } diff --git a/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql b/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql index 621d2a0105c..7d7b8e2d2a5 100644 --- a/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql +++ b/java/ql/test/query-tests/security/CWE-798/semmle/tests/HardcodedCredentialsApiCall.ql @@ -9,7 +9,7 @@ class HardcodedCredentialsApiCallTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "HardcodedCredentialsApiCall" and - exists(DataFlow::Node sink | HardcodedCredentialApiCallFlow::flow(_, sink) | + exists(DataFlow::Node sink | HardcodedCredentialApiCallFlow::flowTo(sink) | sink.getLocation() = location and element = sink.toString() and value = "" From 59b1460c49203dd3052f6bda579100bf1c416e9b Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:15:53 -0400 Subject: [PATCH 064/141] Documentation for UnsafeCertTrustQuery --- .../lib/semmle/code/java/security/UnsafeCertTrustQuery.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll index 83658be36ad..0b45e150c0c 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeCertTrustQuery.qll @@ -22,6 +22,9 @@ deprecated class SslEndpointIdentificationFlowConfig extends TaintTracking::Conf } } +/** + * A taint flow configuration for SSL connections created without a proper certificate trust configuration. + */ module SslEndpointIdentificationFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof SslConnectionInit } @@ -30,6 +33,9 @@ module SslEndpointIdentificationFlowConfig implements DataFlow::ConfigSig { predicate isBarrier(DataFlow::Node sanitizer) { sanitizer instanceof SslUnsafeCertTrustSanitizer } } +/** + * Taint flow for SSL connections created without a proper certificate trust configuration. + */ module SslEndpointIdentificationFlow = TaintTracking::Global; /** From 11d72ffc1fc2542ead9a0a8a347a5cea2b2f1e27 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:18:09 -0400 Subject: [PATCH 065/141] Documentation for UnsafeContentUriResolutionQuery --- .../code/java/security/UnsafeContentUriResolutionQuery.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll index 1a5f6c6b37b..424edace82a 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeContentUriResolutionQuery.qll @@ -26,6 +26,9 @@ deprecated class UnsafeContentResolutionConf extends TaintTracking::Configuratio } } +/** + * A taint-tracking configuration to find paths from remote sources to content URI resolutions. + */ module UnsafeContentResolutionConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof RemoteFlowSource } From c7fd216c3c85bf5faf9a85205d1e134d22801431 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:18:54 -0400 Subject: [PATCH 066/141] Documentation for RsaWithoutOaepQuery --- java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll index 87affb3b457..848a1c2b990 100644 --- a/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll +++ b/java/ql/lib/semmle/code/java/security/RsaWithoutOaepQuery.qll @@ -26,6 +26,9 @@ deprecated class RsaWithoutOaepConfig extends DataFlow::Configuration { } } +/** + * A configuration for finding RSA ciphers initialized without using OAEP padding. + */ module RsaWithoutOaepConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { exists(CompileTimeConstantExpr specExpr, string spec | From 96cf4f16faeda1749ac7dc03362158b2ca0a2bea Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:21:49 -0400 Subject: [PATCH 067/141] Documentation for ExternalAPIs --- java/ql/lib/semmle/code/java/security/ExternalAPIs.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll index 6e534b89c1d..89b24006475 100644 --- a/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll +++ b/java/ql/lib/semmle/code/java/security/ExternalAPIs.qll @@ -111,6 +111,9 @@ deprecated class UntrustedDataToExternalApiConfig extends TaintTracking::Configu override predicate isSink(DataFlow::Node sink) { sink instanceof ExternalApiDataNode } } +/** + * Taint tracking configuration for flow from `RemoteFlowSource`s to `ExternalApiDataNode`s. + */ module UntrustedDataToExternalApiConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } From 1016b7323f5cd8f29fbd22e666fb7653d7b447e5 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:22:46 -0400 Subject: [PATCH 068/141] Documentation for ConditionalBypassQuery --- .../lib/semmle/code/java/security/ConditionalBypassQuery.qll | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll b/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll index eb5d6672ae3..a45afda4105 100644 --- a/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ConditionalBypassQuery.qll @@ -53,6 +53,9 @@ deprecated class ConditionalBypassFlowConfig extends TaintTracking::Configuratio } } +/** + * A taint tracking configuration for untrusted data flowing to sensitive conditions. + */ module ConditionalBypassFlowConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } @@ -64,6 +67,6 @@ module ConditionalBypassFlowConfig implements DataFlow::ConfigSig { } /** - * A taint tracking configuration for untrusted data flowing to sensitive conditions. + * Taint tracking flow for untrusted data flowing to sensitive conditions. */ module ConditionalBypassFlow = TaintTracking::Global; From 1a89c3fa7c4c236124e670c3c7c8fa70970de81d Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:24:25 -0400 Subject: [PATCH 069/141] Documentation for AndroidSensitiveCommunicationQuery --- .../code/java/security/AndroidSensitiveCommunicationQuery.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll index 3c9c2b920cb..e8d5a6d42d1 100644 --- a/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/AndroidSensitiveCommunicationQuery.qll @@ -151,6 +151,9 @@ deprecated class SensitiveCommunicationConfig extends TaintTracking::Configurati } } +/** + * Taint configuration tracking flow from variables containing sensitive information to broadcast Intents. + */ module SensitiveCommunicationConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source.asExpr() instanceof SensitiveInfoExpr } From cf7aa2e4208e97e90cf37b4ce33bc03b18602086 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:27:45 -0400 Subject: [PATCH 070/141] Documentation UnsafeDeserializationQuery --- .../code/java/security/UnsafeDeserializationQuery.qll | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index f76edbc80a4..b6d78b6318e 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -534,6 +534,12 @@ deprecated class SafeObjectMapperConfig extends DataFlow2::Configuration { } } +/** + * Tracks flow from calls that set a type validator to a subsequent Jackson deserialization method call, + * including across builder method calls. + * + * Such a Jackson deserialization method call is safe because validation will likely prevent instantiating unexpected types. + */ module SafeObjectMapperConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node src) { src instanceof SetPolymorphicTypeValidatorSource } From 312508e27933b71eff2ec314b9955e6edf2146e4 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:28:10 -0400 Subject: [PATCH 071/141] Documentation for IntentUriPermissionManipulationQuery --- .../java/security/IntentUriPermissionManipulationQuery.qll | 3 +++ 1 file changed, 3 insertions(+) diff --git a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll index 1a7a8502ddb..f563b4bf093 100644 --- a/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/IntentUriPermissionManipulationQuery.qll @@ -35,6 +35,9 @@ deprecated class IntentUriPermissionManipulationConf extends TaintTracking::Conf } } +/** + * A taint tracking configuration for user-provided Intents being returned to third party apps. + */ module IntentUriPermissionManipulationConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource } From 58ad8e429215f7b79a9c6a030c61738e048c8b34 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Wed, 29 Mar 2023 22:43:26 -0400 Subject: [PATCH 072/141] ExternallyControlledFormatString change note --- .../change-notes/2023-03-29-moved-configurations-for-queries.md | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md b/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md index b99d43364fa..d7cc29f5521 100644 --- a/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md +++ b/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md @@ -7,3 +7,4 @@ category: minorAnalysis * Added the `XssQuery.qll` library to provide the `XssFlow` taint-tracking module to reason about cross site scripting vulnerabilities. * Added the `LdapInjectionQuery.qll` library to provide the `LdapInjectionFlow` taint-tracking module to reason about LDAP injection vulnerabilities. * Added the `ResponseSplittingQuery.qll` library to provide the `ResponseSplittingFlow` taint-tracking module to reason about response splitting vulnerabilities. +* Added the `ExternallyControlledFormatStringQuery.qll` library to provide the `ExternallyControlledFormatStringFlow` taint-tracking module to reason about externally controlled format string vulnerabilities. \ No newline at end of file From 47783326c277e5086ea9c41f9a0fe5969accbc1a Mon Sep 17 00:00:00 2001 From: erik-krogh Date: Thu, 30 Mar 2023 14:15:25 +0200 Subject: [PATCH 073/141] add test for https.createServer in DisablingCertificateValidation.ql --- .../CWE-295/DisablingCertificateValidation.expected | 1 + javascript/ql/test/query-tests/Security/CWE-295/tst.js | 6 +++++- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/javascript/ql/test/query-tests/Security/CWE-295/DisablingCertificateValidation.expected b/javascript/ql/test/query-tests/Security/CWE-295/DisablingCertificateValidation.expected index a99ae396964..649326b7c6d 100644 --- a/javascript/ql/test/query-tests/Security/CWE-295/DisablingCertificateValidation.expected +++ b/javascript/ql/test/query-tests/Security/CWE-295/DisablingCertificateValidation.expected @@ -9,3 +9,4 @@ | tst.js:45:2:45:28 | rejectU ... !!false | Disabling certificate validation is strongly discouraged. | | tst.js:48:2:48:26 | rejectU ... : !true | Disabling certificate validation is strongly discouraged. | | tst.js:74:9:74:33 | rejectU ... : false | Disabling certificate validation is strongly discouraged. | +| tst.js:80:5:80:29 | rejectU ... : false | Disabling certificate validation is strongly discouraged. | diff --git a/javascript/ql/test/query-tests/Security/CWE-295/tst.js b/javascript/ql/test/query-tests/Security/CWE-295/tst.js index 8088b767e18..d64239d64db 100644 --- a/javascript/ql/test/query-tests/Security/CWE-295/tst.js +++ b/javascript/ql/test/query-tests/Security/CWE-295/tst.js @@ -74,4 +74,8 @@ function getSomeunsafeOptions() { rejectUnauthorized: false // NOT OK } } -new https.Agent(getSomeunsafeOptions()); \ No newline at end of file +new https.Agent(getSomeunsafeOptions()); + +https.createServer({ + rejectUnauthorized: false // NOT OK +}); \ No newline at end of file From 06ad5b3949979da1b7a162a424b6c1061e232c0c Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Thu, 30 Mar 2023 16:41:04 +0200 Subject: [PATCH 074/141] Revert "Swift: add upgrade/downgrade scripts" This reverts commit 48c23033918a5ebac9ab8d543f9b1c0f13008a52. This is done to merge main and readd the scripts in another commit. --- .../module_decl_exported_modules.ql | 15 - .../module_decl_imported_modules.ql | 15 - .../old.dbscheme | 2597 ---------------- .../swift.dbscheme | 2601 ----------------- .../upgrade.properties | 4 - .../old.dbscheme | 2601 ----------------- .../swift.dbscheme | 2597 ---------------- .../upgrade.properties | 4 - 8 files changed, 10434 deletions(-) delete mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql delete mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql delete mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme delete mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme delete mode 100644 swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties delete mode 100644 swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme delete mode 100644 swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme delete mode 100644 swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql deleted file mode 100644 index 6f2f7125742..00000000000 --- a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_exported_modules.ql +++ /dev/null @@ -1,15 +0,0 @@ -class Element extends @element { - string toString() { none() } -} - -int getExportedModuleIndex(Element m, Element i) { - i = - rank[result + 1](Element j, string name | - module_decl_exported_modules(m, j) and type_decls(j, name) - | - j order by name - ) -} - -from Element m, Element i -select m, getExportedModuleIndex(m, i), i diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql deleted file mode 100644 index 88093d6e5e5..00000000000 --- a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/module_decl_imported_modules.ql +++ /dev/null @@ -1,15 +0,0 @@ -class Element extends @element { - string toString() { none() } -} - -int getImportedModuleIndex(Element m, Element i) { - i = - rank[result + 1](Element j, string name | - module_decl_imported_modules(m, j) and type_decls(j, name) - | - j order by name - ) -} - -from Element m, Element i -select m, getImportedModuleIndex(m, i), i diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme deleted file mode 100644 index db22947f6ae..00000000000 --- a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/old.dbscheme +++ /dev/null @@ -1,2597 +0,0 @@ -// generated by codegen/codegen.py - -// from prefix.dbscheme -/** - * The source location of the snapshot. - */ -sourceLocationPrefix( - string prefix: string ref -); - - -// from schema.py - -@element = - @callable -| @file -| @generic_context -| @locatable -| @location -| @type -; - -#keyset[id] -element_is_unknown( - int id: @element ref -); - -@callable = - @abstract_closure_expr -| @abstract_function_decl -; - -#keyset[id] -callable_names( - int id: @callable ref, - string name: string ref -); - -#keyset[id] -callable_self_params( - int id: @callable ref, - int self_param: @param_decl_or_none ref -); - -#keyset[id, index] -callable_params( - int id: @callable ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -#keyset[id] -callable_bodies( - int id: @callable ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id, index] -callable_captures( - int id: @callable ref, - int index: int ref, - int capture: @captured_decl_or_none ref -); - -@file = - @db_file -; - -#keyset[id] -files( - int id: @file ref, - string name: string ref -); - -#keyset[id] -file_is_successfully_extracted( - int id: @file ref -); - -@locatable = - @argument -| @ast_node -| @comment -| @diagnostics -| @error_element -; - -#keyset[id] -locatable_locations( - int id: @locatable ref, - int location: @location_or_none ref -); - -@location = - @db_location -; - -#keyset[id] -locations( - int id: @location ref, - int file: @file_or_none ref, - int start_line: int ref, - int start_column: int ref, - int end_line: int ref, - int end_column: int ref -); - -@ast_node = - @availability_info -| @availability_spec -| @case_label_item -| @condition_element -| @decl -| @expr -| @pattern -| @stmt -| @stmt_condition -| @type_repr -; - -comments( - unique int id: @comment, - string text: string ref -); - -db_files( - unique int id: @db_file -); - -db_locations( - unique int id: @db_location -); - -diagnostics( - unique int id: @diagnostics, - string text: string ref, - int kind: int ref -); - -@error_element = - @error_expr -| @error_type -| @overloaded_decl_ref_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_chain_result_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @unresolved_type -| @unresolved_type_conversion_expr -| @unspecified_element -; - -availability_infos( - unique int id: @availability_info -); - -#keyset[id] -availability_info_is_unavailable( - int id: @availability_info ref -); - -#keyset[id, index] -availability_info_specs( - int id: @availability_info ref, - int index: int ref, - int spec: @availability_spec_or_none ref -); - -@availability_spec = - @other_availability_spec -| @platform_version_availability_spec -; - -unspecified_elements( - unique int id: @unspecified_element, - string property: string ref, - string error: string ref -); - -#keyset[id] -unspecified_element_parents( - int id: @unspecified_element ref, - int parent: @element ref -); - -#keyset[id] -unspecified_element_indices( - int id: @unspecified_element ref, - int index: int ref -); - -other_availability_specs( - unique int id: @other_availability_spec -); - -platform_version_availability_specs( - unique int id: @platform_version_availability_spec, - string platform: string ref, - string version: string ref -); - -@decl = - @captured_decl -| @enum_case_decl -| @extension_decl -| @if_config_decl -| @import_decl -| @missing_member_decl -| @operator_decl -| @pattern_binding_decl -| @pound_diagnostic_decl -| @precedence_group_decl -| @top_level_code_decl -| @value_decl -; - -#keyset[id] -decls( //dir=decl - int id: @decl ref, - int module: @module_decl_or_none ref -); - -#keyset[id, index] -decl_members( //dir=decl - int id: @decl ref, - int index: int ref, - int member: @decl_or_none ref -); - -@generic_context = - @abstract_function_decl -| @extension_decl -| @generic_type_decl -| @subscript_decl -; - -#keyset[id, index] -generic_context_generic_type_params( //dir=decl - int id: @generic_context ref, - int index: int ref, - int generic_type_param: @generic_type_param_decl_or_none ref -); - -captured_decls( //dir=decl - unique int id: @captured_decl, - int decl: @value_decl_or_none ref -); - -#keyset[id] -captured_decl_is_direct( //dir=decl - int id: @captured_decl ref -); - -#keyset[id] -captured_decl_is_escaping( //dir=decl - int id: @captured_decl ref -); - -enum_case_decls( //dir=decl - unique int id: @enum_case_decl -); - -#keyset[id, index] -enum_case_decl_elements( //dir=decl - int id: @enum_case_decl ref, - int index: int ref, - int element: @enum_element_decl_or_none ref -); - -extension_decls( //dir=decl - unique int id: @extension_decl, - int extended_type_decl: @nominal_type_decl_or_none ref -); - -#keyset[id, index] -extension_decl_protocols( //dir=decl - int id: @extension_decl ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -if_config_decls( //dir=decl - unique int id: @if_config_decl -); - -#keyset[id, index] -if_config_decl_active_elements( //dir=decl - int id: @if_config_decl ref, - int index: int ref, - int active_element: @ast_node_or_none ref -); - -import_decls( //dir=decl - unique int id: @import_decl -); - -#keyset[id] -import_decl_is_exported( //dir=decl - int id: @import_decl ref -); - -#keyset[id] -import_decl_imported_modules( //dir=decl - int id: @import_decl ref, - int imported_module: @module_decl_or_none ref -); - -#keyset[id, index] -import_decl_declarations( //dir=decl - int id: @import_decl ref, - int index: int ref, - int declaration: @value_decl_or_none ref -); - -missing_member_decls( //dir=decl - unique int id: @missing_member_decl, - string name: string ref -); - -@operator_decl = - @infix_operator_decl -| @postfix_operator_decl -| @prefix_operator_decl -; - -#keyset[id] -operator_decls( //dir=decl - int id: @operator_decl ref, - string name: string ref -); - -pattern_binding_decls( //dir=decl - unique int id: @pattern_binding_decl -); - -#keyset[id, index] -pattern_binding_decl_inits( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int init: @expr_or_none ref -); - -#keyset[id, index] -pattern_binding_decl_patterns( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int pattern: @pattern_or_none ref -); - -pound_diagnostic_decls( //dir=decl - unique int id: @pound_diagnostic_decl, - int kind: int ref, - int message: @string_literal_expr_or_none ref -); - -precedence_group_decls( //dir=decl - unique int id: @precedence_group_decl -); - -top_level_code_decls( //dir=decl - unique int id: @top_level_code_decl, - int body: @brace_stmt_or_none ref -); - -@value_decl = - @abstract_function_decl -| @abstract_storage_decl -| @enum_element_decl -| @type_decl -; - -#keyset[id] -value_decls( //dir=decl - int id: @value_decl ref, - int interface_type: @type_or_none ref -); - -@abstract_function_decl = - @constructor_decl -| @destructor_decl -| @func_decl -; - -@abstract_storage_decl = - @subscript_decl -| @var_decl -; - -#keyset[id, index] -abstract_storage_decl_accessor_decls( //dir=decl - int id: @abstract_storage_decl ref, - int index: int ref, - int accessor_decl: @accessor_decl_or_none ref -); - -enum_element_decls( //dir=decl - unique int id: @enum_element_decl, - string name: string ref -); - -#keyset[id, index] -enum_element_decl_params( //dir=decl - int id: @enum_element_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -infix_operator_decls( //dir=decl - unique int id: @infix_operator_decl -); - -#keyset[id] -infix_operator_decl_precedence_groups( //dir=decl - int id: @infix_operator_decl ref, - int precedence_group: @precedence_group_decl_or_none ref -); - -postfix_operator_decls( //dir=decl - unique int id: @postfix_operator_decl -); - -prefix_operator_decls( //dir=decl - unique int id: @prefix_operator_decl -); - -@type_decl = - @abstract_type_param_decl -| @generic_type_decl -| @module_decl -; - -#keyset[id] -type_decls( //dir=decl - int id: @type_decl ref, - string name: string ref -); - -#keyset[id, index] -type_decl_base_types( //dir=decl - int id: @type_decl ref, - int index: int ref, - int base_type: @type_or_none ref -); - -@abstract_type_param_decl = - @associated_type_decl -| @generic_type_param_decl -; - -constructor_decls( //dir=decl - unique int id: @constructor_decl -); - -destructor_decls( //dir=decl - unique int id: @destructor_decl -); - -@func_decl = - @accessor_decl -| @concrete_func_decl -; - -@generic_type_decl = - @nominal_type_decl -| @opaque_type_decl -| @type_alias_decl -; - -module_decls( //dir=decl - unique int id: @module_decl -); - -#keyset[id] -module_decl_is_builtin_module( //dir=decl - int id: @module_decl ref -); - -#keyset[id] -module_decl_is_system_module( //dir=decl - int id: @module_decl ref -); - -module_decl_imported_modules( //dir=decl - int id: @module_decl ref, - int imported_module: @module_decl_or_none ref -); - -module_decl_exported_modules( //dir=decl - int id: @module_decl ref, - int exported_module: @module_decl_or_none ref -); - -subscript_decls( //dir=decl - unique int id: @subscript_decl, - int element_type: @type_or_none ref -); - -#keyset[id, index] -subscript_decl_params( //dir=decl - int id: @subscript_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -@var_decl = - @concrete_var_decl -| @param_decl -; - -#keyset[id] -var_decls( //dir=decl - int id: @var_decl ref, - string name: string ref, - int type_: @type_or_none ref -); - -#keyset[id] -var_decl_attached_property_wrapper_types( //dir=decl - int id: @var_decl ref, - int attached_property_wrapper_type: @type_or_none ref -); - -#keyset[id] -var_decl_parent_patterns( //dir=decl - int id: @var_decl ref, - int parent_pattern: @pattern_or_none ref -); - -#keyset[id] -var_decl_parent_initializers( //dir=decl - int id: @var_decl ref, - int parent_initializer: @expr_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var: @var_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var: @var_decl_or_none ref -); - -accessor_decls( //dir=decl - unique int id: @accessor_decl -); - -#keyset[id] -accessor_decl_is_getter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_setter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_will_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_did_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_read( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_modify( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_address( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_mutable_address( //dir=decl - int id: @accessor_decl ref -); - -associated_type_decls( //dir=decl - unique int id: @associated_type_decl -); - -concrete_func_decls( //dir=decl - unique int id: @concrete_func_decl -); - -concrete_var_decls( //dir=decl - unique int id: @concrete_var_decl, - int introducer_int: int ref -); - -generic_type_param_decls( //dir=decl - unique int id: @generic_type_param_decl -); - -@nominal_type_decl = - @class_decl -| @enum_decl -| @protocol_decl -| @struct_decl -; - -#keyset[id] -nominal_type_decls( //dir=decl - int id: @nominal_type_decl ref, - int type_: @type_or_none ref -); - -opaque_type_decls( //dir=decl - unique int id: @opaque_type_decl, - int naming_declaration: @value_decl_or_none ref -); - -#keyset[id, index] -opaque_type_decl_opaque_generic_params( //dir=decl - int id: @opaque_type_decl ref, - int index: int ref, - int opaque_generic_param: @generic_type_param_type_or_none ref -); - -param_decls( //dir=decl - unique int id: @param_decl -); - -#keyset[id] -param_decl_is_inout( //dir=decl - int id: @param_decl ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_vars( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var: @var_decl_or_none ref -); - -type_alias_decls( //dir=decl - unique int id: @type_alias_decl -); - -class_decls( //dir=decl - unique int id: @class_decl -); - -enum_decls( //dir=decl - unique int id: @enum_decl -); - -protocol_decls( //dir=decl - unique int id: @protocol_decl -); - -struct_decls( //dir=decl - unique int id: @struct_decl -); - -arguments( //dir=expr - unique int id: @argument, - string label: string ref, - int expr: @expr_or_none ref -); - -@expr = - @abstract_closure_expr -| @any_try_expr -| @applied_property_wrapper_expr -| @apply_expr -| @assign_expr -| @bind_optional_expr -| @capture_list_expr -| @collection_expr -| @decl_ref_expr -| @default_argument_expr -| @discard_assignment_expr -| @dot_syntax_base_ignored_expr -| @dynamic_type_expr -| @enum_is_case_expr -| @error_expr -| @explicit_cast_expr -| @force_value_expr -| @identity_expr -| @if_expr -| @implicit_conversion_expr -| @in_out_expr -| @key_path_application_expr -| @key_path_dot_expr -| @key_path_expr -| @lazy_initializer_expr -| @literal_expr -| @lookup_expr -| @make_temporarily_escapable_expr -| @obj_c_selector_expr -| @one_way_expr -| @opaque_value_expr -| @open_existential_expr -| @optional_evaluation_expr -| @other_constructor_decl_ref_expr -| @overloaded_decl_ref_expr -| @property_wrapper_value_placeholder_expr -| @rebind_self_in_constructor_expr -| @sequence_expr -| @super_ref_expr -| @tap_expr -| @tuple_element_expr -| @tuple_expr -| @type_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @vararg_expansion_expr -; - -#keyset[id] -expr_types( //dir=expr - int id: @expr ref, - int type_: @type_or_none ref -); - -@abstract_closure_expr = - @auto_closure_expr -| @closure_expr -; - -@any_try_expr = - @force_try_expr -| @optional_try_expr -| @try_expr -; - -#keyset[id] -any_try_exprs( //dir=expr - int id: @any_try_expr ref, - int sub_expr: @expr_or_none ref -); - -applied_property_wrapper_exprs( //dir=expr - unique int id: @applied_property_wrapper_expr, - int kind: int ref, - int value: @expr_or_none ref, - int param: @param_decl_or_none ref -); - -@apply_expr = - @binary_expr -| @call_expr -| @postfix_unary_expr -| @prefix_unary_expr -| @self_apply_expr -; - -#keyset[id] -apply_exprs( //dir=expr - int id: @apply_expr ref, - int function: @expr_or_none ref -); - -#keyset[id, index] -apply_expr_arguments( //dir=expr - int id: @apply_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -assign_exprs( //dir=expr - unique int id: @assign_expr, - int dest: @expr_or_none ref, - int source: @expr_or_none ref -); - -bind_optional_exprs( //dir=expr - unique int id: @bind_optional_expr, - int sub_expr: @expr_or_none ref -); - -capture_list_exprs( //dir=expr - unique int id: @capture_list_expr, - int closure_body: @closure_expr_or_none ref -); - -#keyset[id, index] -capture_list_expr_binding_decls( //dir=expr - int id: @capture_list_expr ref, - int index: int ref, - int binding_decl: @pattern_binding_decl_or_none ref -); - -@collection_expr = - @array_expr -| @dictionary_expr -; - -decl_ref_exprs( //dir=expr - unique int id: @decl_ref_expr, - int decl: @decl_or_none ref -); - -#keyset[id, index] -decl_ref_expr_replacement_types( //dir=expr - int id: @decl_ref_expr ref, - int index: int ref, - int replacement_type: @type_or_none ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_ordinary_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -default_argument_exprs( //dir=expr - unique int id: @default_argument_expr, - int param_decl: @param_decl_or_none ref, - int param_index: int ref -); - -#keyset[id] -default_argument_expr_caller_side_defaults( //dir=expr - int id: @default_argument_expr ref, - int caller_side_default: @expr_or_none ref -); - -discard_assignment_exprs( //dir=expr - unique int id: @discard_assignment_expr -); - -dot_syntax_base_ignored_exprs( //dir=expr - unique int id: @dot_syntax_base_ignored_expr, - int qualifier: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -dynamic_type_exprs( //dir=expr - unique int id: @dynamic_type_expr, - int base: @expr_or_none ref -); - -enum_is_case_exprs( //dir=expr - unique int id: @enum_is_case_expr, - int sub_expr: @expr_or_none ref, - int element: @enum_element_decl_or_none ref -); - -error_exprs( //dir=expr - unique int id: @error_expr -); - -@explicit_cast_expr = - @checked_cast_expr -| @coerce_expr -; - -#keyset[id] -explicit_cast_exprs( //dir=expr - int id: @explicit_cast_expr ref, - int sub_expr: @expr_or_none ref -); - -force_value_exprs( //dir=expr - unique int id: @force_value_expr, - int sub_expr: @expr_or_none ref -); - -@identity_expr = - @await_expr -| @dot_self_expr -| @paren_expr -| @unresolved_member_chain_result_expr -; - -#keyset[id] -identity_exprs( //dir=expr - int id: @identity_expr ref, - int sub_expr: @expr_or_none ref -); - -if_exprs( //dir=expr - unique int id: @if_expr, - int condition: @expr_or_none ref, - int then_expr: @expr_or_none ref, - int else_expr: @expr_or_none ref -); - -@implicit_conversion_expr = - @abi_safe_conversion_expr -| @any_hashable_erasure_expr -| @archetype_to_super_expr -| @array_to_pointer_expr -| @bridge_from_obj_c_expr -| @bridge_to_obj_c_expr -| @class_metatype_to_object_expr -| @collection_upcast_conversion_expr -| @conditional_bridge_from_obj_c_expr -| @covariant_function_conversion_expr -| @covariant_return_conversion_expr -| @derived_to_base_expr -| @destructure_tuple_expr -| @differentiable_function_expr -| @differentiable_function_extract_original_expr -| @erasure_expr -| @existential_metatype_to_object_expr -| @foreign_object_conversion_expr -| @function_conversion_expr -| @in_out_to_pointer_expr -| @inject_into_optional_expr -| @linear_function_expr -| @linear_function_extract_original_expr -| @linear_to_differentiable_function_expr -| @load_expr -| @metatype_conversion_expr -| @pointer_to_pointer_expr -| @protocol_metatype_to_object_expr -| @string_to_pointer_expr -| @underlying_to_opaque_expr -| @unevaluated_instance_expr -| @unresolved_type_conversion_expr -; - -#keyset[id] -implicit_conversion_exprs( //dir=expr - int id: @implicit_conversion_expr ref, - int sub_expr: @expr_or_none ref -); - -in_out_exprs( //dir=expr - unique int id: @in_out_expr, - int sub_expr: @expr_or_none ref -); - -key_path_application_exprs( //dir=expr - unique int id: @key_path_application_expr, - int base: @expr_or_none ref, - int key_path: @expr_or_none ref -); - -key_path_dot_exprs( //dir=expr - unique int id: @key_path_dot_expr -); - -key_path_exprs( //dir=expr - unique int id: @key_path_expr -); - -#keyset[id] -key_path_expr_roots( //dir=expr - int id: @key_path_expr ref, - int root: @type_repr_or_none ref -); - -#keyset[id] -key_path_expr_parsed_paths( //dir=expr - int id: @key_path_expr ref, - int parsed_path: @expr_or_none ref -); - -lazy_initializer_exprs( //dir=expr - unique int id: @lazy_initializer_expr, - int sub_expr: @expr_or_none ref -); - -@literal_expr = - @builtin_literal_expr -| @interpolated_string_literal_expr -| @nil_literal_expr -| @object_literal_expr -| @regex_literal_expr -; - -@lookup_expr = - @dynamic_lookup_expr -| @member_ref_expr -| @subscript_expr -; - -#keyset[id] -lookup_exprs( //dir=expr - int id: @lookup_expr ref, - int base: @expr_or_none ref -); - -#keyset[id] -lookup_expr_members( //dir=expr - int id: @lookup_expr ref, - int member: @decl_or_none ref -); - -make_temporarily_escapable_exprs( //dir=expr - unique int id: @make_temporarily_escapable_expr, - int escaping_closure: @opaque_value_expr_or_none ref, - int nonescaping_closure: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -obj_c_selector_exprs( //dir=expr - unique int id: @obj_c_selector_expr, - int sub_expr: @expr_or_none ref, - int method: @abstract_function_decl_or_none ref -); - -one_way_exprs( //dir=expr - unique int id: @one_way_expr, - int sub_expr: @expr_or_none ref -); - -opaque_value_exprs( //dir=expr - unique int id: @opaque_value_expr -); - -open_existential_exprs( //dir=expr - unique int id: @open_existential_expr, - int sub_expr: @expr_or_none ref, - int existential: @expr_or_none ref, - int opaque_expr: @opaque_value_expr_or_none ref -); - -optional_evaluation_exprs( //dir=expr - unique int id: @optional_evaluation_expr, - int sub_expr: @expr_or_none ref -); - -other_constructor_decl_ref_exprs( //dir=expr - unique int id: @other_constructor_decl_ref_expr, - int constructor_decl: @constructor_decl_or_none ref -); - -overloaded_decl_ref_exprs( //dir=expr - unique int id: @overloaded_decl_ref_expr -); - -#keyset[id, index] -overloaded_decl_ref_expr_possible_declarations( //dir=expr - int id: @overloaded_decl_ref_expr ref, - int index: int ref, - int possible_declaration: @value_decl_or_none ref -); - -property_wrapper_value_placeholder_exprs( //dir=expr - unique int id: @property_wrapper_value_placeholder_expr, - int placeholder: @opaque_value_expr_or_none ref -); - -#keyset[id] -property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr - int id: @property_wrapper_value_placeholder_expr ref, - int wrapped_value: @expr_or_none ref -); - -rebind_self_in_constructor_exprs( //dir=expr - unique int id: @rebind_self_in_constructor_expr, - int sub_expr: @expr_or_none ref, - int self: @var_decl_or_none ref -); - -sequence_exprs( //dir=expr - unique int id: @sequence_expr -); - -#keyset[id, index] -sequence_expr_elements( //dir=expr - int id: @sequence_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -super_ref_exprs( //dir=expr - unique int id: @super_ref_expr, - int self: @var_decl_or_none ref -); - -tap_exprs( //dir=expr - unique int id: @tap_expr, - int body: @brace_stmt_or_none ref, - int var: @var_decl_or_none ref -); - -#keyset[id] -tap_expr_sub_exprs( //dir=expr - int id: @tap_expr ref, - int sub_expr: @expr_or_none ref -); - -tuple_element_exprs( //dir=expr - unique int id: @tuple_element_expr, - int sub_expr: @expr_or_none ref, - int index: int ref -); - -tuple_exprs( //dir=expr - unique int id: @tuple_expr -); - -#keyset[id, index] -tuple_expr_elements( //dir=expr - int id: @tuple_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -type_exprs( //dir=expr - unique int id: @type_expr -); - -#keyset[id] -type_expr_type_reprs( //dir=expr - int id: @type_expr ref, - int type_repr: @type_repr_or_none ref -); - -unresolved_decl_ref_exprs( //dir=expr - unique int id: @unresolved_decl_ref_expr -); - -#keyset[id] -unresolved_decl_ref_expr_names( //dir=expr - int id: @unresolved_decl_ref_expr ref, - string name: string ref -); - -unresolved_dot_exprs( //dir=expr - unique int id: @unresolved_dot_expr, - int base: @expr_or_none ref, - string name: string ref -); - -unresolved_member_exprs( //dir=expr - unique int id: @unresolved_member_expr, - string name: string ref -); - -unresolved_pattern_exprs( //dir=expr - unique int id: @unresolved_pattern_expr, - int sub_pattern: @pattern_or_none ref -); - -unresolved_specialize_exprs( //dir=expr - unique int id: @unresolved_specialize_expr, - int sub_expr: @expr_or_none ref -); - -vararg_expansion_exprs( //dir=expr - unique int id: @vararg_expansion_expr, - int sub_expr: @expr_or_none ref -); - -abi_safe_conversion_exprs( //dir=expr - unique int id: @abi_safe_conversion_expr -); - -any_hashable_erasure_exprs( //dir=expr - unique int id: @any_hashable_erasure_expr -); - -archetype_to_super_exprs( //dir=expr - unique int id: @archetype_to_super_expr -); - -array_exprs( //dir=expr - unique int id: @array_expr -); - -#keyset[id, index] -array_expr_elements( //dir=expr - int id: @array_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -array_to_pointer_exprs( //dir=expr - unique int id: @array_to_pointer_expr -); - -auto_closure_exprs( //dir=expr - unique int id: @auto_closure_expr -); - -await_exprs( //dir=expr - unique int id: @await_expr -); - -binary_exprs( //dir=expr - unique int id: @binary_expr -); - -bridge_from_obj_c_exprs( //dir=expr - unique int id: @bridge_from_obj_c_expr -); - -bridge_to_obj_c_exprs( //dir=expr - unique int id: @bridge_to_obj_c_expr -); - -@builtin_literal_expr = - @boolean_literal_expr -| @magic_identifier_literal_expr -| @number_literal_expr -| @string_literal_expr -; - -call_exprs( //dir=expr - unique int id: @call_expr -); - -@checked_cast_expr = - @conditional_checked_cast_expr -| @forced_checked_cast_expr -| @is_expr -; - -class_metatype_to_object_exprs( //dir=expr - unique int id: @class_metatype_to_object_expr -); - -closure_exprs( //dir=expr - unique int id: @closure_expr -); - -coerce_exprs( //dir=expr - unique int id: @coerce_expr -); - -collection_upcast_conversion_exprs( //dir=expr - unique int id: @collection_upcast_conversion_expr -); - -conditional_bridge_from_obj_c_exprs( //dir=expr - unique int id: @conditional_bridge_from_obj_c_expr -); - -covariant_function_conversion_exprs( //dir=expr - unique int id: @covariant_function_conversion_expr -); - -covariant_return_conversion_exprs( //dir=expr - unique int id: @covariant_return_conversion_expr -); - -derived_to_base_exprs( //dir=expr - unique int id: @derived_to_base_expr -); - -destructure_tuple_exprs( //dir=expr - unique int id: @destructure_tuple_expr -); - -dictionary_exprs( //dir=expr - unique int id: @dictionary_expr -); - -#keyset[id, index] -dictionary_expr_elements( //dir=expr - int id: @dictionary_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -differentiable_function_exprs( //dir=expr - unique int id: @differentiable_function_expr -); - -differentiable_function_extract_original_exprs( //dir=expr - unique int id: @differentiable_function_extract_original_expr -); - -dot_self_exprs( //dir=expr - unique int id: @dot_self_expr -); - -@dynamic_lookup_expr = - @dynamic_member_ref_expr -| @dynamic_subscript_expr -; - -erasure_exprs( //dir=expr - unique int id: @erasure_expr -); - -existential_metatype_to_object_exprs( //dir=expr - unique int id: @existential_metatype_to_object_expr -); - -force_try_exprs( //dir=expr - unique int id: @force_try_expr -); - -foreign_object_conversion_exprs( //dir=expr - unique int id: @foreign_object_conversion_expr -); - -function_conversion_exprs( //dir=expr - unique int id: @function_conversion_expr -); - -in_out_to_pointer_exprs( //dir=expr - unique int id: @in_out_to_pointer_expr -); - -inject_into_optional_exprs( //dir=expr - unique int id: @inject_into_optional_expr -); - -interpolated_string_literal_exprs( //dir=expr - unique int id: @interpolated_string_literal_expr -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_expr: @opaque_value_expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_count_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int literal_capacity_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_appending_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int appending_expr: @tap_expr_or_none ref -); - -linear_function_exprs( //dir=expr - unique int id: @linear_function_expr -); - -linear_function_extract_original_exprs( //dir=expr - unique int id: @linear_function_extract_original_expr -); - -linear_to_differentiable_function_exprs( //dir=expr - unique int id: @linear_to_differentiable_function_expr -); - -load_exprs( //dir=expr - unique int id: @load_expr -); - -member_ref_exprs( //dir=expr - unique int id: @member_ref_expr -); - -#keyset[id] -member_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_ordinary_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @member_ref_expr ref -); - -metatype_conversion_exprs( //dir=expr - unique int id: @metatype_conversion_expr -); - -nil_literal_exprs( //dir=expr - unique int id: @nil_literal_expr -); - -object_literal_exprs( //dir=expr - unique int id: @object_literal_expr, - int kind: int ref -); - -#keyset[id, index] -object_literal_expr_arguments( //dir=expr - int id: @object_literal_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -optional_try_exprs( //dir=expr - unique int id: @optional_try_expr -); - -paren_exprs( //dir=expr - unique int id: @paren_expr -); - -pointer_to_pointer_exprs( //dir=expr - unique int id: @pointer_to_pointer_expr -); - -postfix_unary_exprs( //dir=expr - unique int id: @postfix_unary_expr -); - -prefix_unary_exprs( //dir=expr - unique int id: @prefix_unary_expr -); - -protocol_metatype_to_object_exprs( //dir=expr - unique int id: @protocol_metatype_to_object_expr -); - -regex_literal_exprs( //dir=expr - unique int id: @regex_literal_expr, - string pattern: string ref, - int version: int ref -); - -@self_apply_expr = - @constructor_ref_call_expr -| @dot_syntax_call_expr -; - -#keyset[id] -self_apply_exprs( //dir=expr - int id: @self_apply_expr ref, - int base: @expr_or_none ref -); - -string_to_pointer_exprs( //dir=expr - unique int id: @string_to_pointer_expr -); - -subscript_exprs( //dir=expr - unique int id: @subscript_expr -); - -#keyset[id, index] -subscript_expr_arguments( //dir=expr - int id: @subscript_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -#keyset[id] -subscript_expr_has_direct_to_storage_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_ordinary_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_distributed_thunk_semantics( //dir=expr - int id: @subscript_expr ref -); - -try_exprs( //dir=expr - unique int id: @try_expr -); - -underlying_to_opaque_exprs( //dir=expr - unique int id: @underlying_to_opaque_expr -); - -unevaluated_instance_exprs( //dir=expr - unique int id: @unevaluated_instance_expr -); - -unresolved_member_chain_result_exprs( //dir=expr - unique int id: @unresolved_member_chain_result_expr -); - -unresolved_type_conversion_exprs( //dir=expr - unique int id: @unresolved_type_conversion_expr -); - -boolean_literal_exprs( //dir=expr - unique int id: @boolean_literal_expr, - boolean value: boolean ref -); - -conditional_checked_cast_exprs( //dir=expr - unique int id: @conditional_checked_cast_expr -); - -constructor_ref_call_exprs( //dir=expr - unique int id: @constructor_ref_call_expr -); - -dot_syntax_call_exprs( //dir=expr - unique int id: @dot_syntax_call_expr -); - -dynamic_member_ref_exprs( //dir=expr - unique int id: @dynamic_member_ref_expr -); - -dynamic_subscript_exprs( //dir=expr - unique int id: @dynamic_subscript_expr -); - -forced_checked_cast_exprs( //dir=expr - unique int id: @forced_checked_cast_expr -); - -is_exprs( //dir=expr - unique int id: @is_expr -); - -magic_identifier_literal_exprs( //dir=expr - unique int id: @magic_identifier_literal_expr, - string kind: string ref -); - -@number_literal_expr = - @float_literal_expr -| @integer_literal_expr -; - -string_literal_exprs( //dir=expr - unique int id: @string_literal_expr, - string value: string ref -); - -float_literal_exprs( //dir=expr - unique int id: @float_literal_expr, - string string_value: string ref -); - -integer_literal_exprs( //dir=expr - unique int id: @integer_literal_expr, - string string_value: string ref -); - -@pattern = - @any_pattern -| @binding_pattern -| @bool_pattern -| @enum_element_pattern -| @expr_pattern -| @is_pattern -| @named_pattern -| @optional_some_pattern -| @paren_pattern -| @tuple_pattern -| @typed_pattern -; - -any_patterns( //dir=pattern - unique int id: @any_pattern -); - -binding_patterns( //dir=pattern - unique int id: @binding_pattern, - int sub_pattern: @pattern_or_none ref -); - -bool_patterns( //dir=pattern - unique int id: @bool_pattern, - boolean value: boolean ref -); - -enum_element_patterns( //dir=pattern - unique int id: @enum_element_pattern, - int element: @enum_element_decl_or_none ref -); - -#keyset[id] -enum_element_pattern_sub_patterns( //dir=pattern - int id: @enum_element_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -expr_patterns( //dir=pattern - unique int id: @expr_pattern, - int sub_expr: @expr_or_none ref -); - -is_patterns( //dir=pattern - unique int id: @is_pattern -); - -#keyset[id] -is_pattern_cast_type_reprs( //dir=pattern - int id: @is_pattern ref, - int cast_type_repr: @type_repr_or_none ref -); - -#keyset[id] -is_pattern_sub_patterns( //dir=pattern - int id: @is_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -named_patterns( //dir=pattern - unique int id: @named_pattern, - string name: string ref -); - -optional_some_patterns( //dir=pattern - unique int id: @optional_some_pattern, - int sub_pattern: @pattern_or_none ref -); - -paren_patterns( //dir=pattern - unique int id: @paren_pattern, - int sub_pattern: @pattern_or_none ref -); - -tuple_patterns( //dir=pattern - unique int id: @tuple_pattern -); - -#keyset[id, index] -tuple_pattern_elements( //dir=pattern - int id: @tuple_pattern ref, - int index: int ref, - int element: @pattern_or_none ref -); - -typed_patterns( //dir=pattern - unique int id: @typed_pattern, - int sub_pattern: @pattern_or_none ref -); - -#keyset[id] -typed_pattern_type_reprs( //dir=pattern - int id: @typed_pattern ref, - int type_repr: @type_repr_or_none ref -); - -case_label_items( //dir=stmt - unique int id: @case_label_item, - int pattern: @pattern_or_none ref -); - -#keyset[id] -case_label_item_guards( //dir=stmt - int id: @case_label_item ref, - int guard: @expr_or_none ref -); - -condition_elements( //dir=stmt - unique int id: @condition_element -); - -#keyset[id] -condition_element_booleans( //dir=stmt - int id: @condition_element ref, - int boolean_: @expr_or_none ref -); - -#keyset[id] -condition_element_patterns( //dir=stmt - int id: @condition_element ref, - int pattern: @pattern_or_none ref -); - -#keyset[id] -condition_element_initializers( //dir=stmt - int id: @condition_element ref, - int initializer: @expr_or_none ref -); - -#keyset[id] -condition_element_availabilities( //dir=stmt - int id: @condition_element ref, - int availability: @availability_info_or_none ref -); - -@stmt = - @brace_stmt -| @break_stmt -| @case_stmt -| @continue_stmt -| @defer_stmt -| @fail_stmt -| @fallthrough_stmt -| @labeled_stmt -| @pound_assert_stmt -| @return_stmt -| @throw_stmt -| @yield_stmt -; - -stmt_conditions( //dir=stmt - unique int id: @stmt_condition -); - -#keyset[id, index] -stmt_condition_elements( //dir=stmt - int id: @stmt_condition ref, - int index: int ref, - int element: @condition_element_or_none ref -); - -brace_stmts( //dir=stmt - unique int id: @brace_stmt -); - -#keyset[id, index] -brace_stmt_elements( //dir=stmt - int id: @brace_stmt ref, - int index: int ref, - int element: @ast_node_or_none ref -); - -break_stmts( //dir=stmt - unique int id: @break_stmt -); - -#keyset[id] -break_stmt_target_names( //dir=stmt - int id: @break_stmt ref, - string target_name: string ref -); - -#keyset[id] -break_stmt_targets( //dir=stmt - int id: @break_stmt ref, - int target: @stmt_or_none ref -); - -case_stmts( //dir=stmt - unique int id: @case_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -case_stmt_labels( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int label: @case_label_item_or_none ref -); - -#keyset[id, index] -case_stmt_variables( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int variable: @var_decl_or_none ref -); - -continue_stmts( //dir=stmt - unique int id: @continue_stmt -); - -#keyset[id] -continue_stmt_target_names( //dir=stmt - int id: @continue_stmt ref, - string target_name: string ref -); - -#keyset[id] -continue_stmt_targets( //dir=stmt - int id: @continue_stmt ref, - int target: @stmt_or_none ref -); - -defer_stmts( //dir=stmt - unique int id: @defer_stmt, - int body: @brace_stmt_or_none ref -); - -fail_stmts( //dir=stmt - unique int id: @fail_stmt -); - -fallthrough_stmts( //dir=stmt - unique int id: @fallthrough_stmt, - int fallthrough_source: @case_stmt_or_none ref, - int fallthrough_dest: @case_stmt_or_none ref -); - -@labeled_stmt = - @do_catch_stmt -| @do_stmt -| @for_each_stmt -| @labeled_conditional_stmt -| @repeat_while_stmt -| @switch_stmt -; - -#keyset[id] -labeled_stmt_labels( //dir=stmt - int id: @labeled_stmt ref, - string label: string ref -); - -pound_assert_stmts( //dir=stmt - unique int id: @pound_assert_stmt, - int condition: @expr_or_none ref, - string message: string ref -); - -return_stmts( //dir=stmt - unique int id: @return_stmt -); - -#keyset[id] -return_stmt_results( //dir=stmt - int id: @return_stmt ref, - int result: @expr_or_none ref -); - -throw_stmts( //dir=stmt - unique int id: @throw_stmt, - int sub_expr: @expr_or_none ref -); - -yield_stmts( //dir=stmt - unique int id: @yield_stmt -); - -#keyset[id, index] -yield_stmt_results( //dir=stmt - int id: @yield_stmt ref, - int index: int ref, - int result: @expr_or_none ref -); - -do_catch_stmts( //dir=stmt - unique int id: @do_catch_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -do_catch_stmt_catches( //dir=stmt - int id: @do_catch_stmt ref, - int index: int ref, - int catch: @case_stmt_or_none ref -); - -do_stmts( //dir=stmt - unique int id: @do_stmt, - int body: @brace_stmt_or_none ref -); - -for_each_stmts( //dir=stmt - unique int id: @for_each_stmt, - int pattern: @pattern_or_none ref, - int sequence: @expr_or_none ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id] -for_each_stmt_wheres( //dir=stmt - int id: @for_each_stmt ref, - int where: @expr_or_none ref -); - -@labeled_conditional_stmt = - @guard_stmt -| @if_stmt -| @while_stmt -; - -#keyset[id] -labeled_conditional_stmts( //dir=stmt - int id: @labeled_conditional_stmt ref, - int condition: @stmt_condition_or_none ref -); - -repeat_while_stmts( //dir=stmt - unique int id: @repeat_while_stmt, - int condition: @expr_or_none ref, - int body: @stmt_or_none ref -); - -switch_stmts( //dir=stmt - unique int id: @switch_stmt, - int expr: @expr_or_none ref -); - -#keyset[id, index] -switch_stmt_cases( //dir=stmt - int id: @switch_stmt ref, - int index: int ref, - int case_: @case_stmt_or_none ref -); - -guard_stmts( //dir=stmt - unique int id: @guard_stmt, - int body: @brace_stmt_or_none ref -); - -if_stmts( //dir=stmt - unique int id: @if_stmt, - int then: @stmt_or_none ref -); - -#keyset[id] -if_stmt_elses( //dir=stmt - int id: @if_stmt ref, - int else: @stmt_or_none ref -); - -while_stmts( //dir=stmt - unique int id: @while_stmt, - int body: @stmt_or_none ref -); - -@type = - @any_function_type -| @any_generic_type -| @any_metatype_type -| @builtin_type -| @dependent_member_type -| @dynamic_self_type -| @error_type -| @existential_type -| @in_out_type -| @l_value_type -| @module_type -| @parameterized_protocol_type -| @protocol_composition_type -| @reference_storage_type -| @substitutable_type -| @sugar_type -| @tuple_type -| @unresolved_type -; - -#keyset[id] -types( //dir=type - int id: @type ref, - string name: string ref, - int canonical_type: @type_or_none ref -); - -type_reprs( //dir=type - unique int id: @type_repr, - int type_: @type_or_none ref -); - -@any_function_type = - @function_type -| @generic_function_type -; - -#keyset[id] -any_function_types( //dir=type - int id: @any_function_type ref, - int result: @type_or_none ref -); - -#keyset[id, index] -any_function_type_param_types( //dir=type - int id: @any_function_type ref, - int index: int ref, - int param_type: @type_or_none ref -); - -#keyset[id] -any_function_type_is_throwing( //dir=type - int id: @any_function_type ref -); - -#keyset[id] -any_function_type_is_async( //dir=type - int id: @any_function_type ref -); - -@any_generic_type = - @nominal_or_bound_generic_nominal_type -| @unbound_generic_type -; - -#keyset[id] -any_generic_types( //dir=type - int id: @any_generic_type ref, - int declaration: @generic_type_decl_or_none ref -); - -#keyset[id] -any_generic_type_parents( //dir=type - int id: @any_generic_type ref, - int parent: @type_or_none ref -); - -@any_metatype_type = - @existential_metatype_type -| @metatype_type -; - -@builtin_type = - @any_builtin_integer_type -| @builtin_bridge_object_type -| @builtin_default_actor_storage_type -| @builtin_executor_type -| @builtin_float_type -| @builtin_job_type -| @builtin_native_object_type -| @builtin_raw_pointer_type -| @builtin_raw_unsafe_continuation_type -| @builtin_unsafe_value_buffer_type -| @builtin_vector_type -; - -dependent_member_types( //dir=type - unique int id: @dependent_member_type, - int base_type: @type_or_none ref, - int associated_type_decl: @associated_type_decl_or_none ref -); - -dynamic_self_types( //dir=type - unique int id: @dynamic_self_type, - int static_self_type: @type_or_none ref -); - -error_types( //dir=type - unique int id: @error_type -); - -existential_types( //dir=type - unique int id: @existential_type, - int constraint: @type_or_none ref -); - -in_out_types( //dir=type - unique int id: @in_out_type, - int object_type: @type_or_none ref -); - -l_value_types( //dir=type - unique int id: @l_value_type, - int object_type: @type_or_none ref -); - -module_types( //dir=type - unique int id: @module_type, - int module: @module_decl_or_none ref -); - -parameterized_protocol_types( //dir=type - unique int id: @parameterized_protocol_type, - int base: @protocol_type_or_none ref -); - -#keyset[id, index] -parameterized_protocol_type_args( //dir=type - int id: @parameterized_protocol_type ref, - int index: int ref, - int arg: @type_or_none ref -); - -protocol_composition_types( //dir=type - unique int id: @protocol_composition_type -); - -#keyset[id, index] -protocol_composition_type_members( //dir=type - int id: @protocol_composition_type ref, - int index: int ref, - int member: @type_or_none ref -); - -@reference_storage_type = - @unmanaged_storage_type -| @unowned_storage_type -| @weak_storage_type -; - -#keyset[id] -reference_storage_types( //dir=type - int id: @reference_storage_type ref, - int referent_type: @type_or_none ref -); - -@substitutable_type = - @archetype_type -| @generic_type_param_type -; - -@sugar_type = - @paren_type -| @syntax_sugar_type -| @type_alias_type -; - -tuple_types( //dir=type - unique int id: @tuple_type -); - -#keyset[id, index] -tuple_type_types( //dir=type - int id: @tuple_type ref, - int index: int ref, - int type_: @type_or_none ref -); - -#keyset[id, index] -tuple_type_names( //dir=type - int id: @tuple_type ref, - int index: int ref, - string name: string ref -); - -unresolved_types( //dir=type - unique int id: @unresolved_type -); - -@any_builtin_integer_type = - @builtin_integer_literal_type -| @builtin_integer_type -; - -@archetype_type = - @opaque_type_archetype_type -| @opened_archetype_type -| @primary_archetype_type -; - -#keyset[id] -archetype_types( //dir=type - int id: @archetype_type ref, - int interface_type: @type_or_none ref -); - -#keyset[id] -archetype_type_superclasses( //dir=type - int id: @archetype_type ref, - int superclass: @type_or_none ref -); - -#keyset[id, index] -archetype_type_protocols( //dir=type - int id: @archetype_type ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -builtin_bridge_object_types( //dir=type - unique int id: @builtin_bridge_object_type -); - -builtin_default_actor_storage_types( //dir=type - unique int id: @builtin_default_actor_storage_type -); - -builtin_executor_types( //dir=type - unique int id: @builtin_executor_type -); - -builtin_float_types( //dir=type - unique int id: @builtin_float_type -); - -builtin_job_types( //dir=type - unique int id: @builtin_job_type -); - -builtin_native_object_types( //dir=type - unique int id: @builtin_native_object_type -); - -builtin_raw_pointer_types( //dir=type - unique int id: @builtin_raw_pointer_type -); - -builtin_raw_unsafe_continuation_types( //dir=type - unique int id: @builtin_raw_unsafe_continuation_type -); - -builtin_unsafe_value_buffer_types( //dir=type - unique int id: @builtin_unsafe_value_buffer_type -); - -builtin_vector_types( //dir=type - unique int id: @builtin_vector_type -); - -existential_metatype_types( //dir=type - unique int id: @existential_metatype_type -); - -function_types( //dir=type - unique int id: @function_type -); - -generic_function_types( //dir=type - unique int id: @generic_function_type -); - -#keyset[id, index] -generic_function_type_generic_params( //dir=type - int id: @generic_function_type ref, - int index: int ref, - int generic_param: @generic_type_param_type_or_none ref -); - -generic_type_param_types( //dir=type - unique int id: @generic_type_param_type -); - -metatype_types( //dir=type - unique int id: @metatype_type -); - -@nominal_or_bound_generic_nominal_type = - @bound_generic_type -| @nominal_type -; - -paren_types( //dir=type - unique int id: @paren_type, - int type_: @type_or_none ref -); - -@syntax_sugar_type = - @dictionary_type -| @unary_syntax_sugar_type -; - -type_alias_types( //dir=type - unique int id: @type_alias_type, - int decl: @type_alias_decl_or_none ref -); - -unbound_generic_types( //dir=type - unique int id: @unbound_generic_type -); - -unmanaged_storage_types( //dir=type - unique int id: @unmanaged_storage_type -); - -unowned_storage_types( //dir=type - unique int id: @unowned_storage_type -); - -weak_storage_types( //dir=type - unique int id: @weak_storage_type -); - -@bound_generic_type = - @bound_generic_class_type -| @bound_generic_enum_type -| @bound_generic_struct_type -; - -#keyset[id, index] -bound_generic_type_arg_types( //dir=type - int id: @bound_generic_type ref, - int index: int ref, - int arg_type: @type_or_none ref -); - -builtin_integer_literal_types( //dir=type - unique int id: @builtin_integer_literal_type -); - -builtin_integer_types( //dir=type - unique int id: @builtin_integer_type -); - -#keyset[id] -builtin_integer_type_widths( //dir=type - int id: @builtin_integer_type ref, - int width: int ref -); - -dictionary_types( //dir=type - unique int id: @dictionary_type, - int key_type: @type_or_none ref, - int value_type: @type_or_none ref -); - -@nominal_type = - @class_type -| @enum_type -| @protocol_type -| @struct_type -; - -opaque_type_archetype_types( //dir=type - unique int id: @opaque_type_archetype_type, - int declaration: @opaque_type_decl_or_none ref -); - -opened_archetype_types( //dir=type - unique int id: @opened_archetype_type -); - -primary_archetype_types( //dir=type - unique int id: @primary_archetype_type -); - -@unary_syntax_sugar_type = - @array_slice_type -| @optional_type -| @variadic_sequence_type -; - -#keyset[id] -unary_syntax_sugar_types( //dir=type - int id: @unary_syntax_sugar_type ref, - int base_type: @type_or_none ref -); - -array_slice_types( //dir=type - unique int id: @array_slice_type -); - -bound_generic_class_types( //dir=type - unique int id: @bound_generic_class_type -); - -bound_generic_enum_types( //dir=type - unique int id: @bound_generic_enum_type -); - -bound_generic_struct_types( //dir=type - unique int id: @bound_generic_struct_type -); - -class_types( //dir=type - unique int id: @class_type -); - -enum_types( //dir=type - unique int id: @enum_type -); - -optional_types( //dir=type - unique int id: @optional_type -); - -protocol_types( //dir=type - unique int id: @protocol_type -); - -struct_types( //dir=type - unique int id: @struct_type -); - -variadic_sequence_types( //dir=type - unique int id: @variadic_sequence_type -); - -@abstract_function_decl_or_none = - @abstract_function_decl -| @unspecified_element -; - -@accessor_decl_or_none = - @accessor_decl -| @unspecified_element -; - -@argument_or_none = - @argument -| @unspecified_element -; - -@associated_type_decl_or_none = - @associated_type_decl -| @unspecified_element -; - -@ast_node_or_none = - @ast_node -| @unspecified_element -; - -@availability_info_or_none = - @availability_info -| @unspecified_element -; - -@availability_spec_or_none = - @availability_spec -| @unspecified_element -; - -@brace_stmt_or_none = - @brace_stmt -| @unspecified_element -; - -@captured_decl_or_none = - @captured_decl -| @unspecified_element -; - -@case_label_item_or_none = - @case_label_item -| @unspecified_element -; - -@case_stmt_or_none = - @case_stmt -| @unspecified_element -; - -@closure_expr_or_none = - @closure_expr -| @unspecified_element -; - -@condition_element_or_none = - @condition_element -| @unspecified_element -; - -@constructor_decl_or_none = - @constructor_decl -| @unspecified_element -; - -@decl_or_none = - @decl -| @unspecified_element -; - -@enum_element_decl_or_none = - @enum_element_decl -| @unspecified_element -; - -@expr_or_none = - @expr -| @unspecified_element -; - -@file_or_none = - @file -| @unspecified_element -; - -@generic_type_decl_or_none = - @generic_type_decl -| @unspecified_element -; - -@generic_type_param_decl_or_none = - @generic_type_param_decl -| @unspecified_element -; - -@generic_type_param_type_or_none = - @generic_type_param_type -| @unspecified_element -; - -@location_or_none = - @location -| @unspecified_element -; - -@module_decl_or_none = - @module_decl -| @unspecified_element -; - -@nominal_type_decl_or_none = - @nominal_type_decl -| @unspecified_element -; - -@opaque_type_decl_or_none = - @opaque_type_decl -| @unspecified_element -; - -@opaque_value_expr_or_none = - @opaque_value_expr -| @unspecified_element -; - -@param_decl_or_none = - @param_decl -| @unspecified_element -; - -@pattern_or_none = - @pattern -| @unspecified_element -; - -@pattern_binding_decl_or_none = - @pattern_binding_decl -| @unspecified_element -; - -@precedence_group_decl_or_none = - @precedence_group_decl -| @unspecified_element -; - -@protocol_decl_or_none = - @protocol_decl -| @unspecified_element -; - -@protocol_type_or_none = - @protocol_type -| @unspecified_element -; - -@stmt_or_none = - @stmt -| @unspecified_element -; - -@stmt_condition_or_none = - @stmt_condition -| @unspecified_element -; - -@string_literal_expr_or_none = - @string_literal_expr -| @unspecified_element -; - -@tap_expr_or_none = - @tap_expr -| @unspecified_element -; - -@type_or_none = - @type -| @unspecified_element -; - -@type_alias_decl_or_none = - @type_alias_decl -| @unspecified_element -; - -@type_repr_or_none = - @type_repr -| @unspecified_element -; - -@value_decl_or_none = - @unspecified_element -| @value_decl -; - -@var_decl_or_none = - @unspecified_element -| @var_decl -; diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme deleted file mode 100644 index c2f01f2beb6..00000000000 --- a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/swift.dbscheme +++ /dev/null @@ -1,2601 +0,0 @@ -// generated by codegen/codegen.py - -// from prefix.dbscheme -/** - * The source location of the snapshot. - */ -sourceLocationPrefix( - string prefix: string ref -); - - -// from schema.py - -@element = - @callable -| @file -| @generic_context -| @locatable -| @location -| @type -; - -#keyset[id] -element_is_unknown( - int id: @element ref -); - -@callable = - @abstract_closure_expr -| @abstract_function_decl -; - -#keyset[id] -callable_names( - int id: @callable ref, - string name: string ref -); - -#keyset[id] -callable_self_params( - int id: @callable ref, - int self_param: @param_decl_or_none ref -); - -#keyset[id, index] -callable_params( - int id: @callable ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -#keyset[id] -callable_bodies( - int id: @callable ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id, index] -callable_captures( - int id: @callable ref, - int index: int ref, - int capture: @captured_decl_or_none ref -); - -@file = - @db_file -; - -#keyset[id] -files( - int id: @file ref, - string name: string ref -); - -#keyset[id] -file_is_successfully_extracted( - int id: @file ref -); - -@locatable = - @argument -| @ast_node -| @comment -| @diagnostics -| @error_element -; - -#keyset[id] -locatable_locations( - int id: @locatable ref, - int location: @location_or_none ref -); - -@location = - @db_location -; - -#keyset[id] -locations( - int id: @location ref, - int file: @file_or_none ref, - int start_line: int ref, - int start_column: int ref, - int end_line: int ref, - int end_column: int ref -); - -@ast_node = - @availability_info -| @availability_spec -| @case_label_item -| @condition_element -| @decl -| @expr -| @pattern -| @stmt -| @stmt_condition -| @type_repr -; - -comments( - unique int id: @comment, - string text: string ref -); - -db_files( - unique int id: @db_file -); - -db_locations( - unique int id: @db_location -); - -diagnostics( - unique int id: @diagnostics, - string text: string ref, - int kind: int ref -); - -@error_element = - @error_expr -| @error_type -| @overloaded_decl_ref_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_chain_result_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @unresolved_type -| @unresolved_type_conversion_expr -| @unspecified_element -; - -availability_infos( - unique int id: @availability_info -); - -#keyset[id] -availability_info_is_unavailable( - int id: @availability_info ref -); - -#keyset[id, index] -availability_info_specs( - int id: @availability_info ref, - int index: int ref, - int spec: @availability_spec_or_none ref -); - -@availability_spec = - @other_availability_spec -| @platform_version_availability_spec -; - -unspecified_elements( - unique int id: @unspecified_element, - string property: string ref, - string error: string ref -); - -#keyset[id] -unspecified_element_parents( - int id: @unspecified_element ref, - int parent: @element ref -); - -#keyset[id] -unspecified_element_indices( - int id: @unspecified_element ref, - int index: int ref -); - -other_availability_specs( - unique int id: @other_availability_spec -); - -platform_version_availability_specs( - unique int id: @platform_version_availability_spec, - string platform: string ref, - string version: string ref -); - -@decl = - @captured_decl -| @enum_case_decl -| @extension_decl -| @if_config_decl -| @import_decl -| @missing_member_decl -| @operator_decl -| @pattern_binding_decl -| @pound_diagnostic_decl -| @precedence_group_decl -| @top_level_code_decl -| @value_decl -; - -#keyset[id] -decls( //dir=decl - int id: @decl ref, - int module: @module_decl_or_none ref -); - -#keyset[id, index] -decl_members( //dir=decl - int id: @decl ref, - int index: int ref, - int member: @decl_or_none ref -); - -@generic_context = - @abstract_function_decl -| @extension_decl -| @generic_type_decl -| @subscript_decl -; - -#keyset[id, index] -generic_context_generic_type_params( //dir=decl - int id: @generic_context ref, - int index: int ref, - int generic_type_param: @generic_type_param_decl_or_none ref -); - -captured_decls( //dir=decl - unique int id: @captured_decl, - int decl: @value_decl_or_none ref -); - -#keyset[id] -captured_decl_is_direct( //dir=decl - int id: @captured_decl ref -); - -#keyset[id] -captured_decl_is_escaping( //dir=decl - int id: @captured_decl ref -); - -enum_case_decls( //dir=decl - unique int id: @enum_case_decl -); - -#keyset[id, index] -enum_case_decl_elements( //dir=decl - int id: @enum_case_decl ref, - int index: int ref, - int element: @enum_element_decl_or_none ref -); - -extension_decls( //dir=decl - unique int id: @extension_decl, - int extended_type_decl: @nominal_type_decl_or_none ref -); - -#keyset[id, index] -extension_decl_protocols( //dir=decl - int id: @extension_decl ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -if_config_decls( //dir=decl - unique int id: @if_config_decl -); - -#keyset[id, index] -if_config_decl_active_elements( //dir=decl - int id: @if_config_decl ref, - int index: int ref, - int active_element: @ast_node_or_none ref -); - -import_decls( //dir=decl - unique int id: @import_decl -); - -#keyset[id] -import_decl_is_exported( //dir=decl - int id: @import_decl ref -); - -#keyset[id] -import_decl_imported_modules( //dir=decl - int id: @import_decl ref, - int imported_module: @module_decl_or_none ref -); - -#keyset[id, index] -import_decl_declarations( //dir=decl - int id: @import_decl ref, - int index: int ref, - int declaration: @value_decl_or_none ref -); - -missing_member_decls( //dir=decl - unique int id: @missing_member_decl, - string name: string ref -); - -@operator_decl = - @infix_operator_decl -| @postfix_operator_decl -| @prefix_operator_decl -; - -#keyset[id] -operator_decls( //dir=decl - int id: @operator_decl ref, - string name: string ref -); - -pattern_binding_decls( //dir=decl - unique int id: @pattern_binding_decl -); - -#keyset[id, index] -pattern_binding_decl_inits( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int init: @expr_or_none ref -); - -#keyset[id, index] -pattern_binding_decl_patterns( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int pattern: @pattern_or_none ref -); - -pound_diagnostic_decls( //dir=decl - unique int id: @pound_diagnostic_decl, - int kind: int ref, - int message: @string_literal_expr_or_none ref -); - -precedence_group_decls( //dir=decl - unique int id: @precedence_group_decl -); - -top_level_code_decls( //dir=decl - unique int id: @top_level_code_decl, - int body: @brace_stmt_or_none ref -); - -@value_decl = - @abstract_function_decl -| @abstract_storage_decl -| @enum_element_decl -| @type_decl -; - -#keyset[id] -value_decls( //dir=decl - int id: @value_decl ref, - int interface_type: @type_or_none ref -); - -@abstract_function_decl = - @constructor_decl -| @destructor_decl -| @func_decl -; - -@abstract_storage_decl = - @subscript_decl -| @var_decl -; - -#keyset[id, index] -abstract_storage_decl_accessor_decls( //dir=decl - int id: @abstract_storage_decl ref, - int index: int ref, - int accessor_decl: @accessor_decl_or_none ref -); - -enum_element_decls( //dir=decl - unique int id: @enum_element_decl, - string name: string ref -); - -#keyset[id, index] -enum_element_decl_params( //dir=decl - int id: @enum_element_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -infix_operator_decls( //dir=decl - unique int id: @infix_operator_decl -); - -#keyset[id] -infix_operator_decl_precedence_groups( //dir=decl - int id: @infix_operator_decl ref, - int precedence_group: @precedence_group_decl_or_none ref -); - -postfix_operator_decls( //dir=decl - unique int id: @postfix_operator_decl -); - -prefix_operator_decls( //dir=decl - unique int id: @prefix_operator_decl -); - -@type_decl = - @abstract_type_param_decl -| @generic_type_decl -| @module_decl -; - -#keyset[id] -type_decls( //dir=decl - int id: @type_decl ref, - string name: string ref -); - -#keyset[id, index] -type_decl_base_types( //dir=decl - int id: @type_decl ref, - int index: int ref, - int base_type: @type_or_none ref -); - -@abstract_type_param_decl = - @associated_type_decl -| @generic_type_param_decl -; - -constructor_decls( //dir=decl - unique int id: @constructor_decl -); - -destructor_decls( //dir=decl - unique int id: @destructor_decl -); - -@func_decl = - @accessor_decl -| @concrete_func_decl -; - -@generic_type_decl = - @nominal_type_decl -| @opaque_type_decl -| @type_alias_decl -; - -module_decls( //dir=decl - unique int id: @module_decl -); - -#keyset[id] -module_decl_is_builtin_module( //dir=decl - int id: @module_decl ref -); - -#keyset[id] -module_decl_is_system_module( //dir=decl - int id: @module_decl ref -); - -#keyset[id, index] -module_decl_imported_modules( //dir=decl - int id: @module_decl ref, - int index: int ref, - int imported_module: @module_decl_or_none ref -); - -#keyset[id, index] -module_decl_exported_modules( //dir=decl - int id: @module_decl ref, - int index: int ref, - int exported_module: @module_decl_or_none ref -); - -subscript_decls( //dir=decl - unique int id: @subscript_decl, - int element_type: @type_or_none ref -); - -#keyset[id, index] -subscript_decl_params( //dir=decl - int id: @subscript_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -@var_decl = - @concrete_var_decl -| @param_decl -; - -#keyset[id] -var_decls( //dir=decl - int id: @var_decl ref, - string name: string ref, - int type_: @type_or_none ref -); - -#keyset[id] -var_decl_attached_property_wrapper_types( //dir=decl - int id: @var_decl ref, - int attached_property_wrapper_type: @type_or_none ref -); - -#keyset[id] -var_decl_parent_patterns( //dir=decl - int id: @var_decl ref, - int parent_pattern: @pattern_or_none ref -); - -#keyset[id] -var_decl_parent_initializers( //dir=decl - int id: @var_decl ref, - int parent_initializer: @expr_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var: @var_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var: @var_decl_or_none ref -); - -accessor_decls( //dir=decl - unique int id: @accessor_decl -); - -#keyset[id] -accessor_decl_is_getter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_setter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_will_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_did_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_read( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_modify( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_address( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_mutable_address( //dir=decl - int id: @accessor_decl ref -); - -associated_type_decls( //dir=decl - unique int id: @associated_type_decl -); - -concrete_func_decls( //dir=decl - unique int id: @concrete_func_decl -); - -concrete_var_decls( //dir=decl - unique int id: @concrete_var_decl, - int introducer_int: int ref -); - -generic_type_param_decls( //dir=decl - unique int id: @generic_type_param_decl -); - -@nominal_type_decl = - @class_decl -| @enum_decl -| @protocol_decl -| @struct_decl -; - -#keyset[id] -nominal_type_decls( //dir=decl - int id: @nominal_type_decl ref, - int type_: @type_or_none ref -); - -opaque_type_decls( //dir=decl - unique int id: @opaque_type_decl, - int naming_declaration: @value_decl_or_none ref -); - -#keyset[id, index] -opaque_type_decl_opaque_generic_params( //dir=decl - int id: @opaque_type_decl ref, - int index: int ref, - int opaque_generic_param: @generic_type_param_type_or_none ref -); - -param_decls( //dir=decl - unique int id: @param_decl -); - -#keyset[id] -param_decl_is_inout( //dir=decl - int id: @param_decl ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_vars( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var: @var_decl_or_none ref -); - -type_alias_decls( //dir=decl - unique int id: @type_alias_decl -); - -class_decls( //dir=decl - unique int id: @class_decl -); - -enum_decls( //dir=decl - unique int id: @enum_decl -); - -protocol_decls( //dir=decl - unique int id: @protocol_decl -); - -struct_decls( //dir=decl - unique int id: @struct_decl -); - -arguments( //dir=expr - unique int id: @argument, - string label: string ref, - int expr: @expr_or_none ref -); - -@expr = - @abstract_closure_expr -| @any_try_expr -| @applied_property_wrapper_expr -| @apply_expr -| @assign_expr -| @bind_optional_expr -| @capture_list_expr -| @collection_expr -| @decl_ref_expr -| @default_argument_expr -| @discard_assignment_expr -| @dot_syntax_base_ignored_expr -| @dynamic_type_expr -| @enum_is_case_expr -| @error_expr -| @explicit_cast_expr -| @force_value_expr -| @identity_expr -| @if_expr -| @implicit_conversion_expr -| @in_out_expr -| @key_path_application_expr -| @key_path_dot_expr -| @key_path_expr -| @lazy_initializer_expr -| @literal_expr -| @lookup_expr -| @make_temporarily_escapable_expr -| @obj_c_selector_expr -| @one_way_expr -| @opaque_value_expr -| @open_existential_expr -| @optional_evaluation_expr -| @other_constructor_decl_ref_expr -| @overloaded_decl_ref_expr -| @property_wrapper_value_placeholder_expr -| @rebind_self_in_constructor_expr -| @sequence_expr -| @super_ref_expr -| @tap_expr -| @tuple_element_expr -| @tuple_expr -| @type_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @vararg_expansion_expr -; - -#keyset[id] -expr_types( //dir=expr - int id: @expr ref, - int type_: @type_or_none ref -); - -@abstract_closure_expr = - @auto_closure_expr -| @closure_expr -; - -@any_try_expr = - @force_try_expr -| @optional_try_expr -| @try_expr -; - -#keyset[id] -any_try_exprs( //dir=expr - int id: @any_try_expr ref, - int sub_expr: @expr_or_none ref -); - -applied_property_wrapper_exprs( //dir=expr - unique int id: @applied_property_wrapper_expr, - int kind: int ref, - int value: @expr_or_none ref, - int param: @param_decl_or_none ref -); - -@apply_expr = - @binary_expr -| @call_expr -| @postfix_unary_expr -| @prefix_unary_expr -| @self_apply_expr -; - -#keyset[id] -apply_exprs( //dir=expr - int id: @apply_expr ref, - int function: @expr_or_none ref -); - -#keyset[id, index] -apply_expr_arguments( //dir=expr - int id: @apply_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -assign_exprs( //dir=expr - unique int id: @assign_expr, - int dest: @expr_or_none ref, - int source: @expr_or_none ref -); - -bind_optional_exprs( //dir=expr - unique int id: @bind_optional_expr, - int sub_expr: @expr_or_none ref -); - -capture_list_exprs( //dir=expr - unique int id: @capture_list_expr, - int closure_body: @closure_expr_or_none ref -); - -#keyset[id, index] -capture_list_expr_binding_decls( //dir=expr - int id: @capture_list_expr ref, - int index: int ref, - int binding_decl: @pattern_binding_decl_or_none ref -); - -@collection_expr = - @array_expr -| @dictionary_expr -; - -decl_ref_exprs( //dir=expr - unique int id: @decl_ref_expr, - int decl: @decl_or_none ref -); - -#keyset[id, index] -decl_ref_expr_replacement_types( //dir=expr - int id: @decl_ref_expr ref, - int index: int ref, - int replacement_type: @type_or_none ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_ordinary_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -default_argument_exprs( //dir=expr - unique int id: @default_argument_expr, - int param_decl: @param_decl_or_none ref, - int param_index: int ref -); - -#keyset[id] -default_argument_expr_caller_side_defaults( //dir=expr - int id: @default_argument_expr ref, - int caller_side_default: @expr_or_none ref -); - -discard_assignment_exprs( //dir=expr - unique int id: @discard_assignment_expr -); - -dot_syntax_base_ignored_exprs( //dir=expr - unique int id: @dot_syntax_base_ignored_expr, - int qualifier: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -dynamic_type_exprs( //dir=expr - unique int id: @dynamic_type_expr, - int base: @expr_or_none ref -); - -enum_is_case_exprs( //dir=expr - unique int id: @enum_is_case_expr, - int sub_expr: @expr_or_none ref, - int element: @enum_element_decl_or_none ref -); - -error_exprs( //dir=expr - unique int id: @error_expr -); - -@explicit_cast_expr = - @checked_cast_expr -| @coerce_expr -; - -#keyset[id] -explicit_cast_exprs( //dir=expr - int id: @explicit_cast_expr ref, - int sub_expr: @expr_or_none ref -); - -force_value_exprs( //dir=expr - unique int id: @force_value_expr, - int sub_expr: @expr_or_none ref -); - -@identity_expr = - @await_expr -| @dot_self_expr -| @paren_expr -| @unresolved_member_chain_result_expr -; - -#keyset[id] -identity_exprs( //dir=expr - int id: @identity_expr ref, - int sub_expr: @expr_or_none ref -); - -if_exprs( //dir=expr - unique int id: @if_expr, - int condition: @expr_or_none ref, - int then_expr: @expr_or_none ref, - int else_expr: @expr_or_none ref -); - -@implicit_conversion_expr = - @abi_safe_conversion_expr -| @any_hashable_erasure_expr -| @archetype_to_super_expr -| @array_to_pointer_expr -| @bridge_from_obj_c_expr -| @bridge_to_obj_c_expr -| @class_metatype_to_object_expr -| @collection_upcast_conversion_expr -| @conditional_bridge_from_obj_c_expr -| @covariant_function_conversion_expr -| @covariant_return_conversion_expr -| @derived_to_base_expr -| @destructure_tuple_expr -| @differentiable_function_expr -| @differentiable_function_extract_original_expr -| @erasure_expr -| @existential_metatype_to_object_expr -| @foreign_object_conversion_expr -| @function_conversion_expr -| @in_out_to_pointer_expr -| @inject_into_optional_expr -| @linear_function_expr -| @linear_function_extract_original_expr -| @linear_to_differentiable_function_expr -| @load_expr -| @metatype_conversion_expr -| @pointer_to_pointer_expr -| @protocol_metatype_to_object_expr -| @string_to_pointer_expr -| @underlying_to_opaque_expr -| @unevaluated_instance_expr -| @unresolved_type_conversion_expr -; - -#keyset[id] -implicit_conversion_exprs( //dir=expr - int id: @implicit_conversion_expr ref, - int sub_expr: @expr_or_none ref -); - -in_out_exprs( //dir=expr - unique int id: @in_out_expr, - int sub_expr: @expr_or_none ref -); - -key_path_application_exprs( //dir=expr - unique int id: @key_path_application_expr, - int base: @expr_or_none ref, - int key_path: @expr_or_none ref -); - -key_path_dot_exprs( //dir=expr - unique int id: @key_path_dot_expr -); - -key_path_exprs( //dir=expr - unique int id: @key_path_expr -); - -#keyset[id] -key_path_expr_roots( //dir=expr - int id: @key_path_expr ref, - int root: @type_repr_or_none ref -); - -#keyset[id] -key_path_expr_parsed_paths( //dir=expr - int id: @key_path_expr ref, - int parsed_path: @expr_or_none ref -); - -lazy_initializer_exprs( //dir=expr - unique int id: @lazy_initializer_expr, - int sub_expr: @expr_or_none ref -); - -@literal_expr = - @builtin_literal_expr -| @interpolated_string_literal_expr -| @nil_literal_expr -| @object_literal_expr -| @regex_literal_expr -; - -@lookup_expr = - @dynamic_lookup_expr -| @member_ref_expr -| @subscript_expr -; - -#keyset[id] -lookup_exprs( //dir=expr - int id: @lookup_expr ref, - int base: @expr_or_none ref -); - -#keyset[id] -lookup_expr_members( //dir=expr - int id: @lookup_expr ref, - int member: @decl_or_none ref -); - -make_temporarily_escapable_exprs( //dir=expr - unique int id: @make_temporarily_escapable_expr, - int escaping_closure: @opaque_value_expr_or_none ref, - int nonescaping_closure: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -obj_c_selector_exprs( //dir=expr - unique int id: @obj_c_selector_expr, - int sub_expr: @expr_or_none ref, - int method: @abstract_function_decl_or_none ref -); - -one_way_exprs( //dir=expr - unique int id: @one_way_expr, - int sub_expr: @expr_or_none ref -); - -opaque_value_exprs( //dir=expr - unique int id: @opaque_value_expr -); - -open_existential_exprs( //dir=expr - unique int id: @open_existential_expr, - int sub_expr: @expr_or_none ref, - int existential: @expr_or_none ref, - int opaque_expr: @opaque_value_expr_or_none ref -); - -optional_evaluation_exprs( //dir=expr - unique int id: @optional_evaluation_expr, - int sub_expr: @expr_or_none ref -); - -other_constructor_decl_ref_exprs( //dir=expr - unique int id: @other_constructor_decl_ref_expr, - int constructor_decl: @constructor_decl_or_none ref -); - -overloaded_decl_ref_exprs( //dir=expr - unique int id: @overloaded_decl_ref_expr -); - -#keyset[id, index] -overloaded_decl_ref_expr_possible_declarations( //dir=expr - int id: @overloaded_decl_ref_expr ref, - int index: int ref, - int possible_declaration: @value_decl_or_none ref -); - -property_wrapper_value_placeholder_exprs( //dir=expr - unique int id: @property_wrapper_value_placeholder_expr, - int placeholder: @opaque_value_expr_or_none ref -); - -#keyset[id] -property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr - int id: @property_wrapper_value_placeholder_expr ref, - int wrapped_value: @expr_or_none ref -); - -rebind_self_in_constructor_exprs( //dir=expr - unique int id: @rebind_self_in_constructor_expr, - int sub_expr: @expr_or_none ref, - int self: @var_decl_or_none ref -); - -sequence_exprs( //dir=expr - unique int id: @sequence_expr -); - -#keyset[id, index] -sequence_expr_elements( //dir=expr - int id: @sequence_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -super_ref_exprs( //dir=expr - unique int id: @super_ref_expr, - int self: @var_decl_or_none ref -); - -tap_exprs( //dir=expr - unique int id: @tap_expr, - int body: @brace_stmt_or_none ref, - int var: @var_decl_or_none ref -); - -#keyset[id] -tap_expr_sub_exprs( //dir=expr - int id: @tap_expr ref, - int sub_expr: @expr_or_none ref -); - -tuple_element_exprs( //dir=expr - unique int id: @tuple_element_expr, - int sub_expr: @expr_or_none ref, - int index: int ref -); - -tuple_exprs( //dir=expr - unique int id: @tuple_expr -); - -#keyset[id, index] -tuple_expr_elements( //dir=expr - int id: @tuple_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -type_exprs( //dir=expr - unique int id: @type_expr -); - -#keyset[id] -type_expr_type_reprs( //dir=expr - int id: @type_expr ref, - int type_repr: @type_repr_or_none ref -); - -unresolved_decl_ref_exprs( //dir=expr - unique int id: @unresolved_decl_ref_expr -); - -#keyset[id] -unresolved_decl_ref_expr_names( //dir=expr - int id: @unresolved_decl_ref_expr ref, - string name: string ref -); - -unresolved_dot_exprs( //dir=expr - unique int id: @unresolved_dot_expr, - int base: @expr_or_none ref, - string name: string ref -); - -unresolved_member_exprs( //dir=expr - unique int id: @unresolved_member_expr, - string name: string ref -); - -unresolved_pattern_exprs( //dir=expr - unique int id: @unresolved_pattern_expr, - int sub_pattern: @pattern_or_none ref -); - -unresolved_specialize_exprs( //dir=expr - unique int id: @unresolved_specialize_expr, - int sub_expr: @expr_or_none ref -); - -vararg_expansion_exprs( //dir=expr - unique int id: @vararg_expansion_expr, - int sub_expr: @expr_or_none ref -); - -abi_safe_conversion_exprs( //dir=expr - unique int id: @abi_safe_conversion_expr -); - -any_hashable_erasure_exprs( //dir=expr - unique int id: @any_hashable_erasure_expr -); - -archetype_to_super_exprs( //dir=expr - unique int id: @archetype_to_super_expr -); - -array_exprs( //dir=expr - unique int id: @array_expr -); - -#keyset[id, index] -array_expr_elements( //dir=expr - int id: @array_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -array_to_pointer_exprs( //dir=expr - unique int id: @array_to_pointer_expr -); - -auto_closure_exprs( //dir=expr - unique int id: @auto_closure_expr -); - -await_exprs( //dir=expr - unique int id: @await_expr -); - -binary_exprs( //dir=expr - unique int id: @binary_expr -); - -bridge_from_obj_c_exprs( //dir=expr - unique int id: @bridge_from_obj_c_expr -); - -bridge_to_obj_c_exprs( //dir=expr - unique int id: @bridge_to_obj_c_expr -); - -@builtin_literal_expr = - @boolean_literal_expr -| @magic_identifier_literal_expr -| @number_literal_expr -| @string_literal_expr -; - -call_exprs( //dir=expr - unique int id: @call_expr -); - -@checked_cast_expr = - @conditional_checked_cast_expr -| @forced_checked_cast_expr -| @is_expr -; - -class_metatype_to_object_exprs( //dir=expr - unique int id: @class_metatype_to_object_expr -); - -closure_exprs( //dir=expr - unique int id: @closure_expr -); - -coerce_exprs( //dir=expr - unique int id: @coerce_expr -); - -collection_upcast_conversion_exprs( //dir=expr - unique int id: @collection_upcast_conversion_expr -); - -conditional_bridge_from_obj_c_exprs( //dir=expr - unique int id: @conditional_bridge_from_obj_c_expr -); - -covariant_function_conversion_exprs( //dir=expr - unique int id: @covariant_function_conversion_expr -); - -covariant_return_conversion_exprs( //dir=expr - unique int id: @covariant_return_conversion_expr -); - -derived_to_base_exprs( //dir=expr - unique int id: @derived_to_base_expr -); - -destructure_tuple_exprs( //dir=expr - unique int id: @destructure_tuple_expr -); - -dictionary_exprs( //dir=expr - unique int id: @dictionary_expr -); - -#keyset[id, index] -dictionary_expr_elements( //dir=expr - int id: @dictionary_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -differentiable_function_exprs( //dir=expr - unique int id: @differentiable_function_expr -); - -differentiable_function_extract_original_exprs( //dir=expr - unique int id: @differentiable_function_extract_original_expr -); - -dot_self_exprs( //dir=expr - unique int id: @dot_self_expr -); - -@dynamic_lookup_expr = - @dynamic_member_ref_expr -| @dynamic_subscript_expr -; - -erasure_exprs( //dir=expr - unique int id: @erasure_expr -); - -existential_metatype_to_object_exprs( //dir=expr - unique int id: @existential_metatype_to_object_expr -); - -force_try_exprs( //dir=expr - unique int id: @force_try_expr -); - -foreign_object_conversion_exprs( //dir=expr - unique int id: @foreign_object_conversion_expr -); - -function_conversion_exprs( //dir=expr - unique int id: @function_conversion_expr -); - -in_out_to_pointer_exprs( //dir=expr - unique int id: @in_out_to_pointer_expr -); - -inject_into_optional_exprs( //dir=expr - unique int id: @inject_into_optional_expr -); - -interpolated_string_literal_exprs( //dir=expr - unique int id: @interpolated_string_literal_expr -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_expr: @opaque_value_expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_count_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int literal_capacity_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_appending_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int appending_expr: @tap_expr_or_none ref -); - -linear_function_exprs( //dir=expr - unique int id: @linear_function_expr -); - -linear_function_extract_original_exprs( //dir=expr - unique int id: @linear_function_extract_original_expr -); - -linear_to_differentiable_function_exprs( //dir=expr - unique int id: @linear_to_differentiable_function_expr -); - -load_exprs( //dir=expr - unique int id: @load_expr -); - -member_ref_exprs( //dir=expr - unique int id: @member_ref_expr -); - -#keyset[id] -member_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_ordinary_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @member_ref_expr ref -); - -metatype_conversion_exprs( //dir=expr - unique int id: @metatype_conversion_expr -); - -nil_literal_exprs( //dir=expr - unique int id: @nil_literal_expr -); - -object_literal_exprs( //dir=expr - unique int id: @object_literal_expr, - int kind: int ref -); - -#keyset[id, index] -object_literal_expr_arguments( //dir=expr - int id: @object_literal_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -optional_try_exprs( //dir=expr - unique int id: @optional_try_expr -); - -paren_exprs( //dir=expr - unique int id: @paren_expr -); - -pointer_to_pointer_exprs( //dir=expr - unique int id: @pointer_to_pointer_expr -); - -postfix_unary_exprs( //dir=expr - unique int id: @postfix_unary_expr -); - -prefix_unary_exprs( //dir=expr - unique int id: @prefix_unary_expr -); - -protocol_metatype_to_object_exprs( //dir=expr - unique int id: @protocol_metatype_to_object_expr -); - -regex_literal_exprs( //dir=expr - unique int id: @regex_literal_expr, - string pattern: string ref, - int version: int ref -); - -@self_apply_expr = - @constructor_ref_call_expr -| @dot_syntax_call_expr -; - -#keyset[id] -self_apply_exprs( //dir=expr - int id: @self_apply_expr ref, - int base: @expr_or_none ref -); - -string_to_pointer_exprs( //dir=expr - unique int id: @string_to_pointer_expr -); - -subscript_exprs( //dir=expr - unique int id: @subscript_expr -); - -#keyset[id, index] -subscript_expr_arguments( //dir=expr - int id: @subscript_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -#keyset[id] -subscript_expr_has_direct_to_storage_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_ordinary_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_distributed_thunk_semantics( //dir=expr - int id: @subscript_expr ref -); - -try_exprs( //dir=expr - unique int id: @try_expr -); - -underlying_to_opaque_exprs( //dir=expr - unique int id: @underlying_to_opaque_expr -); - -unevaluated_instance_exprs( //dir=expr - unique int id: @unevaluated_instance_expr -); - -unresolved_member_chain_result_exprs( //dir=expr - unique int id: @unresolved_member_chain_result_expr -); - -unresolved_type_conversion_exprs( //dir=expr - unique int id: @unresolved_type_conversion_expr -); - -boolean_literal_exprs( //dir=expr - unique int id: @boolean_literal_expr, - boolean value: boolean ref -); - -conditional_checked_cast_exprs( //dir=expr - unique int id: @conditional_checked_cast_expr -); - -constructor_ref_call_exprs( //dir=expr - unique int id: @constructor_ref_call_expr -); - -dot_syntax_call_exprs( //dir=expr - unique int id: @dot_syntax_call_expr -); - -dynamic_member_ref_exprs( //dir=expr - unique int id: @dynamic_member_ref_expr -); - -dynamic_subscript_exprs( //dir=expr - unique int id: @dynamic_subscript_expr -); - -forced_checked_cast_exprs( //dir=expr - unique int id: @forced_checked_cast_expr -); - -is_exprs( //dir=expr - unique int id: @is_expr -); - -magic_identifier_literal_exprs( //dir=expr - unique int id: @magic_identifier_literal_expr, - string kind: string ref -); - -@number_literal_expr = - @float_literal_expr -| @integer_literal_expr -; - -string_literal_exprs( //dir=expr - unique int id: @string_literal_expr, - string value: string ref -); - -float_literal_exprs( //dir=expr - unique int id: @float_literal_expr, - string string_value: string ref -); - -integer_literal_exprs( //dir=expr - unique int id: @integer_literal_expr, - string string_value: string ref -); - -@pattern = - @any_pattern -| @binding_pattern -| @bool_pattern -| @enum_element_pattern -| @expr_pattern -| @is_pattern -| @named_pattern -| @optional_some_pattern -| @paren_pattern -| @tuple_pattern -| @typed_pattern -; - -any_patterns( //dir=pattern - unique int id: @any_pattern -); - -binding_patterns( //dir=pattern - unique int id: @binding_pattern, - int sub_pattern: @pattern_or_none ref -); - -bool_patterns( //dir=pattern - unique int id: @bool_pattern, - boolean value: boolean ref -); - -enum_element_patterns( //dir=pattern - unique int id: @enum_element_pattern, - int element: @enum_element_decl_or_none ref -); - -#keyset[id] -enum_element_pattern_sub_patterns( //dir=pattern - int id: @enum_element_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -expr_patterns( //dir=pattern - unique int id: @expr_pattern, - int sub_expr: @expr_or_none ref -); - -is_patterns( //dir=pattern - unique int id: @is_pattern -); - -#keyset[id] -is_pattern_cast_type_reprs( //dir=pattern - int id: @is_pattern ref, - int cast_type_repr: @type_repr_or_none ref -); - -#keyset[id] -is_pattern_sub_patterns( //dir=pattern - int id: @is_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -named_patterns( //dir=pattern - unique int id: @named_pattern, - string name: string ref -); - -optional_some_patterns( //dir=pattern - unique int id: @optional_some_pattern, - int sub_pattern: @pattern_or_none ref -); - -paren_patterns( //dir=pattern - unique int id: @paren_pattern, - int sub_pattern: @pattern_or_none ref -); - -tuple_patterns( //dir=pattern - unique int id: @tuple_pattern -); - -#keyset[id, index] -tuple_pattern_elements( //dir=pattern - int id: @tuple_pattern ref, - int index: int ref, - int element: @pattern_or_none ref -); - -typed_patterns( //dir=pattern - unique int id: @typed_pattern, - int sub_pattern: @pattern_or_none ref -); - -#keyset[id] -typed_pattern_type_reprs( //dir=pattern - int id: @typed_pattern ref, - int type_repr: @type_repr_or_none ref -); - -case_label_items( //dir=stmt - unique int id: @case_label_item, - int pattern: @pattern_or_none ref -); - -#keyset[id] -case_label_item_guards( //dir=stmt - int id: @case_label_item ref, - int guard: @expr_or_none ref -); - -condition_elements( //dir=stmt - unique int id: @condition_element -); - -#keyset[id] -condition_element_booleans( //dir=stmt - int id: @condition_element ref, - int boolean_: @expr_or_none ref -); - -#keyset[id] -condition_element_patterns( //dir=stmt - int id: @condition_element ref, - int pattern: @pattern_or_none ref -); - -#keyset[id] -condition_element_initializers( //dir=stmt - int id: @condition_element ref, - int initializer: @expr_or_none ref -); - -#keyset[id] -condition_element_availabilities( //dir=stmt - int id: @condition_element ref, - int availability: @availability_info_or_none ref -); - -@stmt = - @brace_stmt -| @break_stmt -| @case_stmt -| @continue_stmt -| @defer_stmt -| @fail_stmt -| @fallthrough_stmt -| @labeled_stmt -| @pound_assert_stmt -| @return_stmt -| @throw_stmt -| @yield_stmt -; - -stmt_conditions( //dir=stmt - unique int id: @stmt_condition -); - -#keyset[id, index] -stmt_condition_elements( //dir=stmt - int id: @stmt_condition ref, - int index: int ref, - int element: @condition_element_or_none ref -); - -brace_stmts( //dir=stmt - unique int id: @brace_stmt -); - -#keyset[id, index] -brace_stmt_elements( //dir=stmt - int id: @brace_stmt ref, - int index: int ref, - int element: @ast_node_or_none ref -); - -break_stmts( //dir=stmt - unique int id: @break_stmt -); - -#keyset[id] -break_stmt_target_names( //dir=stmt - int id: @break_stmt ref, - string target_name: string ref -); - -#keyset[id] -break_stmt_targets( //dir=stmt - int id: @break_stmt ref, - int target: @stmt_or_none ref -); - -case_stmts( //dir=stmt - unique int id: @case_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -case_stmt_labels( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int label: @case_label_item_or_none ref -); - -#keyset[id, index] -case_stmt_variables( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int variable: @var_decl_or_none ref -); - -continue_stmts( //dir=stmt - unique int id: @continue_stmt -); - -#keyset[id] -continue_stmt_target_names( //dir=stmt - int id: @continue_stmt ref, - string target_name: string ref -); - -#keyset[id] -continue_stmt_targets( //dir=stmt - int id: @continue_stmt ref, - int target: @stmt_or_none ref -); - -defer_stmts( //dir=stmt - unique int id: @defer_stmt, - int body: @brace_stmt_or_none ref -); - -fail_stmts( //dir=stmt - unique int id: @fail_stmt -); - -fallthrough_stmts( //dir=stmt - unique int id: @fallthrough_stmt, - int fallthrough_source: @case_stmt_or_none ref, - int fallthrough_dest: @case_stmt_or_none ref -); - -@labeled_stmt = - @do_catch_stmt -| @do_stmt -| @for_each_stmt -| @labeled_conditional_stmt -| @repeat_while_stmt -| @switch_stmt -; - -#keyset[id] -labeled_stmt_labels( //dir=stmt - int id: @labeled_stmt ref, - string label: string ref -); - -pound_assert_stmts( //dir=stmt - unique int id: @pound_assert_stmt, - int condition: @expr_or_none ref, - string message: string ref -); - -return_stmts( //dir=stmt - unique int id: @return_stmt -); - -#keyset[id] -return_stmt_results( //dir=stmt - int id: @return_stmt ref, - int result: @expr_or_none ref -); - -throw_stmts( //dir=stmt - unique int id: @throw_stmt, - int sub_expr: @expr_or_none ref -); - -yield_stmts( //dir=stmt - unique int id: @yield_stmt -); - -#keyset[id, index] -yield_stmt_results( //dir=stmt - int id: @yield_stmt ref, - int index: int ref, - int result: @expr_or_none ref -); - -do_catch_stmts( //dir=stmt - unique int id: @do_catch_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -do_catch_stmt_catches( //dir=stmt - int id: @do_catch_stmt ref, - int index: int ref, - int catch: @case_stmt_or_none ref -); - -do_stmts( //dir=stmt - unique int id: @do_stmt, - int body: @brace_stmt_or_none ref -); - -for_each_stmts( //dir=stmt - unique int id: @for_each_stmt, - int pattern: @pattern_or_none ref, - int sequence: @expr_or_none ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id] -for_each_stmt_wheres( //dir=stmt - int id: @for_each_stmt ref, - int where: @expr_or_none ref -); - -@labeled_conditional_stmt = - @guard_stmt -| @if_stmt -| @while_stmt -; - -#keyset[id] -labeled_conditional_stmts( //dir=stmt - int id: @labeled_conditional_stmt ref, - int condition: @stmt_condition_or_none ref -); - -repeat_while_stmts( //dir=stmt - unique int id: @repeat_while_stmt, - int condition: @expr_or_none ref, - int body: @stmt_or_none ref -); - -switch_stmts( //dir=stmt - unique int id: @switch_stmt, - int expr: @expr_or_none ref -); - -#keyset[id, index] -switch_stmt_cases( //dir=stmt - int id: @switch_stmt ref, - int index: int ref, - int case_: @case_stmt_or_none ref -); - -guard_stmts( //dir=stmt - unique int id: @guard_stmt, - int body: @brace_stmt_or_none ref -); - -if_stmts( //dir=stmt - unique int id: @if_stmt, - int then: @stmt_or_none ref -); - -#keyset[id] -if_stmt_elses( //dir=stmt - int id: @if_stmt ref, - int else: @stmt_or_none ref -); - -while_stmts( //dir=stmt - unique int id: @while_stmt, - int body: @stmt_or_none ref -); - -@type = - @any_function_type -| @any_generic_type -| @any_metatype_type -| @builtin_type -| @dependent_member_type -| @dynamic_self_type -| @error_type -| @existential_type -| @in_out_type -| @l_value_type -| @module_type -| @parameterized_protocol_type -| @protocol_composition_type -| @reference_storage_type -| @substitutable_type -| @sugar_type -| @tuple_type -| @unresolved_type -; - -#keyset[id] -types( //dir=type - int id: @type ref, - string name: string ref, - int canonical_type: @type_or_none ref -); - -type_reprs( //dir=type - unique int id: @type_repr, - int type_: @type_or_none ref -); - -@any_function_type = - @function_type -| @generic_function_type -; - -#keyset[id] -any_function_types( //dir=type - int id: @any_function_type ref, - int result: @type_or_none ref -); - -#keyset[id, index] -any_function_type_param_types( //dir=type - int id: @any_function_type ref, - int index: int ref, - int param_type: @type_or_none ref -); - -#keyset[id] -any_function_type_is_throwing( //dir=type - int id: @any_function_type ref -); - -#keyset[id] -any_function_type_is_async( //dir=type - int id: @any_function_type ref -); - -@any_generic_type = - @nominal_or_bound_generic_nominal_type -| @unbound_generic_type -; - -#keyset[id] -any_generic_types( //dir=type - int id: @any_generic_type ref, - int declaration: @generic_type_decl_or_none ref -); - -#keyset[id] -any_generic_type_parents( //dir=type - int id: @any_generic_type ref, - int parent: @type_or_none ref -); - -@any_metatype_type = - @existential_metatype_type -| @metatype_type -; - -@builtin_type = - @any_builtin_integer_type -| @builtin_bridge_object_type -| @builtin_default_actor_storage_type -| @builtin_executor_type -| @builtin_float_type -| @builtin_job_type -| @builtin_native_object_type -| @builtin_raw_pointer_type -| @builtin_raw_unsafe_continuation_type -| @builtin_unsafe_value_buffer_type -| @builtin_vector_type -; - -dependent_member_types( //dir=type - unique int id: @dependent_member_type, - int base_type: @type_or_none ref, - int associated_type_decl: @associated_type_decl_or_none ref -); - -dynamic_self_types( //dir=type - unique int id: @dynamic_self_type, - int static_self_type: @type_or_none ref -); - -error_types( //dir=type - unique int id: @error_type -); - -existential_types( //dir=type - unique int id: @existential_type, - int constraint: @type_or_none ref -); - -in_out_types( //dir=type - unique int id: @in_out_type, - int object_type: @type_or_none ref -); - -l_value_types( //dir=type - unique int id: @l_value_type, - int object_type: @type_or_none ref -); - -module_types( //dir=type - unique int id: @module_type, - int module: @module_decl_or_none ref -); - -parameterized_protocol_types( //dir=type - unique int id: @parameterized_protocol_type, - int base: @protocol_type_or_none ref -); - -#keyset[id, index] -parameterized_protocol_type_args( //dir=type - int id: @parameterized_protocol_type ref, - int index: int ref, - int arg: @type_or_none ref -); - -protocol_composition_types( //dir=type - unique int id: @protocol_composition_type -); - -#keyset[id, index] -protocol_composition_type_members( //dir=type - int id: @protocol_composition_type ref, - int index: int ref, - int member: @type_or_none ref -); - -@reference_storage_type = - @unmanaged_storage_type -| @unowned_storage_type -| @weak_storage_type -; - -#keyset[id] -reference_storage_types( //dir=type - int id: @reference_storage_type ref, - int referent_type: @type_or_none ref -); - -@substitutable_type = - @archetype_type -| @generic_type_param_type -; - -@sugar_type = - @paren_type -| @syntax_sugar_type -| @type_alias_type -; - -tuple_types( //dir=type - unique int id: @tuple_type -); - -#keyset[id, index] -tuple_type_types( //dir=type - int id: @tuple_type ref, - int index: int ref, - int type_: @type_or_none ref -); - -#keyset[id, index] -tuple_type_names( //dir=type - int id: @tuple_type ref, - int index: int ref, - string name: string ref -); - -unresolved_types( //dir=type - unique int id: @unresolved_type -); - -@any_builtin_integer_type = - @builtin_integer_literal_type -| @builtin_integer_type -; - -@archetype_type = - @opaque_type_archetype_type -| @opened_archetype_type -| @primary_archetype_type -; - -#keyset[id] -archetype_types( //dir=type - int id: @archetype_type ref, - int interface_type: @type_or_none ref -); - -#keyset[id] -archetype_type_superclasses( //dir=type - int id: @archetype_type ref, - int superclass: @type_or_none ref -); - -#keyset[id, index] -archetype_type_protocols( //dir=type - int id: @archetype_type ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -builtin_bridge_object_types( //dir=type - unique int id: @builtin_bridge_object_type -); - -builtin_default_actor_storage_types( //dir=type - unique int id: @builtin_default_actor_storage_type -); - -builtin_executor_types( //dir=type - unique int id: @builtin_executor_type -); - -builtin_float_types( //dir=type - unique int id: @builtin_float_type -); - -builtin_job_types( //dir=type - unique int id: @builtin_job_type -); - -builtin_native_object_types( //dir=type - unique int id: @builtin_native_object_type -); - -builtin_raw_pointer_types( //dir=type - unique int id: @builtin_raw_pointer_type -); - -builtin_raw_unsafe_continuation_types( //dir=type - unique int id: @builtin_raw_unsafe_continuation_type -); - -builtin_unsafe_value_buffer_types( //dir=type - unique int id: @builtin_unsafe_value_buffer_type -); - -builtin_vector_types( //dir=type - unique int id: @builtin_vector_type -); - -existential_metatype_types( //dir=type - unique int id: @existential_metatype_type -); - -function_types( //dir=type - unique int id: @function_type -); - -generic_function_types( //dir=type - unique int id: @generic_function_type -); - -#keyset[id, index] -generic_function_type_generic_params( //dir=type - int id: @generic_function_type ref, - int index: int ref, - int generic_param: @generic_type_param_type_or_none ref -); - -generic_type_param_types( //dir=type - unique int id: @generic_type_param_type -); - -metatype_types( //dir=type - unique int id: @metatype_type -); - -@nominal_or_bound_generic_nominal_type = - @bound_generic_type -| @nominal_type -; - -paren_types( //dir=type - unique int id: @paren_type, - int type_: @type_or_none ref -); - -@syntax_sugar_type = - @dictionary_type -| @unary_syntax_sugar_type -; - -type_alias_types( //dir=type - unique int id: @type_alias_type, - int decl: @type_alias_decl_or_none ref -); - -unbound_generic_types( //dir=type - unique int id: @unbound_generic_type -); - -unmanaged_storage_types( //dir=type - unique int id: @unmanaged_storage_type -); - -unowned_storage_types( //dir=type - unique int id: @unowned_storage_type -); - -weak_storage_types( //dir=type - unique int id: @weak_storage_type -); - -@bound_generic_type = - @bound_generic_class_type -| @bound_generic_enum_type -| @bound_generic_struct_type -; - -#keyset[id, index] -bound_generic_type_arg_types( //dir=type - int id: @bound_generic_type ref, - int index: int ref, - int arg_type: @type_or_none ref -); - -builtin_integer_literal_types( //dir=type - unique int id: @builtin_integer_literal_type -); - -builtin_integer_types( //dir=type - unique int id: @builtin_integer_type -); - -#keyset[id] -builtin_integer_type_widths( //dir=type - int id: @builtin_integer_type ref, - int width: int ref -); - -dictionary_types( //dir=type - unique int id: @dictionary_type, - int key_type: @type_or_none ref, - int value_type: @type_or_none ref -); - -@nominal_type = - @class_type -| @enum_type -| @protocol_type -| @struct_type -; - -opaque_type_archetype_types( //dir=type - unique int id: @opaque_type_archetype_type, - int declaration: @opaque_type_decl_or_none ref -); - -opened_archetype_types( //dir=type - unique int id: @opened_archetype_type -); - -primary_archetype_types( //dir=type - unique int id: @primary_archetype_type -); - -@unary_syntax_sugar_type = - @array_slice_type -| @optional_type -| @variadic_sequence_type -; - -#keyset[id] -unary_syntax_sugar_types( //dir=type - int id: @unary_syntax_sugar_type ref, - int base_type: @type_or_none ref -); - -array_slice_types( //dir=type - unique int id: @array_slice_type -); - -bound_generic_class_types( //dir=type - unique int id: @bound_generic_class_type -); - -bound_generic_enum_types( //dir=type - unique int id: @bound_generic_enum_type -); - -bound_generic_struct_types( //dir=type - unique int id: @bound_generic_struct_type -); - -class_types( //dir=type - unique int id: @class_type -); - -enum_types( //dir=type - unique int id: @enum_type -); - -optional_types( //dir=type - unique int id: @optional_type -); - -protocol_types( //dir=type - unique int id: @protocol_type -); - -struct_types( //dir=type - unique int id: @struct_type -); - -variadic_sequence_types( //dir=type - unique int id: @variadic_sequence_type -); - -@abstract_function_decl_or_none = - @abstract_function_decl -| @unspecified_element -; - -@accessor_decl_or_none = - @accessor_decl -| @unspecified_element -; - -@argument_or_none = - @argument -| @unspecified_element -; - -@associated_type_decl_or_none = - @associated_type_decl -| @unspecified_element -; - -@ast_node_or_none = - @ast_node -| @unspecified_element -; - -@availability_info_or_none = - @availability_info -| @unspecified_element -; - -@availability_spec_or_none = - @availability_spec -| @unspecified_element -; - -@brace_stmt_or_none = - @brace_stmt -| @unspecified_element -; - -@captured_decl_or_none = - @captured_decl -| @unspecified_element -; - -@case_label_item_or_none = - @case_label_item -| @unspecified_element -; - -@case_stmt_or_none = - @case_stmt -| @unspecified_element -; - -@closure_expr_or_none = - @closure_expr -| @unspecified_element -; - -@condition_element_or_none = - @condition_element -| @unspecified_element -; - -@constructor_decl_or_none = - @constructor_decl -| @unspecified_element -; - -@decl_or_none = - @decl -| @unspecified_element -; - -@enum_element_decl_or_none = - @enum_element_decl -| @unspecified_element -; - -@expr_or_none = - @expr -| @unspecified_element -; - -@file_or_none = - @file -| @unspecified_element -; - -@generic_type_decl_or_none = - @generic_type_decl -| @unspecified_element -; - -@generic_type_param_decl_or_none = - @generic_type_param_decl -| @unspecified_element -; - -@generic_type_param_type_or_none = - @generic_type_param_type -| @unspecified_element -; - -@location_or_none = - @location -| @unspecified_element -; - -@module_decl_or_none = - @module_decl -| @unspecified_element -; - -@nominal_type_decl_or_none = - @nominal_type_decl -| @unspecified_element -; - -@opaque_type_decl_or_none = - @opaque_type_decl -| @unspecified_element -; - -@opaque_value_expr_or_none = - @opaque_value_expr -| @unspecified_element -; - -@param_decl_or_none = - @param_decl -| @unspecified_element -; - -@pattern_or_none = - @pattern -| @unspecified_element -; - -@pattern_binding_decl_or_none = - @pattern_binding_decl -| @unspecified_element -; - -@precedence_group_decl_or_none = - @precedence_group_decl -| @unspecified_element -; - -@protocol_decl_or_none = - @protocol_decl -| @unspecified_element -; - -@protocol_type_or_none = - @protocol_type -| @unspecified_element -; - -@stmt_or_none = - @stmt -| @unspecified_element -; - -@stmt_condition_or_none = - @stmt_condition -| @unspecified_element -; - -@string_literal_expr_or_none = - @string_literal_expr -| @unspecified_element -; - -@tap_expr_or_none = - @tap_expr -| @unspecified_element -; - -@type_or_none = - @type -| @unspecified_element -; - -@type_alias_decl_or_none = - @type_alias_decl -| @unspecified_element -; - -@type_repr_or_none = - @type_repr -| @unspecified_element -; - -@value_decl_or_none = - @unspecified_element -| @value_decl -; - -@var_decl_or_none = - @unspecified_element -| @var_decl -; diff --git a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties b/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties deleted file mode 100644 index 160d55476c9..00000000000 --- a/swift/downgrades/db22947f6ae7024092c0da65b4fafb973f2331a3/upgrade.properties +++ /dev/null @@ -1,4 +0,0 @@ -description: Revert turning exported and imported modules into unindexed sets -compatibility: full -module_decl_imported_modules.rel: run module_decl_imported_modules.ql -module_decl_exported_modules.rel: run module_decl_exported_modules.ql diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme deleted file mode 100644 index c2f01f2beb6..00000000000 --- a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/old.dbscheme +++ /dev/null @@ -1,2601 +0,0 @@ -// generated by codegen/codegen.py - -// from prefix.dbscheme -/** - * The source location of the snapshot. - */ -sourceLocationPrefix( - string prefix: string ref -); - - -// from schema.py - -@element = - @callable -| @file -| @generic_context -| @locatable -| @location -| @type -; - -#keyset[id] -element_is_unknown( - int id: @element ref -); - -@callable = - @abstract_closure_expr -| @abstract_function_decl -; - -#keyset[id] -callable_names( - int id: @callable ref, - string name: string ref -); - -#keyset[id] -callable_self_params( - int id: @callable ref, - int self_param: @param_decl_or_none ref -); - -#keyset[id, index] -callable_params( - int id: @callable ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -#keyset[id] -callable_bodies( - int id: @callable ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id, index] -callable_captures( - int id: @callable ref, - int index: int ref, - int capture: @captured_decl_or_none ref -); - -@file = - @db_file -; - -#keyset[id] -files( - int id: @file ref, - string name: string ref -); - -#keyset[id] -file_is_successfully_extracted( - int id: @file ref -); - -@locatable = - @argument -| @ast_node -| @comment -| @diagnostics -| @error_element -; - -#keyset[id] -locatable_locations( - int id: @locatable ref, - int location: @location_or_none ref -); - -@location = - @db_location -; - -#keyset[id] -locations( - int id: @location ref, - int file: @file_or_none ref, - int start_line: int ref, - int start_column: int ref, - int end_line: int ref, - int end_column: int ref -); - -@ast_node = - @availability_info -| @availability_spec -| @case_label_item -| @condition_element -| @decl -| @expr -| @pattern -| @stmt -| @stmt_condition -| @type_repr -; - -comments( - unique int id: @comment, - string text: string ref -); - -db_files( - unique int id: @db_file -); - -db_locations( - unique int id: @db_location -); - -diagnostics( - unique int id: @diagnostics, - string text: string ref, - int kind: int ref -); - -@error_element = - @error_expr -| @error_type -| @overloaded_decl_ref_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_chain_result_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @unresolved_type -| @unresolved_type_conversion_expr -| @unspecified_element -; - -availability_infos( - unique int id: @availability_info -); - -#keyset[id] -availability_info_is_unavailable( - int id: @availability_info ref -); - -#keyset[id, index] -availability_info_specs( - int id: @availability_info ref, - int index: int ref, - int spec: @availability_spec_or_none ref -); - -@availability_spec = - @other_availability_spec -| @platform_version_availability_spec -; - -unspecified_elements( - unique int id: @unspecified_element, - string property: string ref, - string error: string ref -); - -#keyset[id] -unspecified_element_parents( - int id: @unspecified_element ref, - int parent: @element ref -); - -#keyset[id] -unspecified_element_indices( - int id: @unspecified_element ref, - int index: int ref -); - -other_availability_specs( - unique int id: @other_availability_spec -); - -platform_version_availability_specs( - unique int id: @platform_version_availability_spec, - string platform: string ref, - string version: string ref -); - -@decl = - @captured_decl -| @enum_case_decl -| @extension_decl -| @if_config_decl -| @import_decl -| @missing_member_decl -| @operator_decl -| @pattern_binding_decl -| @pound_diagnostic_decl -| @precedence_group_decl -| @top_level_code_decl -| @value_decl -; - -#keyset[id] -decls( //dir=decl - int id: @decl ref, - int module: @module_decl_or_none ref -); - -#keyset[id, index] -decl_members( //dir=decl - int id: @decl ref, - int index: int ref, - int member: @decl_or_none ref -); - -@generic_context = - @abstract_function_decl -| @extension_decl -| @generic_type_decl -| @subscript_decl -; - -#keyset[id, index] -generic_context_generic_type_params( //dir=decl - int id: @generic_context ref, - int index: int ref, - int generic_type_param: @generic_type_param_decl_or_none ref -); - -captured_decls( //dir=decl - unique int id: @captured_decl, - int decl: @value_decl_or_none ref -); - -#keyset[id] -captured_decl_is_direct( //dir=decl - int id: @captured_decl ref -); - -#keyset[id] -captured_decl_is_escaping( //dir=decl - int id: @captured_decl ref -); - -enum_case_decls( //dir=decl - unique int id: @enum_case_decl -); - -#keyset[id, index] -enum_case_decl_elements( //dir=decl - int id: @enum_case_decl ref, - int index: int ref, - int element: @enum_element_decl_or_none ref -); - -extension_decls( //dir=decl - unique int id: @extension_decl, - int extended_type_decl: @nominal_type_decl_or_none ref -); - -#keyset[id, index] -extension_decl_protocols( //dir=decl - int id: @extension_decl ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -if_config_decls( //dir=decl - unique int id: @if_config_decl -); - -#keyset[id, index] -if_config_decl_active_elements( //dir=decl - int id: @if_config_decl ref, - int index: int ref, - int active_element: @ast_node_or_none ref -); - -import_decls( //dir=decl - unique int id: @import_decl -); - -#keyset[id] -import_decl_is_exported( //dir=decl - int id: @import_decl ref -); - -#keyset[id] -import_decl_imported_modules( //dir=decl - int id: @import_decl ref, - int imported_module: @module_decl_or_none ref -); - -#keyset[id, index] -import_decl_declarations( //dir=decl - int id: @import_decl ref, - int index: int ref, - int declaration: @value_decl_or_none ref -); - -missing_member_decls( //dir=decl - unique int id: @missing_member_decl, - string name: string ref -); - -@operator_decl = - @infix_operator_decl -| @postfix_operator_decl -| @prefix_operator_decl -; - -#keyset[id] -operator_decls( //dir=decl - int id: @operator_decl ref, - string name: string ref -); - -pattern_binding_decls( //dir=decl - unique int id: @pattern_binding_decl -); - -#keyset[id, index] -pattern_binding_decl_inits( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int init: @expr_or_none ref -); - -#keyset[id, index] -pattern_binding_decl_patterns( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int pattern: @pattern_or_none ref -); - -pound_diagnostic_decls( //dir=decl - unique int id: @pound_diagnostic_decl, - int kind: int ref, - int message: @string_literal_expr_or_none ref -); - -precedence_group_decls( //dir=decl - unique int id: @precedence_group_decl -); - -top_level_code_decls( //dir=decl - unique int id: @top_level_code_decl, - int body: @brace_stmt_or_none ref -); - -@value_decl = - @abstract_function_decl -| @abstract_storage_decl -| @enum_element_decl -| @type_decl -; - -#keyset[id] -value_decls( //dir=decl - int id: @value_decl ref, - int interface_type: @type_or_none ref -); - -@abstract_function_decl = - @constructor_decl -| @destructor_decl -| @func_decl -; - -@abstract_storage_decl = - @subscript_decl -| @var_decl -; - -#keyset[id, index] -abstract_storage_decl_accessor_decls( //dir=decl - int id: @abstract_storage_decl ref, - int index: int ref, - int accessor_decl: @accessor_decl_or_none ref -); - -enum_element_decls( //dir=decl - unique int id: @enum_element_decl, - string name: string ref -); - -#keyset[id, index] -enum_element_decl_params( //dir=decl - int id: @enum_element_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -infix_operator_decls( //dir=decl - unique int id: @infix_operator_decl -); - -#keyset[id] -infix_operator_decl_precedence_groups( //dir=decl - int id: @infix_operator_decl ref, - int precedence_group: @precedence_group_decl_or_none ref -); - -postfix_operator_decls( //dir=decl - unique int id: @postfix_operator_decl -); - -prefix_operator_decls( //dir=decl - unique int id: @prefix_operator_decl -); - -@type_decl = - @abstract_type_param_decl -| @generic_type_decl -| @module_decl -; - -#keyset[id] -type_decls( //dir=decl - int id: @type_decl ref, - string name: string ref -); - -#keyset[id, index] -type_decl_base_types( //dir=decl - int id: @type_decl ref, - int index: int ref, - int base_type: @type_or_none ref -); - -@abstract_type_param_decl = - @associated_type_decl -| @generic_type_param_decl -; - -constructor_decls( //dir=decl - unique int id: @constructor_decl -); - -destructor_decls( //dir=decl - unique int id: @destructor_decl -); - -@func_decl = - @accessor_decl -| @concrete_func_decl -; - -@generic_type_decl = - @nominal_type_decl -| @opaque_type_decl -| @type_alias_decl -; - -module_decls( //dir=decl - unique int id: @module_decl -); - -#keyset[id] -module_decl_is_builtin_module( //dir=decl - int id: @module_decl ref -); - -#keyset[id] -module_decl_is_system_module( //dir=decl - int id: @module_decl ref -); - -#keyset[id, index] -module_decl_imported_modules( //dir=decl - int id: @module_decl ref, - int index: int ref, - int imported_module: @module_decl_or_none ref -); - -#keyset[id, index] -module_decl_exported_modules( //dir=decl - int id: @module_decl ref, - int index: int ref, - int exported_module: @module_decl_or_none ref -); - -subscript_decls( //dir=decl - unique int id: @subscript_decl, - int element_type: @type_or_none ref -); - -#keyset[id, index] -subscript_decl_params( //dir=decl - int id: @subscript_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -@var_decl = - @concrete_var_decl -| @param_decl -; - -#keyset[id] -var_decls( //dir=decl - int id: @var_decl ref, - string name: string ref, - int type_: @type_or_none ref -); - -#keyset[id] -var_decl_attached_property_wrapper_types( //dir=decl - int id: @var_decl ref, - int attached_property_wrapper_type: @type_or_none ref -); - -#keyset[id] -var_decl_parent_patterns( //dir=decl - int id: @var_decl ref, - int parent_pattern: @pattern_or_none ref -); - -#keyset[id] -var_decl_parent_initializers( //dir=decl - int id: @var_decl ref, - int parent_initializer: @expr_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var: @var_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var: @var_decl_or_none ref -); - -accessor_decls( //dir=decl - unique int id: @accessor_decl -); - -#keyset[id] -accessor_decl_is_getter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_setter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_will_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_did_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_read( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_modify( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_address( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_mutable_address( //dir=decl - int id: @accessor_decl ref -); - -associated_type_decls( //dir=decl - unique int id: @associated_type_decl -); - -concrete_func_decls( //dir=decl - unique int id: @concrete_func_decl -); - -concrete_var_decls( //dir=decl - unique int id: @concrete_var_decl, - int introducer_int: int ref -); - -generic_type_param_decls( //dir=decl - unique int id: @generic_type_param_decl -); - -@nominal_type_decl = - @class_decl -| @enum_decl -| @protocol_decl -| @struct_decl -; - -#keyset[id] -nominal_type_decls( //dir=decl - int id: @nominal_type_decl ref, - int type_: @type_or_none ref -); - -opaque_type_decls( //dir=decl - unique int id: @opaque_type_decl, - int naming_declaration: @value_decl_or_none ref -); - -#keyset[id, index] -opaque_type_decl_opaque_generic_params( //dir=decl - int id: @opaque_type_decl ref, - int index: int ref, - int opaque_generic_param: @generic_type_param_type_or_none ref -); - -param_decls( //dir=decl - unique int id: @param_decl -); - -#keyset[id] -param_decl_is_inout( //dir=decl - int id: @param_decl ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_vars( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var: @var_decl_or_none ref -); - -type_alias_decls( //dir=decl - unique int id: @type_alias_decl -); - -class_decls( //dir=decl - unique int id: @class_decl -); - -enum_decls( //dir=decl - unique int id: @enum_decl -); - -protocol_decls( //dir=decl - unique int id: @protocol_decl -); - -struct_decls( //dir=decl - unique int id: @struct_decl -); - -arguments( //dir=expr - unique int id: @argument, - string label: string ref, - int expr: @expr_or_none ref -); - -@expr = - @abstract_closure_expr -| @any_try_expr -| @applied_property_wrapper_expr -| @apply_expr -| @assign_expr -| @bind_optional_expr -| @capture_list_expr -| @collection_expr -| @decl_ref_expr -| @default_argument_expr -| @discard_assignment_expr -| @dot_syntax_base_ignored_expr -| @dynamic_type_expr -| @enum_is_case_expr -| @error_expr -| @explicit_cast_expr -| @force_value_expr -| @identity_expr -| @if_expr -| @implicit_conversion_expr -| @in_out_expr -| @key_path_application_expr -| @key_path_dot_expr -| @key_path_expr -| @lazy_initializer_expr -| @literal_expr -| @lookup_expr -| @make_temporarily_escapable_expr -| @obj_c_selector_expr -| @one_way_expr -| @opaque_value_expr -| @open_existential_expr -| @optional_evaluation_expr -| @other_constructor_decl_ref_expr -| @overloaded_decl_ref_expr -| @property_wrapper_value_placeholder_expr -| @rebind_self_in_constructor_expr -| @sequence_expr -| @super_ref_expr -| @tap_expr -| @tuple_element_expr -| @tuple_expr -| @type_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @vararg_expansion_expr -; - -#keyset[id] -expr_types( //dir=expr - int id: @expr ref, - int type_: @type_or_none ref -); - -@abstract_closure_expr = - @auto_closure_expr -| @closure_expr -; - -@any_try_expr = - @force_try_expr -| @optional_try_expr -| @try_expr -; - -#keyset[id] -any_try_exprs( //dir=expr - int id: @any_try_expr ref, - int sub_expr: @expr_or_none ref -); - -applied_property_wrapper_exprs( //dir=expr - unique int id: @applied_property_wrapper_expr, - int kind: int ref, - int value: @expr_or_none ref, - int param: @param_decl_or_none ref -); - -@apply_expr = - @binary_expr -| @call_expr -| @postfix_unary_expr -| @prefix_unary_expr -| @self_apply_expr -; - -#keyset[id] -apply_exprs( //dir=expr - int id: @apply_expr ref, - int function: @expr_or_none ref -); - -#keyset[id, index] -apply_expr_arguments( //dir=expr - int id: @apply_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -assign_exprs( //dir=expr - unique int id: @assign_expr, - int dest: @expr_or_none ref, - int source: @expr_or_none ref -); - -bind_optional_exprs( //dir=expr - unique int id: @bind_optional_expr, - int sub_expr: @expr_or_none ref -); - -capture_list_exprs( //dir=expr - unique int id: @capture_list_expr, - int closure_body: @closure_expr_or_none ref -); - -#keyset[id, index] -capture_list_expr_binding_decls( //dir=expr - int id: @capture_list_expr ref, - int index: int ref, - int binding_decl: @pattern_binding_decl_or_none ref -); - -@collection_expr = - @array_expr -| @dictionary_expr -; - -decl_ref_exprs( //dir=expr - unique int id: @decl_ref_expr, - int decl: @decl_or_none ref -); - -#keyset[id, index] -decl_ref_expr_replacement_types( //dir=expr - int id: @decl_ref_expr ref, - int index: int ref, - int replacement_type: @type_or_none ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_ordinary_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -default_argument_exprs( //dir=expr - unique int id: @default_argument_expr, - int param_decl: @param_decl_or_none ref, - int param_index: int ref -); - -#keyset[id] -default_argument_expr_caller_side_defaults( //dir=expr - int id: @default_argument_expr ref, - int caller_side_default: @expr_or_none ref -); - -discard_assignment_exprs( //dir=expr - unique int id: @discard_assignment_expr -); - -dot_syntax_base_ignored_exprs( //dir=expr - unique int id: @dot_syntax_base_ignored_expr, - int qualifier: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -dynamic_type_exprs( //dir=expr - unique int id: @dynamic_type_expr, - int base: @expr_or_none ref -); - -enum_is_case_exprs( //dir=expr - unique int id: @enum_is_case_expr, - int sub_expr: @expr_or_none ref, - int element: @enum_element_decl_or_none ref -); - -error_exprs( //dir=expr - unique int id: @error_expr -); - -@explicit_cast_expr = - @checked_cast_expr -| @coerce_expr -; - -#keyset[id] -explicit_cast_exprs( //dir=expr - int id: @explicit_cast_expr ref, - int sub_expr: @expr_or_none ref -); - -force_value_exprs( //dir=expr - unique int id: @force_value_expr, - int sub_expr: @expr_or_none ref -); - -@identity_expr = - @await_expr -| @dot_self_expr -| @paren_expr -| @unresolved_member_chain_result_expr -; - -#keyset[id] -identity_exprs( //dir=expr - int id: @identity_expr ref, - int sub_expr: @expr_or_none ref -); - -if_exprs( //dir=expr - unique int id: @if_expr, - int condition: @expr_or_none ref, - int then_expr: @expr_or_none ref, - int else_expr: @expr_or_none ref -); - -@implicit_conversion_expr = - @abi_safe_conversion_expr -| @any_hashable_erasure_expr -| @archetype_to_super_expr -| @array_to_pointer_expr -| @bridge_from_obj_c_expr -| @bridge_to_obj_c_expr -| @class_metatype_to_object_expr -| @collection_upcast_conversion_expr -| @conditional_bridge_from_obj_c_expr -| @covariant_function_conversion_expr -| @covariant_return_conversion_expr -| @derived_to_base_expr -| @destructure_tuple_expr -| @differentiable_function_expr -| @differentiable_function_extract_original_expr -| @erasure_expr -| @existential_metatype_to_object_expr -| @foreign_object_conversion_expr -| @function_conversion_expr -| @in_out_to_pointer_expr -| @inject_into_optional_expr -| @linear_function_expr -| @linear_function_extract_original_expr -| @linear_to_differentiable_function_expr -| @load_expr -| @metatype_conversion_expr -| @pointer_to_pointer_expr -| @protocol_metatype_to_object_expr -| @string_to_pointer_expr -| @underlying_to_opaque_expr -| @unevaluated_instance_expr -| @unresolved_type_conversion_expr -; - -#keyset[id] -implicit_conversion_exprs( //dir=expr - int id: @implicit_conversion_expr ref, - int sub_expr: @expr_or_none ref -); - -in_out_exprs( //dir=expr - unique int id: @in_out_expr, - int sub_expr: @expr_or_none ref -); - -key_path_application_exprs( //dir=expr - unique int id: @key_path_application_expr, - int base: @expr_or_none ref, - int key_path: @expr_or_none ref -); - -key_path_dot_exprs( //dir=expr - unique int id: @key_path_dot_expr -); - -key_path_exprs( //dir=expr - unique int id: @key_path_expr -); - -#keyset[id] -key_path_expr_roots( //dir=expr - int id: @key_path_expr ref, - int root: @type_repr_or_none ref -); - -#keyset[id] -key_path_expr_parsed_paths( //dir=expr - int id: @key_path_expr ref, - int parsed_path: @expr_or_none ref -); - -lazy_initializer_exprs( //dir=expr - unique int id: @lazy_initializer_expr, - int sub_expr: @expr_or_none ref -); - -@literal_expr = - @builtin_literal_expr -| @interpolated_string_literal_expr -| @nil_literal_expr -| @object_literal_expr -| @regex_literal_expr -; - -@lookup_expr = - @dynamic_lookup_expr -| @member_ref_expr -| @subscript_expr -; - -#keyset[id] -lookup_exprs( //dir=expr - int id: @lookup_expr ref, - int base: @expr_or_none ref -); - -#keyset[id] -lookup_expr_members( //dir=expr - int id: @lookup_expr ref, - int member: @decl_or_none ref -); - -make_temporarily_escapable_exprs( //dir=expr - unique int id: @make_temporarily_escapable_expr, - int escaping_closure: @opaque_value_expr_or_none ref, - int nonescaping_closure: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -obj_c_selector_exprs( //dir=expr - unique int id: @obj_c_selector_expr, - int sub_expr: @expr_or_none ref, - int method: @abstract_function_decl_or_none ref -); - -one_way_exprs( //dir=expr - unique int id: @one_way_expr, - int sub_expr: @expr_or_none ref -); - -opaque_value_exprs( //dir=expr - unique int id: @opaque_value_expr -); - -open_existential_exprs( //dir=expr - unique int id: @open_existential_expr, - int sub_expr: @expr_or_none ref, - int existential: @expr_or_none ref, - int opaque_expr: @opaque_value_expr_or_none ref -); - -optional_evaluation_exprs( //dir=expr - unique int id: @optional_evaluation_expr, - int sub_expr: @expr_or_none ref -); - -other_constructor_decl_ref_exprs( //dir=expr - unique int id: @other_constructor_decl_ref_expr, - int constructor_decl: @constructor_decl_or_none ref -); - -overloaded_decl_ref_exprs( //dir=expr - unique int id: @overloaded_decl_ref_expr -); - -#keyset[id, index] -overloaded_decl_ref_expr_possible_declarations( //dir=expr - int id: @overloaded_decl_ref_expr ref, - int index: int ref, - int possible_declaration: @value_decl_or_none ref -); - -property_wrapper_value_placeholder_exprs( //dir=expr - unique int id: @property_wrapper_value_placeholder_expr, - int placeholder: @opaque_value_expr_or_none ref -); - -#keyset[id] -property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr - int id: @property_wrapper_value_placeholder_expr ref, - int wrapped_value: @expr_or_none ref -); - -rebind_self_in_constructor_exprs( //dir=expr - unique int id: @rebind_self_in_constructor_expr, - int sub_expr: @expr_or_none ref, - int self: @var_decl_or_none ref -); - -sequence_exprs( //dir=expr - unique int id: @sequence_expr -); - -#keyset[id, index] -sequence_expr_elements( //dir=expr - int id: @sequence_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -super_ref_exprs( //dir=expr - unique int id: @super_ref_expr, - int self: @var_decl_or_none ref -); - -tap_exprs( //dir=expr - unique int id: @tap_expr, - int body: @brace_stmt_or_none ref, - int var: @var_decl_or_none ref -); - -#keyset[id] -tap_expr_sub_exprs( //dir=expr - int id: @tap_expr ref, - int sub_expr: @expr_or_none ref -); - -tuple_element_exprs( //dir=expr - unique int id: @tuple_element_expr, - int sub_expr: @expr_or_none ref, - int index: int ref -); - -tuple_exprs( //dir=expr - unique int id: @tuple_expr -); - -#keyset[id, index] -tuple_expr_elements( //dir=expr - int id: @tuple_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -type_exprs( //dir=expr - unique int id: @type_expr -); - -#keyset[id] -type_expr_type_reprs( //dir=expr - int id: @type_expr ref, - int type_repr: @type_repr_or_none ref -); - -unresolved_decl_ref_exprs( //dir=expr - unique int id: @unresolved_decl_ref_expr -); - -#keyset[id] -unresolved_decl_ref_expr_names( //dir=expr - int id: @unresolved_decl_ref_expr ref, - string name: string ref -); - -unresolved_dot_exprs( //dir=expr - unique int id: @unresolved_dot_expr, - int base: @expr_or_none ref, - string name: string ref -); - -unresolved_member_exprs( //dir=expr - unique int id: @unresolved_member_expr, - string name: string ref -); - -unresolved_pattern_exprs( //dir=expr - unique int id: @unresolved_pattern_expr, - int sub_pattern: @pattern_or_none ref -); - -unresolved_specialize_exprs( //dir=expr - unique int id: @unresolved_specialize_expr, - int sub_expr: @expr_or_none ref -); - -vararg_expansion_exprs( //dir=expr - unique int id: @vararg_expansion_expr, - int sub_expr: @expr_or_none ref -); - -abi_safe_conversion_exprs( //dir=expr - unique int id: @abi_safe_conversion_expr -); - -any_hashable_erasure_exprs( //dir=expr - unique int id: @any_hashable_erasure_expr -); - -archetype_to_super_exprs( //dir=expr - unique int id: @archetype_to_super_expr -); - -array_exprs( //dir=expr - unique int id: @array_expr -); - -#keyset[id, index] -array_expr_elements( //dir=expr - int id: @array_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -array_to_pointer_exprs( //dir=expr - unique int id: @array_to_pointer_expr -); - -auto_closure_exprs( //dir=expr - unique int id: @auto_closure_expr -); - -await_exprs( //dir=expr - unique int id: @await_expr -); - -binary_exprs( //dir=expr - unique int id: @binary_expr -); - -bridge_from_obj_c_exprs( //dir=expr - unique int id: @bridge_from_obj_c_expr -); - -bridge_to_obj_c_exprs( //dir=expr - unique int id: @bridge_to_obj_c_expr -); - -@builtin_literal_expr = - @boolean_literal_expr -| @magic_identifier_literal_expr -| @number_literal_expr -| @string_literal_expr -; - -call_exprs( //dir=expr - unique int id: @call_expr -); - -@checked_cast_expr = - @conditional_checked_cast_expr -| @forced_checked_cast_expr -| @is_expr -; - -class_metatype_to_object_exprs( //dir=expr - unique int id: @class_metatype_to_object_expr -); - -closure_exprs( //dir=expr - unique int id: @closure_expr -); - -coerce_exprs( //dir=expr - unique int id: @coerce_expr -); - -collection_upcast_conversion_exprs( //dir=expr - unique int id: @collection_upcast_conversion_expr -); - -conditional_bridge_from_obj_c_exprs( //dir=expr - unique int id: @conditional_bridge_from_obj_c_expr -); - -covariant_function_conversion_exprs( //dir=expr - unique int id: @covariant_function_conversion_expr -); - -covariant_return_conversion_exprs( //dir=expr - unique int id: @covariant_return_conversion_expr -); - -derived_to_base_exprs( //dir=expr - unique int id: @derived_to_base_expr -); - -destructure_tuple_exprs( //dir=expr - unique int id: @destructure_tuple_expr -); - -dictionary_exprs( //dir=expr - unique int id: @dictionary_expr -); - -#keyset[id, index] -dictionary_expr_elements( //dir=expr - int id: @dictionary_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -differentiable_function_exprs( //dir=expr - unique int id: @differentiable_function_expr -); - -differentiable_function_extract_original_exprs( //dir=expr - unique int id: @differentiable_function_extract_original_expr -); - -dot_self_exprs( //dir=expr - unique int id: @dot_self_expr -); - -@dynamic_lookup_expr = - @dynamic_member_ref_expr -| @dynamic_subscript_expr -; - -erasure_exprs( //dir=expr - unique int id: @erasure_expr -); - -existential_metatype_to_object_exprs( //dir=expr - unique int id: @existential_metatype_to_object_expr -); - -force_try_exprs( //dir=expr - unique int id: @force_try_expr -); - -foreign_object_conversion_exprs( //dir=expr - unique int id: @foreign_object_conversion_expr -); - -function_conversion_exprs( //dir=expr - unique int id: @function_conversion_expr -); - -in_out_to_pointer_exprs( //dir=expr - unique int id: @in_out_to_pointer_expr -); - -inject_into_optional_exprs( //dir=expr - unique int id: @inject_into_optional_expr -); - -interpolated_string_literal_exprs( //dir=expr - unique int id: @interpolated_string_literal_expr -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_expr: @opaque_value_expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_count_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int literal_capacity_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_appending_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int appending_expr: @tap_expr_or_none ref -); - -linear_function_exprs( //dir=expr - unique int id: @linear_function_expr -); - -linear_function_extract_original_exprs( //dir=expr - unique int id: @linear_function_extract_original_expr -); - -linear_to_differentiable_function_exprs( //dir=expr - unique int id: @linear_to_differentiable_function_expr -); - -load_exprs( //dir=expr - unique int id: @load_expr -); - -member_ref_exprs( //dir=expr - unique int id: @member_ref_expr -); - -#keyset[id] -member_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_ordinary_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @member_ref_expr ref -); - -metatype_conversion_exprs( //dir=expr - unique int id: @metatype_conversion_expr -); - -nil_literal_exprs( //dir=expr - unique int id: @nil_literal_expr -); - -object_literal_exprs( //dir=expr - unique int id: @object_literal_expr, - int kind: int ref -); - -#keyset[id, index] -object_literal_expr_arguments( //dir=expr - int id: @object_literal_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -optional_try_exprs( //dir=expr - unique int id: @optional_try_expr -); - -paren_exprs( //dir=expr - unique int id: @paren_expr -); - -pointer_to_pointer_exprs( //dir=expr - unique int id: @pointer_to_pointer_expr -); - -postfix_unary_exprs( //dir=expr - unique int id: @postfix_unary_expr -); - -prefix_unary_exprs( //dir=expr - unique int id: @prefix_unary_expr -); - -protocol_metatype_to_object_exprs( //dir=expr - unique int id: @protocol_metatype_to_object_expr -); - -regex_literal_exprs( //dir=expr - unique int id: @regex_literal_expr, - string pattern: string ref, - int version: int ref -); - -@self_apply_expr = - @constructor_ref_call_expr -| @dot_syntax_call_expr -; - -#keyset[id] -self_apply_exprs( //dir=expr - int id: @self_apply_expr ref, - int base: @expr_or_none ref -); - -string_to_pointer_exprs( //dir=expr - unique int id: @string_to_pointer_expr -); - -subscript_exprs( //dir=expr - unique int id: @subscript_expr -); - -#keyset[id, index] -subscript_expr_arguments( //dir=expr - int id: @subscript_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -#keyset[id] -subscript_expr_has_direct_to_storage_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_ordinary_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_distributed_thunk_semantics( //dir=expr - int id: @subscript_expr ref -); - -try_exprs( //dir=expr - unique int id: @try_expr -); - -underlying_to_opaque_exprs( //dir=expr - unique int id: @underlying_to_opaque_expr -); - -unevaluated_instance_exprs( //dir=expr - unique int id: @unevaluated_instance_expr -); - -unresolved_member_chain_result_exprs( //dir=expr - unique int id: @unresolved_member_chain_result_expr -); - -unresolved_type_conversion_exprs( //dir=expr - unique int id: @unresolved_type_conversion_expr -); - -boolean_literal_exprs( //dir=expr - unique int id: @boolean_literal_expr, - boolean value: boolean ref -); - -conditional_checked_cast_exprs( //dir=expr - unique int id: @conditional_checked_cast_expr -); - -constructor_ref_call_exprs( //dir=expr - unique int id: @constructor_ref_call_expr -); - -dot_syntax_call_exprs( //dir=expr - unique int id: @dot_syntax_call_expr -); - -dynamic_member_ref_exprs( //dir=expr - unique int id: @dynamic_member_ref_expr -); - -dynamic_subscript_exprs( //dir=expr - unique int id: @dynamic_subscript_expr -); - -forced_checked_cast_exprs( //dir=expr - unique int id: @forced_checked_cast_expr -); - -is_exprs( //dir=expr - unique int id: @is_expr -); - -magic_identifier_literal_exprs( //dir=expr - unique int id: @magic_identifier_literal_expr, - string kind: string ref -); - -@number_literal_expr = - @float_literal_expr -| @integer_literal_expr -; - -string_literal_exprs( //dir=expr - unique int id: @string_literal_expr, - string value: string ref -); - -float_literal_exprs( //dir=expr - unique int id: @float_literal_expr, - string string_value: string ref -); - -integer_literal_exprs( //dir=expr - unique int id: @integer_literal_expr, - string string_value: string ref -); - -@pattern = - @any_pattern -| @binding_pattern -| @bool_pattern -| @enum_element_pattern -| @expr_pattern -| @is_pattern -| @named_pattern -| @optional_some_pattern -| @paren_pattern -| @tuple_pattern -| @typed_pattern -; - -any_patterns( //dir=pattern - unique int id: @any_pattern -); - -binding_patterns( //dir=pattern - unique int id: @binding_pattern, - int sub_pattern: @pattern_or_none ref -); - -bool_patterns( //dir=pattern - unique int id: @bool_pattern, - boolean value: boolean ref -); - -enum_element_patterns( //dir=pattern - unique int id: @enum_element_pattern, - int element: @enum_element_decl_or_none ref -); - -#keyset[id] -enum_element_pattern_sub_patterns( //dir=pattern - int id: @enum_element_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -expr_patterns( //dir=pattern - unique int id: @expr_pattern, - int sub_expr: @expr_or_none ref -); - -is_patterns( //dir=pattern - unique int id: @is_pattern -); - -#keyset[id] -is_pattern_cast_type_reprs( //dir=pattern - int id: @is_pattern ref, - int cast_type_repr: @type_repr_or_none ref -); - -#keyset[id] -is_pattern_sub_patterns( //dir=pattern - int id: @is_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -named_patterns( //dir=pattern - unique int id: @named_pattern, - string name: string ref -); - -optional_some_patterns( //dir=pattern - unique int id: @optional_some_pattern, - int sub_pattern: @pattern_or_none ref -); - -paren_patterns( //dir=pattern - unique int id: @paren_pattern, - int sub_pattern: @pattern_or_none ref -); - -tuple_patterns( //dir=pattern - unique int id: @tuple_pattern -); - -#keyset[id, index] -tuple_pattern_elements( //dir=pattern - int id: @tuple_pattern ref, - int index: int ref, - int element: @pattern_or_none ref -); - -typed_patterns( //dir=pattern - unique int id: @typed_pattern, - int sub_pattern: @pattern_or_none ref -); - -#keyset[id] -typed_pattern_type_reprs( //dir=pattern - int id: @typed_pattern ref, - int type_repr: @type_repr_or_none ref -); - -case_label_items( //dir=stmt - unique int id: @case_label_item, - int pattern: @pattern_or_none ref -); - -#keyset[id] -case_label_item_guards( //dir=stmt - int id: @case_label_item ref, - int guard: @expr_or_none ref -); - -condition_elements( //dir=stmt - unique int id: @condition_element -); - -#keyset[id] -condition_element_booleans( //dir=stmt - int id: @condition_element ref, - int boolean_: @expr_or_none ref -); - -#keyset[id] -condition_element_patterns( //dir=stmt - int id: @condition_element ref, - int pattern: @pattern_or_none ref -); - -#keyset[id] -condition_element_initializers( //dir=stmt - int id: @condition_element ref, - int initializer: @expr_or_none ref -); - -#keyset[id] -condition_element_availabilities( //dir=stmt - int id: @condition_element ref, - int availability: @availability_info_or_none ref -); - -@stmt = - @brace_stmt -| @break_stmt -| @case_stmt -| @continue_stmt -| @defer_stmt -| @fail_stmt -| @fallthrough_stmt -| @labeled_stmt -| @pound_assert_stmt -| @return_stmt -| @throw_stmt -| @yield_stmt -; - -stmt_conditions( //dir=stmt - unique int id: @stmt_condition -); - -#keyset[id, index] -stmt_condition_elements( //dir=stmt - int id: @stmt_condition ref, - int index: int ref, - int element: @condition_element_or_none ref -); - -brace_stmts( //dir=stmt - unique int id: @brace_stmt -); - -#keyset[id, index] -brace_stmt_elements( //dir=stmt - int id: @brace_stmt ref, - int index: int ref, - int element: @ast_node_or_none ref -); - -break_stmts( //dir=stmt - unique int id: @break_stmt -); - -#keyset[id] -break_stmt_target_names( //dir=stmt - int id: @break_stmt ref, - string target_name: string ref -); - -#keyset[id] -break_stmt_targets( //dir=stmt - int id: @break_stmt ref, - int target: @stmt_or_none ref -); - -case_stmts( //dir=stmt - unique int id: @case_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -case_stmt_labels( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int label: @case_label_item_or_none ref -); - -#keyset[id, index] -case_stmt_variables( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int variable: @var_decl_or_none ref -); - -continue_stmts( //dir=stmt - unique int id: @continue_stmt -); - -#keyset[id] -continue_stmt_target_names( //dir=stmt - int id: @continue_stmt ref, - string target_name: string ref -); - -#keyset[id] -continue_stmt_targets( //dir=stmt - int id: @continue_stmt ref, - int target: @stmt_or_none ref -); - -defer_stmts( //dir=stmt - unique int id: @defer_stmt, - int body: @brace_stmt_or_none ref -); - -fail_stmts( //dir=stmt - unique int id: @fail_stmt -); - -fallthrough_stmts( //dir=stmt - unique int id: @fallthrough_stmt, - int fallthrough_source: @case_stmt_or_none ref, - int fallthrough_dest: @case_stmt_or_none ref -); - -@labeled_stmt = - @do_catch_stmt -| @do_stmt -| @for_each_stmt -| @labeled_conditional_stmt -| @repeat_while_stmt -| @switch_stmt -; - -#keyset[id] -labeled_stmt_labels( //dir=stmt - int id: @labeled_stmt ref, - string label: string ref -); - -pound_assert_stmts( //dir=stmt - unique int id: @pound_assert_stmt, - int condition: @expr_or_none ref, - string message: string ref -); - -return_stmts( //dir=stmt - unique int id: @return_stmt -); - -#keyset[id] -return_stmt_results( //dir=stmt - int id: @return_stmt ref, - int result: @expr_or_none ref -); - -throw_stmts( //dir=stmt - unique int id: @throw_stmt, - int sub_expr: @expr_or_none ref -); - -yield_stmts( //dir=stmt - unique int id: @yield_stmt -); - -#keyset[id, index] -yield_stmt_results( //dir=stmt - int id: @yield_stmt ref, - int index: int ref, - int result: @expr_or_none ref -); - -do_catch_stmts( //dir=stmt - unique int id: @do_catch_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -do_catch_stmt_catches( //dir=stmt - int id: @do_catch_stmt ref, - int index: int ref, - int catch: @case_stmt_or_none ref -); - -do_stmts( //dir=stmt - unique int id: @do_stmt, - int body: @brace_stmt_or_none ref -); - -for_each_stmts( //dir=stmt - unique int id: @for_each_stmt, - int pattern: @pattern_or_none ref, - int sequence: @expr_or_none ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id] -for_each_stmt_wheres( //dir=stmt - int id: @for_each_stmt ref, - int where: @expr_or_none ref -); - -@labeled_conditional_stmt = - @guard_stmt -| @if_stmt -| @while_stmt -; - -#keyset[id] -labeled_conditional_stmts( //dir=stmt - int id: @labeled_conditional_stmt ref, - int condition: @stmt_condition_or_none ref -); - -repeat_while_stmts( //dir=stmt - unique int id: @repeat_while_stmt, - int condition: @expr_or_none ref, - int body: @stmt_or_none ref -); - -switch_stmts( //dir=stmt - unique int id: @switch_stmt, - int expr: @expr_or_none ref -); - -#keyset[id, index] -switch_stmt_cases( //dir=stmt - int id: @switch_stmt ref, - int index: int ref, - int case_: @case_stmt_or_none ref -); - -guard_stmts( //dir=stmt - unique int id: @guard_stmt, - int body: @brace_stmt_or_none ref -); - -if_stmts( //dir=stmt - unique int id: @if_stmt, - int then: @stmt_or_none ref -); - -#keyset[id] -if_stmt_elses( //dir=stmt - int id: @if_stmt ref, - int else: @stmt_or_none ref -); - -while_stmts( //dir=stmt - unique int id: @while_stmt, - int body: @stmt_or_none ref -); - -@type = - @any_function_type -| @any_generic_type -| @any_metatype_type -| @builtin_type -| @dependent_member_type -| @dynamic_self_type -| @error_type -| @existential_type -| @in_out_type -| @l_value_type -| @module_type -| @parameterized_protocol_type -| @protocol_composition_type -| @reference_storage_type -| @substitutable_type -| @sugar_type -| @tuple_type -| @unresolved_type -; - -#keyset[id] -types( //dir=type - int id: @type ref, - string name: string ref, - int canonical_type: @type_or_none ref -); - -type_reprs( //dir=type - unique int id: @type_repr, - int type_: @type_or_none ref -); - -@any_function_type = - @function_type -| @generic_function_type -; - -#keyset[id] -any_function_types( //dir=type - int id: @any_function_type ref, - int result: @type_or_none ref -); - -#keyset[id, index] -any_function_type_param_types( //dir=type - int id: @any_function_type ref, - int index: int ref, - int param_type: @type_or_none ref -); - -#keyset[id] -any_function_type_is_throwing( //dir=type - int id: @any_function_type ref -); - -#keyset[id] -any_function_type_is_async( //dir=type - int id: @any_function_type ref -); - -@any_generic_type = - @nominal_or_bound_generic_nominal_type -| @unbound_generic_type -; - -#keyset[id] -any_generic_types( //dir=type - int id: @any_generic_type ref, - int declaration: @generic_type_decl_or_none ref -); - -#keyset[id] -any_generic_type_parents( //dir=type - int id: @any_generic_type ref, - int parent: @type_or_none ref -); - -@any_metatype_type = - @existential_metatype_type -| @metatype_type -; - -@builtin_type = - @any_builtin_integer_type -| @builtin_bridge_object_type -| @builtin_default_actor_storage_type -| @builtin_executor_type -| @builtin_float_type -| @builtin_job_type -| @builtin_native_object_type -| @builtin_raw_pointer_type -| @builtin_raw_unsafe_continuation_type -| @builtin_unsafe_value_buffer_type -| @builtin_vector_type -; - -dependent_member_types( //dir=type - unique int id: @dependent_member_type, - int base_type: @type_or_none ref, - int associated_type_decl: @associated_type_decl_or_none ref -); - -dynamic_self_types( //dir=type - unique int id: @dynamic_self_type, - int static_self_type: @type_or_none ref -); - -error_types( //dir=type - unique int id: @error_type -); - -existential_types( //dir=type - unique int id: @existential_type, - int constraint: @type_or_none ref -); - -in_out_types( //dir=type - unique int id: @in_out_type, - int object_type: @type_or_none ref -); - -l_value_types( //dir=type - unique int id: @l_value_type, - int object_type: @type_or_none ref -); - -module_types( //dir=type - unique int id: @module_type, - int module: @module_decl_or_none ref -); - -parameterized_protocol_types( //dir=type - unique int id: @parameterized_protocol_type, - int base: @protocol_type_or_none ref -); - -#keyset[id, index] -parameterized_protocol_type_args( //dir=type - int id: @parameterized_protocol_type ref, - int index: int ref, - int arg: @type_or_none ref -); - -protocol_composition_types( //dir=type - unique int id: @protocol_composition_type -); - -#keyset[id, index] -protocol_composition_type_members( //dir=type - int id: @protocol_composition_type ref, - int index: int ref, - int member: @type_or_none ref -); - -@reference_storage_type = - @unmanaged_storage_type -| @unowned_storage_type -| @weak_storage_type -; - -#keyset[id] -reference_storage_types( //dir=type - int id: @reference_storage_type ref, - int referent_type: @type_or_none ref -); - -@substitutable_type = - @archetype_type -| @generic_type_param_type -; - -@sugar_type = - @paren_type -| @syntax_sugar_type -| @type_alias_type -; - -tuple_types( //dir=type - unique int id: @tuple_type -); - -#keyset[id, index] -tuple_type_types( //dir=type - int id: @tuple_type ref, - int index: int ref, - int type_: @type_or_none ref -); - -#keyset[id, index] -tuple_type_names( //dir=type - int id: @tuple_type ref, - int index: int ref, - string name: string ref -); - -unresolved_types( //dir=type - unique int id: @unresolved_type -); - -@any_builtin_integer_type = - @builtin_integer_literal_type -| @builtin_integer_type -; - -@archetype_type = - @opaque_type_archetype_type -| @opened_archetype_type -| @primary_archetype_type -; - -#keyset[id] -archetype_types( //dir=type - int id: @archetype_type ref, - int interface_type: @type_or_none ref -); - -#keyset[id] -archetype_type_superclasses( //dir=type - int id: @archetype_type ref, - int superclass: @type_or_none ref -); - -#keyset[id, index] -archetype_type_protocols( //dir=type - int id: @archetype_type ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -builtin_bridge_object_types( //dir=type - unique int id: @builtin_bridge_object_type -); - -builtin_default_actor_storage_types( //dir=type - unique int id: @builtin_default_actor_storage_type -); - -builtin_executor_types( //dir=type - unique int id: @builtin_executor_type -); - -builtin_float_types( //dir=type - unique int id: @builtin_float_type -); - -builtin_job_types( //dir=type - unique int id: @builtin_job_type -); - -builtin_native_object_types( //dir=type - unique int id: @builtin_native_object_type -); - -builtin_raw_pointer_types( //dir=type - unique int id: @builtin_raw_pointer_type -); - -builtin_raw_unsafe_continuation_types( //dir=type - unique int id: @builtin_raw_unsafe_continuation_type -); - -builtin_unsafe_value_buffer_types( //dir=type - unique int id: @builtin_unsafe_value_buffer_type -); - -builtin_vector_types( //dir=type - unique int id: @builtin_vector_type -); - -existential_metatype_types( //dir=type - unique int id: @existential_metatype_type -); - -function_types( //dir=type - unique int id: @function_type -); - -generic_function_types( //dir=type - unique int id: @generic_function_type -); - -#keyset[id, index] -generic_function_type_generic_params( //dir=type - int id: @generic_function_type ref, - int index: int ref, - int generic_param: @generic_type_param_type_or_none ref -); - -generic_type_param_types( //dir=type - unique int id: @generic_type_param_type -); - -metatype_types( //dir=type - unique int id: @metatype_type -); - -@nominal_or_bound_generic_nominal_type = - @bound_generic_type -| @nominal_type -; - -paren_types( //dir=type - unique int id: @paren_type, - int type_: @type_or_none ref -); - -@syntax_sugar_type = - @dictionary_type -| @unary_syntax_sugar_type -; - -type_alias_types( //dir=type - unique int id: @type_alias_type, - int decl: @type_alias_decl_or_none ref -); - -unbound_generic_types( //dir=type - unique int id: @unbound_generic_type -); - -unmanaged_storage_types( //dir=type - unique int id: @unmanaged_storage_type -); - -unowned_storage_types( //dir=type - unique int id: @unowned_storage_type -); - -weak_storage_types( //dir=type - unique int id: @weak_storage_type -); - -@bound_generic_type = - @bound_generic_class_type -| @bound_generic_enum_type -| @bound_generic_struct_type -; - -#keyset[id, index] -bound_generic_type_arg_types( //dir=type - int id: @bound_generic_type ref, - int index: int ref, - int arg_type: @type_or_none ref -); - -builtin_integer_literal_types( //dir=type - unique int id: @builtin_integer_literal_type -); - -builtin_integer_types( //dir=type - unique int id: @builtin_integer_type -); - -#keyset[id] -builtin_integer_type_widths( //dir=type - int id: @builtin_integer_type ref, - int width: int ref -); - -dictionary_types( //dir=type - unique int id: @dictionary_type, - int key_type: @type_or_none ref, - int value_type: @type_or_none ref -); - -@nominal_type = - @class_type -| @enum_type -| @protocol_type -| @struct_type -; - -opaque_type_archetype_types( //dir=type - unique int id: @opaque_type_archetype_type, - int declaration: @opaque_type_decl_or_none ref -); - -opened_archetype_types( //dir=type - unique int id: @opened_archetype_type -); - -primary_archetype_types( //dir=type - unique int id: @primary_archetype_type -); - -@unary_syntax_sugar_type = - @array_slice_type -| @optional_type -| @variadic_sequence_type -; - -#keyset[id] -unary_syntax_sugar_types( //dir=type - int id: @unary_syntax_sugar_type ref, - int base_type: @type_or_none ref -); - -array_slice_types( //dir=type - unique int id: @array_slice_type -); - -bound_generic_class_types( //dir=type - unique int id: @bound_generic_class_type -); - -bound_generic_enum_types( //dir=type - unique int id: @bound_generic_enum_type -); - -bound_generic_struct_types( //dir=type - unique int id: @bound_generic_struct_type -); - -class_types( //dir=type - unique int id: @class_type -); - -enum_types( //dir=type - unique int id: @enum_type -); - -optional_types( //dir=type - unique int id: @optional_type -); - -protocol_types( //dir=type - unique int id: @protocol_type -); - -struct_types( //dir=type - unique int id: @struct_type -); - -variadic_sequence_types( //dir=type - unique int id: @variadic_sequence_type -); - -@abstract_function_decl_or_none = - @abstract_function_decl -| @unspecified_element -; - -@accessor_decl_or_none = - @accessor_decl -| @unspecified_element -; - -@argument_or_none = - @argument -| @unspecified_element -; - -@associated_type_decl_or_none = - @associated_type_decl -| @unspecified_element -; - -@ast_node_or_none = - @ast_node -| @unspecified_element -; - -@availability_info_or_none = - @availability_info -| @unspecified_element -; - -@availability_spec_or_none = - @availability_spec -| @unspecified_element -; - -@brace_stmt_or_none = - @brace_stmt -| @unspecified_element -; - -@captured_decl_or_none = - @captured_decl -| @unspecified_element -; - -@case_label_item_or_none = - @case_label_item -| @unspecified_element -; - -@case_stmt_or_none = - @case_stmt -| @unspecified_element -; - -@closure_expr_or_none = - @closure_expr -| @unspecified_element -; - -@condition_element_or_none = - @condition_element -| @unspecified_element -; - -@constructor_decl_or_none = - @constructor_decl -| @unspecified_element -; - -@decl_or_none = - @decl -| @unspecified_element -; - -@enum_element_decl_or_none = - @enum_element_decl -| @unspecified_element -; - -@expr_or_none = - @expr -| @unspecified_element -; - -@file_or_none = - @file -| @unspecified_element -; - -@generic_type_decl_or_none = - @generic_type_decl -| @unspecified_element -; - -@generic_type_param_decl_or_none = - @generic_type_param_decl -| @unspecified_element -; - -@generic_type_param_type_or_none = - @generic_type_param_type -| @unspecified_element -; - -@location_or_none = - @location -| @unspecified_element -; - -@module_decl_or_none = - @module_decl -| @unspecified_element -; - -@nominal_type_decl_or_none = - @nominal_type_decl -| @unspecified_element -; - -@opaque_type_decl_or_none = - @opaque_type_decl -| @unspecified_element -; - -@opaque_value_expr_or_none = - @opaque_value_expr -| @unspecified_element -; - -@param_decl_or_none = - @param_decl -| @unspecified_element -; - -@pattern_or_none = - @pattern -| @unspecified_element -; - -@pattern_binding_decl_or_none = - @pattern_binding_decl -| @unspecified_element -; - -@precedence_group_decl_or_none = - @precedence_group_decl -| @unspecified_element -; - -@protocol_decl_or_none = - @protocol_decl -| @unspecified_element -; - -@protocol_type_or_none = - @protocol_type -| @unspecified_element -; - -@stmt_or_none = - @stmt -| @unspecified_element -; - -@stmt_condition_or_none = - @stmt_condition -| @unspecified_element -; - -@string_literal_expr_or_none = - @string_literal_expr -| @unspecified_element -; - -@tap_expr_or_none = - @tap_expr -| @unspecified_element -; - -@type_or_none = - @type -| @unspecified_element -; - -@type_alias_decl_or_none = - @type_alias_decl -| @unspecified_element -; - -@type_repr_or_none = - @type_repr -| @unspecified_element -; - -@value_decl_or_none = - @unspecified_element -| @value_decl -; - -@var_decl_or_none = - @unspecified_element -| @var_decl -; diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme deleted file mode 100644 index db22947f6ae..00000000000 --- a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/swift.dbscheme +++ /dev/null @@ -1,2597 +0,0 @@ -// generated by codegen/codegen.py - -// from prefix.dbscheme -/** - * The source location of the snapshot. - */ -sourceLocationPrefix( - string prefix: string ref -); - - -// from schema.py - -@element = - @callable -| @file -| @generic_context -| @locatable -| @location -| @type -; - -#keyset[id] -element_is_unknown( - int id: @element ref -); - -@callable = - @abstract_closure_expr -| @abstract_function_decl -; - -#keyset[id] -callable_names( - int id: @callable ref, - string name: string ref -); - -#keyset[id] -callable_self_params( - int id: @callable ref, - int self_param: @param_decl_or_none ref -); - -#keyset[id, index] -callable_params( - int id: @callable ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -#keyset[id] -callable_bodies( - int id: @callable ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id, index] -callable_captures( - int id: @callable ref, - int index: int ref, - int capture: @captured_decl_or_none ref -); - -@file = - @db_file -; - -#keyset[id] -files( - int id: @file ref, - string name: string ref -); - -#keyset[id] -file_is_successfully_extracted( - int id: @file ref -); - -@locatable = - @argument -| @ast_node -| @comment -| @diagnostics -| @error_element -; - -#keyset[id] -locatable_locations( - int id: @locatable ref, - int location: @location_or_none ref -); - -@location = - @db_location -; - -#keyset[id] -locations( - int id: @location ref, - int file: @file_or_none ref, - int start_line: int ref, - int start_column: int ref, - int end_line: int ref, - int end_column: int ref -); - -@ast_node = - @availability_info -| @availability_spec -| @case_label_item -| @condition_element -| @decl -| @expr -| @pattern -| @stmt -| @stmt_condition -| @type_repr -; - -comments( - unique int id: @comment, - string text: string ref -); - -db_files( - unique int id: @db_file -); - -db_locations( - unique int id: @db_location -); - -diagnostics( - unique int id: @diagnostics, - string text: string ref, - int kind: int ref -); - -@error_element = - @error_expr -| @error_type -| @overloaded_decl_ref_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_chain_result_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @unresolved_type -| @unresolved_type_conversion_expr -| @unspecified_element -; - -availability_infos( - unique int id: @availability_info -); - -#keyset[id] -availability_info_is_unavailable( - int id: @availability_info ref -); - -#keyset[id, index] -availability_info_specs( - int id: @availability_info ref, - int index: int ref, - int spec: @availability_spec_or_none ref -); - -@availability_spec = - @other_availability_spec -| @platform_version_availability_spec -; - -unspecified_elements( - unique int id: @unspecified_element, - string property: string ref, - string error: string ref -); - -#keyset[id] -unspecified_element_parents( - int id: @unspecified_element ref, - int parent: @element ref -); - -#keyset[id] -unspecified_element_indices( - int id: @unspecified_element ref, - int index: int ref -); - -other_availability_specs( - unique int id: @other_availability_spec -); - -platform_version_availability_specs( - unique int id: @platform_version_availability_spec, - string platform: string ref, - string version: string ref -); - -@decl = - @captured_decl -| @enum_case_decl -| @extension_decl -| @if_config_decl -| @import_decl -| @missing_member_decl -| @operator_decl -| @pattern_binding_decl -| @pound_diagnostic_decl -| @precedence_group_decl -| @top_level_code_decl -| @value_decl -; - -#keyset[id] -decls( //dir=decl - int id: @decl ref, - int module: @module_decl_or_none ref -); - -#keyset[id, index] -decl_members( //dir=decl - int id: @decl ref, - int index: int ref, - int member: @decl_or_none ref -); - -@generic_context = - @abstract_function_decl -| @extension_decl -| @generic_type_decl -| @subscript_decl -; - -#keyset[id, index] -generic_context_generic_type_params( //dir=decl - int id: @generic_context ref, - int index: int ref, - int generic_type_param: @generic_type_param_decl_or_none ref -); - -captured_decls( //dir=decl - unique int id: @captured_decl, - int decl: @value_decl_or_none ref -); - -#keyset[id] -captured_decl_is_direct( //dir=decl - int id: @captured_decl ref -); - -#keyset[id] -captured_decl_is_escaping( //dir=decl - int id: @captured_decl ref -); - -enum_case_decls( //dir=decl - unique int id: @enum_case_decl -); - -#keyset[id, index] -enum_case_decl_elements( //dir=decl - int id: @enum_case_decl ref, - int index: int ref, - int element: @enum_element_decl_or_none ref -); - -extension_decls( //dir=decl - unique int id: @extension_decl, - int extended_type_decl: @nominal_type_decl_or_none ref -); - -#keyset[id, index] -extension_decl_protocols( //dir=decl - int id: @extension_decl ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -if_config_decls( //dir=decl - unique int id: @if_config_decl -); - -#keyset[id, index] -if_config_decl_active_elements( //dir=decl - int id: @if_config_decl ref, - int index: int ref, - int active_element: @ast_node_or_none ref -); - -import_decls( //dir=decl - unique int id: @import_decl -); - -#keyset[id] -import_decl_is_exported( //dir=decl - int id: @import_decl ref -); - -#keyset[id] -import_decl_imported_modules( //dir=decl - int id: @import_decl ref, - int imported_module: @module_decl_or_none ref -); - -#keyset[id, index] -import_decl_declarations( //dir=decl - int id: @import_decl ref, - int index: int ref, - int declaration: @value_decl_or_none ref -); - -missing_member_decls( //dir=decl - unique int id: @missing_member_decl, - string name: string ref -); - -@operator_decl = - @infix_operator_decl -| @postfix_operator_decl -| @prefix_operator_decl -; - -#keyset[id] -operator_decls( //dir=decl - int id: @operator_decl ref, - string name: string ref -); - -pattern_binding_decls( //dir=decl - unique int id: @pattern_binding_decl -); - -#keyset[id, index] -pattern_binding_decl_inits( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int init: @expr_or_none ref -); - -#keyset[id, index] -pattern_binding_decl_patterns( //dir=decl - int id: @pattern_binding_decl ref, - int index: int ref, - int pattern: @pattern_or_none ref -); - -pound_diagnostic_decls( //dir=decl - unique int id: @pound_diagnostic_decl, - int kind: int ref, - int message: @string_literal_expr_or_none ref -); - -precedence_group_decls( //dir=decl - unique int id: @precedence_group_decl -); - -top_level_code_decls( //dir=decl - unique int id: @top_level_code_decl, - int body: @brace_stmt_or_none ref -); - -@value_decl = - @abstract_function_decl -| @abstract_storage_decl -| @enum_element_decl -| @type_decl -; - -#keyset[id] -value_decls( //dir=decl - int id: @value_decl ref, - int interface_type: @type_or_none ref -); - -@abstract_function_decl = - @constructor_decl -| @destructor_decl -| @func_decl -; - -@abstract_storage_decl = - @subscript_decl -| @var_decl -; - -#keyset[id, index] -abstract_storage_decl_accessor_decls( //dir=decl - int id: @abstract_storage_decl ref, - int index: int ref, - int accessor_decl: @accessor_decl_or_none ref -); - -enum_element_decls( //dir=decl - unique int id: @enum_element_decl, - string name: string ref -); - -#keyset[id, index] -enum_element_decl_params( //dir=decl - int id: @enum_element_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -infix_operator_decls( //dir=decl - unique int id: @infix_operator_decl -); - -#keyset[id] -infix_operator_decl_precedence_groups( //dir=decl - int id: @infix_operator_decl ref, - int precedence_group: @precedence_group_decl_or_none ref -); - -postfix_operator_decls( //dir=decl - unique int id: @postfix_operator_decl -); - -prefix_operator_decls( //dir=decl - unique int id: @prefix_operator_decl -); - -@type_decl = - @abstract_type_param_decl -| @generic_type_decl -| @module_decl -; - -#keyset[id] -type_decls( //dir=decl - int id: @type_decl ref, - string name: string ref -); - -#keyset[id, index] -type_decl_base_types( //dir=decl - int id: @type_decl ref, - int index: int ref, - int base_type: @type_or_none ref -); - -@abstract_type_param_decl = - @associated_type_decl -| @generic_type_param_decl -; - -constructor_decls( //dir=decl - unique int id: @constructor_decl -); - -destructor_decls( //dir=decl - unique int id: @destructor_decl -); - -@func_decl = - @accessor_decl -| @concrete_func_decl -; - -@generic_type_decl = - @nominal_type_decl -| @opaque_type_decl -| @type_alias_decl -; - -module_decls( //dir=decl - unique int id: @module_decl -); - -#keyset[id] -module_decl_is_builtin_module( //dir=decl - int id: @module_decl ref -); - -#keyset[id] -module_decl_is_system_module( //dir=decl - int id: @module_decl ref -); - -module_decl_imported_modules( //dir=decl - int id: @module_decl ref, - int imported_module: @module_decl_or_none ref -); - -module_decl_exported_modules( //dir=decl - int id: @module_decl ref, - int exported_module: @module_decl_or_none ref -); - -subscript_decls( //dir=decl - unique int id: @subscript_decl, - int element_type: @type_or_none ref -); - -#keyset[id, index] -subscript_decl_params( //dir=decl - int id: @subscript_decl ref, - int index: int ref, - int param: @param_decl_or_none ref -); - -@var_decl = - @concrete_var_decl -| @param_decl -; - -#keyset[id] -var_decls( //dir=decl - int id: @var_decl ref, - string name: string ref, - int type_: @type_or_none ref -); - -#keyset[id] -var_decl_attached_property_wrapper_types( //dir=decl - int id: @var_decl ref, - int attached_property_wrapper_type: @type_or_none ref -); - -#keyset[id] -var_decl_parent_patterns( //dir=decl - int id: @var_decl ref, - int parent_pattern: @pattern_or_none ref -); - -#keyset[id] -var_decl_parent_initializers( //dir=decl - int id: @var_decl ref, - int parent_initializer: @expr_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_backing_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_backing_var: @var_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_var_bindings( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -var_decl_property_wrapper_projection_vars( //dir=decl - int id: @var_decl ref, - int property_wrapper_projection_var: @var_decl_or_none ref -); - -accessor_decls( //dir=decl - unique int id: @accessor_decl -); - -#keyset[id] -accessor_decl_is_getter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_setter( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_will_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_did_set( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_read( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_modify( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_address( //dir=decl - int id: @accessor_decl ref -); - -#keyset[id] -accessor_decl_is_unsafe_mutable_address( //dir=decl - int id: @accessor_decl ref -); - -associated_type_decls( //dir=decl - unique int id: @associated_type_decl -); - -concrete_func_decls( //dir=decl - unique int id: @concrete_func_decl -); - -concrete_var_decls( //dir=decl - unique int id: @concrete_var_decl, - int introducer_int: int ref -); - -generic_type_param_decls( //dir=decl - unique int id: @generic_type_param_decl -); - -@nominal_type_decl = - @class_decl -| @enum_decl -| @protocol_decl -| @struct_decl -; - -#keyset[id] -nominal_type_decls( //dir=decl - int id: @nominal_type_decl ref, - int type_: @type_or_none ref -); - -opaque_type_decls( //dir=decl - unique int id: @opaque_type_decl, - int naming_declaration: @value_decl_or_none ref -); - -#keyset[id, index] -opaque_type_decl_opaque_generic_params( //dir=decl - int id: @opaque_type_decl ref, - int index: int ref, - int opaque_generic_param: @generic_type_param_type_or_none ref -); - -param_decls( //dir=decl - unique int id: @param_decl -); - -#keyset[id] -param_decl_is_inout( //dir=decl - int id: @param_decl ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref -); - -#keyset[id] -param_decl_property_wrapper_local_wrapped_vars( //dir=decl - int id: @param_decl ref, - int property_wrapper_local_wrapped_var: @var_decl_or_none ref -); - -type_alias_decls( //dir=decl - unique int id: @type_alias_decl -); - -class_decls( //dir=decl - unique int id: @class_decl -); - -enum_decls( //dir=decl - unique int id: @enum_decl -); - -protocol_decls( //dir=decl - unique int id: @protocol_decl -); - -struct_decls( //dir=decl - unique int id: @struct_decl -); - -arguments( //dir=expr - unique int id: @argument, - string label: string ref, - int expr: @expr_or_none ref -); - -@expr = - @abstract_closure_expr -| @any_try_expr -| @applied_property_wrapper_expr -| @apply_expr -| @assign_expr -| @bind_optional_expr -| @capture_list_expr -| @collection_expr -| @decl_ref_expr -| @default_argument_expr -| @discard_assignment_expr -| @dot_syntax_base_ignored_expr -| @dynamic_type_expr -| @enum_is_case_expr -| @error_expr -| @explicit_cast_expr -| @force_value_expr -| @identity_expr -| @if_expr -| @implicit_conversion_expr -| @in_out_expr -| @key_path_application_expr -| @key_path_dot_expr -| @key_path_expr -| @lazy_initializer_expr -| @literal_expr -| @lookup_expr -| @make_temporarily_escapable_expr -| @obj_c_selector_expr -| @one_way_expr -| @opaque_value_expr -| @open_existential_expr -| @optional_evaluation_expr -| @other_constructor_decl_ref_expr -| @overloaded_decl_ref_expr -| @property_wrapper_value_placeholder_expr -| @rebind_self_in_constructor_expr -| @sequence_expr -| @super_ref_expr -| @tap_expr -| @tuple_element_expr -| @tuple_expr -| @type_expr -| @unresolved_decl_ref_expr -| @unresolved_dot_expr -| @unresolved_member_expr -| @unresolved_pattern_expr -| @unresolved_specialize_expr -| @vararg_expansion_expr -; - -#keyset[id] -expr_types( //dir=expr - int id: @expr ref, - int type_: @type_or_none ref -); - -@abstract_closure_expr = - @auto_closure_expr -| @closure_expr -; - -@any_try_expr = - @force_try_expr -| @optional_try_expr -| @try_expr -; - -#keyset[id] -any_try_exprs( //dir=expr - int id: @any_try_expr ref, - int sub_expr: @expr_or_none ref -); - -applied_property_wrapper_exprs( //dir=expr - unique int id: @applied_property_wrapper_expr, - int kind: int ref, - int value: @expr_or_none ref, - int param: @param_decl_or_none ref -); - -@apply_expr = - @binary_expr -| @call_expr -| @postfix_unary_expr -| @prefix_unary_expr -| @self_apply_expr -; - -#keyset[id] -apply_exprs( //dir=expr - int id: @apply_expr ref, - int function: @expr_or_none ref -); - -#keyset[id, index] -apply_expr_arguments( //dir=expr - int id: @apply_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -assign_exprs( //dir=expr - unique int id: @assign_expr, - int dest: @expr_or_none ref, - int source: @expr_or_none ref -); - -bind_optional_exprs( //dir=expr - unique int id: @bind_optional_expr, - int sub_expr: @expr_or_none ref -); - -capture_list_exprs( //dir=expr - unique int id: @capture_list_expr, - int closure_body: @closure_expr_or_none ref -); - -#keyset[id, index] -capture_list_expr_binding_decls( //dir=expr - int id: @capture_list_expr ref, - int index: int ref, - int binding_decl: @pattern_binding_decl_or_none ref -); - -@collection_expr = - @array_expr -| @dictionary_expr -; - -decl_ref_exprs( //dir=expr - unique int id: @decl_ref_expr, - int decl: @decl_or_none ref -); - -#keyset[id, index] -decl_ref_expr_replacement_types( //dir=expr - int id: @decl_ref_expr ref, - int index: int ref, - int replacement_type: @type_or_none ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_ordinary_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -#keyset[id] -decl_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @decl_ref_expr ref -); - -default_argument_exprs( //dir=expr - unique int id: @default_argument_expr, - int param_decl: @param_decl_or_none ref, - int param_index: int ref -); - -#keyset[id] -default_argument_expr_caller_side_defaults( //dir=expr - int id: @default_argument_expr ref, - int caller_side_default: @expr_or_none ref -); - -discard_assignment_exprs( //dir=expr - unique int id: @discard_assignment_expr -); - -dot_syntax_base_ignored_exprs( //dir=expr - unique int id: @dot_syntax_base_ignored_expr, - int qualifier: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -dynamic_type_exprs( //dir=expr - unique int id: @dynamic_type_expr, - int base: @expr_or_none ref -); - -enum_is_case_exprs( //dir=expr - unique int id: @enum_is_case_expr, - int sub_expr: @expr_or_none ref, - int element: @enum_element_decl_or_none ref -); - -error_exprs( //dir=expr - unique int id: @error_expr -); - -@explicit_cast_expr = - @checked_cast_expr -| @coerce_expr -; - -#keyset[id] -explicit_cast_exprs( //dir=expr - int id: @explicit_cast_expr ref, - int sub_expr: @expr_or_none ref -); - -force_value_exprs( //dir=expr - unique int id: @force_value_expr, - int sub_expr: @expr_or_none ref -); - -@identity_expr = - @await_expr -| @dot_self_expr -| @paren_expr -| @unresolved_member_chain_result_expr -; - -#keyset[id] -identity_exprs( //dir=expr - int id: @identity_expr ref, - int sub_expr: @expr_or_none ref -); - -if_exprs( //dir=expr - unique int id: @if_expr, - int condition: @expr_or_none ref, - int then_expr: @expr_or_none ref, - int else_expr: @expr_or_none ref -); - -@implicit_conversion_expr = - @abi_safe_conversion_expr -| @any_hashable_erasure_expr -| @archetype_to_super_expr -| @array_to_pointer_expr -| @bridge_from_obj_c_expr -| @bridge_to_obj_c_expr -| @class_metatype_to_object_expr -| @collection_upcast_conversion_expr -| @conditional_bridge_from_obj_c_expr -| @covariant_function_conversion_expr -| @covariant_return_conversion_expr -| @derived_to_base_expr -| @destructure_tuple_expr -| @differentiable_function_expr -| @differentiable_function_extract_original_expr -| @erasure_expr -| @existential_metatype_to_object_expr -| @foreign_object_conversion_expr -| @function_conversion_expr -| @in_out_to_pointer_expr -| @inject_into_optional_expr -| @linear_function_expr -| @linear_function_extract_original_expr -| @linear_to_differentiable_function_expr -| @load_expr -| @metatype_conversion_expr -| @pointer_to_pointer_expr -| @protocol_metatype_to_object_expr -| @string_to_pointer_expr -| @underlying_to_opaque_expr -| @unevaluated_instance_expr -| @unresolved_type_conversion_expr -; - -#keyset[id] -implicit_conversion_exprs( //dir=expr - int id: @implicit_conversion_expr ref, - int sub_expr: @expr_or_none ref -); - -in_out_exprs( //dir=expr - unique int id: @in_out_expr, - int sub_expr: @expr_or_none ref -); - -key_path_application_exprs( //dir=expr - unique int id: @key_path_application_expr, - int base: @expr_or_none ref, - int key_path: @expr_or_none ref -); - -key_path_dot_exprs( //dir=expr - unique int id: @key_path_dot_expr -); - -key_path_exprs( //dir=expr - unique int id: @key_path_expr -); - -#keyset[id] -key_path_expr_roots( //dir=expr - int id: @key_path_expr ref, - int root: @type_repr_or_none ref -); - -#keyset[id] -key_path_expr_parsed_paths( //dir=expr - int id: @key_path_expr ref, - int parsed_path: @expr_or_none ref -); - -lazy_initializer_exprs( //dir=expr - unique int id: @lazy_initializer_expr, - int sub_expr: @expr_or_none ref -); - -@literal_expr = - @builtin_literal_expr -| @interpolated_string_literal_expr -| @nil_literal_expr -| @object_literal_expr -| @regex_literal_expr -; - -@lookup_expr = - @dynamic_lookup_expr -| @member_ref_expr -| @subscript_expr -; - -#keyset[id] -lookup_exprs( //dir=expr - int id: @lookup_expr ref, - int base: @expr_or_none ref -); - -#keyset[id] -lookup_expr_members( //dir=expr - int id: @lookup_expr ref, - int member: @decl_or_none ref -); - -make_temporarily_escapable_exprs( //dir=expr - unique int id: @make_temporarily_escapable_expr, - int escaping_closure: @opaque_value_expr_or_none ref, - int nonescaping_closure: @expr_or_none ref, - int sub_expr: @expr_or_none ref -); - -obj_c_selector_exprs( //dir=expr - unique int id: @obj_c_selector_expr, - int sub_expr: @expr_or_none ref, - int method: @abstract_function_decl_or_none ref -); - -one_way_exprs( //dir=expr - unique int id: @one_way_expr, - int sub_expr: @expr_or_none ref -); - -opaque_value_exprs( //dir=expr - unique int id: @opaque_value_expr -); - -open_existential_exprs( //dir=expr - unique int id: @open_existential_expr, - int sub_expr: @expr_or_none ref, - int existential: @expr_or_none ref, - int opaque_expr: @opaque_value_expr_or_none ref -); - -optional_evaluation_exprs( //dir=expr - unique int id: @optional_evaluation_expr, - int sub_expr: @expr_or_none ref -); - -other_constructor_decl_ref_exprs( //dir=expr - unique int id: @other_constructor_decl_ref_expr, - int constructor_decl: @constructor_decl_or_none ref -); - -overloaded_decl_ref_exprs( //dir=expr - unique int id: @overloaded_decl_ref_expr -); - -#keyset[id, index] -overloaded_decl_ref_expr_possible_declarations( //dir=expr - int id: @overloaded_decl_ref_expr ref, - int index: int ref, - int possible_declaration: @value_decl_or_none ref -); - -property_wrapper_value_placeholder_exprs( //dir=expr - unique int id: @property_wrapper_value_placeholder_expr, - int placeholder: @opaque_value_expr_or_none ref -); - -#keyset[id] -property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr - int id: @property_wrapper_value_placeholder_expr ref, - int wrapped_value: @expr_or_none ref -); - -rebind_self_in_constructor_exprs( //dir=expr - unique int id: @rebind_self_in_constructor_expr, - int sub_expr: @expr_or_none ref, - int self: @var_decl_or_none ref -); - -sequence_exprs( //dir=expr - unique int id: @sequence_expr -); - -#keyset[id, index] -sequence_expr_elements( //dir=expr - int id: @sequence_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -super_ref_exprs( //dir=expr - unique int id: @super_ref_expr, - int self: @var_decl_or_none ref -); - -tap_exprs( //dir=expr - unique int id: @tap_expr, - int body: @brace_stmt_or_none ref, - int var: @var_decl_or_none ref -); - -#keyset[id] -tap_expr_sub_exprs( //dir=expr - int id: @tap_expr ref, - int sub_expr: @expr_or_none ref -); - -tuple_element_exprs( //dir=expr - unique int id: @tuple_element_expr, - int sub_expr: @expr_or_none ref, - int index: int ref -); - -tuple_exprs( //dir=expr - unique int id: @tuple_expr -); - -#keyset[id, index] -tuple_expr_elements( //dir=expr - int id: @tuple_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -type_exprs( //dir=expr - unique int id: @type_expr -); - -#keyset[id] -type_expr_type_reprs( //dir=expr - int id: @type_expr ref, - int type_repr: @type_repr_or_none ref -); - -unresolved_decl_ref_exprs( //dir=expr - unique int id: @unresolved_decl_ref_expr -); - -#keyset[id] -unresolved_decl_ref_expr_names( //dir=expr - int id: @unresolved_decl_ref_expr ref, - string name: string ref -); - -unresolved_dot_exprs( //dir=expr - unique int id: @unresolved_dot_expr, - int base: @expr_or_none ref, - string name: string ref -); - -unresolved_member_exprs( //dir=expr - unique int id: @unresolved_member_expr, - string name: string ref -); - -unresolved_pattern_exprs( //dir=expr - unique int id: @unresolved_pattern_expr, - int sub_pattern: @pattern_or_none ref -); - -unresolved_specialize_exprs( //dir=expr - unique int id: @unresolved_specialize_expr, - int sub_expr: @expr_or_none ref -); - -vararg_expansion_exprs( //dir=expr - unique int id: @vararg_expansion_expr, - int sub_expr: @expr_or_none ref -); - -abi_safe_conversion_exprs( //dir=expr - unique int id: @abi_safe_conversion_expr -); - -any_hashable_erasure_exprs( //dir=expr - unique int id: @any_hashable_erasure_expr -); - -archetype_to_super_exprs( //dir=expr - unique int id: @archetype_to_super_expr -); - -array_exprs( //dir=expr - unique int id: @array_expr -); - -#keyset[id, index] -array_expr_elements( //dir=expr - int id: @array_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -array_to_pointer_exprs( //dir=expr - unique int id: @array_to_pointer_expr -); - -auto_closure_exprs( //dir=expr - unique int id: @auto_closure_expr -); - -await_exprs( //dir=expr - unique int id: @await_expr -); - -binary_exprs( //dir=expr - unique int id: @binary_expr -); - -bridge_from_obj_c_exprs( //dir=expr - unique int id: @bridge_from_obj_c_expr -); - -bridge_to_obj_c_exprs( //dir=expr - unique int id: @bridge_to_obj_c_expr -); - -@builtin_literal_expr = - @boolean_literal_expr -| @magic_identifier_literal_expr -| @number_literal_expr -| @string_literal_expr -; - -call_exprs( //dir=expr - unique int id: @call_expr -); - -@checked_cast_expr = - @conditional_checked_cast_expr -| @forced_checked_cast_expr -| @is_expr -; - -class_metatype_to_object_exprs( //dir=expr - unique int id: @class_metatype_to_object_expr -); - -closure_exprs( //dir=expr - unique int id: @closure_expr -); - -coerce_exprs( //dir=expr - unique int id: @coerce_expr -); - -collection_upcast_conversion_exprs( //dir=expr - unique int id: @collection_upcast_conversion_expr -); - -conditional_bridge_from_obj_c_exprs( //dir=expr - unique int id: @conditional_bridge_from_obj_c_expr -); - -covariant_function_conversion_exprs( //dir=expr - unique int id: @covariant_function_conversion_expr -); - -covariant_return_conversion_exprs( //dir=expr - unique int id: @covariant_return_conversion_expr -); - -derived_to_base_exprs( //dir=expr - unique int id: @derived_to_base_expr -); - -destructure_tuple_exprs( //dir=expr - unique int id: @destructure_tuple_expr -); - -dictionary_exprs( //dir=expr - unique int id: @dictionary_expr -); - -#keyset[id, index] -dictionary_expr_elements( //dir=expr - int id: @dictionary_expr ref, - int index: int ref, - int element: @expr_or_none ref -); - -differentiable_function_exprs( //dir=expr - unique int id: @differentiable_function_expr -); - -differentiable_function_extract_original_exprs( //dir=expr - unique int id: @differentiable_function_extract_original_expr -); - -dot_self_exprs( //dir=expr - unique int id: @dot_self_expr -); - -@dynamic_lookup_expr = - @dynamic_member_ref_expr -| @dynamic_subscript_expr -; - -erasure_exprs( //dir=expr - unique int id: @erasure_expr -); - -existential_metatype_to_object_exprs( //dir=expr - unique int id: @existential_metatype_to_object_expr -); - -force_try_exprs( //dir=expr - unique int id: @force_try_expr -); - -foreign_object_conversion_exprs( //dir=expr - unique int id: @foreign_object_conversion_expr -); - -function_conversion_exprs( //dir=expr - unique int id: @function_conversion_expr -); - -in_out_to_pointer_exprs( //dir=expr - unique int id: @in_out_to_pointer_expr -); - -inject_into_optional_exprs( //dir=expr - unique int id: @inject_into_optional_expr -); - -interpolated_string_literal_exprs( //dir=expr - unique int id: @interpolated_string_literal_expr -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_expr: @opaque_value_expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int interpolation_count_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int literal_capacity_expr: @expr_or_none ref -); - -#keyset[id] -interpolated_string_literal_expr_appending_exprs( //dir=expr - int id: @interpolated_string_literal_expr ref, - int appending_expr: @tap_expr_or_none ref -); - -linear_function_exprs( //dir=expr - unique int id: @linear_function_expr -); - -linear_function_extract_original_exprs( //dir=expr - unique int id: @linear_function_extract_original_expr -); - -linear_to_differentiable_function_exprs( //dir=expr - unique int id: @linear_to_differentiable_function_expr -); - -load_exprs( //dir=expr - unique int id: @load_expr -); - -member_ref_exprs( //dir=expr - unique int id: @member_ref_expr -); - -#keyset[id] -member_ref_expr_has_direct_to_storage_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_ordinary_semantics( //dir=expr - int id: @member_ref_expr ref -); - -#keyset[id] -member_ref_expr_has_distributed_thunk_semantics( //dir=expr - int id: @member_ref_expr ref -); - -metatype_conversion_exprs( //dir=expr - unique int id: @metatype_conversion_expr -); - -nil_literal_exprs( //dir=expr - unique int id: @nil_literal_expr -); - -object_literal_exprs( //dir=expr - unique int id: @object_literal_expr, - int kind: int ref -); - -#keyset[id, index] -object_literal_expr_arguments( //dir=expr - int id: @object_literal_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -optional_try_exprs( //dir=expr - unique int id: @optional_try_expr -); - -paren_exprs( //dir=expr - unique int id: @paren_expr -); - -pointer_to_pointer_exprs( //dir=expr - unique int id: @pointer_to_pointer_expr -); - -postfix_unary_exprs( //dir=expr - unique int id: @postfix_unary_expr -); - -prefix_unary_exprs( //dir=expr - unique int id: @prefix_unary_expr -); - -protocol_metatype_to_object_exprs( //dir=expr - unique int id: @protocol_metatype_to_object_expr -); - -regex_literal_exprs( //dir=expr - unique int id: @regex_literal_expr, - string pattern: string ref, - int version: int ref -); - -@self_apply_expr = - @constructor_ref_call_expr -| @dot_syntax_call_expr -; - -#keyset[id] -self_apply_exprs( //dir=expr - int id: @self_apply_expr ref, - int base: @expr_or_none ref -); - -string_to_pointer_exprs( //dir=expr - unique int id: @string_to_pointer_expr -); - -subscript_exprs( //dir=expr - unique int id: @subscript_expr -); - -#keyset[id, index] -subscript_expr_arguments( //dir=expr - int id: @subscript_expr ref, - int index: int ref, - int argument: @argument_or_none ref -); - -#keyset[id] -subscript_expr_has_direct_to_storage_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_direct_to_implementation_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_ordinary_semantics( //dir=expr - int id: @subscript_expr ref -); - -#keyset[id] -subscript_expr_has_distributed_thunk_semantics( //dir=expr - int id: @subscript_expr ref -); - -try_exprs( //dir=expr - unique int id: @try_expr -); - -underlying_to_opaque_exprs( //dir=expr - unique int id: @underlying_to_opaque_expr -); - -unevaluated_instance_exprs( //dir=expr - unique int id: @unevaluated_instance_expr -); - -unresolved_member_chain_result_exprs( //dir=expr - unique int id: @unresolved_member_chain_result_expr -); - -unresolved_type_conversion_exprs( //dir=expr - unique int id: @unresolved_type_conversion_expr -); - -boolean_literal_exprs( //dir=expr - unique int id: @boolean_literal_expr, - boolean value: boolean ref -); - -conditional_checked_cast_exprs( //dir=expr - unique int id: @conditional_checked_cast_expr -); - -constructor_ref_call_exprs( //dir=expr - unique int id: @constructor_ref_call_expr -); - -dot_syntax_call_exprs( //dir=expr - unique int id: @dot_syntax_call_expr -); - -dynamic_member_ref_exprs( //dir=expr - unique int id: @dynamic_member_ref_expr -); - -dynamic_subscript_exprs( //dir=expr - unique int id: @dynamic_subscript_expr -); - -forced_checked_cast_exprs( //dir=expr - unique int id: @forced_checked_cast_expr -); - -is_exprs( //dir=expr - unique int id: @is_expr -); - -magic_identifier_literal_exprs( //dir=expr - unique int id: @magic_identifier_literal_expr, - string kind: string ref -); - -@number_literal_expr = - @float_literal_expr -| @integer_literal_expr -; - -string_literal_exprs( //dir=expr - unique int id: @string_literal_expr, - string value: string ref -); - -float_literal_exprs( //dir=expr - unique int id: @float_literal_expr, - string string_value: string ref -); - -integer_literal_exprs( //dir=expr - unique int id: @integer_literal_expr, - string string_value: string ref -); - -@pattern = - @any_pattern -| @binding_pattern -| @bool_pattern -| @enum_element_pattern -| @expr_pattern -| @is_pattern -| @named_pattern -| @optional_some_pattern -| @paren_pattern -| @tuple_pattern -| @typed_pattern -; - -any_patterns( //dir=pattern - unique int id: @any_pattern -); - -binding_patterns( //dir=pattern - unique int id: @binding_pattern, - int sub_pattern: @pattern_or_none ref -); - -bool_patterns( //dir=pattern - unique int id: @bool_pattern, - boolean value: boolean ref -); - -enum_element_patterns( //dir=pattern - unique int id: @enum_element_pattern, - int element: @enum_element_decl_or_none ref -); - -#keyset[id] -enum_element_pattern_sub_patterns( //dir=pattern - int id: @enum_element_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -expr_patterns( //dir=pattern - unique int id: @expr_pattern, - int sub_expr: @expr_or_none ref -); - -is_patterns( //dir=pattern - unique int id: @is_pattern -); - -#keyset[id] -is_pattern_cast_type_reprs( //dir=pattern - int id: @is_pattern ref, - int cast_type_repr: @type_repr_or_none ref -); - -#keyset[id] -is_pattern_sub_patterns( //dir=pattern - int id: @is_pattern ref, - int sub_pattern: @pattern_or_none ref -); - -named_patterns( //dir=pattern - unique int id: @named_pattern, - string name: string ref -); - -optional_some_patterns( //dir=pattern - unique int id: @optional_some_pattern, - int sub_pattern: @pattern_or_none ref -); - -paren_patterns( //dir=pattern - unique int id: @paren_pattern, - int sub_pattern: @pattern_or_none ref -); - -tuple_patterns( //dir=pattern - unique int id: @tuple_pattern -); - -#keyset[id, index] -tuple_pattern_elements( //dir=pattern - int id: @tuple_pattern ref, - int index: int ref, - int element: @pattern_or_none ref -); - -typed_patterns( //dir=pattern - unique int id: @typed_pattern, - int sub_pattern: @pattern_or_none ref -); - -#keyset[id] -typed_pattern_type_reprs( //dir=pattern - int id: @typed_pattern ref, - int type_repr: @type_repr_or_none ref -); - -case_label_items( //dir=stmt - unique int id: @case_label_item, - int pattern: @pattern_or_none ref -); - -#keyset[id] -case_label_item_guards( //dir=stmt - int id: @case_label_item ref, - int guard: @expr_or_none ref -); - -condition_elements( //dir=stmt - unique int id: @condition_element -); - -#keyset[id] -condition_element_booleans( //dir=stmt - int id: @condition_element ref, - int boolean_: @expr_or_none ref -); - -#keyset[id] -condition_element_patterns( //dir=stmt - int id: @condition_element ref, - int pattern: @pattern_or_none ref -); - -#keyset[id] -condition_element_initializers( //dir=stmt - int id: @condition_element ref, - int initializer: @expr_or_none ref -); - -#keyset[id] -condition_element_availabilities( //dir=stmt - int id: @condition_element ref, - int availability: @availability_info_or_none ref -); - -@stmt = - @brace_stmt -| @break_stmt -| @case_stmt -| @continue_stmt -| @defer_stmt -| @fail_stmt -| @fallthrough_stmt -| @labeled_stmt -| @pound_assert_stmt -| @return_stmt -| @throw_stmt -| @yield_stmt -; - -stmt_conditions( //dir=stmt - unique int id: @stmt_condition -); - -#keyset[id, index] -stmt_condition_elements( //dir=stmt - int id: @stmt_condition ref, - int index: int ref, - int element: @condition_element_or_none ref -); - -brace_stmts( //dir=stmt - unique int id: @brace_stmt -); - -#keyset[id, index] -brace_stmt_elements( //dir=stmt - int id: @brace_stmt ref, - int index: int ref, - int element: @ast_node_or_none ref -); - -break_stmts( //dir=stmt - unique int id: @break_stmt -); - -#keyset[id] -break_stmt_target_names( //dir=stmt - int id: @break_stmt ref, - string target_name: string ref -); - -#keyset[id] -break_stmt_targets( //dir=stmt - int id: @break_stmt ref, - int target: @stmt_or_none ref -); - -case_stmts( //dir=stmt - unique int id: @case_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -case_stmt_labels( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int label: @case_label_item_or_none ref -); - -#keyset[id, index] -case_stmt_variables( //dir=stmt - int id: @case_stmt ref, - int index: int ref, - int variable: @var_decl_or_none ref -); - -continue_stmts( //dir=stmt - unique int id: @continue_stmt -); - -#keyset[id] -continue_stmt_target_names( //dir=stmt - int id: @continue_stmt ref, - string target_name: string ref -); - -#keyset[id] -continue_stmt_targets( //dir=stmt - int id: @continue_stmt ref, - int target: @stmt_or_none ref -); - -defer_stmts( //dir=stmt - unique int id: @defer_stmt, - int body: @brace_stmt_or_none ref -); - -fail_stmts( //dir=stmt - unique int id: @fail_stmt -); - -fallthrough_stmts( //dir=stmt - unique int id: @fallthrough_stmt, - int fallthrough_source: @case_stmt_or_none ref, - int fallthrough_dest: @case_stmt_or_none ref -); - -@labeled_stmt = - @do_catch_stmt -| @do_stmt -| @for_each_stmt -| @labeled_conditional_stmt -| @repeat_while_stmt -| @switch_stmt -; - -#keyset[id] -labeled_stmt_labels( //dir=stmt - int id: @labeled_stmt ref, - string label: string ref -); - -pound_assert_stmts( //dir=stmt - unique int id: @pound_assert_stmt, - int condition: @expr_or_none ref, - string message: string ref -); - -return_stmts( //dir=stmt - unique int id: @return_stmt -); - -#keyset[id] -return_stmt_results( //dir=stmt - int id: @return_stmt ref, - int result: @expr_or_none ref -); - -throw_stmts( //dir=stmt - unique int id: @throw_stmt, - int sub_expr: @expr_or_none ref -); - -yield_stmts( //dir=stmt - unique int id: @yield_stmt -); - -#keyset[id, index] -yield_stmt_results( //dir=stmt - int id: @yield_stmt ref, - int index: int ref, - int result: @expr_or_none ref -); - -do_catch_stmts( //dir=stmt - unique int id: @do_catch_stmt, - int body: @stmt_or_none ref -); - -#keyset[id, index] -do_catch_stmt_catches( //dir=stmt - int id: @do_catch_stmt ref, - int index: int ref, - int catch: @case_stmt_or_none ref -); - -do_stmts( //dir=stmt - unique int id: @do_stmt, - int body: @brace_stmt_or_none ref -); - -for_each_stmts( //dir=stmt - unique int id: @for_each_stmt, - int pattern: @pattern_or_none ref, - int sequence: @expr_or_none ref, - int body: @brace_stmt_or_none ref -); - -#keyset[id] -for_each_stmt_wheres( //dir=stmt - int id: @for_each_stmt ref, - int where: @expr_or_none ref -); - -@labeled_conditional_stmt = - @guard_stmt -| @if_stmt -| @while_stmt -; - -#keyset[id] -labeled_conditional_stmts( //dir=stmt - int id: @labeled_conditional_stmt ref, - int condition: @stmt_condition_or_none ref -); - -repeat_while_stmts( //dir=stmt - unique int id: @repeat_while_stmt, - int condition: @expr_or_none ref, - int body: @stmt_or_none ref -); - -switch_stmts( //dir=stmt - unique int id: @switch_stmt, - int expr: @expr_or_none ref -); - -#keyset[id, index] -switch_stmt_cases( //dir=stmt - int id: @switch_stmt ref, - int index: int ref, - int case_: @case_stmt_or_none ref -); - -guard_stmts( //dir=stmt - unique int id: @guard_stmt, - int body: @brace_stmt_or_none ref -); - -if_stmts( //dir=stmt - unique int id: @if_stmt, - int then: @stmt_or_none ref -); - -#keyset[id] -if_stmt_elses( //dir=stmt - int id: @if_stmt ref, - int else: @stmt_or_none ref -); - -while_stmts( //dir=stmt - unique int id: @while_stmt, - int body: @stmt_or_none ref -); - -@type = - @any_function_type -| @any_generic_type -| @any_metatype_type -| @builtin_type -| @dependent_member_type -| @dynamic_self_type -| @error_type -| @existential_type -| @in_out_type -| @l_value_type -| @module_type -| @parameterized_protocol_type -| @protocol_composition_type -| @reference_storage_type -| @substitutable_type -| @sugar_type -| @tuple_type -| @unresolved_type -; - -#keyset[id] -types( //dir=type - int id: @type ref, - string name: string ref, - int canonical_type: @type_or_none ref -); - -type_reprs( //dir=type - unique int id: @type_repr, - int type_: @type_or_none ref -); - -@any_function_type = - @function_type -| @generic_function_type -; - -#keyset[id] -any_function_types( //dir=type - int id: @any_function_type ref, - int result: @type_or_none ref -); - -#keyset[id, index] -any_function_type_param_types( //dir=type - int id: @any_function_type ref, - int index: int ref, - int param_type: @type_or_none ref -); - -#keyset[id] -any_function_type_is_throwing( //dir=type - int id: @any_function_type ref -); - -#keyset[id] -any_function_type_is_async( //dir=type - int id: @any_function_type ref -); - -@any_generic_type = - @nominal_or_bound_generic_nominal_type -| @unbound_generic_type -; - -#keyset[id] -any_generic_types( //dir=type - int id: @any_generic_type ref, - int declaration: @generic_type_decl_or_none ref -); - -#keyset[id] -any_generic_type_parents( //dir=type - int id: @any_generic_type ref, - int parent: @type_or_none ref -); - -@any_metatype_type = - @existential_metatype_type -| @metatype_type -; - -@builtin_type = - @any_builtin_integer_type -| @builtin_bridge_object_type -| @builtin_default_actor_storage_type -| @builtin_executor_type -| @builtin_float_type -| @builtin_job_type -| @builtin_native_object_type -| @builtin_raw_pointer_type -| @builtin_raw_unsafe_continuation_type -| @builtin_unsafe_value_buffer_type -| @builtin_vector_type -; - -dependent_member_types( //dir=type - unique int id: @dependent_member_type, - int base_type: @type_or_none ref, - int associated_type_decl: @associated_type_decl_or_none ref -); - -dynamic_self_types( //dir=type - unique int id: @dynamic_self_type, - int static_self_type: @type_or_none ref -); - -error_types( //dir=type - unique int id: @error_type -); - -existential_types( //dir=type - unique int id: @existential_type, - int constraint: @type_or_none ref -); - -in_out_types( //dir=type - unique int id: @in_out_type, - int object_type: @type_or_none ref -); - -l_value_types( //dir=type - unique int id: @l_value_type, - int object_type: @type_or_none ref -); - -module_types( //dir=type - unique int id: @module_type, - int module: @module_decl_or_none ref -); - -parameterized_protocol_types( //dir=type - unique int id: @parameterized_protocol_type, - int base: @protocol_type_or_none ref -); - -#keyset[id, index] -parameterized_protocol_type_args( //dir=type - int id: @parameterized_protocol_type ref, - int index: int ref, - int arg: @type_or_none ref -); - -protocol_composition_types( //dir=type - unique int id: @protocol_composition_type -); - -#keyset[id, index] -protocol_composition_type_members( //dir=type - int id: @protocol_composition_type ref, - int index: int ref, - int member: @type_or_none ref -); - -@reference_storage_type = - @unmanaged_storage_type -| @unowned_storage_type -| @weak_storage_type -; - -#keyset[id] -reference_storage_types( //dir=type - int id: @reference_storage_type ref, - int referent_type: @type_or_none ref -); - -@substitutable_type = - @archetype_type -| @generic_type_param_type -; - -@sugar_type = - @paren_type -| @syntax_sugar_type -| @type_alias_type -; - -tuple_types( //dir=type - unique int id: @tuple_type -); - -#keyset[id, index] -tuple_type_types( //dir=type - int id: @tuple_type ref, - int index: int ref, - int type_: @type_or_none ref -); - -#keyset[id, index] -tuple_type_names( //dir=type - int id: @tuple_type ref, - int index: int ref, - string name: string ref -); - -unresolved_types( //dir=type - unique int id: @unresolved_type -); - -@any_builtin_integer_type = - @builtin_integer_literal_type -| @builtin_integer_type -; - -@archetype_type = - @opaque_type_archetype_type -| @opened_archetype_type -| @primary_archetype_type -; - -#keyset[id] -archetype_types( //dir=type - int id: @archetype_type ref, - int interface_type: @type_or_none ref -); - -#keyset[id] -archetype_type_superclasses( //dir=type - int id: @archetype_type ref, - int superclass: @type_or_none ref -); - -#keyset[id, index] -archetype_type_protocols( //dir=type - int id: @archetype_type ref, - int index: int ref, - int protocol: @protocol_decl_or_none ref -); - -builtin_bridge_object_types( //dir=type - unique int id: @builtin_bridge_object_type -); - -builtin_default_actor_storage_types( //dir=type - unique int id: @builtin_default_actor_storage_type -); - -builtin_executor_types( //dir=type - unique int id: @builtin_executor_type -); - -builtin_float_types( //dir=type - unique int id: @builtin_float_type -); - -builtin_job_types( //dir=type - unique int id: @builtin_job_type -); - -builtin_native_object_types( //dir=type - unique int id: @builtin_native_object_type -); - -builtin_raw_pointer_types( //dir=type - unique int id: @builtin_raw_pointer_type -); - -builtin_raw_unsafe_continuation_types( //dir=type - unique int id: @builtin_raw_unsafe_continuation_type -); - -builtin_unsafe_value_buffer_types( //dir=type - unique int id: @builtin_unsafe_value_buffer_type -); - -builtin_vector_types( //dir=type - unique int id: @builtin_vector_type -); - -existential_metatype_types( //dir=type - unique int id: @existential_metatype_type -); - -function_types( //dir=type - unique int id: @function_type -); - -generic_function_types( //dir=type - unique int id: @generic_function_type -); - -#keyset[id, index] -generic_function_type_generic_params( //dir=type - int id: @generic_function_type ref, - int index: int ref, - int generic_param: @generic_type_param_type_or_none ref -); - -generic_type_param_types( //dir=type - unique int id: @generic_type_param_type -); - -metatype_types( //dir=type - unique int id: @metatype_type -); - -@nominal_or_bound_generic_nominal_type = - @bound_generic_type -| @nominal_type -; - -paren_types( //dir=type - unique int id: @paren_type, - int type_: @type_or_none ref -); - -@syntax_sugar_type = - @dictionary_type -| @unary_syntax_sugar_type -; - -type_alias_types( //dir=type - unique int id: @type_alias_type, - int decl: @type_alias_decl_or_none ref -); - -unbound_generic_types( //dir=type - unique int id: @unbound_generic_type -); - -unmanaged_storage_types( //dir=type - unique int id: @unmanaged_storage_type -); - -unowned_storage_types( //dir=type - unique int id: @unowned_storage_type -); - -weak_storage_types( //dir=type - unique int id: @weak_storage_type -); - -@bound_generic_type = - @bound_generic_class_type -| @bound_generic_enum_type -| @bound_generic_struct_type -; - -#keyset[id, index] -bound_generic_type_arg_types( //dir=type - int id: @bound_generic_type ref, - int index: int ref, - int arg_type: @type_or_none ref -); - -builtin_integer_literal_types( //dir=type - unique int id: @builtin_integer_literal_type -); - -builtin_integer_types( //dir=type - unique int id: @builtin_integer_type -); - -#keyset[id] -builtin_integer_type_widths( //dir=type - int id: @builtin_integer_type ref, - int width: int ref -); - -dictionary_types( //dir=type - unique int id: @dictionary_type, - int key_type: @type_or_none ref, - int value_type: @type_or_none ref -); - -@nominal_type = - @class_type -| @enum_type -| @protocol_type -| @struct_type -; - -opaque_type_archetype_types( //dir=type - unique int id: @opaque_type_archetype_type, - int declaration: @opaque_type_decl_or_none ref -); - -opened_archetype_types( //dir=type - unique int id: @opened_archetype_type -); - -primary_archetype_types( //dir=type - unique int id: @primary_archetype_type -); - -@unary_syntax_sugar_type = - @array_slice_type -| @optional_type -| @variadic_sequence_type -; - -#keyset[id] -unary_syntax_sugar_types( //dir=type - int id: @unary_syntax_sugar_type ref, - int base_type: @type_or_none ref -); - -array_slice_types( //dir=type - unique int id: @array_slice_type -); - -bound_generic_class_types( //dir=type - unique int id: @bound_generic_class_type -); - -bound_generic_enum_types( //dir=type - unique int id: @bound_generic_enum_type -); - -bound_generic_struct_types( //dir=type - unique int id: @bound_generic_struct_type -); - -class_types( //dir=type - unique int id: @class_type -); - -enum_types( //dir=type - unique int id: @enum_type -); - -optional_types( //dir=type - unique int id: @optional_type -); - -protocol_types( //dir=type - unique int id: @protocol_type -); - -struct_types( //dir=type - unique int id: @struct_type -); - -variadic_sequence_types( //dir=type - unique int id: @variadic_sequence_type -); - -@abstract_function_decl_or_none = - @abstract_function_decl -| @unspecified_element -; - -@accessor_decl_or_none = - @accessor_decl -| @unspecified_element -; - -@argument_or_none = - @argument -| @unspecified_element -; - -@associated_type_decl_or_none = - @associated_type_decl -| @unspecified_element -; - -@ast_node_or_none = - @ast_node -| @unspecified_element -; - -@availability_info_or_none = - @availability_info -| @unspecified_element -; - -@availability_spec_or_none = - @availability_spec -| @unspecified_element -; - -@brace_stmt_or_none = - @brace_stmt -| @unspecified_element -; - -@captured_decl_or_none = - @captured_decl -| @unspecified_element -; - -@case_label_item_or_none = - @case_label_item -| @unspecified_element -; - -@case_stmt_or_none = - @case_stmt -| @unspecified_element -; - -@closure_expr_or_none = - @closure_expr -| @unspecified_element -; - -@condition_element_or_none = - @condition_element -| @unspecified_element -; - -@constructor_decl_or_none = - @constructor_decl -| @unspecified_element -; - -@decl_or_none = - @decl -| @unspecified_element -; - -@enum_element_decl_or_none = - @enum_element_decl -| @unspecified_element -; - -@expr_or_none = - @expr -| @unspecified_element -; - -@file_or_none = - @file -| @unspecified_element -; - -@generic_type_decl_or_none = - @generic_type_decl -| @unspecified_element -; - -@generic_type_param_decl_or_none = - @generic_type_param_decl -| @unspecified_element -; - -@generic_type_param_type_or_none = - @generic_type_param_type -| @unspecified_element -; - -@location_or_none = - @location -| @unspecified_element -; - -@module_decl_or_none = - @module_decl -| @unspecified_element -; - -@nominal_type_decl_or_none = - @nominal_type_decl -| @unspecified_element -; - -@opaque_type_decl_or_none = - @opaque_type_decl -| @unspecified_element -; - -@opaque_value_expr_or_none = - @opaque_value_expr -| @unspecified_element -; - -@param_decl_or_none = - @param_decl -| @unspecified_element -; - -@pattern_or_none = - @pattern -| @unspecified_element -; - -@pattern_binding_decl_or_none = - @pattern_binding_decl -| @unspecified_element -; - -@precedence_group_decl_or_none = - @precedence_group_decl -| @unspecified_element -; - -@protocol_decl_or_none = - @protocol_decl -| @unspecified_element -; - -@protocol_type_or_none = - @protocol_type -| @unspecified_element -; - -@stmt_or_none = - @stmt -| @unspecified_element -; - -@stmt_condition_or_none = - @stmt_condition -| @unspecified_element -; - -@string_literal_expr_or_none = - @string_literal_expr -| @unspecified_element -; - -@tap_expr_or_none = - @tap_expr -| @unspecified_element -; - -@type_or_none = - @type -| @unspecified_element -; - -@type_alias_decl_or_none = - @type_alias_decl -| @unspecified_element -; - -@type_repr_or_none = - @type_repr -| @unspecified_element -; - -@value_decl_or_none = - @unspecified_element -| @value_decl -; - -@var_decl_or_none = - @unspecified_element -| @var_decl -; diff --git a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties b/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties deleted file mode 100644 index def634ba268..00000000000 --- a/swift/ql/lib/upgrades/c2f01f2beb67e5a57e9df9b6d1c51e35e8d5b0a2/upgrade.properties +++ /dev/null @@ -1,4 +0,0 @@ -description: Turn exported and imported modules into unindexed sets -compatibility: full -module_decl_imported_modules.rel: reorder module_decl_imported_modules(int id, int index, int imported) id imported -module_decl_exported_modules.rel: reorder module_decl_exported_modules(int id, int index, int exported) id exported From 3d6916eb7268ad2d68f3b8f69db5001062d5afc6 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Thu, 30 Mar 2023 16:44:28 +0200 Subject: [PATCH 075/141] Swift: add upgrade/downgrade scripts --- .../module_decl_exported_modules.ql | 15 + .../module_decl_imported_modules.ql | 15 + .../old.dbscheme | 2598 ++++++++++++++++ .../swift.dbscheme | 2602 +++++++++++++++++ .../upgrade.properties | 4 + .../old.dbscheme | 2602 +++++++++++++++++ .../swift.dbscheme | 2598 ++++++++++++++++ .../upgrade.properties | 4 + 8 files changed, 10438 insertions(+) create mode 100644 swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_exported_modules.ql create mode 100644 swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_imported_modules.ql create mode 100644 swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/old.dbscheme create mode 100644 swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/swift.dbscheme create mode 100644 swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/upgrade.properties create mode 100644 swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme create mode 100644 swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme create mode 100644 swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties diff --git a/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_exported_modules.ql b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_exported_modules.ql new file mode 100644 index 00000000000..6f2f7125742 --- /dev/null +++ b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_exported_modules.ql @@ -0,0 +1,15 @@ +class Element extends @element { + string toString() { none() } +} + +int getExportedModuleIndex(Element m, Element i) { + i = + rank[result + 1](Element j, string name | + module_decl_exported_modules(m, j) and type_decls(j, name) + | + j order by name + ) +} + +from Element m, Element i +select m, getExportedModuleIndex(m, i), i diff --git a/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_imported_modules.ql b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_imported_modules.ql new file mode 100644 index 00000000000..88093d6e5e5 --- /dev/null +++ b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/module_decl_imported_modules.ql @@ -0,0 +1,15 @@ +class Element extends @element { + string toString() { none() } +} + +int getImportedModuleIndex(Element m, Element i) { + i = + rank[result + 1](Element j, string name | + module_decl_imported_modules(m, j) and type_decls(j, name) + | + j order by name + ) +} + +from Element m, Element i +select m, getImportedModuleIndex(m, i), i diff --git a/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/old.dbscheme b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/old.dbscheme new file mode 100644 index 00000000000..e457bc35325 --- /dev/null +++ b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/old.dbscheme @@ -0,0 +1,2598 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/swift.dbscheme b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/swift.dbscheme new file mode 100644 index 00000000000..e646f9e0308 --- /dev/null +++ b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/swift.dbscheme @@ -0,0 +1,2602 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/upgrade.properties b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/upgrade.properties new file mode 100644 index 00000000000..160d55476c9 --- /dev/null +++ b/swift/downgrades/e457bc35325b05725c00471da8843f293fe26f8d/upgrade.properties @@ -0,0 +1,4 @@ +description: Revert turning exported and imported modules into unindexed sets +compatibility: full +module_decl_imported_modules.rel: run module_decl_imported_modules.ql +module_decl_exported_modules.rel: run module_decl_exported_modules.ql diff --git a/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme b/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme new file mode 100644 index 00000000000..e646f9e0308 --- /dev/null +++ b/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/old.dbscheme @@ -0,0 +1,2602 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id, index] +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int index: int ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme b/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme new file mode 100644 index 00000000000..e457bc35325 --- /dev/null +++ b/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/swift.dbscheme @@ -0,0 +1,2598 @@ +// generated by codegen/codegen.py + +// from prefix.dbscheme +/** + * The source location of the snapshot. + */ +sourceLocationPrefix( + string prefix: string ref +); + + +// from schema.py + +@element = + @callable +| @file +| @generic_context +| @locatable +| @location +| @type +; + +#keyset[id] +element_is_unknown( + int id: @element ref +); + +@callable = + @abstract_closure_expr +| @abstract_function_decl +; + +#keyset[id] +callable_names( + int id: @callable ref, + string name: string ref +); + +#keyset[id] +callable_self_params( + int id: @callable ref, + int self_param: @param_decl_or_none ref +); + +#keyset[id, index] +callable_params( + int id: @callable ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +#keyset[id] +callable_bodies( + int id: @callable ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id, index] +callable_captures( + int id: @callable ref, + int index: int ref, + int capture: @captured_decl_or_none ref +); + +@file = + @db_file +; + +#keyset[id] +files( + int id: @file ref, + string name: string ref +); + +#keyset[id] +file_is_successfully_extracted( + int id: @file ref +); + +@locatable = + @argument +| @ast_node +| @comment +| @diagnostics +| @error_element +; + +#keyset[id] +locatable_locations( + int id: @locatable ref, + int location: @location_or_none ref +); + +@location = + @db_location +; + +#keyset[id] +locations( + int id: @location ref, + int file: @file_or_none ref, + int start_line: int ref, + int start_column: int ref, + int end_line: int ref, + int end_column: int ref +); + +@ast_node = + @availability_info +| @availability_spec +| @case_label_item +| @condition_element +| @decl +| @expr +| @pattern +| @stmt +| @stmt_condition +| @type_repr +; + +comments( + unique int id: @comment, + string text: string ref +); + +db_files( + unique int id: @db_file +); + +db_locations( + unique int id: @db_location +); + +diagnostics( + unique int id: @diagnostics, + string text: string ref, + int kind: int ref +); + +@error_element = + @error_expr +| @error_type +| @overloaded_decl_ref_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_chain_result_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @unresolved_type +| @unresolved_type_conversion_expr +| @unspecified_element +; + +availability_infos( + unique int id: @availability_info +); + +#keyset[id] +availability_info_is_unavailable( + int id: @availability_info ref +); + +#keyset[id, index] +availability_info_specs( + int id: @availability_info ref, + int index: int ref, + int spec: @availability_spec_or_none ref +); + +@availability_spec = + @other_availability_spec +| @platform_version_availability_spec +; + +unspecified_elements( + unique int id: @unspecified_element, + string property: string ref, + string error: string ref +); + +#keyset[id] +unspecified_element_parents( + int id: @unspecified_element ref, + int parent: @element ref +); + +#keyset[id] +unspecified_element_indices( + int id: @unspecified_element ref, + int index: int ref +); + +other_availability_specs( + unique int id: @other_availability_spec +); + +platform_version_availability_specs( + unique int id: @platform_version_availability_spec, + string platform: string ref, + string version: string ref +); + +@decl = + @captured_decl +| @enum_case_decl +| @extension_decl +| @if_config_decl +| @import_decl +| @missing_member_decl +| @operator_decl +| @pattern_binding_decl +| @pound_diagnostic_decl +| @precedence_group_decl +| @top_level_code_decl +| @value_decl +; + +#keyset[id] +decls( //dir=decl + int id: @decl ref, + int module: @module_decl_or_none ref +); + +#keyset[id, index] +decl_members( //dir=decl + int id: @decl ref, + int index: int ref, + int member: @decl_or_none ref +); + +@generic_context = + @abstract_function_decl +| @extension_decl +| @generic_type_decl +| @subscript_decl +; + +#keyset[id, index] +generic_context_generic_type_params( //dir=decl + int id: @generic_context ref, + int index: int ref, + int generic_type_param: @generic_type_param_decl_or_none ref +); + +captured_decls( //dir=decl + unique int id: @captured_decl, + int decl: @value_decl_or_none ref +); + +#keyset[id] +captured_decl_is_direct( //dir=decl + int id: @captured_decl ref +); + +#keyset[id] +captured_decl_is_escaping( //dir=decl + int id: @captured_decl ref +); + +enum_case_decls( //dir=decl + unique int id: @enum_case_decl +); + +#keyset[id, index] +enum_case_decl_elements( //dir=decl + int id: @enum_case_decl ref, + int index: int ref, + int element: @enum_element_decl_or_none ref +); + +extension_decls( //dir=decl + unique int id: @extension_decl, + int extended_type_decl: @nominal_type_decl_or_none ref +); + +#keyset[id, index] +extension_decl_protocols( //dir=decl + int id: @extension_decl ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +if_config_decls( //dir=decl + unique int id: @if_config_decl +); + +#keyset[id, index] +if_config_decl_active_elements( //dir=decl + int id: @if_config_decl ref, + int index: int ref, + int active_element: @ast_node_or_none ref +); + +import_decls( //dir=decl + unique int id: @import_decl +); + +#keyset[id] +import_decl_is_exported( //dir=decl + int id: @import_decl ref +); + +#keyset[id] +import_decl_imported_modules( //dir=decl + int id: @import_decl ref, + int imported_module: @module_decl_or_none ref +); + +#keyset[id, index] +import_decl_declarations( //dir=decl + int id: @import_decl ref, + int index: int ref, + int declaration: @value_decl_or_none ref +); + +missing_member_decls( //dir=decl + unique int id: @missing_member_decl, + string name: string ref +); + +@operator_decl = + @infix_operator_decl +| @postfix_operator_decl +| @prefix_operator_decl +; + +#keyset[id] +operator_decls( //dir=decl + int id: @operator_decl ref, + string name: string ref +); + +pattern_binding_decls( //dir=decl + unique int id: @pattern_binding_decl +); + +#keyset[id, index] +pattern_binding_decl_inits( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int init: @expr_or_none ref +); + +#keyset[id, index] +pattern_binding_decl_patterns( //dir=decl + int id: @pattern_binding_decl ref, + int index: int ref, + int pattern: @pattern_or_none ref +); + +pound_diagnostic_decls( //dir=decl + unique int id: @pound_diagnostic_decl, + int kind: int ref, + int message: @string_literal_expr_or_none ref +); + +precedence_group_decls( //dir=decl + unique int id: @precedence_group_decl +); + +top_level_code_decls( //dir=decl + unique int id: @top_level_code_decl, + int body: @brace_stmt_or_none ref +); + +@value_decl = + @abstract_function_decl +| @abstract_storage_decl +| @enum_element_decl +| @type_decl +; + +#keyset[id] +value_decls( //dir=decl + int id: @value_decl ref, + int interface_type: @type_or_none ref +); + +@abstract_function_decl = + @constructor_decl +| @destructor_decl +| @func_decl +; + +@abstract_storage_decl = + @subscript_decl +| @var_decl +; + +#keyset[id, index] +abstract_storage_decl_accessor_decls( //dir=decl + int id: @abstract_storage_decl ref, + int index: int ref, + int accessor_decl: @accessor_decl_or_none ref +); + +enum_element_decls( //dir=decl + unique int id: @enum_element_decl, + string name: string ref +); + +#keyset[id, index] +enum_element_decl_params( //dir=decl + int id: @enum_element_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +infix_operator_decls( //dir=decl + unique int id: @infix_operator_decl +); + +#keyset[id] +infix_operator_decl_precedence_groups( //dir=decl + int id: @infix_operator_decl ref, + int precedence_group: @precedence_group_decl_or_none ref +); + +postfix_operator_decls( //dir=decl + unique int id: @postfix_operator_decl +); + +prefix_operator_decls( //dir=decl + unique int id: @prefix_operator_decl +); + +@type_decl = + @abstract_type_param_decl +| @generic_type_decl +| @module_decl +; + +#keyset[id] +type_decls( //dir=decl + int id: @type_decl ref, + string name: string ref +); + +#keyset[id, index] +type_decl_base_types( //dir=decl + int id: @type_decl ref, + int index: int ref, + int base_type: @type_or_none ref +); + +@abstract_type_param_decl = + @associated_type_decl +| @generic_type_param_decl +; + +constructor_decls( //dir=decl + unique int id: @constructor_decl +); + +destructor_decls( //dir=decl + unique int id: @destructor_decl +); + +@func_decl = + @accessor_decl +| @concrete_func_decl +; + +@generic_type_decl = + @nominal_type_decl +| @opaque_type_decl +| @type_alias_decl +; + +module_decls( //dir=decl + unique int id: @module_decl +); + +#keyset[id] +module_decl_is_builtin_module( //dir=decl + int id: @module_decl ref +); + +#keyset[id] +module_decl_is_system_module( //dir=decl + int id: @module_decl ref +); + +module_decl_imported_modules( //dir=decl + int id: @module_decl ref, + int imported_module: @module_decl_or_none ref +); + +module_decl_exported_modules( //dir=decl + int id: @module_decl ref, + int exported_module: @module_decl_or_none ref +); + +subscript_decls( //dir=decl + unique int id: @subscript_decl, + int element_type: @type_or_none ref +); + +#keyset[id, index] +subscript_decl_params( //dir=decl + int id: @subscript_decl ref, + int index: int ref, + int param: @param_decl_or_none ref +); + +@var_decl = + @concrete_var_decl +| @param_decl +; + +#keyset[id] +var_decls( //dir=decl + int id: @var_decl ref, + string name: string ref, + int type_: @type_or_none ref +); + +#keyset[id] +var_decl_attached_property_wrapper_types( //dir=decl + int id: @var_decl ref, + int attached_property_wrapper_type: @type_or_none ref +); + +#keyset[id] +var_decl_parent_patterns( //dir=decl + int id: @var_decl ref, + int parent_pattern: @pattern_or_none ref +); + +#keyset[id] +var_decl_parent_initializers( //dir=decl + int id: @var_decl ref, + int parent_initializer: @expr_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_backing_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_backing_var: @var_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_var_bindings( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +var_decl_property_wrapper_projection_vars( //dir=decl + int id: @var_decl ref, + int property_wrapper_projection_var: @var_decl_or_none ref +); + +accessor_decls( //dir=decl + unique int id: @accessor_decl +); + +#keyset[id] +accessor_decl_is_getter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_setter( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_will_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_did_set( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_read( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_modify( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_address( //dir=decl + int id: @accessor_decl ref +); + +#keyset[id] +accessor_decl_is_unsafe_mutable_address( //dir=decl + int id: @accessor_decl ref +); + +associated_type_decls( //dir=decl + unique int id: @associated_type_decl +); + +concrete_func_decls( //dir=decl + unique int id: @concrete_func_decl +); + +concrete_var_decls( //dir=decl + unique int id: @concrete_var_decl, + int introducer_int: int ref +); + +generic_type_param_decls( //dir=decl + unique int id: @generic_type_param_decl +); + +@nominal_type_decl = + @class_decl +| @enum_decl +| @protocol_decl +| @struct_decl +; + +#keyset[id] +nominal_type_decls( //dir=decl + int id: @nominal_type_decl ref, + int type_: @type_or_none ref +); + +opaque_type_decls( //dir=decl + unique int id: @opaque_type_decl, + int naming_declaration: @value_decl_or_none ref +); + +#keyset[id, index] +opaque_type_decl_opaque_generic_params( //dir=decl + int id: @opaque_type_decl ref, + int index: int ref, + int opaque_generic_param: @generic_type_param_type_or_none ref +); + +param_decls( //dir=decl + unique int id: @param_decl +); + +#keyset[id] +param_decl_is_inout( //dir=decl + int id: @param_decl ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_var_bindings( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var_binding: @pattern_binding_decl_or_none ref +); + +#keyset[id] +param_decl_property_wrapper_local_wrapped_vars( //dir=decl + int id: @param_decl ref, + int property_wrapper_local_wrapped_var: @var_decl_or_none ref +); + +type_alias_decls( //dir=decl + unique int id: @type_alias_decl, + int aliased_type: @type_or_none ref +); + +class_decls( //dir=decl + unique int id: @class_decl +); + +enum_decls( //dir=decl + unique int id: @enum_decl +); + +protocol_decls( //dir=decl + unique int id: @protocol_decl +); + +struct_decls( //dir=decl + unique int id: @struct_decl +); + +arguments( //dir=expr + unique int id: @argument, + string label: string ref, + int expr: @expr_or_none ref +); + +@expr = + @abstract_closure_expr +| @any_try_expr +| @applied_property_wrapper_expr +| @apply_expr +| @assign_expr +| @bind_optional_expr +| @capture_list_expr +| @collection_expr +| @decl_ref_expr +| @default_argument_expr +| @discard_assignment_expr +| @dot_syntax_base_ignored_expr +| @dynamic_type_expr +| @enum_is_case_expr +| @error_expr +| @explicit_cast_expr +| @force_value_expr +| @identity_expr +| @if_expr +| @implicit_conversion_expr +| @in_out_expr +| @key_path_application_expr +| @key_path_dot_expr +| @key_path_expr +| @lazy_initializer_expr +| @literal_expr +| @lookup_expr +| @make_temporarily_escapable_expr +| @obj_c_selector_expr +| @one_way_expr +| @opaque_value_expr +| @open_existential_expr +| @optional_evaluation_expr +| @other_constructor_decl_ref_expr +| @overloaded_decl_ref_expr +| @property_wrapper_value_placeholder_expr +| @rebind_self_in_constructor_expr +| @sequence_expr +| @super_ref_expr +| @tap_expr +| @tuple_element_expr +| @tuple_expr +| @type_expr +| @unresolved_decl_ref_expr +| @unresolved_dot_expr +| @unresolved_member_expr +| @unresolved_pattern_expr +| @unresolved_specialize_expr +| @vararg_expansion_expr +; + +#keyset[id] +expr_types( //dir=expr + int id: @expr ref, + int type_: @type_or_none ref +); + +@abstract_closure_expr = + @auto_closure_expr +| @closure_expr +; + +@any_try_expr = + @force_try_expr +| @optional_try_expr +| @try_expr +; + +#keyset[id] +any_try_exprs( //dir=expr + int id: @any_try_expr ref, + int sub_expr: @expr_or_none ref +); + +applied_property_wrapper_exprs( //dir=expr + unique int id: @applied_property_wrapper_expr, + int kind: int ref, + int value: @expr_or_none ref, + int param: @param_decl_or_none ref +); + +@apply_expr = + @binary_expr +| @call_expr +| @postfix_unary_expr +| @prefix_unary_expr +| @self_apply_expr +; + +#keyset[id] +apply_exprs( //dir=expr + int id: @apply_expr ref, + int function: @expr_or_none ref +); + +#keyset[id, index] +apply_expr_arguments( //dir=expr + int id: @apply_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +assign_exprs( //dir=expr + unique int id: @assign_expr, + int dest: @expr_or_none ref, + int source: @expr_or_none ref +); + +bind_optional_exprs( //dir=expr + unique int id: @bind_optional_expr, + int sub_expr: @expr_or_none ref +); + +capture_list_exprs( //dir=expr + unique int id: @capture_list_expr, + int closure_body: @closure_expr_or_none ref +); + +#keyset[id, index] +capture_list_expr_binding_decls( //dir=expr + int id: @capture_list_expr ref, + int index: int ref, + int binding_decl: @pattern_binding_decl_or_none ref +); + +@collection_expr = + @array_expr +| @dictionary_expr +; + +decl_ref_exprs( //dir=expr + unique int id: @decl_ref_expr, + int decl: @decl_or_none ref +); + +#keyset[id, index] +decl_ref_expr_replacement_types( //dir=expr + int id: @decl_ref_expr ref, + int index: int ref, + int replacement_type: @type_or_none ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_ordinary_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +#keyset[id] +decl_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @decl_ref_expr ref +); + +default_argument_exprs( //dir=expr + unique int id: @default_argument_expr, + int param_decl: @param_decl_or_none ref, + int param_index: int ref +); + +#keyset[id] +default_argument_expr_caller_side_defaults( //dir=expr + int id: @default_argument_expr ref, + int caller_side_default: @expr_or_none ref +); + +discard_assignment_exprs( //dir=expr + unique int id: @discard_assignment_expr +); + +dot_syntax_base_ignored_exprs( //dir=expr + unique int id: @dot_syntax_base_ignored_expr, + int qualifier: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +dynamic_type_exprs( //dir=expr + unique int id: @dynamic_type_expr, + int base: @expr_or_none ref +); + +enum_is_case_exprs( //dir=expr + unique int id: @enum_is_case_expr, + int sub_expr: @expr_or_none ref, + int element: @enum_element_decl_or_none ref +); + +error_exprs( //dir=expr + unique int id: @error_expr +); + +@explicit_cast_expr = + @checked_cast_expr +| @coerce_expr +; + +#keyset[id] +explicit_cast_exprs( //dir=expr + int id: @explicit_cast_expr ref, + int sub_expr: @expr_or_none ref +); + +force_value_exprs( //dir=expr + unique int id: @force_value_expr, + int sub_expr: @expr_or_none ref +); + +@identity_expr = + @await_expr +| @dot_self_expr +| @paren_expr +| @unresolved_member_chain_result_expr +; + +#keyset[id] +identity_exprs( //dir=expr + int id: @identity_expr ref, + int sub_expr: @expr_or_none ref +); + +if_exprs( //dir=expr + unique int id: @if_expr, + int condition: @expr_or_none ref, + int then_expr: @expr_or_none ref, + int else_expr: @expr_or_none ref +); + +@implicit_conversion_expr = + @abi_safe_conversion_expr +| @any_hashable_erasure_expr +| @archetype_to_super_expr +| @array_to_pointer_expr +| @bridge_from_obj_c_expr +| @bridge_to_obj_c_expr +| @class_metatype_to_object_expr +| @collection_upcast_conversion_expr +| @conditional_bridge_from_obj_c_expr +| @covariant_function_conversion_expr +| @covariant_return_conversion_expr +| @derived_to_base_expr +| @destructure_tuple_expr +| @differentiable_function_expr +| @differentiable_function_extract_original_expr +| @erasure_expr +| @existential_metatype_to_object_expr +| @foreign_object_conversion_expr +| @function_conversion_expr +| @in_out_to_pointer_expr +| @inject_into_optional_expr +| @linear_function_expr +| @linear_function_extract_original_expr +| @linear_to_differentiable_function_expr +| @load_expr +| @metatype_conversion_expr +| @pointer_to_pointer_expr +| @protocol_metatype_to_object_expr +| @string_to_pointer_expr +| @underlying_to_opaque_expr +| @unevaluated_instance_expr +| @unresolved_type_conversion_expr +; + +#keyset[id] +implicit_conversion_exprs( //dir=expr + int id: @implicit_conversion_expr ref, + int sub_expr: @expr_or_none ref +); + +in_out_exprs( //dir=expr + unique int id: @in_out_expr, + int sub_expr: @expr_or_none ref +); + +key_path_application_exprs( //dir=expr + unique int id: @key_path_application_expr, + int base: @expr_or_none ref, + int key_path: @expr_or_none ref +); + +key_path_dot_exprs( //dir=expr + unique int id: @key_path_dot_expr +); + +key_path_exprs( //dir=expr + unique int id: @key_path_expr +); + +#keyset[id] +key_path_expr_roots( //dir=expr + int id: @key_path_expr ref, + int root: @type_repr_or_none ref +); + +#keyset[id] +key_path_expr_parsed_paths( //dir=expr + int id: @key_path_expr ref, + int parsed_path: @expr_or_none ref +); + +lazy_initializer_exprs( //dir=expr + unique int id: @lazy_initializer_expr, + int sub_expr: @expr_or_none ref +); + +@literal_expr = + @builtin_literal_expr +| @interpolated_string_literal_expr +| @nil_literal_expr +| @object_literal_expr +| @regex_literal_expr +; + +@lookup_expr = + @dynamic_lookup_expr +| @member_ref_expr +| @subscript_expr +; + +#keyset[id] +lookup_exprs( //dir=expr + int id: @lookup_expr ref, + int base: @expr_or_none ref +); + +#keyset[id] +lookup_expr_members( //dir=expr + int id: @lookup_expr ref, + int member: @decl_or_none ref +); + +make_temporarily_escapable_exprs( //dir=expr + unique int id: @make_temporarily_escapable_expr, + int escaping_closure: @opaque_value_expr_or_none ref, + int nonescaping_closure: @expr_or_none ref, + int sub_expr: @expr_or_none ref +); + +obj_c_selector_exprs( //dir=expr + unique int id: @obj_c_selector_expr, + int sub_expr: @expr_or_none ref, + int method: @abstract_function_decl_or_none ref +); + +one_way_exprs( //dir=expr + unique int id: @one_way_expr, + int sub_expr: @expr_or_none ref +); + +opaque_value_exprs( //dir=expr + unique int id: @opaque_value_expr +); + +open_existential_exprs( //dir=expr + unique int id: @open_existential_expr, + int sub_expr: @expr_or_none ref, + int existential: @expr_or_none ref, + int opaque_expr: @opaque_value_expr_or_none ref +); + +optional_evaluation_exprs( //dir=expr + unique int id: @optional_evaluation_expr, + int sub_expr: @expr_or_none ref +); + +other_constructor_decl_ref_exprs( //dir=expr + unique int id: @other_constructor_decl_ref_expr, + int constructor_decl: @constructor_decl_or_none ref +); + +overloaded_decl_ref_exprs( //dir=expr + unique int id: @overloaded_decl_ref_expr +); + +#keyset[id, index] +overloaded_decl_ref_expr_possible_declarations( //dir=expr + int id: @overloaded_decl_ref_expr ref, + int index: int ref, + int possible_declaration: @value_decl_or_none ref +); + +property_wrapper_value_placeholder_exprs( //dir=expr + unique int id: @property_wrapper_value_placeholder_expr, + int placeholder: @opaque_value_expr_or_none ref +); + +#keyset[id] +property_wrapper_value_placeholder_expr_wrapped_values( //dir=expr + int id: @property_wrapper_value_placeholder_expr ref, + int wrapped_value: @expr_or_none ref +); + +rebind_self_in_constructor_exprs( //dir=expr + unique int id: @rebind_self_in_constructor_expr, + int sub_expr: @expr_or_none ref, + int self: @var_decl_or_none ref +); + +sequence_exprs( //dir=expr + unique int id: @sequence_expr +); + +#keyset[id, index] +sequence_expr_elements( //dir=expr + int id: @sequence_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +super_ref_exprs( //dir=expr + unique int id: @super_ref_expr, + int self: @var_decl_or_none ref +); + +tap_exprs( //dir=expr + unique int id: @tap_expr, + int body: @brace_stmt_or_none ref, + int var: @var_decl_or_none ref +); + +#keyset[id] +tap_expr_sub_exprs( //dir=expr + int id: @tap_expr ref, + int sub_expr: @expr_or_none ref +); + +tuple_element_exprs( //dir=expr + unique int id: @tuple_element_expr, + int sub_expr: @expr_or_none ref, + int index: int ref +); + +tuple_exprs( //dir=expr + unique int id: @tuple_expr +); + +#keyset[id, index] +tuple_expr_elements( //dir=expr + int id: @tuple_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +type_exprs( //dir=expr + unique int id: @type_expr +); + +#keyset[id] +type_expr_type_reprs( //dir=expr + int id: @type_expr ref, + int type_repr: @type_repr_or_none ref +); + +unresolved_decl_ref_exprs( //dir=expr + unique int id: @unresolved_decl_ref_expr +); + +#keyset[id] +unresolved_decl_ref_expr_names( //dir=expr + int id: @unresolved_decl_ref_expr ref, + string name: string ref +); + +unresolved_dot_exprs( //dir=expr + unique int id: @unresolved_dot_expr, + int base: @expr_or_none ref, + string name: string ref +); + +unresolved_member_exprs( //dir=expr + unique int id: @unresolved_member_expr, + string name: string ref +); + +unresolved_pattern_exprs( //dir=expr + unique int id: @unresolved_pattern_expr, + int sub_pattern: @pattern_or_none ref +); + +unresolved_specialize_exprs( //dir=expr + unique int id: @unresolved_specialize_expr, + int sub_expr: @expr_or_none ref +); + +vararg_expansion_exprs( //dir=expr + unique int id: @vararg_expansion_expr, + int sub_expr: @expr_or_none ref +); + +abi_safe_conversion_exprs( //dir=expr + unique int id: @abi_safe_conversion_expr +); + +any_hashable_erasure_exprs( //dir=expr + unique int id: @any_hashable_erasure_expr +); + +archetype_to_super_exprs( //dir=expr + unique int id: @archetype_to_super_expr +); + +array_exprs( //dir=expr + unique int id: @array_expr +); + +#keyset[id, index] +array_expr_elements( //dir=expr + int id: @array_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +array_to_pointer_exprs( //dir=expr + unique int id: @array_to_pointer_expr +); + +auto_closure_exprs( //dir=expr + unique int id: @auto_closure_expr +); + +await_exprs( //dir=expr + unique int id: @await_expr +); + +binary_exprs( //dir=expr + unique int id: @binary_expr +); + +bridge_from_obj_c_exprs( //dir=expr + unique int id: @bridge_from_obj_c_expr +); + +bridge_to_obj_c_exprs( //dir=expr + unique int id: @bridge_to_obj_c_expr +); + +@builtin_literal_expr = + @boolean_literal_expr +| @magic_identifier_literal_expr +| @number_literal_expr +| @string_literal_expr +; + +call_exprs( //dir=expr + unique int id: @call_expr +); + +@checked_cast_expr = + @conditional_checked_cast_expr +| @forced_checked_cast_expr +| @is_expr +; + +class_metatype_to_object_exprs( //dir=expr + unique int id: @class_metatype_to_object_expr +); + +closure_exprs( //dir=expr + unique int id: @closure_expr +); + +coerce_exprs( //dir=expr + unique int id: @coerce_expr +); + +collection_upcast_conversion_exprs( //dir=expr + unique int id: @collection_upcast_conversion_expr +); + +conditional_bridge_from_obj_c_exprs( //dir=expr + unique int id: @conditional_bridge_from_obj_c_expr +); + +covariant_function_conversion_exprs( //dir=expr + unique int id: @covariant_function_conversion_expr +); + +covariant_return_conversion_exprs( //dir=expr + unique int id: @covariant_return_conversion_expr +); + +derived_to_base_exprs( //dir=expr + unique int id: @derived_to_base_expr +); + +destructure_tuple_exprs( //dir=expr + unique int id: @destructure_tuple_expr +); + +dictionary_exprs( //dir=expr + unique int id: @dictionary_expr +); + +#keyset[id, index] +dictionary_expr_elements( //dir=expr + int id: @dictionary_expr ref, + int index: int ref, + int element: @expr_or_none ref +); + +differentiable_function_exprs( //dir=expr + unique int id: @differentiable_function_expr +); + +differentiable_function_extract_original_exprs( //dir=expr + unique int id: @differentiable_function_extract_original_expr +); + +dot_self_exprs( //dir=expr + unique int id: @dot_self_expr +); + +@dynamic_lookup_expr = + @dynamic_member_ref_expr +| @dynamic_subscript_expr +; + +erasure_exprs( //dir=expr + unique int id: @erasure_expr +); + +existential_metatype_to_object_exprs( //dir=expr + unique int id: @existential_metatype_to_object_expr +); + +force_try_exprs( //dir=expr + unique int id: @force_try_expr +); + +foreign_object_conversion_exprs( //dir=expr + unique int id: @foreign_object_conversion_expr +); + +function_conversion_exprs( //dir=expr + unique int id: @function_conversion_expr +); + +in_out_to_pointer_exprs( //dir=expr + unique int id: @in_out_to_pointer_expr +); + +inject_into_optional_exprs( //dir=expr + unique int id: @inject_into_optional_expr +); + +interpolated_string_literal_exprs( //dir=expr + unique int id: @interpolated_string_literal_expr +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_expr: @opaque_value_expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_interpolation_count_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int interpolation_count_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_literal_capacity_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int literal_capacity_expr: @expr_or_none ref +); + +#keyset[id] +interpolated_string_literal_expr_appending_exprs( //dir=expr + int id: @interpolated_string_literal_expr ref, + int appending_expr: @tap_expr_or_none ref +); + +linear_function_exprs( //dir=expr + unique int id: @linear_function_expr +); + +linear_function_extract_original_exprs( //dir=expr + unique int id: @linear_function_extract_original_expr +); + +linear_to_differentiable_function_exprs( //dir=expr + unique int id: @linear_to_differentiable_function_expr +); + +load_exprs( //dir=expr + unique int id: @load_expr +); + +member_ref_exprs( //dir=expr + unique int id: @member_ref_expr +); + +#keyset[id] +member_ref_expr_has_direct_to_storage_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_ordinary_semantics( //dir=expr + int id: @member_ref_expr ref +); + +#keyset[id] +member_ref_expr_has_distributed_thunk_semantics( //dir=expr + int id: @member_ref_expr ref +); + +metatype_conversion_exprs( //dir=expr + unique int id: @metatype_conversion_expr +); + +nil_literal_exprs( //dir=expr + unique int id: @nil_literal_expr +); + +object_literal_exprs( //dir=expr + unique int id: @object_literal_expr, + int kind: int ref +); + +#keyset[id, index] +object_literal_expr_arguments( //dir=expr + int id: @object_literal_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +optional_try_exprs( //dir=expr + unique int id: @optional_try_expr +); + +paren_exprs( //dir=expr + unique int id: @paren_expr +); + +pointer_to_pointer_exprs( //dir=expr + unique int id: @pointer_to_pointer_expr +); + +postfix_unary_exprs( //dir=expr + unique int id: @postfix_unary_expr +); + +prefix_unary_exprs( //dir=expr + unique int id: @prefix_unary_expr +); + +protocol_metatype_to_object_exprs( //dir=expr + unique int id: @protocol_metatype_to_object_expr +); + +regex_literal_exprs( //dir=expr + unique int id: @regex_literal_expr, + string pattern: string ref, + int version: int ref +); + +@self_apply_expr = + @constructor_ref_call_expr +| @dot_syntax_call_expr +; + +#keyset[id] +self_apply_exprs( //dir=expr + int id: @self_apply_expr ref, + int base: @expr_or_none ref +); + +string_to_pointer_exprs( //dir=expr + unique int id: @string_to_pointer_expr +); + +subscript_exprs( //dir=expr + unique int id: @subscript_expr +); + +#keyset[id, index] +subscript_expr_arguments( //dir=expr + int id: @subscript_expr ref, + int index: int ref, + int argument: @argument_or_none ref +); + +#keyset[id] +subscript_expr_has_direct_to_storage_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_direct_to_implementation_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_ordinary_semantics( //dir=expr + int id: @subscript_expr ref +); + +#keyset[id] +subscript_expr_has_distributed_thunk_semantics( //dir=expr + int id: @subscript_expr ref +); + +try_exprs( //dir=expr + unique int id: @try_expr +); + +underlying_to_opaque_exprs( //dir=expr + unique int id: @underlying_to_opaque_expr +); + +unevaluated_instance_exprs( //dir=expr + unique int id: @unevaluated_instance_expr +); + +unresolved_member_chain_result_exprs( //dir=expr + unique int id: @unresolved_member_chain_result_expr +); + +unresolved_type_conversion_exprs( //dir=expr + unique int id: @unresolved_type_conversion_expr +); + +boolean_literal_exprs( //dir=expr + unique int id: @boolean_literal_expr, + boolean value: boolean ref +); + +conditional_checked_cast_exprs( //dir=expr + unique int id: @conditional_checked_cast_expr +); + +constructor_ref_call_exprs( //dir=expr + unique int id: @constructor_ref_call_expr +); + +dot_syntax_call_exprs( //dir=expr + unique int id: @dot_syntax_call_expr +); + +dynamic_member_ref_exprs( //dir=expr + unique int id: @dynamic_member_ref_expr +); + +dynamic_subscript_exprs( //dir=expr + unique int id: @dynamic_subscript_expr +); + +forced_checked_cast_exprs( //dir=expr + unique int id: @forced_checked_cast_expr +); + +is_exprs( //dir=expr + unique int id: @is_expr +); + +magic_identifier_literal_exprs( //dir=expr + unique int id: @magic_identifier_literal_expr, + string kind: string ref +); + +@number_literal_expr = + @float_literal_expr +| @integer_literal_expr +; + +string_literal_exprs( //dir=expr + unique int id: @string_literal_expr, + string value: string ref +); + +float_literal_exprs( //dir=expr + unique int id: @float_literal_expr, + string string_value: string ref +); + +integer_literal_exprs( //dir=expr + unique int id: @integer_literal_expr, + string string_value: string ref +); + +@pattern = + @any_pattern +| @binding_pattern +| @bool_pattern +| @enum_element_pattern +| @expr_pattern +| @is_pattern +| @named_pattern +| @optional_some_pattern +| @paren_pattern +| @tuple_pattern +| @typed_pattern +; + +any_patterns( //dir=pattern + unique int id: @any_pattern +); + +binding_patterns( //dir=pattern + unique int id: @binding_pattern, + int sub_pattern: @pattern_or_none ref +); + +bool_patterns( //dir=pattern + unique int id: @bool_pattern, + boolean value: boolean ref +); + +enum_element_patterns( //dir=pattern + unique int id: @enum_element_pattern, + int element: @enum_element_decl_or_none ref +); + +#keyset[id] +enum_element_pattern_sub_patterns( //dir=pattern + int id: @enum_element_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +expr_patterns( //dir=pattern + unique int id: @expr_pattern, + int sub_expr: @expr_or_none ref +); + +is_patterns( //dir=pattern + unique int id: @is_pattern +); + +#keyset[id] +is_pattern_cast_type_reprs( //dir=pattern + int id: @is_pattern ref, + int cast_type_repr: @type_repr_or_none ref +); + +#keyset[id] +is_pattern_sub_patterns( //dir=pattern + int id: @is_pattern ref, + int sub_pattern: @pattern_or_none ref +); + +named_patterns( //dir=pattern + unique int id: @named_pattern, + string name: string ref +); + +optional_some_patterns( //dir=pattern + unique int id: @optional_some_pattern, + int sub_pattern: @pattern_or_none ref +); + +paren_patterns( //dir=pattern + unique int id: @paren_pattern, + int sub_pattern: @pattern_or_none ref +); + +tuple_patterns( //dir=pattern + unique int id: @tuple_pattern +); + +#keyset[id, index] +tuple_pattern_elements( //dir=pattern + int id: @tuple_pattern ref, + int index: int ref, + int element: @pattern_or_none ref +); + +typed_patterns( //dir=pattern + unique int id: @typed_pattern, + int sub_pattern: @pattern_or_none ref +); + +#keyset[id] +typed_pattern_type_reprs( //dir=pattern + int id: @typed_pattern ref, + int type_repr: @type_repr_or_none ref +); + +case_label_items( //dir=stmt + unique int id: @case_label_item, + int pattern: @pattern_or_none ref +); + +#keyset[id] +case_label_item_guards( //dir=stmt + int id: @case_label_item ref, + int guard: @expr_or_none ref +); + +condition_elements( //dir=stmt + unique int id: @condition_element +); + +#keyset[id] +condition_element_booleans( //dir=stmt + int id: @condition_element ref, + int boolean_: @expr_or_none ref +); + +#keyset[id] +condition_element_patterns( //dir=stmt + int id: @condition_element ref, + int pattern: @pattern_or_none ref +); + +#keyset[id] +condition_element_initializers( //dir=stmt + int id: @condition_element ref, + int initializer: @expr_or_none ref +); + +#keyset[id] +condition_element_availabilities( //dir=stmt + int id: @condition_element ref, + int availability: @availability_info_or_none ref +); + +@stmt = + @brace_stmt +| @break_stmt +| @case_stmt +| @continue_stmt +| @defer_stmt +| @fail_stmt +| @fallthrough_stmt +| @labeled_stmt +| @pound_assert_stmt +| @return_stmt +| @throw_stmt +| @yield_stmt +; + +stmt_conditions( //dir=stmt + unique int id: @stmt_condition +); + +#keyset[id, index] +stmt_condition_elements( //dir=stmt + int id: @stmt_condition ref, + int index: int ref, + int element: @condition_element_or_none ref +); + +brace_stmts( //dir=stmt + unique int id: @brace_stmt +); + +#keyset[id, index] +brace_stmt_elements( //dir=stmt + int id: @brace_stmt ref, + int index: int ref, + int element: @ast_node_or_none ref +); + +break_stmts( //dir=stmt + unique int id: @break_stmt +); + +#keyset[id] +break_stmt_target_names( //dir=stmt + int id: @break_stmt ref, + string target_name: string ref +); + +#keyset[id] +break_stmt_targets( //dir=stmt + int id: @break_stmt ref, + int target: @stmt_or_none ref +); + +case_stmts( //dir=stmt + unique int id: @case_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +case_stmt_labels( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int label: @case_label_item_or_none ref +); + +#keyset[id, index] +case_stmt_variables( //dir=stmt + int id: @case_stmt ref, + int index: int ref, + int variable: @var_decl_or_none ref +); + +continue_stmts( //dir=stmt + unique int id: @continue_stmt +); + +#keyset[id] +continue_stmt_target_names( //dir=stmt + int id: @continue_stmt ref, + string target_name: string ref +); + +#keyset[id] +continue_stmt_targets( //dir=stmt + int id: @continue_stmt ref, + int target: @stmt_or_none ref +); + +defer_stmts( //dir=stmt + unique int id: @defer_stmt, + int body: @brace_stmt_or_none ref +); + +fail_stmts( //dir=stmt + unique int id: @fail_stmt +); + +fallthrough_stmts( //dir=stmt + unique int id: @fallthrough_stmt, + int fallthrough_source: @case_stmt_or_none ref, + int fallthrough_dest: @case_stmt_or_none ref +); + +@labeled_stmt = + @do_catch_stmt +| @do_stmt +| @for_each_stmt +| @labeled_conditional_stmt +| @repeat_while_stmt +| @switch_stmt +; + +#keyset[id] +labeled_stmt_labels( //dir=stmt + int id: @labeled_stmt ref, + string label: string ref +); + +pound_assert_stmts( //dir=stmt + unique int id: @pound_assert_stmt, + int condition: @expr_or_none ref, + string message: string ref +); + +return_stmts( //dir=stmt + unique int id: @return_stmt +); + +#keyset[id] +return_stmt_results( //dir=stmt + int id: @return_stmt ref, + int result: @expr_or_none ref +); + +throw_stmts( //dir=stmt + unique int id: @throw_stmt, + int sub_expr: @expr_or_none ref +); + +yield_stmts( //dir=stmt + unique int id: @yield_stmt +); + +#keyset[id, index] +yield_stmt_results( //dir=stmt + int id: @yield_stmt ref, + int index: int ref, + int result: @expr_or_none ref +); + +do_catch_stmts( //dir=stmt + unique int id: @do_catch_stmt, + int body: @stmt_or_none ref +); + +#keyset[id, index] +do_catch_stmt_catches( //dir=stmt + int id: @do_catch_stmt ref, + int index: int ref, + int catch: @case_stmt_or_none ref +); + +do_stmts( //dir=stmt + unique int id: @do_stmt, + int body: @brace_stmt_or_none ref +); + +for_each_stmts( //dir=stmt + unique int id: @for_each_stmt, + int pattern: @pattern_or_none ref, + int sequence: @expr_or_none ref, + int body: @brace_stmt_or_none ref +); + +#keyset[id] +for_each_stmt_wheres( //dir=stmt + int id: @for_each_stmt ref, + int where: @expr_or_none ref +); + +@labeled_conditional_stmt = + @guard_stmt +| @if_stmt +| @while_stmt +; + +#keyset[id] +labeled_conditional_stmts( //dir=stmt + int id: @labeled_conditional_stmt ref, + int condition: @stmt_condition_or_none ref +); + +repeat_while_stmts( //dir=stmt + unique int id: @repeat_while_stmt, + int condition: @expr_or_none ref, + int body: @stmt_or_none ref +); + +switch_stmts( //dir=stmt + unique int id: @switch_stmt, + int expr: @expr_or_none ref +); + +#keyset[id, index] +switch_stmt_cases( //dir=stmt + int id: @switch_stmt ref, + int index: int ref, + int case_: @case_stmt_or_none ref +); + +guard_stmts( //dir=stmt + unique int id: @guard_stmt, + int body: @brace_stmt_or_none ref +); + +if_stmts( //dir=stmt + unique int id: @if_stmt, + int then: @stmt_or_none ref +); + +#keyset[id] +if_stmt_elses( //dir=stmt + int id: @if_stmt ref, + int else: @stmt_or_none ref +); + +while_stmts( //dir=stmt + unique int id: @while_stmt, + int body: @stmt_or_none ref +); + +@type = + @any_function_type +| @any_generic_type +| @any_metatype_type +| @builtin_type +| @dependent_member_type +| @dynamic_self_type +| @error_type +| @existential_type +| @in_out_type +| @l_value_type +| @module_type +| @parameterized_protocol_type +| @protocol_composition_type +| @reference_storage_type +| @substitutable_type +| @sugar_type +| @tuple_type +| @unresolved_type +; + +#keyset[id] +types( //dir=type + int id: @type ref, + string name: string ref, + int canonical_type: @type_or_none ref +); + +type_reprs( //dir=type + unique int id: @type_repr, + int type_: @type_or_none ref +); + +@any_function_type = + @function_type +| @generic_function_type +; + +#keyset[id] +any_function_types( //dir=type + int id: @any_function_type ref, + int result: @type_or_none ref +); + +#keyset[id, index] +any_function_type_param_types( //dir=type + int id: @any_function_type ref, + int index: int ref, + int param_type: @type_or_none ref +); + +#keyset[id] +any_function_type_is_throwing( //dir=type + int id: @any_function_type ref +); + +#keyset[id] +any_function_type_is_async( //dir=type + int id: @any_function_type ref +); + +@any_generic_type = + @nominal_or_bound_generic_nominal_type +| @unbound_generic_type +; + +#keyset[id] +any_generic_types( //dir=type + int id: @any_generic_type ref, + int declaration: @generic_type_decl_or_none ref +); + +#keyset[id] +any_generic_type_parents( //dir=type + int id: @any_generic_type ref, + int parent: @type_or_none ref +); + +@any_metatype_type = + @existential_metatype_type +| @metatype_type +; + +@builtin_type = + @any_builtin_integer_type +| @builtin_bridge_object_type +| @builtin_default_actor_storage_type +| @builtin_executor_type +| @builtin_float_type +| @builtin_job_type +| @builtin_native_object_type +| @builtin_raw_pointer_type +| @builtin_raw_unsafe_continuation_type +| @builtin_unsafe_value_buffer_type +| @builtin_vector_type +; + +dependent_member_types( //dir=type + unique int id: @dependent_member_type, + int base_type: @type_or_none ref, + int associated_type_decl: @associated_type_decl_or_none ref +); + +dynamic_self_types( //dir=type + unique int id: @dynamic_self_type, + int static_self_type: @type_or_none ref +); + +error_types( //dir=type + unique int id: @error_type +); + +existential_types( //dir=type + unique int id: @existential_type, + int constraint: @type_or_none ref +); + +in_out_types( //dir=type + unique int id: @in_out_type, + int object_type: @type_or_none ref +); + +l_value_types( //dir=type + unique int id: @l_value_type, + int object_type: @type_or_none ref +); + +module_types( //dir=type + unique int id: @module_type, + int module: @module_decl_or_none ref +); + +parameterized_protocol_types( //dir=type + unique int id: @parameterized_protocol_type, + int base: @protocol_type_or_none ref +); + +#keyset[id, index] +parameterized_protocol_type_args( //dir=type + int id: @parameterized_protocol_type ref, + int index: int ref, + int arg: @type_or_none ref +); + +protocol_composition_types( //dir=type + unique int id: @protocol_composition_type +); + +#keyset[id, index] +protocol_composition_type_members( //dir=type + int id: @protocol_composition_type ref, + int index: int ref, + int member: @type_or_none ref +); + +@reference_storage_type = + @unmanaged_storage_type +| @unowned_storage_type +| @weak_storage_type +; + +#keyset[id] +reference_storage_types( //dir=type + int id: @reference_storage_type ref, + int referent_type: @type_or_none ref +); + +@substitutable_type = + @archetype_type +| @generic_type_param_type +; + +@sugar_type = + @paren_type +| @syntax_sugar_type +| @type_alias_type +; + +tuple_types( //dir=type + unique int id: @tuple_type +); + +#keyset[id, index] +tuple_type_types( //dir=type + int id: @tuple_type ref, + int index: int ref, + int type_: @type_or_none ref +); + +#keyset[id, index] +tuple_type_names( //dir=type + int id: @tuple_type ref, + int index: int ref, + string name: string ref +); + +unresolved_types( //dir=type + unique int id: @unresolved_type +); + +@any_builtin_integer_type = + @builtin_integer_literal_type +| @builtin_integer_type +; + +@archetype_type = + @opaque_type_archetype_type +| @opened_archetype_type +| @primary_archetype_type +; + +#keyset[id] +archetype_types( //dir=type + int id: @archetype_type ref, + int interface_type: @type_or_none ref +); + +#keyset[id] +archetype_type_superclasses( //dir=type + int id: @archetype_type ref, + int superclass: @type_or_none ref +); + +#keyset[id, index] +archetype_type_protocols( //dir=type + int id: @archetype_type ref, + int index: int ref, + int protocol: @protocol_decl_or_none ref +); + +builtin_bridge_object_types( //dir=type + unique int id: @builtin_bridge_object_type +); + +builtin_default_actor_storage_types( //dir=type + unique int id: @builtin_default_actor_storage_type +); + +builtin_executor_types( //dir=type + unique int id: @builtin_executor_type +); + +builtin_float_types( //dir=type + unique int id: @builtin_float_type +); + +builtin_job_types( //dir=type + unique int id: @builtin_job_type +); + +builtin_native_object_types( //dir=type + unique int id: @builtin_native_object_type +); + +builtin_raw_pointer_types( //dir=type + unique int id: @builtin_raw_pointer_type +); + +builtin_raw_unsafe_continuation_types( //dir=type + unique int id: @builtin_raw_unsafe_continuation_type +); + +builtin_unsafe_value_buffer_types( //dir=type + unique int id: @builtin_unsafe_value_buffer_type +); + +builtin_vector_types( //dir=type + unique int id: @builtin_vector_type +); + +existential_metatype_types( //dir=type + unique int id: @existential_metatype_type +); + +function_types( //dir=type + unique int id: @function_type +); + +generic_function_types( //dir=type + unique int id: @generic_function_type +); + +#keyset[id, index] +generic_function_type_generic_params( //dir=type + int id: @generic_function_type ref, + int index: int ref, + int generic_param: @generic_type_param_type_or_none ref +); + +generic_type_param_types( //dir=type + unique int id: @generic_type_param_type +); + +metatype_types( //dir=type + unique int id: @metatype_type +); + +@nominal_or_bound_generic_nominal_type = + @bound_generic_type +| @nominal_type +; + +paren_types( //dir=type + unique int id: @paren_type, + int type_: @type_or_none ref +); + +@syntax_sugar_type = + @dictionary_type +| @unary_syntax_sugar_type +; + +type_alias_types( //dir=type + unique int id: @type_alias_type, + int decl: @type_alias_decl_or_none ref +); + +unbound_generic_types( //dir=type + unique int id: @unbound_generic_type +); + +unmanaged_storage_types( //dir=type + unique int id: @unmanaged_storage_type +); + +unowned_storage_types( //dir=type + unique int id: @unowned_storage_type +); + +weak_storage_types( //dir=type + unique int id: @weak_storage_type +); + +@bound_generic_type = + @bound_generic_class_type +| @bound_generic_enum_type +| @bound_generic_struct_type +; + +#keyset[id, index] +bound_generic_type_arg_types( //dir=type + int id: @bound_generic_type ref, + int index: int ref, + int arg_type: @type_or_none ref +); + +builtin_integer_literal_types( //dir=type + unique int id: @builtin_integer_literal_type +); + +builtin_integer_types( //dir=type + unique int id: @builtin_integer_type +); + +#keyset[id] +builtin_integer_type_widths( //dir=type + int id: @builtin_integer_type ref, + int width: int ref +); + +dictionary_types( //dir=type + unique int id: @dictionary_type, + int key_type: @type_or_none ref, + int value_type: @type_or_none ref +); + +@nominal_type = + @class_type +| @enum_type +| @protocol_type +| @struct_type +; + +opaque_type_archetype_types( //dir=type + unique int id: @opaque_type_archetype_type, + int declaration: @opaque_type_decl_or_none ref +); + +opened_archetype_types( //dir=type + unique int id: @opened_archetype_type +); + +primary_archetype_types( //dir=type + unique int id: @primary_archetype_type +); + +@unary_syntax_sugar_type = + @array_slice_type +| @optional_type +| @variadic_sequence_type +; + +#keyset[id] +unary_syntax_sugar_types( //dir=type + int id: @unary_syntax_sugar_type ref, + int base_type: @type_or_none ref +); + +array_slice_types( //dir=type + unique int id: @array_slice_type +); + +bound_generic_class_types( //dir=type + unique int id: @bound_generic_class_type +); + +bound_generic_enum_types( //dir=type + unique int id: @bound_generic_enum_type +); + +bound_generic_struct_types( //dir=type + unique int id: @bound_generic_struct_type +); + +class_types( //dir=type + unique int id: @class_type +); + +enum_types( //dir=type + unique int id: @enum_type +); + +optional_types( //dir=type + unique int id: @optional_type +); + +protocol_types( //dir=type + unique int id: @protocol_type +); + +struct_types( //dir=type + unique int id: @struct_type +); + +variadic_sequence_types( //dir=type + unique int id: @variadic_sequence_type +); + +@abstract_function_decl_or_none = + @abstract_function_decl +| @unspecified_element +; + +@accessor_decl_or_none = + @accessor_decl +| @unspecified_element +; + +@argument_or_none = + @argument +| @unspecified_element +; + +@associated_type_decl_or_none = + @associated_type_decl +| @unspecified_element +; + +@ast_node_or_none = + @ast_node +| @unspecified_element +; + +@availability_info_or_none = + @availability_info +| @unspecified_element +; + +@availability_spec_or_none = + @availability_spec +| @unspecified_element +; + +@brace_stmt_or_none = + @brace_stmt +| @unspecified_element +; + +@captured_decl_or_none = + @captured_decl +| @unspecified_element +; + +@case_label_item_or_none = + @case_label_item +| @unspecified_element +; + +@case_stmt_or_none = + @case_stmt +| @unspecified_element +; + +@closure_expr_or_none = + @closure_expr +| @unspecified_element +; + +@condition_element_or_none = + @condition_element +| @unspecified_element +; + +@constructor_decl_or_none = + @constructor_decl +| @unspecified_element +; + +@decl_or_none = + @decl +| @unspecified_element +; + +@enum_element_decl_or_none = + @enum_element_decl +| @unspecified_element +; + +@expr_or_none = + @expr +| @unspecified_element +; + +@file_or_none = + @file +| @unspecified_element +; + +@generic_type_decl_or_none = + @generic_type_decl +| @unspecified_element +; + +@generic_type_param_decl_or_none = + @generic_type_param_decl +| @unspecified_element +; + +@generic_type_param_type_or_none = + @generic_type_param_type +| @unspecified_element +; + +@location_or_none = + @location +| @unspecified_element +; + +@module_decl_or_none = + @module_decl +| @unspecified_element +; + +@nominal_type_decl_or_none = + @nominal_type_decl +| @unspecified_element +; + +@opaque_type_decl_or_none = + @opaque_type_decl +| @unspecified_element +; + +@opaque_value_expr_or_none = + @opaque_value_expr +| @unspecified_element +; + +@param_decl_or_none = + @param_decl +| @unspecified_element +; + +@pattern_or_none = + @pattern +| @unspecified_element +; + +@pattern_binding_decl_or_none = + @pattern_binding_decl +| @unspecified_element +; + +@precedence_group_decl_or_none = + @precedence_group_decl +| @unspecified_element +; + +@protocol_decl_or_none = + @protocol_decl +| @unspecified_element +; + +@protocol_type_or_none = + @protocol_type +| @unspecified_element +; + +@stmt_or_none = + @stmt +| @unspecified_element +; + +@stmt_condition_or_none = + @stmt_condition +| @unspecified_element +; + +@string_literal_expr_or_none = + @string_literal_expr +| @unspecified_element +; + +@tap_expr_or_none = + @tap_expr +| @unspecified_element +; + +@type_or_none = + @type +| @unspecified_element +; + +@type_alias_decl_or_none = + @type_alias_decl +| @unspecified_element +; + +@type_repr_or_none = + @type_repr +| @unspecified_element +; + +@value_decl_or_none = + @unspecified_element +| @value_decl +; + +@var_decl_or_none = + @unspecified_element +| @var_decl +; diff --git a/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties b/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties new file mode 100644 index 00000000000..def634ba268 --- /dev/null +++ b/swift/ql/lib/upgrades/e646f9e0308ec7135c83c0fdf96896d2737a8013/upgrade.properties @@ -0,0 +1,4 @@ +description: Turn exported and imported modules into unindexed sets +compatibility: full +module_decl_imported_modules.rel: reorder module_decl_imported_modules(int id, int index, int imported) id imported +module_decl_exported_modules.rel: reorder module_decl_exported_modules(int id, int index, int exported) id exported From 81a26f039679649d5e984c438b7ef2e01b1a9be0 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Wed, 22 Mar 2023 15:44:07 +0000 Subject: [PATCH 076/141] Java: Add expanded arguments --- java/ql/lib/config/semmlecode.dbscheme | 13 +++++++++++++ java/ql/lib/semmle/code/java/Compilation.qll | 10 ++++++++++ 2 files changed, 23 insertions(+) diff --git a/java/ql/lib/config/semmlecode.dbscheme b/java/ql/lib/config/semmlecode.dbscheme index 934bf10b4bd..7cbc85b1f3e 100644 --- a/java/ql/lib/config/semmlecode.dbscheme +++ b/java/ql/lib/config/semmlecode.dbscheme @@ -60,6 +60,19 @@ compilation_args( string arg : string ref ); +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_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 diff --git a/java/ql/lib/semmle/code/java/Compilation.qll b/java/ql/lib/semmle/code/java/Compilation.qll index c4b846edade..2610413c20b 100644 --- a/java/ql/lib/semmle/code/java/Compilation.qll +++ b/java/ql/lib/semmle/code/java/Compilation.qll @@ -83,6 +83,16 @@ class Compilation extends @compilation { */ string getArgument(int i) { compilation_args(this, i, result) } + /** + * Gets an expanded argument passed to the extractor on this invocation. + */ + string getAnExpandedArgument() { result = getExpandedArgument(_) } + + /** + * Gets the `i`th expanded argument passed to the extractor on this invocation. + */ + string getExpandedArgument(int i) { compilation_expanded_args(this, i, result) } + /** * Gets the total amount of CPU time spent processing all the files in the * compiler. From b381f00a7333c789a09ed8c52d603e051c6fefdc Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Wed, 22 Mar 2023 16:10:21 +0000 Subject: [PATCH 077/141] Java: Add changenote for expanded arguments --- java/ql/lib/change-notes/2023-03-22-expanded-args | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2023-03-22-expanded-args diff --git a/java/ql/lib/change-notes/2023-03-22-expanded-args b/java/ql/lib/change-notes/2023-03-22-expanded-args new file mode 100644 index 00000000000..9d5fe32e6b8 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-22-expanded-args @@ -0,0 +1,4 @@ +--- +category: feature +--- +* Predicates `Compilation.getExpandedArgument` and `Compilation.getAnExpandedArgument` has been added. From 69567449de1b7339c36d094c47eff837929228ad Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Thu, 23 Mar 2023 12:50:40 +0000 Subject: [PATCH 078/141] Java: Update stats --- java/ql/lib/config/semmlecode.dbscheme.stats | 3290 ++++++++++-------- 1 file changed, 1833 insertions(+), 1457 deletions(-) diff --git a/java/ql/lib/config/semmlecode.dbscheme.stats b/java/ql/lib/config/semmlecode.dbscheme.stats index 05a477fec73..f069e1773d8 100644 --- a/java/ql/lib/config/semmlecode.dbscheme.stats +++ b/java/ql/lib/config/semmlecode.dbscheme.stats @@ -2,7 +2,7 @@ @javacompilation - 8628 + 1138 @kotlincompilation @@ -10,7 +10,7 @@ @diagnostic - 64190 + 57106 @externalDataElement @@ -30,11 +30,11 @@ @folder - 293711 + 211876 @package - 121135 + 96053 @primitive @@ -56,6 +56,10 @@ @kt_nullable_type 262 + + @location_default + 82315299 + @kt_notnull_type 156265 @@ -68,10 +72,6 @@ @fielddecl 210035 - - @location_default - 82315299 - @field 2886451 @@ -110,7 +110,7 @@ @import - 441072 + 356137 @block @@ -118,7 +118,7 @@ @ifstmt - 188285 + 188282 @forstmt @@ -126,7 +126,7 @@ @enhancedforstmt - 23697 + 21607 @whilestmt @@ -150,7 +150,7 @@ @returnstmt - 345813 + 345793 @throwstmt @@ -174,7 +174,7 @@ @assertstmt - 15159 + 15158 @localvariabledeclstmt @@ -182,7 +182,7 @@ @localtypedeclstmt - 3533 + 3532 @constructorinvocationstmt @@ -194,7 +194,7 @@ @case - 107945 + 107927 @catchclause @@ -214,11 +214,11 @@ @whenbranch - 207293 + 207292 @arrayaccess - 409681 + 409677 @arraycreationexpr @@ -250,7 +250,7 @@ @assignandexpr - 3971 + 3970 @assignorexpr @@ -258,19 +258,19 @@ @booleanliteral - 589912 + 524468 @integerliteral - 1151458 + 1151446 @longliteral - 185904 + 185873 @floatingpointliteral - 2824996 + 2824967 @doubleliteral @@ -282,7 +282,7 @@ @stringliteral - 1262818 + 1262851 @nullliteral @@ -318,7 +318,7 @@ @urshiftexpr - 9644 + 9643 @andbitexpr @@ -358,7 +358,7 @@ @eqexpr - 104275 + 104273 @neexpr @@ -366,7 +366,7 @@ @postincexpr - 41859 + 41857 @postdecexpr @@ -382,7 +382,7 @@ @minusexpr - 744386 + 744379 @plusexpr @@ -394,11 +394,11 @@ @lognotexpr - 40111 + 40110 @castexpr - 93187 + 93185 @newexpr @@ -426,7 +426,7 @@ @superaccess - 53024 + 53021 @varaccess @@ -434,7 +434,7 @@ @methodaccess - 1512385 + 1512380 @unannotatedtypeaccess @@ -446,7 +446,7 @@ @wildcardtypeaccess - 74889 + 78834 @declannotation @@ -510,7 +510,7 @@ @errorexpr - 1 + 4 @whenexpr @@ -526,7 +526,7 @@ @implicitcastexpr - 28818 + 28817 @implicitnotnullexpr @@ -542,7 +542,7 @@ @stmtexpr - 50553 + 50550 @stringtemplateexpr @@ -566,7 +566,7 @@ @propertyref - 8440 + 8439 @localvar @@ -574,7 +574,7 @@ @module - 7965 + 6092 @requires @@ -582,19 +582,19 @@ @exports - 35013 + 26163 @opens - 165 + 716 @uses - 10786 + 7884 @provides - 2323 + 1792 @javadoc @@ -646,11 +646,11 @@ @ktcomment - 74439 + 116780 @ktcommentsection - 47690 + 74919 @kt_property @@ -660,23 +660,23 @@ compilations - 8628 + 2356 id - 8628 + 2356 kind - 165 + 94 cwd - 165 + 94 name - 8628 + 2356 @@ -690,7 +690,7 @@ 1 2 - 8628 + 2356 @@ -706,7 +706,7 @@ 1 2 - 8628 + 2356 @@ -722,7 +722,7 @@ 1 2 - 8628 + 2356 @@ -736,9 +736,9 @@ 12 - 52 - 53 - 165 + 25 + 26 + 94 @@ -754,7 +754,7 @@ 1 2 - 165 + 94 @@ -768,9 +768,9 @@ 12 - 52 - 53 - 165 + 25 + 26 + 94 @@ -784,9 +784,9 @@ 12 - 52 - 53 - 165 + 25 + 26 + 94 @@ -802,7 +802,7 @@ 1 2 - 165 + 94 @@ -816,9 +816,9 @@ 12 - 52 - 53 - 165 + 25 + 26 + 94 @@ -834,7 +834,7 @@ 1 2 - 8628 + 2356 @@ -850,7 +850,7 @@ 1 2 - 8628 + 2356 @@ -866,7 +866,7 @@ 1 2 - 8628 + 2356 @@ -1248,20 +1248,166 @@ - compilation_compiling_files - 62421 + compilation_expanded_args + 69428 id - 731 + 1138 num - 9199 + 45527 + + + arg + 54632 + + + + + id + num + + + 12 + + + 42 + 43 + 569 + + + 80 + 81 + 569 + + + + + + + id + arg + + + 12 + + + 40 + 41 + 569 + + + 78 + 79 + 569 + + + + + + + num + id + + + 12 + + + 1 + 2 + 21625 + + + 2 + 3 + 23901 + + + + + + + num + arg + + + 12 + + + 1 + 2 + 35283 + + + 2 + 3 + 10243 + + + + + + + arg + id + + + 12 + + + 1 + 2 + 42112 + + + 2 + 3 + 12519 + + + + + + + arg + num + + + 12 + + + 1 + 2 + 53494 + + + 2 + 3 + 1138 + + + + + + + + + compilation_compiling_files + 60809 + + + id + 757 + + + num + 9485 file - 62421 + 60809 @@ -1275,67 +1421,62 @@ 1 2 - 59 + 104 2 - 6 - 59 + 4 + 56 - 6 - 10 - 59 + 4 + 7 + 60 - 10 - 14 - 59 + 7 + 11 + 69 - 14 - 20 - 59 + 11 + 15 + 56 - 20 - 27 - 67 + 15 + 22 + 60 - 27 - 35 - 59 + 22 + 31 + 65 - 36 + 32 47 - 59 + 65 51 - 70 - 59 + 88 + 69 - 72 - 123 - 59 + 93 + 151 + 60 - 124 - 176 - 59 + 163 + 367 + 60 - 208 - 1130 - 59 - - - 1233 - 1234 - 7 + 441 + 2179 + 26 @@ -1351,67 +1492,62 @@ 1 2 - 59 + 104 2 - 6 - 59 + 4 + 56 - 6 - 10 - 59 + 4 + 7 + 60 - 10 - 14 - 59 + 7 + 11 + 69 - 14 - 20 - 59 + 11 + 15 + 56 - 20 - 27 - 67 + 15 + 22 + 60 - 27 - 35 - 59 + 22 + 31 + 65 - 36 + 32 47 - 59 + 65 51 - 70 - 59 + 88 + 69 - 72 - 123 - 59 + 93 + 151 + 60 - 124 - 176 - 59 + 163 + 367 + 60 - 208 - 1130 - 59 - - - 1233 - 1234 - 7 + 441 + 2179 + 26 @@ -1427,42 +1563,37 @@ 1 2 - 775 + 4080 2 3 - 4342 + 452 3 - 5 - 790 + 4 + 2552 - 5 - 6 - 880 + 4 + 7 + 805 - 6 - 8 - 686 + 7 + 17 + 827 - 8 - 16 - 768 + 17 + 104 + 714 - 16 - 42 - 701 - - - 42 - 99 - 253 + 105 + 175 + 52 @@ -1478,42 +1609,37 @@ 1 2 - 775 + 4080 2 3 - 4342 + 452 3 - 5 - 790 + 4 + 2552 - 5 - 6 - 880 + 4 + 7 + 805 - 6 - 8 - 686 + 7 + 17 + 827 - 8 - 16 - 768 + 17 + 104 + 714 - 16 - 42 - 701 - - - 42 - 99 - 253 + 105 + 175 + 52 @@ -1529,7 +1655,7 @@ 1 2 - 62421 + 60809 @@ -1545,7 +1671,7 @@ 1 2 - 62421 + 60809 @@ -1555,19 +1681,19 @@ compilation_compiling_files_completed - 62421 + 60809 id - 731 + 757 num - 9199 + 9485 result - 7 + 4 @@ -1581,67 +1707,62 @@ 1 2 - 59 + 104 2 - 6 - 59 + 4 + 56 - 6 - 10 - 59 + 4 + 7 + 60 - 10 - 14 - 59 + 7 + 11 + 69 - 14 - 20 - 59 + 11 + 15 + 56 - 20 - 27 - 67 + 15 + 22 + 60 - 27 - 35 - 59 + 22 + 31 + 65 - 36 + 32 47 - 59 + 65 51 - 70 - 59 + 88 + 69 - 72 - 123 - 59 + 93 + 151 + 60 - 124 - 176 - 59 + 163 + 367 + 60 - 208 - 1130 - 59 - - - 1233 - 1234 - 7 + 441 + 2179 + 26 @@ -1657,7 +1778,7 @@ 1 2 - 731 + 757 @@ -1673,42 +1794,37 @@ 1 2 - 775 + 4080 2 3 - 4342 + 452 3 - 5 - 790 + 4 + 2552 - 5 - 6 - 880 + 4 + 7 + 805 - 6 - 8 - 686 + 7 + 17 + 827 - 8 - 16 - 768 + 17 + 104 + 714 - 16 - 42 - 701 - - - 42 - 99 - 253 + 105 + 175 + 52 @@ -1724,7 +1840,7 @@ 1 2 - 9199 + 9485 @@ -1738,9 +1854,9 @@ 12 - 98 - 99 - 7 + 174 + 175 + 4 @@ -1754,9 +1870,9 @@ 12 - 1233 - 1234 - 7 + 2178 + 2179 + 4 @@ -1766,23 +1882,23 @@ compilation_time - 252612 + 166778 id - 731 + 238 num - 9207 + 30464 kind - 29 + 477 seconds - 123672 + 83269 @@ -1794,161 +1910,51 @@ 12 - 2 - 3 - 59 - - - 3 - 7 - 59 - - - 7 - 11 - 59 - - - 11 - 15 - 59 - - - 15 - 21 - 59 - - - 21 - 28 - 67 - - - 28 - 36 - 59 - - - 37 - 48 - 59 - - - 52 - 71 - 59 - - - 73 - 124 - 59 - - - 125 - 177 - 59 - - - 209 - 1131 - 59 - - - 1234 - 1235 - 7 - - - - - - - id - kind - - - 12 - - - 4 - 5 - 731 - - - - - - - id - seconds - - - 12 - - - 4 - 5 - 59 - - - 6 - 13 - 59 - - - 14 - 21 - 59 - - - 22 - 29 - 59 - - - 30 - 41 - 59 - - - 42 - 55 - 67 - - - 56 - 71 - 59 - - - 74 + 94 95 - 59 + 119 - 104 - 141 - 59 + 255 + 256 + 119 + + + + + + + id + kind + + + 12 + + + 4 + 5 + 238 + + + + + + + id + seconds + + + 12 + + + 188 + 189 + 119 - 146 - 247 - 59 - - - 250 - 353 - 59 - - - 418 - 2247 - 59 - - - 2436 - 2437 - 7 + 510 + 511 + 119 @@ -1964,42 +1970,12 @@ 1 2 - 775 + 19234 2 3 - 4342 - - - 3 - 5 - 790 - - - 5 - 6 - 880 - - - 6 - 8 - 686 - - - 8 - 16 - 768 - - - 16 - 42 - 701 - - - 42 - 99 - 261 + 11230 @@ -2015,7 +1991,7 @@ 4 5 - 9207 + 30464 @@ -2031,42 +2007,12 @@ 3 4 - 775 + 19353 5 6 - 4342 - - - 7 - 10 - 790 - - - 11 - 12 - 880 - - - 13 - 16 - 686 - - - 17 - 32 - 768 - - - 33 - 84 - 701 - - - 85 - 198 - 261 + 11110 @@ -2080,9 +2026,9 @@ 12 - 98 - 99 - 29 + 2 + 3 + 477 @@ -2096,9 +2042,9 @@ 12 - 1234 - 1235 - 29 + 255 + 256 + 477 @@ -2114,17 +2060,17 @@ 1 2 - 14 + 238 - 8222 - 8223 - 7 + 348 + 349 + 119 - 8364 - 8365 - 7 + 349 + 350 + 119 @@ -2140,12 +2086,12 @@ 1 2 - 122389 + 83150 2 - 99 - 1283 + 3 + 119 @@ -2161,12 +2107,12 @@ 1 2 - 121889 + 83150 - 2 - 1235 - 1783 + 255 + 256 + 119 @@ -2182,12 +2128,12 @@ 1 2 - 123582 + 83150 - 2 + 3 4 - 89 + 119 @@ -2197,23 +2143,23 @@ diagnostic_for - 64190 + 57106 diagnostic - 64190 + 57106 compilation - 716 + 374 file_number - 7 + 6678 file_number_diagnostic_number - 14475 + 1248 @@ -2227,7 +2173,7 @@ 1 2 - 64190 + 57106 @@ -2243,7 +2189,7 @@ 1 2 - 64190 + 57106 @@ -2259,7 +2205,7 @@ 1 2 - 64190 + 57106 @@ -2275,47 +2221,27 @@ 1 2 - 268 + 124 - 3 - 5 - 59 + 34 + 35 + 62 - 5 - 8 - 52 + 266 + 267 + 62 - 8 - 14 - 44 + 303 + 304 + 62 - 14 - 22 - 59 - - - 22 - 39 - 59 - - - 42 - 55 - 59 - - - 60 - 169 - 59 - - - 228 - 1941 - 52 + 310 + 311 + 62 @@ -2331,7 +2257,22 @@ 1 2 - 716 + 124 + + + 14 + 15 + 62 + + + 102 + 103 + 124 + + + 104 + 105 + 62 @@ -2347,47 +2288,22 @@ 1 2 - 268 - - - 3 - 5 - 59 - - - 5 - 8 - 52 + 124 8 - 14 - 44 + 9 + 62 - 14 - 22 - 59 + 15 + 16 + 62 - 22 - 39 - 59 - - - 42 - 55 - 59 - - - 60 - 169 - 59 - - - 228 - 1941 - 52 + 20 + 21 + 124 @@ -2401,9 +2317,44 @@ 12 - 8603 - 8604 - 7 + 1 + 5 + 312 + + + 6 + 7 + 3682 + + + 7 + 8 + 312 + + + 8 + 9 + 686 + + + 9 + 12 + 499 + + + 12 + 15 + 561 + + + 17 + 30 + 561 + + + 47 + 48 + 62 @@ -2417,9 +2368,19 @@ 12 - 96 - 97 - 7 + 1 + 3 + 436 + + + 3 + 4 + 5367 + + + 4 + 5 + 873 @@ -2433,9 +2394,39 @@ 12 - 1940 - 1941 - 7 + 1 + 2 + 124 + + + 2 + 3 + 3994 + + + 3 + 4 + 873 + + + 4 + 5 + 312 + + + 5 + 6 + 436 + + + 6 + 8 + 499 + + + 8 + 21 + 436 @@ -2448,45 +2439,70 @@ 12 - - 1 - 2 - 3290 - 2 3 - 238 + 312 3 4 - 5081 - - - 4 - 5 - 2439 + 124 5 6 - 261 - - - 6 - 7 - 1462 + 124 7 - 14 - 1208 + 8 + 124 - 14 - 97 - 492 + 9 + 10 + 62 + + + 12 + 13 + 62 + + + 21 + 22 + 62 + + + 25 + 26 + 62 + + + 39 + 40 + 62 + + + 47 + 48 + 62 + + + 77 + 78 + 62 + + + 321 + 322 + 62 + + + 324 + 325 + 62 @@ -2499,45 +2515,25 @@ 12 - - 1 - 2 - 3290 - 2 3 - 238 + 312 3 4 - 5081 + 436 4 5 - 2439 - - - 5 - 6 - 261 + 436 6 7 - 1462 - - - 7 - 14 - 1208 - - - 14 - 97 - 492 + 62 @@ -2553,7 +2549,67 @@ 1 2 - 14475 + 312 + + + 2 + 3 + 124 + + + 3 + 4 + 124 + + + 4 + 5 + 124 + + + 5 + 6 + 62 + + + 7 + 8 + 62 + + + 12 + 13 + 62 + + + 15 + 16 + 62 + + + 22 + 23 + 62 + + + 27 + 28 + 62 + + + 41 + 42 + 62 + + + 105 + 106 + 62 + + + 107 + 108 + 62 @@ -2684,23 +2740,23 @@ compilation_finished - 8628 + 2261 id - 8628 + 2261 cpu_seconds - 165 + 94 elapsed_seconds - 8628 + 2261 result - 165 + 94 @@ -2714,7 +2770,7 @@ 1 2 - 8628 + 2261 @@ -2730,7 +2786,7 @@ 1 2 - 8628 + 2261 @@ -2746,7 +2802,7 @@ 1 2 - 8628 + 2261 @@ -2760,9 +2816,9 @@ 12 - 52 - 53 - 165 + 24 + 25 + 94 @@ -2776,9 +2832,9 @@ 12 - 52 - 53 - 165 + 24 + 25 + 94 @@ -2794,7 +2850,7 @@ 1 2 - 165 + 94 @@ -2810,7 +2866,7 @@ 1 2 - 8628 + 2261 @@ -2826,7 +2882,7 @@ 1 2 - 8628 + 2261 @@ -2842,7 +2898,7 @@ 1 2 - 8628 + 2261 @@ -2856,9 +2912,9 @@ 12 - 52 - 53 - 165 + 24 + 25 + 94 @@ -2874,7 +2930,7 @@ 1 2 - 165 + 94 @@ -2888,9 +2944,9 @@ 12 - 52 - 53 - 165 + 24 + 25 + 94 @@ -2900,35 +2956,35 @@ diagnostics - 64190 + 57106 id - 64190 + 57106 generated_by - 7 + 124 severity - 29 + 62 error_tag - 7 + 62 error_message - 2604 + 1435 full_error_message - 7 + 39319 location - 7 + 312 @@ -2942,7 +2998,7 @@ 1 2 - 64190 + 57106 @@ -2958,7 +3014,7 @@ 1 2 - 64190 + 57106 @@ -2974,7 +3030,7 @@ 1 2 - 64190 + 57106 @@ -2990,7 +3046,7 @@ 1 2 - 64190 + 57106 @@ -3006,7 +3062,7 @@ 1 2 - 64190 + 57106 @@ -3022,7 +3078,7 @@ 1 2 - 64190 + 57106 @@ -3036,9 +3092,14 @@ 12 - 8603 - 8604 - 7 + 2 + 3 + 62 + + + 913 + 914 + 62 @@ -3052,9 +3113,9 @@ 12 - 4 - 5 - 7 + 1 + 2 + 124 @@ -3070,7 +3131,7 @@ 1 2 - 7 + 124 @@ -3084,9 +3145,14 @@ 12 - 349 - 350 - 7 + 2 + 3 + 62 + + + 21 + 22 + 62 @@ -3102,7 +3168,12 @@ 1 2 - 7 + 62 + + + 629 + 630 + 62 @@ -3118,7 +3189,12 @@ 1 2 - 7 + 62 + + + 4 + 5 + 62 @@ -3132,24 +3208,9 @@ 12 - 4 - 5 - 7 - - - 13 - 14 - 7 - - - 95 - 96 - 7 - - - 8491 - 8492 - 7 + 915 + 916 + 62 @@ -3163,9 +3224,9 @@ 12 - 1 - 2 - 29 + 2 + 3 + 62 @@ -3181,7 +3242,7 @@ 1 2 - 29 + 62 @@ -3195,24 +3256,9 @@ 12 - 4 - 5 - 7 - - - 13 - 14 - 7 - - - 95 - 96 - 7 - - - 237 - 238 - 7 + 23 + 24 + 62 @@ -3226,9 +3272,9 @@ 12 - 1 - 2 - 29 + 630 + 631 + 62 @@ -3242,9 +3288,9 @@ 12 - 1 - 2 - 29 + 5 + 6 + 62 @@ -3258,9 +3304,9 @@ 12 - 8603 - 8604 - 7 + 915 + 916 + 62 @@ -3274,9 +3320,9 @@ 12 - 1 - 2 - 7 + 2 + 3 + 62 @@ -3290,9 +3336,9 @@ 12 - 4 - 5 - 7 + 1 + 2 + 62 @@ -3306,9 +3352,9 @@ 12 - 349 - 350 - 7 + 23 + 24 + 62 @@ -3322,9 +3368,9 @@ 12 - 1 - 2 - 7 + 630 + 631 + 62 @@ -3338,9 +3384,9 @@ 12 - 1 - 2 - 7 + 5 + 6 + 62 @@ -3356,81 +3402,151 @@ 1 2 - 2290 + 312 2 - 9 - 201 + 3 + 249 + + + 4 + 7 + 124 + + + 7 + 10 + 124 + + + 13 + 16 + 124 + + + 19 + 23 + 124 + + + 25 + 27 + 124 + + + 48 + 81 + 124 + + + 314 + 315 + 124 + + + + + + + error_message + generated_by + + + 12 + + + 1 + 2 + 1435 + + + + + + + error_message + severity + + + 12 + + + 1 + 2 + 1435 + + + + + + + error_message + error_tag + + + 12 + + + 1 + 2 + 1435 + + + + + + + error_message + full_error_message + + + 12 + + + 1 + 2 + 312 + + + 2 + 3 + 249 + + + 4 + 6 + 124 + + + 6 + 8 + 124 9 - 3692 - 111 + 16 + 124 - - - - - - error_message - generated_by - - - 12 - - 1 - 2 - 2604 + 19 + 23 + 124 - - - - - - error_message - severity - - - 12 - - 1 - 2 - 2604 + 25 + 27 + 124 - - - - - - error_message - error_tag - - - 12 - - 1 - 2 - 2604 + 38 + 49 + 124 - - - - - - error_message - full_error_message - - - 12 - - 1 - 2 - 2604 + 80 + 315 + 124 @@ -3446,7 +3562,12 @@ 1 2 - 2604 + 1373 + + + 3 + 4 + 62 @@ -3460,9 +3581,14 @@ 12 - 8603 - 8604 - 7 + 1 + 2 + 37010 + + + 2 + 37 + 2309 @@ -3478,7 +3604,7 @@ 1 2 - 7 + 39319 @@ -3492,9 +3618,9 @@ 12 - 4 - 5 - 7 + 1 + 2 + 39319 @@ -3510,7 +3636,7 @@ 1 2 - 7 + 39319 @@ -3524,9 +3650,14 @@ 12 - 349 - 350 - 7 + 1 + 2 + 39257 + + + 2 + 3 + 62 @@ -3542,7 +3673,7 @@ 1 2 - 7 + 39319 @@ -3556,9 +3687,29 @@ 12 - 8603 - 8604 - 7 + 2 + 3 + 62 + + + 3 + 4 + 62 + + + 4 + 5 + 62 + + + 6 + 7 + 62 + + + 900 + 901 + 62 @@ -3574,7 +3725,7 @@ 1 2 - 7 + 312 @@ -3588,9 +3739,9 @@ 12 - 4 - 5 - 7 + 1 + 2 + 312 @@ -3606,7 +3757,7 @@ 1 2 - 7 + 312 @@ -3620,9 +3771,19 @@ 12 - 349 - 350 - 7 + 1 + 2 + 187 + + + 2 + 3 + 62 + + + 20 + 21 + 62 @@ -3638,7 +3799,17 @@ 1 2 - 7 + 187 + + + 3 + 4 + 62 + + + 624 + 625 + 62 @@ -7323,15 +7494,15 @@ folders - 293711 + 211876 id - 293711 + 211876 name - 293711 + 211876 @@ -7345,7 +7516,7 @@ 1 2 - 293711 + 211876 @@ -7361,7 +7532,7 @@ 1 2 - 293711 + 211876 @@ -7542,19 +7713,19 @@ jarManifestMain - 172742 + 132371 fileid - 13275 + 8960 keyName - 12611 + 9676 value - 89772 + 67858 @@ -7567,58 +7738,68 @@ 1 - 4 - 995 + 5 + 358 5 6 - 2323 + 1792 6 7 - 2157 + 1075 9 - 13 - 1161 + 10 + 358 13 15 - 1161 + 597 15 - 17 - 829 + 16 + 716 - 17 + 16 18 - 829 + 716 - 19 + 18 21 - 829 + 716 21 - 24 - 1161 + 23 + 477 - 24 + 23 + 26 + 597 + + + 26 27 - 1161 + 358 - 28 - 35 - 663 + 27 + 29 + 716 + + + 29 + 36 + 477 @@ -7633,63 +7814,68 @@ 1 - 4 - 995 + 5 + 358 5 6 - 2489 + 1792 6 7 - 1991 + 1075 8 - 10 - 663 + 11 + 597 - 10 - 12 - 995 - - - 12 + 11 13 - 663 + 597 14 15 - 995 + 597 15 + 16 + 597 + + + 16 17 - 1161 + 358 17 18 - 829 + 716 18 - 20 - 1161 + 19 + 358 + + + 19 + 21 + 716 21 - 24 - 1161 + 23 + 597 - 29 - 30 - 165 + 23 + 29 + 597 @@ -7705,47 +7891,42 @@ 1 2 - 5144 + 4420 2 - 3 - 829 - - - 3 4 - 829 + 716 - 5 - 8 - 995 + 4 + 6 + 597 - 10 - 20 - 995 + 6 + 12 + 836 - 24 - 28 - 829 + 18 + 30 + 836 - 28 - 31 - 995 + 30 + 34 + 716 - 32 - 38 - 995 + 34 + 42 + 836 - 39 - 81 - 995 + 42 + 76 + 716 @@ -7761,42 +7942,42 @@ 1 2 - 5807 + 4898 2 3 - 995 + 597 3 - 5 - 995 + 4 + 716 - 5 - 8 - 995 + 4 + 9 + 836 - 10 - 16 - 1161 + 13 + 18 + 716 - 17 - 26 - 1161 + 18 + 31 + 836 - 27 - 36 - 995 + 32 + 42 + 836 - 37 - 53 - 497 + 51 + 54 + 238 @@ -7812,22 +7993,17 @@ 1 2 - 75999 + 58659 2 - 3 - 4480 + 4 + 5615 - 3 - 6 - 6969 - - - 6 - 81 - 2323 + 4 + 76 + 3584 @@ -7843,17 +8019,17 @@ 1 2 - 75668 + 56269 2 3 - 8794 + 6570 3 - 6 - 5310 + 5 + 5017 @@ -7863,23 +8039,23 @@ jarManifestEntries - 46193 + 30196 fileid - 29 + 61 entryName - 46141 + 30124 keyName - 59 + 27 value - 46171 + 30158 @@ -7893,22 +8069,72 @@ 1 2 - 7 + 4 - 264 - 265 - 7 + 4 + 10 + 3 - 1520 - 1521 - 7 + 10 + 12 + 4 - 4400 - 4401 - 7 + 12 + 31 + 4 + + + 65 + 82 + 4 + + + 123 + 164 + 4 + + + 178 + 240 + 4 + + + 253 + 294 + 4 + + + 307 + 357 + 4 + + + 361 + 395 + 4 + + + 433 + 461 + 4 + + + 591 + 662 + 4 + + + 957 + 2267 + 4 + + + 3647 + 3762 + 3 @@ -7924,12 +8150,12 @@ 1 2 - 22 + 57 - 7 - 8 - 7 + 6 + 10 + 3 @@ -7943,24 +8169,74 @@ 12 - 4 - 5 - 7 + 1 + 2 + 4 - 264 - 265 - 7 + 3 + 8 + 4 - 1520 - 1521 - 7 + 9 + 13 + 4 - 4400 - 4401 - 7 + 24 + 66 + 4 + + + 70 + 124 + 4 + + + 127 + 179 + 4 + + + 195 + 254 + 4 + + + 265 + 308 + 4 + + + 320 + 362 + 4 + + + 381 + 434 + 4 + + + 434 + 592 + 4 + + + 618 + 958 + 4 + + + 1671 + 3648 + 4 + + + 3761 + 3762 + 1 @@ -7976,12 +8252,12 @@ 1 2 - 46133 + 30108 2 - 3 - 7 + 26 + 16 @@ -7997,12 +8273,12 @@ 1 2 - 46133 + 30121 - 7 - 8 - 7 + 6 + 10 + 3 @@ -8018,12 +8294,12 @@ 1 2 - 46126 + 30120 - 2 - 5 - 14 + 3 + 26 + 4 @@ -8039,12 +8315,22 @@ 1 2 - 52 + 21 + + + 2 + 3 + 3 3 4 - 7 + 1 + + + 32 + 33 + 1 @@ -8060,12 +8346,27 @@ 1 2 - 52 + 21 - 6183 - 6184 - 7 + 2 + 3 + 1 + + + 11 + 12 + 1 + + + 369 + 370 + 1 + + + 19366 + 19367 + 1 @@ -8081,12 +8382,22 @@ 1 2 - 52 + 22 - 6184 - 6185 - 7 + 2 + 3 + 1 + + + 369 + 370 + 1 + + + 19390 + 19391 + 1 @@ -8102,7 +8413,12 @@ 1 2 - 46171 + 30156 + + + 2 + 3 + 1 @@ -8118,7 +8434,12 @@ 1 2 - 46171 + 30156 + + + 11 + 12 + 1 @@ -8134,12 +8455,12 @@ 1 2 - 46148 + 30150 2 3 - 22 + 7 @@ -8149,15 +8470,15 @@ packages - 121135 + 96053 id - 121135 + 96053 nodeName - 121135 + 96053 @@ -8171,7 +8492,7 @@ 1 2 - 121135 + 96053 @@ -8187,7 +8508,7 @@ 1 2 - 121135 + 96053 @@ -8745,11 +9066,11 @@ file_class - 7249 + 17711 id - 7249 + 17711 @@ -12653,11 +12974,11 @@ isVarargsParam - 813764 + 684318 param - 813764 + 684318 @@ -12891,30 +13212,30 @@ isAnnotElem - 61065 + 49101 methodid - 61065 + 49101 annotValue - 1574925 + 1421553 parentid - 568174 + 1172586 id2 - 52104 + 1074 value - 1574925 + 1421553 @@ -12928,37 +13249,12 @@ 1 2 - 153493 + 1135381 2 - 3 - 252724 - - - 3 - 4 - 48951 - - - 4 - 6 - 26550 - - - 6 - 7 - 35179 - - - 7 - 9 - 46628 - - - 9 - 13 - 4646 + 18 + 37205 @@ -12974,37 +13270,12 @@ 1 2 - 138061 + 1133350 2 - 3 - 268157 - - - 3 - 4 - 47292 - - - 4 - 6 - 26052 - - - 6 - 8 - 39659 - - - 8 - 10 - 44139 - - - 10 - 13 - 4812 + 20 + 39235 @@ -13020,52 +13291,62 @@ 1 2 - 17091 + 198 2 3 - 5144 + 95 3 4 - 2655 + 88 - 4 - 6 - 4812 + 5 + 8 + 88 - 6 - 9 - 4314 + 8 + 16 + 88 - 9 - 15 - 4148 - - - 16 + 20 25 - 4314 + 88 - 27 - 86 - 3982 + 34 + 59 + 66 86 - 153 - 4148 + 102 + 80 - 164 - 1105 - 1493 + 121 + 185 + 51 + + + 203 + 684 + 80 + + + 1733 + 1734 + 125 + + + 1842 + 153327 + 22 @@ -13081,52 +13362,62 @@ 1 2 - 15266 + 198 2 3 - 6637 + 88 3 4 - 2820 + 88 4 - 6 - 3816 - - - 6 8 - 3816 + 95 8 - 10 - 4812 + 16 + 88 - 10 + 20 25 - 4148 + 88 - 25 - 53 - 3982 + 34 + 59 + 66 - 53 - 132 - 3982 + 86 + 102 + 80 - 134 - 1105 - 2820 + 127 + 185 + 51 + + + 203 + 684 + 80 + + + 1733 + 1734 + 88 + + + 1734 + 153327 + 58 @@ -13142,7 +13433,7 @@ 1 2 - 1574925 + 1421553 @@ -13158,7 +13449,7 @@ 1 2 - 1574925 + 1421553 @@ -14544,15 +14835,15 @@ isLocalClassOrInterface - 3533 + 3532 typeid - 3533 + 3532 parent - 3533 + 3532 @@ -14566,7 +14857,7 @@ 1 2 - 3533 + 3532 @@ -14582,7 +14873,7 @@ 1 2 - 3533 + 3532 @@ -14592,11 +14883,11 @@ isDefConstr - 139383 + 139376 constructorid - 139383 + 139376 @@ -15205,15 +15496,15 @@ implInterface - 3052687 + 3052545 id1 - 757298 + 757262 id2 - 2275569 + 2275463 @@ -15227,37 +15518,37 @@ 1 2 - 210035 + 210026 2 3 - 50057 + 50055 3 4 - 67415 + 67412 4 5 - 62041 + 62038 5 6 - 19333 + 19332 6 7 - 305943 + 305928 7 10 - 42471 + 42469 @@ -15273,12 +15564,12 @@ 1 2 - 2200149 + 2200047 2 63705 - 75420 + 75416 @@ -15288,15 +15579,15 @@ permits - 132 + 3703 id1 - 30 + 1075 id2 - 132 + 3703 @@ -15310,32 +15601,27 @@ 1 2 - 3 + 358 2 3 - 3 + 358 3 4 - 6 + 119 - 4 - 5 - 10 - - - 8 - 9 - 3 + 9 + 10 + 119 10 11 - 3 + 119 @@ -15351,7 +15637,7 @@ 1 2 - 132 + 3703 @@ -15469,23 +15755,23 @@ imports - 441072 + 356137 id - 441072 + 356137 holder - 52468 + 54477 name - 4282 + 8004 kind - 29 + 358 @@ -15499,7 +15785,7 @@ 1 2 - 441072 + 356137 @@ -15515,7 +15801,7 @@ 1 2 - 441072 + 356137 @@ -15531,7 +15817,7 @@ 1 2 - 441072 + 356137 @@ -15547,42 +15833,37 @@ 1 2 - 20638 + 24730 2 3 - 8976 + 8960 3 4 - 4991 + 5017 4 - 5 - 3335 + 6 + 4420 - 5 - 7 - 4096 + 6 + 10 + 4181 - 7 - 12 - 4305 + 10 + 30 + 4181 - 12 - 32 - 3984 - - - 32 - 1529 - 2141 + 31 + 113 + 2986 @@ -15598,12 +15879,12 @@ 1 2 - 50871 + 51132 2 - 54 - 1596 + 8 + 3345 @@ -15619,12 +15900,12 @@ 1 2 - 51200 + 51610 2 - 4 - 1268 + 3 + 2867 @@ -15640,27 +15921,32 @@ 1 2 - 2469 + 3584 2 3 - 962 + 1792 3 4 - 358 + 836 4 - 7 - 328 + 9 + 716 - 7 - 57945 - 164 + 9 + 32 + 716 + + + 45 + 2676 + 358 @@ -15676,38 +15962,43 @@ 1 2 - 4163 + 7048 2 - 6945 + 3 + 716 + + + 3 + 442 + 238 + + + + + + + name + kind + + + 12 + + + 1 + 2 + 7884 + + + 2 + 3 119 - - name - kind - - - 12 - - - 1 - 2 - 4275 - - - 3 - 4 - 7 - - - - - kind id @@ -15716,24 +16007,19 @@ 12 - 15 - 16 - 7 + 13 + 14 + 119 - 68 - 69 - 7 + 306 + 307 + 119 - 1170 - 1171 - 7 - - - 57861 - 57862 - 7 + 2662 + 2663 + 119 @@ -15747,24 +16033,19 @@ 12 - 10 - 11 - 7 + 5 + 6 + 119 - 25 - 26 - 7 + 39 + 40 + 119 - 257 - 258 - 7 - - - 6915 - 6916 - 7 + 436 + 437 + 119 @@ -15780,12 +16061,12 @@ 1 2 - 22 + 238 - 573 - 574 - 7 + 66 + 67 + 119 @@ -17679,15 +17960,15 @@ callableEnclosingExpr - 7299071 + 7298994 id - 7299071 + 7298994 callable_id - 19877 + 19876 @@ -17701,7 +17982,7 @@ 1 2 - 7299071 + 7298994 @@ -17792,15 +18073,15 @@ statementEnclosingExpr - 7258714 + 7258638 id - 7258714 + 7258638 statement_id - 525778 + 525773 @@ -17814,7 +18095,7 @@ 1 2 - 7258714 + 7258638 @@ -17830,7 +18111,7 @@ 1 3 - 29126 + 29125 3 @@ -17840,22 +18121,22 @@ 5 7 - 48474 + 48473 7 8 - 36042 + 36041 8 9 - 38145 + 38144 9 10 - 50447 + 50446 10 @@ -17865,7 +18146,7 @@ 11 12 - 127049 + 127048 12 @@ -17880,7 +18161,7 @@ 40 81 - 40222 + 40221 82 @@ -17970,15 +18251,15 @@ callableBinding - 1832520 + 1832514 callerid - 1832520 + 1832514 callee - 264311 + 264310 @@ -17992,7 +18273,7 @@ 1 2 - 1832520 + 1832514 @@ -18008,7 +18289,7 @@ 1 2 - 162995 + 162994 2 @@ -18144,12 +18425,12 @@ 1 2 - 1855 + 1854 2 3 - 3164 + 3163 3 @@ -18164,15 +18445,15 @@ propertyRefFieldBinding - 2 + 4 id - 2 + 4 field - 2 + 4 @@ -18186,7 +18467,7 @@ 1 2 - 2 + 4 @@ -18202,7 +18483,7 @@ 1 2 - 2 + 4 @@ -18719,11 +19000,11 @@ localvarsKotlinType - 149454 + 149446 id - 149454 + 149446 kttypeid @@ -18741,7 +19022,7 @@ 1 2 - 149454 + 149446 @@ -18767,19 +19048,19 @@ namestrings - 4022436 + 4022471 name - 23384 + 23402 value - 22166 + 22183 parent - 4022436 + 4022471 @@ -18793,7 +19074,7 @@ 1 2 - 23384 + 23402 @@ -18819,12 +19100,12 @@ 3 5 - 2150 + 2163 5 9 - 1769 + 1773 9 @@ -18860,7 +19141,7 @@ 1 2 - 21559 + 21576 2 @@ -18891,12 +19172,12 @@ 3 5 - 1912 + 1925 5 9 - 1665 + 1669 9 @@ -18932,7 +19213,7 @@ 1 2 - 4022436 + 4022471 @@ -18948,7 +19229,7 @@ 1 2 - 4022436 + 4022471 @@ -18958,15 +19239,15 @@ modules - 7965 + 6092 id - 7965 + 6092 name - 7965 + 6092 @@ -18980,7 +19261,7 @@ 1 2 - 7965 + 6092 @@ -18996,7 +19277,7 @@ 1 2 - 7965 + 6092 @@ -19017,15 +19298,15 @@ cumodule - 247580 + 188761 fileId - 247580 + 188761 moduleId - 1161 + 836 @@ -19039,7 +19320,7 @@ 1 2 - 247580 + 188761 @@ -19055,32 +19336,32 @@ 12 13 - 331 + 238 - 39 - 40 - 165 + 36 + 37 + 119 - 64 - 65 - 165 + 72 + 73 + 119 - 71 - 72 - 165 + 75 + 76 + 119 415 416 - 165 + 119 - 879 - 880 - 165 + 958 + 959 + 119 @@ -19090,15 +19371,15 @@ directives - 50279 + 37991 id - 1161 + 836 directive - 50279 + 37991 @@ -19112,37 +19393,37 @@ 3 4 - 165 + 119 4 5 - 165 + 119 7 8 - 165 + 119 9 10 - 165 + 119 43 44 - 165 + 119 89 90 - 165 + 119 - 148 - 149 - 165 + 163 + 164 + 119 @@ -19158,7 +19439,7 @@ 1 2 - 50279 + 37991 @@ -19261,11 +19542,11 @@ isTransitive - 829 + 597 id - 829 + 597 @@ -19283,15 +19564,15 @@ exports - 35013 + 26163 id - 35013 + 26163 target - 35013 + 26163 @@ -19305,7 +19586,7 @@ 1 2 - 35013 + 26163 @@ -19321,7 +19602,7 @@ 1 2 - 35013 + 26163 @@ -19331,15 +19612,15 @@ exportsTo - 28707 + 22579 id - 12279 + 9676 target - 7467 + 5734 @@ -19353,32 +19634,27 @@ 1 2 - 7301 + 5495 2 3 - 1825 + 1792 3 4 - 829 + 836 4 - 5 - 829 + 6 + 716 - 5 - 7 - 995 - - - 9 - 18 - 497 + 6 + 19 + 836 @@ -19394,42 +19670,47 @@ 1 2 - 1991 + 1672 2 3 - 1825 + 1194 3 4 - 663 + 716 4 5 - 663 + 358 5 6 - 663 + 477 6 7 - 331 + 238 8 10 - 663 + 477 - 11 + 10 13 - 663 + 358 + + + 13 + 14 + 238 @@ -19439,15 +19720,15 @@ opens - 165 + 716 id - 165 + 716 target - 165 + 716 @@ -19461,7 +19742,7 @@ 1 2 - 165 + 716 @@ -19477,7 +19758,7 @@ 1 2 - 165 + 716 @@ -19487,15 +19768,15 @@ opensTo - 165 + 716 id - 165 + 716 target - 165 + 238 @@ -19509,7 +19790,7 @@ 1 2 - 165 + 716 @@ -19525,7 +19806,12 @@ 1 2 - 165 + 119 + + + 5 + 6 + 119 @@ -19535,15 +19821,15 @@ uses - 10786 + 7884 id - 10786 + 7884 serviceInterface - 10786 + 7884 @@ -19557,7 +19843,7 @@ 1 2 - 10786 + 7884 @@ -19573,7 +19859,7 @@ 1 2 - 10786 + 7884 @@ -19583,15 +19869,15 @@ provides - 2323 + 1792 id - 2323 + 1792 serviceInterface - 2323 + 1792 @@ -19605,7 +19891,7 @@ 1 2 - 2323 + 1792 @@ -19621,7 +19907,7 @@ 1 2 - 2323 + 1792 @@ -19631,15 +19917,15 @@ providesWith - 5310 + 4181 id - 2323 + 1792 serviceImpl - 5310 + 4181 @@ -19653,22 +19939,27 @@ 1 2 - 1327 + 955 2 3 - 165 + 119 + + + 3 + 4 + 119 4 5 - 663 + 477 6 7 - 165 + 119 @@ -19684,7 +19975,7 @@ 1 2 - 5310 + 4181 @@ -25467,19 +25758,19 @@ ktComments - 74439 + 116780 id - 74439 + 116780 kind - 37 + 13 text - 51562 + 15129 @@ -25493,7 +25784,7 @@ 1 2 - 74439 + 116780 @@ -25509,7 +25800,7 @@ 1 2 - 74439 + 116780 @@ -25523,19 +25814,19 @@ 12 - 1196 - 1197 - 12 + 794 + 795 + 4 - 1284 - 1285 - 12 + 8820 + 8821 + 4 - 3517 - 3518 - 12 + 17201 + 17202 + 4 @@ -25549,19 +25840,19 @@ 12 - 17 - 18 - 12 + 20 + 21 + 4 - 1073 - 1074 - 12 + 680 + 681 + 4 - 3064 - 3065 - 12 + 2774 + 2775 + 4 @@ -25577,17 +25868,42 @@ 1 2 - 46101 + 6780 2 3 - 4232 + 692 3 - 572 - 1228 + 4 + 1506 + + + 4 + 5 + 126 + + + 5 + 6 + 3436 + + + 6 + 16 + 1258 + + + 16 + 32 + 1201 + + + 33 + 4236 + 126 @@ -25603,7 +25919,7 @@ 1 2 - 51562 + 15129 @@ -25613,19 +25929,19 @@ ktCommentSections - 47690 + 74919 id - 47690 + 74919 comment - 43655 + 74910 content - 40577 + 8109 @@ -25639,7 +25955,7 @@ 1 2 - 47690 + 74919 @@ -25655,7 +25971,7 @@ 1 2 - 47690 + 74919 @@ -25671,12 +25987,12 @@ 1 2 - 42029 + 74902 2 - 18 - 1626 + 3 + 8 @@ -25692,12 +26008,12 @@ 1 2 - 42029 + 74902 2 - 18 - 1626 + 3 + 8 @@ -25713,17 +26029,52 @@ 1 2 - 35910 + 3170 2 3 - 3910 + 522 3 - 63 - 757 + 5 + 518 + + + 5 + 6 + 962 + + + 6 + 9 + 622 + + + 9 + 10 + 34 + + + 10 + 11 + 718 + + + 11 + 21 + 675 + + + 21 + 37 + 622 + + + 42 + 504 + 261 @@ -25739,17 +26090,52 @@ 1 2 - 35997 + 3170 2 3 - 3835 + 522 3 - 56 - 744 + 5 + 518 + + + 5 + 6 + 962 + + + 6 + 9 + 622 + + + 9 + 10 + 34 + + + 10 + 11 + 718 + + + 11 + 21 + 675 + + + 21 + 37 + 622 + + + 42 + 504 + 261 @@ -25870,15 +26256,15 @@ ktCommentOwners - 68171 + 76609 id - 43432 + 74810 owner - 66520 + 71853 @@ -25892,22 +26278,12 @@ 1 2 - 28065 + 73186 2 - 3 - 9744 - - - 3 - 4 - 3649 - - - 4 6 - 1973 + 1624 @@ -25923,12 +26299,12 @@ 1 2 - 64881 + 69697 2 - 4 - 1638 + 5 + 2155 From 5c50ddce3d16b4a890edc467cec5ee48e300b31e Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Thu, 23 Mar 2023 12:51:36 +0000 Subject: [PATCH 079/141] Java: Add up/downgrade scripts --- .../old.dbscheme | 1255 +++++++++++++++++ .../semmlecode.dbscheme | 1242 ++++++++++++++++ .../upgrade.properties | 3 + .../old.dbscheme | 1242 ++++++++++++++++ .../semmlecode.dbscheme | 1255 +++++++++++++++++ .../upgrade.properties | 2 + 6 files changed, 4999 insertions(+) create mode 100644 java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/old.dbscheme create mode 100644 java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/semmlecode.dbscheme create mode 100644 java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/upgrade.properties create mode 100644 java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme create mode 100644 java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme create mode 100644 java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties diff --git a/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/old.dbscheme b/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/old.dbscheme new file mode 100644 index 00000000000..7cbc85b1f3e --- /dev/null +++ b/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/old.dbscheme @@ -0,0 +1,1255 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * 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: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_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 + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int 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 +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float 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`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + 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 +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string 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 +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@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 +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * 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; + +/* + * 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; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/semmlecode.dbscheme b/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/semmlecode.dbscheme new file mode 100644 index 00000000000..934bf10b4bd --- /dev/null +++ b/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/semmlecode.dbscheme @@ -0,0 +1,1242 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * 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: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#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 + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int 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 +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float 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`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + 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 +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string 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 +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@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 +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * 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; + +/* + * 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; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/upgrade.properties b/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/upgrade.properties new file mode 100644 index 00000000000..0e9d417b1ee --- /dev/null +++ b/java/downgrades/7cbc85b1f3ecda39661ad4806dedbd0973d2c4c0/upgrade.properties @@ -0,0 +1,3 @@ +description: Remove compilation_expanded_args +compatibility: full +compilation_expanded_args.rel: delete diff --git a/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme b/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme new file mode 100644 index 00000000000..934bf10b4bd --- /dev/null +++ b/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/old.dbscheme @@ -0,0 +1,1242 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * 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: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#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 + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int 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 +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float 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`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + 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 +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string 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 +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@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 +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * 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; + +/* + * 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; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme b/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme new file mode 100644 index 00000000000..7cbc85b1f3e --- /dev/null +++ b/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/semmlecode.dbscheme @@ -0,0 +1,1255 @@ +/** + * An invocation of the compiler. Note that more than one file may be + * compiled per invocation. For example, this command compiles three + * source files: + * + * javac A.java B.java C.java + * + * 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: + * + * javac A.java B.java C.java + */ + unique int id : @compilation, + int kind: int ref, + string cwd : string ref, + string name : string ref +); + +case @compilation.kind of + 1 = @javacompilation +| 2 = @kotlincompilation +; + +compilation_started( + int id : @compilation ref +) + +compilation_info( + int id : @compilation ref, + string info_key: string ref, + string info_value: string ref +) + +/** + * The arguments that were passed to the extractor for a compiler + * invocation. If `id` is for the compiler invocation + * + * javac A.java B.java C.java + * + * then typically there will be rows for + * + * num | arg + * --- | --- + * 0 | *path to extractor* + * 1 | `--javac-args` + * 2 | A.java + * 3 | B.java + * 4 | C.java + */ +#keyset[id, num] +compilation_args( + int id : @compilation ref, + int num : int ref, + string arg : string ref +); + +/** + * The expanded arguments that were passed to the extractor for a + * compiler invocation. This is similar to `compilation_args`, but + * for a `@@@someFile` argument, it includes the arguments from that + * file, rather than just taking the argument literally. + */ +#keyset[id, num] +compilation_expanded_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 + * + * javac A.java B.java C.java + * + * then there will be rows for + * + * num | arg + * --- | --- + * 0 | A.java + * 1 | B.java + * 2 | C.java + */ +#keyset[id, num] +compilation_compiling_files( + int id : @compilation ref, + int num : int ref, + int file : @file ref +); + +/** + * For each file recorded in `compilation_compiling_files`, + * there will be a corresponding row in + * `compilation_compiling_files_completed` once extraction + * of that file is complete. The `result` will indicate the + * extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +#keyset[id, num] +compilation_compiling_files_completed( + int id : @compilation ref, + int num : int ref, + int result : int 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 +); + +/** + * The `cpu_seconds` and `elapsed_seconds` are the CPU time and elapsed + * time (respectively) that the original compilation (not the extraction) + * took for compiler invocation `id`. + */ +compilation_compiler_times( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float 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`. + * The `result` will indicate the extraction result: + * + * 0: Successfully extracted + * 1: Errors were encountered, but extraction recovered + * 2: Errors were encountered, and extraction could not recover + */ +compilation_finished( + unique int id : @compilation ref, + float cpu_seconds : float ref, + float elapsed_seconds : float ref, + int result : int ref +); + +diagnostics( + unique int id: @diagnostic, + string generated_by: string ref, // TODO: Sync this with the other languages? + 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 +); + +/* + * External artifacts + */ + +externalData( + int id : @externalDataElement, + string path : string ref, + int column: int ref, + string value : string ref +); + +snapshotDate( + unique date snapshotDate : date ref +); + +sourceLocationPrefix( + string prefix : string ref +); + +/* + * Duplicate code + */ + +duplicateCode( + unique int id : @duplication, + string relativePath : string ref, + int equivClass : int ref +); + +similarCode( + unique int id : @similarity, + string 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 +); + +/* + * SMAP + */ + +smap_header( + int outputFileId: @file ref, + string outputFilename: string ref, + string defaultStratum: string ref +); + +smap_files( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + string inputFileName: string ref, + int inputFileId: @file ref +); + +smap_lines( + int outputFileId: @file ref, + string stratum: string ref, + int inputFileNum: int ref, + int inputStartLine: int ref, + int inputLineCount: int ref, + int outputStartLine: int ref, + int outputLineIncrement: int ref +); + +/* + * Locations and files + */ + +@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 +); + +hasLocation( + int locatableid: @locatable ref, + int id: @location ref +); + +@sourceline = @locatable ; + +#keyset[element_id] +numlines( + int element_id: @sourceline ref, + int num_lines: int ref, + int num_code: int ref, + int num_comment: int ref +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: string ref +); + +@container = @folder | @file + +containerparent( + int parent: @container ref, + unique int child: @container ref +); + +/* + * Java + */ + +cupackage( + unique int id: @file ref, + int packageid: @package ref +); + +#keyset[fileid,keyName] +jarManifestMain( + int fileid: @file ref, + string keyName: string ref, + string value: string ref +); + +#keyset[fileid,entryName,keyName] +jarManifestEntries( + int fileid: @file ref, + string entryName: string ref, + string keyName: string ref, + string value: string ref +); + +packages( + unique int id: @package, + string nodeName: string ref +); + +primitives( + unique int id: @primitive, + string nodeName: string ref +); + +modifiers( + unique int id: @modifier, + string nodeName: string ref +); + +/** + * An errortype is used when the extractor is unable to extract a type + * correctly for some reason. + */ +error_type( + unique int id: @errortype +); + +classes_or_interfaces( + unique int id: @classorinterface, + string nodeName: string ref, + int parentid: @package ref, + int sourceid: @classorinterface ref +); + +file_class( + int id: @classorinterface ref +); + +class_object( + unique int id: @classorinterface ref, + unique int instance: @field ref +); + +type_companion_object( + unique int id: @classorinterface ref, + unique int instance: @field ref, + unique int companion_object: @classorinterface ref +); + +kt_nullable_types( + unique int id: @kt_nullable_type, + int classid: @reftype ref +) + +kt_notnull_types( + unique int id: @kt_notnull_type, + int classid: @reftype ref +) + +kt_type_alias( + unique int id: @kt_type_alias, + string name: string ref, + int kttypeid: @kt_type ref +) + +@kt_type = @kt_nullable_type | @kt_notnull_type + +isInterface( + unique int id: @classorinterface ref +); + +isRecord( + unique int id: @classorinterface ref +); + +fielddecls( + unique int id: @fielddecl, + int parentid: @reftype ref +); + +#keyset[fieldId] #keyset[fieldDeclId,pos] +fieldDeclaredIn( + int fieldId: @field ref, + int fieldDeclId: @fielddecl ref, + int pos: int ref +); + +fields( + unique int id: @field, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @field ref +); + +fieldsKotlinType( + unique int id: @field ref, + int kttypeid: @kt_type ref +); + +constrs( + unique int id: @constructor, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @constructor ref +); + +constrsKotlinType( + unique int id: @constructor ref, + int kttypeid: @kt_type ref +); + +methods( + unique int id: @method, + string nodeName: string ref, + string signature: string ref, + int typeid: @type ref, + int parentid: @reftype ref, + int sourceid: @method ref +); + +methodsKotlinType( + unique int id: @method ref, + int kttypeid: @kt_type ref +); + +#keyset[parentid,pos] +params( + unique int id: @param, + int typeid: @type ref, + int pos: int ref, + int parentid: @callable ref, + int sourceid: @param ref +); + +paramsKotlinType( + unique int id: @param ref, + int kttypeid: @kt_type ref +); + +paramName( + unique int id: @param ref, + string nodeName: string ref +); + +isVarargsParam( + int param: @param ref +); + +exceptions( + unique int id: @exception, + int typeid: @type ref, + int parentid: @callable ref +); + +isAnnotType( + int interfaceid: @classorinterface ref +); + +isAnnotElem( + int methodid: @method ref +); + +annotValue( + int parentid: @annotation ref, + int id2: @method ref, + unique int value: @expr ref +); + +isEnumType( + int classid: @classorinterface ref +); + +isEnumConst( + int fieldid: @field ref +); + +#keyset[parentid,pos] +typeVars( + unique int id: @typevariable, + string nodeName: string ref, + int pos: int ref, + int kind: int ref, // deprecated + int parentid: @classorinterfaceorcallable ref +); + +wildcards( + unique int id: @wildcard, + string nodeName: string ref, + int kind: int ref +); + +#keyset[parentid,pos] +typeBounds( + unique int id: @typebound, + int typeid: @reftype ref, + int pos: int ref, + int parentid: @boundedtype ref +); + +#keyset[parentid,pos] +typeArgs( + int argumentid: @reftype ref, + int pos: int ref, + int parentid: @classorinterfaceorcallable ref +); + +isParameterized( + int memberid: @member ref +); + +isRaw( + int memberid: @member ref +); + +erasure( + unique int memberid: @member ref, + int erasureid: @member ref +); + +#keyset[classid] #keyset[parent] +isAnonymClass( + int classid: @classorinterface ref, + int parent: @classinstancexpr ref +); + +#keyset[typeid] #keyset[parent] +isLocalClassOrInterface( + int typeid: @classorinterface ref, + int parent: @localtypedeclstmt ref +); + +isDefConstr( + int constructorid: @constructor ref +); + +#keyset[exprId] +lambdaKind( + int exprId: @lambdaexpr ref, + int bodyKind: int ref +); + +arrays( + unique int id: @array, + string nodeName: string ref, + int elementtypeid: @type ref, + int dimension: int ref, + int componenttypeid: @type ref +); + +enclInReftype( + unique int child: @reftype ref, + int parent: @reftype ref +); + +extendsReftype( + int id1: @reftype ref, + int id2: @classorinterface ref +); + +implInterface( + int id1: @classorarray ref, + int id2: @classorinterface ref +); + +permits( + int id1: @classorinterface ref, + int id2: @classorinterface ref +); + +hasModifier( + int id1: @modifiable ref, + int id2: @modifier ref +); + +imports( + unique int id: @import, + int holder: @classorinterfaceorpackage ref, + string name: string ref, + int kind: int ref +); + +#keyset[parent,idx] +stmts( + unique int id: @stmt, + int kind: int ref, + int parent: @stmtparent ref, + int idx: int ref, + int bodydecl: @callable ref +); + +@stmtparent = @callable | @stmt | @switchexpr | @whenexpr| @stmtexpr; + +case @stmt.kind of + 0 = @block +| 1 = @ifstmt +| 2 = @forstmt +| 3 = @enhancedforstmt +| 4 = @whilestmt +| 5 = @dostmt +| 6 = @trystmt +| 7 = @switchstmt +| 8 = @synchronizedstmt +| 9 = @returnstmt +| 10 = @throwstmt +| 11 = @breakstmt +| 12 = @continuestmt +| 13 = @emptystmt +| 14 = @exprstmt +| 15 = @labeledstmt +| 16 = @assertstmt +| 17 = @localvariabledeclstmt +| 18 = @localtypedeclstmt +| 19 = @constructorinvocationstmt +| 20 = @superconstructorinvocationstmt +| 21 = @case +| 22 = @catchclause +| 23 = @yieldstmt +| 24 = @errorstmt +| 25 = @whenbranch +; + +#keyset[parent,idx] +exprs( + unique int id: @expr, + int kind: int ref, + int typeid: @type ref, + int parent: @exprparent ref, + int idx: int ref +); + +exprsKotlinType( + unique int id: @expr ref, + int kttypeid: @kt_type ref +); + +callableEnclosingExpr( + unique int id: @expr ref, + int callable_id: @callable ref +); + +statementEnclosingExpr( + unique int id: @expr ref, + int statement_id: @stmt ref +); + +isParenthesized( + unique int id: @expr ref, + int parentheses: int ref +); + +case @expr.kind of + 1 = @arrayaccess +| 2 = @arraycreationexpr +| 3 = @arrayinit +| 4 = @assignexpr +| 5 = @assignaddexpr +| 6 = @assignsubexpr +| 7 = @assignmulexpr +| 8 = @assigndivexpr +| 9 = @assignremexpr +| 10 = @assignandexpr +| 11 = @assignorexpr +| 12 = @assignxorexpr +| 13 = @assignlshiftexpr +| 14 = @assignrshiftexpr +| 15 = @assignurshiftexpr +| 16 = @booleanliteral +| 17 = @integerliteral +| 18 = @longliteral +| 19 = @floatingpointliteral +| 20 = @doubleliteral +| 21 = @characterliteral +| 22 = @stringliteral +| 23 = @nullliteral +| 24 = @mulexpr +| 25 = @divexpr +| 26 = @remexpr +| 27 = @addexpr +| 28 = @subexpr +| 29 = @lshiftexpr +| 30 = @rshiftexpr +| 31 = @urshiftexpr +| 32 = @andbitexpr +| 33 = @orbitexpr +| 34 = @xorbitexpr +| 35 = @andlogicalexpr +| 36 = @orlogicalexpr +| 37 = @ltexpr +| 38 = @gtexpr +| 39 = @leexpr +| 40 = @geexpr +| 41 = @eqexpr +| 42 = @neexpr +| 43 = @postincexpr +| 44 = @postdecexpr +| 45 = @preincexpr +| 46 = @predecexpr +| 47 = @minusexpr +| 48 = @plusexpr +| 49 = @bitnotexpr +| 50 = @lognotexpr +| 51 = @castexpr +| 52 = @newexpr +| 53 = @conditionalexpr +| 54 = @parexpr // deprecated +| 55 = @instanceofexpr +| 56 = @localvariabledeclexpr +| 57 = @typeliteral +| 58 = @thisaccess +| 59 = @superaccess +| 60 = @varaccess +| 61 = @methodaccess +| 62 = @unannotatedtypeaccess +| 63 = @arraytypeaccess +| 64 = @packageaccess +| 65 = @wildcardtypeaccess +| 66 = @declannotation +| 67 = @uniontypeaccess +| 68 = @lambdaexpr +| 69 = @memberref +| 70 = @annotatedtypeaccess +| 71 = @typeannotation +| 72 = @intersectiontypeaccess +| 73 = @switchexpr +| 74 = @errorexpr +| 75 = @whenexpr +| 76 = @getclassexpr +| 77 = @safecastexpr +| 78 = @implicitcastexpr +| 79 = @implicitnotnullexpr +| 80 = @implicitcoerciontounitexpr +| 81 = @notinstanceofexpr +| 82 = @stmtexpr +| 83 = @stringtemplateexpr +| 84 = @notnullexpr +| 85 = @unsafecoerceexpr +| 86 = @valueeqexpr +| 87 = @valueneexpr +| 88 = @propertyref +; + +/** Holds if this `when` expression was written as an `if` expression. */ +when_if(unique int id: @whenexpr ref); + +/** Holds if this `when` branch was written as an `else` branch. */ +when_branch_else(unique int id: @whenbranch ref); + +@classinstancexpr = @newexpr | @lambdaexpr | @memberref | @propertyref + +@annotation = @declannotation | @typeannotation +@typeaccess = @unannotatedtypeaccess | @annotatedtypeaccess + +@assignment = @assignexpr + | @assignop; + +@unaryassignment = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr; + +@assignop = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + | @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignurshiftexpr; + +@literal = @booleanliteral + | @integerliteral + | @longliteral + | @floatingpointliteral + | @doubleliteral + | @characterliteral + | @stringliteral + | @nullliteral; + +@binaryexpr = @mulexpr + | @divexpr + | @remexpr + | @addexpr + | @subexpr + | @lshiftexpr + | @rshiftexpr + | @urshiftexpr + | @andbitexpr + | @orbitexpr + | @xorbitexpr + | @andlogicalexpr + | @orlogicalexpr + | @ltexpr + | @gtexpr + | @leexpr + | @geexpr + | @eqexpr + | @neexpr + | @valueeqexpr + | @valueneexpr; + +@unaryexpr = @postincexpr + | @postdecexpr + | @preincexpr + | @predecexpr + | @minusexpr + | @plusexpr + | @bitnotexpr + | @lognotexpr + | @notnullexpr; + +@caller = @classinstancexpr + | @methodaccess + | @constructorinvocationstmt + | @superconstructorinvocationstmt; + +callableBinding( + unique int callerid: @caller ref, + int callee: @callable ref +); + +memberRefBinding( + unique int id: @expr ref, + int callable: @callable ref +); + +propertyRefGetBinding( + unique int id: @expr ref, + int getter: @callable ref +); + +propertyRefFieldBinding( + unique int id: @expr ref, + int field: @field ref +); + +propertyRefSetBinding( + unique int id: @expr ref, + int setter: @callable ref +); + +@exprparent = @stmt | @expr | @whenbranch | @callable | @field | @fielddecl | @classorinterface | @param | @localvar | @typevariable; + +variableBinding( + unique int expr: @varaccess ref, + int variable: @variable ref +); + +@variable = @localscopevariable | @field; + +@localscopevariable = @localvar | @param; + +localvars( + unique int id: @localvar, + string nodeName: string ref, + int typeid: @type ref, + int parentid: @localvariabledeclexpr ref +); + +localvarsKotlinType( + unique int id: @localvar ref, + int kttypeid: @kt_type ref +); + +@namedexprorstmt = @breakstmt + | @continuestmt + | @labeledstmt + | @literal; + +namestrings( + string name: string ref, + string value: string ref, + unique int parent: @namedexprorstmt ref +); + +/* + * Modules + */ + +#keyset[name] +modules( + unique int id: @module, + string name: string ref +); + +isOpen( + int id: @module ref +); + +#keyset[fileId] +cumodule( + int fileId: @file ref, + int moduleId: @module ref +); + +@directive = @requires + | @exports + | @opens + | @uses + | @provides + +#keyset[directive] +directives( + int id: @module ref, + int directive: @directive ref +); + +requires( + unique int id: @requires, + int target: @module ref +); + +isTransitive( + int id: @requires ref +); + +isStatic( + int id: @requires ref +); + +exports( + unique int id: @exports, + int target: @package ref +); + +exportsTo( + int id: @exports ref, + int target: @module ref +); + +opens( + unique int id: @opens, + int target: @package ref +); + +opensTo( + int id: @opens ref, + int target: @module ref +); + +uses( + unique int id: @uses, + string serviceInterface: string ref +); + +provides( + unique int id: @provides, + string serviceInterface: string ref +); + +providesWith( + int id: @provides ref, + string serviceImpl: string ref +); + +/* + * Javadoc + */ + +javadoc( + unique int id: @javadoc +); + +isNormalComment( + int commentid : @javadoc ref +); + +isEolComment( + int commentid : @javadoc ref +); + +hasJavadoc( + int documentableid: @member ref, + int javadocid: @javadoc ref +); + +#keyset[parentid,idx] +javadocTag( + unique int id: @javadocTag, + string name: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +#keyset[parentid,idx] +javadocText( + unique int id: @javadocText, + string text: string ref, + int parentid: @javadocParent ref, + int idx: int ref +); + +@javadocParent = @javadoc | @javadocTag; +@javadocElement = @javadocTag | @javadocText; + +@classorinterfaceorpackage = @classorinterface | @package; +@classorinterfaceorcallable = @classorinterface | @callable; +@boundedtype = @typevariable | @wildcard; +@reftype = @classorinterface | @array | @boundedtype | @errortype; +@classorarray = @classorinterface | @array; +@type = @primitive | @reftype; +@callable = @method | @constructor; + +/** A program element that has a name. */ +@element = @package | @modifier | @annotation | @errortype | + @locatableElement; + +@locatableElement = @file | @primitive | @classorinterface | @method | @constructor | @param | @exception | @field | + @boundedtype | @array | @localvar | @expr | @stmt | @import | @fielddecl | @kt_type | @kt_type_alias | + @kt_property; + +@modifiable = @member_modifiable| @param | @localvar | @typevariable; + +@member_modifiable = @classorinterface | @method | @constructor | @field | @kt_property; + +@member = @method | @constructor | @field | @reftype ; + +/** A program element that has a location. */ +@locatable = @typebound | @javadoc | @javadocTag | @javadocText | @xmllocatable | @ktcomment | + @locatableElement; + +@top = @element | @locatable | @folder; + +/* + * 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; + +/* + * 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; + +ktComments( + unique int id: @ktcomment, + int kind: int ref, + string text : string ref +) + +ktCommentSections( + unique int id: @ktcommentsection, + int comment: @ktcomment ref, + string content : string ref +) + +ktCommentSectionNames( + unique int id: @ktcommentsection ref, + string name : string ref +) + +ktCommentSectionSubjectNames( + unique int id: @ktcommentsection ref, + string subjectname : string ref +) + +#keyset[id, owner] +ktCommentOwners( + int id: @ktcomment ref, + int owner: @top ref +) + +ktExtensionFunctions( + unique int id: @method ref, + int typeid: @type ref, + int kttypeid: @kt_type ref +) + +ktProperties( + unique int id: @kt_property, + string nodeName: string ref +) + +ktPropertyGetters( + unique int id: @kt_property ref, + int getter: @method ref +) + +ktPropertySetters( + unique int id: @kt_property ref, + int setter: @method ref +) + +ktPropertyBackingFields( + unique int id: @kt_property ref, + int backingField: @field ref +) + +ktSyntheticBody( + unique int id: @callable ref, + int kind: int ref + // 1: ENUM_VALUES + // 2: ENUM_VALUEOF +) + +ktLocalFunction( + unique int id: @method ref +) + +ktInitializerAssignment( + unique int id: @assignexpr ref +) + +ktPropertyDelegates( + unique int id: @kt_property ref, + unique int variableId: @variable ref +) + +/** + * If `id` is a compiler generated element, then the kind indicates the + * reason that the compiler generated it. + * See `Element.compilerGeneratedReason()` for an explanation of what + * each `kind` means. + */ +compiler_generated( + unique int id: @element ref, + int kind: int ref +) + +ktFunctionOriginalNames( + unique int id: @method ref, + string name: string ref +) + +ktDataClasses( + unique int id: @classorinterface ref +) diff --git a/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties b/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties new file mode 100644 index 00000000000..652e17fd503 --- /dev/null +++ b/java/ql/lib/upgrades/934bf10b4bd34cf648893efcd1d0d7be9471d39f/upgrade.properties @@ -0,0 +1,2 @@ +description: Add compilation_expanded_args +compatibility: backwards From 8250e4393c438bf43a93d88b8f9d3b5630f47596 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Thu, 30 Mar 2023 10:59:12 -0400 Subject: [PATCH 080/141] Typos and rewording Co-authored-by: Tony Torralba --- .../2023-03-29-moved-configurations-for-queries.md | 2 +- .../semmle/code/java/security/InsecureBeanValidationQuery.qll | 2 +- java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md b/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md index d7cc29f5521..e562d714894 100644 --- a/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md +++ b/java/ql/lib/change-notes/2023-03-29-moved-configurations-for-queries.md @@ -3,7 +3,7 @@ category: minorAnalysis --- * Added the `TaintedPathQuery.qll` library to provide the `TaintedPathFlow` and `TaintedPathLocalFlow` taint-tracking modules to reason about tainted path vulnerabilities. * Added the `ZipSlipQuery.qll` library to provide the `ZipSlipFlow` taint-tracking module to reason about zip-slip vulnerabilities. -* Added the `InsecureBeanValidationQuery.qll` library to provide the `BeanValidationFlow` taint-tracking module to reason about bean validation vulnerabilities. +* Added the `InsecureBeanValidationQuery.qll` library to provide the `BeanValidationFlow` taint-tracking module to reason about bean validation vulnerabilities. * Added the `XssQuery.qll` library to provide the `XssFlow` taint-tracking module to reason about cross site scripting vulnerabilities. * Added the `LdapInjectionQuery.qll` library to provide the `LdapInjectionFlow` taint-tracking module to reason about LDAP injection vulnerabilities. * Added the `ResponseSplittingQuery.qll` library to provide the `ResponseSplittingFlow` taint-tracking module to reason about response splitting vulnerabilities. diff --git a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll index 198cf7fb57c..48ba6547ef1 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll @@ -6,7 +6,7 @@ import semmle.code.java.dataflow.FlowSources private import semmle.code.java.dataflow.ExternalFlow /** - * A message interpolator Type that perform Expression Language (EL) evaluations + * A message interpolator Type that perform Expression Language (EL) evaluations. */ class ELMessageInterpolatorType extends RefType { ELMessageInterpolatorType() { diff --git a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll index 8ce1bbdc886..27a54d0ecfa 100644 --- a/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll +++ b/java/ql/lib/semmle/code/java/security/TaintedPathQuery.qll @@ -77,7 +77,7 @@ module TaintedPathConfig implements DataFlow::ConfigSig { module TaintedPathFlow = TaintTracking::Global; /** - * A taint-tracking configuration for tracking flow from user input to the creation of a path. + * A taint-tracking configuration for tracking flow from local user input to the creation of a path. */ module TaintedPathLocalConfig implements DataFlow::ConfigSig { predicate isSource(DataFlow::Node source) { source instanceof LocalUserInput } @@ -100,5 +100,5 @@ module TaintedPathLocalConfig implements DataFlow::ConfigSig { } } -/** Tracks flow from user input to the creation of a path. */ +/** Tracks flow from local user input to the creation of a path. */ module TaintedPathLocalFlow = TaintTracking::Global; From c7a049a867cef19b690794aa55ff1764de0305c9 Mon Sep 17 00:00:00 2001 From: Edward Minnix III Date: Thu, 30 Mar 2023 11:00:00 -0400 Subject: [PATCH 081/141] Mark things which can be private as private Co-authored-by: Tony Torralba --- .../semmle/code/java/security/InsecureBeanValidationQuery.qll | 4 ++-- java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll index 48ba6547ef1..bc47d7ecd10 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll @@ -8,7 +8,7 @@ private import semmle.code.java.dataflow.ExternalFlow /** * A message interpolator Type that perform Expression Language (EL) evaluations. */ -class ELMessageInterpolatorType extends RefType { +private class ELMessageInterpolatorType extends RefType { ELMessageInterpolatorType() { this.getASourceSupertype*() .hasQualifiedName("org.hibernate.validator.messageinterpolation", @@ -19,7 +19,7 @@ class ELMessageInterpolatorType extends RefType { /** * A method call that sets the application's default message interpolator. */ -class SetMessageInterpolatorCall extends MethodAccess { +private class SetMessageInterpolatorCall extends MethodAccess { SetMessageInterpolatorCall() { exists(Method m, RefType t | this.getMethod() = m and diff --git a/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll b/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll index 61323e034d6..78499c69be0 100644 --- a/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll @@ -10,7 +10,7 @@ private import semmle.code.java.dataflow.ExternalFlow /** * A method that returns the name of an archive entry. */ -class ArchiveEntryNameMethod extends Method { +private class ArchiveEntryNameMethod extends Method { ArchiveEntryNameMethod() { exists(RefType archiveEntry | archiveEntry.hasQualifiedName("java.util.zip", "ZipEntry") or From dba5e9e9e271f107bfb7aaddc042bc23af85a827 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 30 Mar 2023 11:03:48 -0400 Subject: [PATCH 082/141] Updates to imports Make some imports private Remove unnecessary imports --- .../java/security/ExternallyControlledFormatStringQuery.qll | 4 ++-- .../lib/semmle/code/java/security/ResponseSplittingQuery.qll | 2 +- java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll | 2 -- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll b/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll index 64448b9012a..25d4e2b4fa5 100644 --- a/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ExternallyControlledFormatStringQuery.qll @@ -1,8 +1,8 @@ /** Provides a taint-tracking configuration to reason about externally controlled format string vulnerabilities. */ import java -import semmle.code.java.dataflow.FlowSources -import semmle.code.java.StringFormat +private import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.StringFormat /** * A taint-tracking configuration for externally controlled format string vulnerabilities. diff --git a/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll b/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll index 95eaab22e0d..5ac4953422a 100644 --- a/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ResponseSplittingQuery.qll @@ -1,7 +1,7 @@ /** Provides a taint tracking configuration to reason about response splitting vulnerabilities. */ import java -import semmle.code.java.dataflow.FlowSources +private import semmle.code.java.dataflow.FlowSources import semmle.code.java.security.ResponseSplitting /** diff --git a/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll b/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll index 78499c69be0..6eaa372075b 100644 --- a/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll +++ b/java/ql/lib/semmle/code/java/security/ZipSlipQuery.qll @@ -1,8 +1,6 @@ /** Provides dataflow configurations to be used in ZipSlip queries. */ import java -import semmle.code.java.controlflow.Guards -import semmle.code.java.dataflow.SSA import semmle.code.java.dataflow.TaintTracking import semmle.code.java.security.PathSanitizer private import semmle.code.java.dataflow.ExternalFlow From ecbd3be5e9da8add96e9017dfa6fffac4732b6a5 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 30 Mar 2023 11:08:41 -0400 Subject: [PATCH 083/141] Remove private marker This class is used in the actual query, so it needs to be exposed. --- .../semmle/code/java/security/InsecureBeanValidationQuery.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll index bc47d7ecd10..3d7c7f2fa94 100644 --- a/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/InsecureBeanValidationQuery.qll @@ -19,7 +19,7 @@ private class ELMessageInterpolatorType extends RefType { /** * A method call that sets the application's default message interpolator. */ -private class SetMessageInterpolatorCall extends MethodAccess { +class SetMessageInterpolatorCall extends MethodAccess { SetMessageInterpolatorCall() { exists(Method m, RefType t | this.getMethod() = m and From beb7d9d7a1f7cba0d4a87465e9c4a775dfa5a024 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 20 Jan 2023 17:43:18 +0000 Subject: [PATCH 084/141] Swift: Test layout change. --- .../CWE-311/CleartextStorageDatabase.expected | 68 +++++++++---------- .../Security/CWE-311/SensitiveExprs.expected | 8 +-- .../Security/CWE-311/testRealm.swift | 19 ++++-- 3 files changed, 51 insertions(+), 44 deletions(-) diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected index 540cdad43da..4d6cc43192f 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected @@ -168,19 +168,19 @@ edges | testGRDB.swift:208:81:208:81 | password : | testGRDB.swift:208:80:208:89 | [...] | | testGRDB.swift:210:85:210:85 | password : | testGRDB.swift:210:84:210:93 | [...] | | testGRDB.swift:212:99:212:99 | password : | testGRDB.swift:212:98:212:107 | [...] | -| testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | value : | -| testRealm.swift:34:2:34:2 | [post] a [data] : | testRealm.swift:34:2:34:2 | [post] a | -| testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | -| testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:34:2:34:2 | [post] a [data] : | -| testRealm.swift:42:2:42:2 | [post] c [data] : | testRealm.swift:42:2:42:2 | [post] c | -| testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | -| testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:42:2:42:2 | [post] c [data] : | -| testRealm.swift:52:2:52:3 | [post] ...! [data] : | testRealm.swift:52:2:52:3 | [post] ...! | -| testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:16:6:16:6 | value : | -| testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:52:2:52:3 | [post] ...! [data] : | -| testRealm.swift:59:2:59:2 | [post] g [data] : | testRealm.swift:59:2:59:2 | [post] g | -| testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | -| testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:59:2:59:2 | [post] g [data] : | +| testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | value : | +| testRealm.swift:41:2:41:2 | [post] a [data] : | testRealm.swift:41:2:41:2 | [post] a | +| testRealm.swift:41:11:41:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | +| testRealm.swift:41:11:41:11 | myPassword : | testRealm.swift:41:2:41:2 | [post] a [data] : | +| testRealm.swift:49:2:49:2 | [post] c [data] : | testRealm.swift:49:2:49:2 | [post] c | +| testRealm.swift:49:11:49:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | +| testRealm.swift:49:11:49:11 | myPassword : | testRealm.swift:49:2:49:2 | [post] c [data] : | +| testRealm.swift:59:2:59:3 | [post] ...! [data] : | testRealm.swift:59:2:59:3 | [post] ...! | +| testRealm.swift:59:12:59:12 | myPassword : | testRealm.swift:27:6:27:6 | value : | +| testRealm.swift:59:12:59:12 | myPassword : | testRealm.swift:59:2:59:3 | [post] ...! [data] : | +| testRealm.swift:66:2:66:2 | [post] g [data] : | testRealm.swift:66:2:66:2 | [post] g | +| testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | +| testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:66:2:66:2 | [post] g [data] : | nodes | file://:0:0:0:0 | .value2 : | semmle.label | .value2 : | | file://:0:0:0:0 | .value : | semmle.label | .value : | @@ -421,19 +421,19 @@ nodes | testGRDB.swift:210:85:210:85 | password : | semmle.label | password : | | testGRDB.swift:212:98:212:107 | [...] | semmle.label | [...] | | testGRDB.swift:212:99:212:99 | password : | semmle.label | password : | -| testRealm.swift:16:6:16:6 | value : | semmle.label | value : | -| testRealm.swift:34:2:34:2 | [post] a | semmle.label | [post] a | -| testRealm.swift:34:2:34:2 | [post] a [data] : | semmle.label | [post] a [data] : | -| testRealm.swift:34:11:34:11 | myPassword : | semmle.label | myPassword : | -| testRealm.swift:42:2:42:2 | [post] c | semmle.label | [post] c | -| testRealm.swift:42:2:42:2 | [post] c [data] : | semmle.label | [post] c [data] : | -| testRealm.swift:42:11:42:11 | myPassword : | semmle.label | myPassword : | -| testRealm.swift:52:2:52:3 | [post] ...! | semmle.label | [post] ...! | -| testRealm.swift:52:2:52:3 | [post] ...! [data] : | semmle.label | [post] ...! [data] : | -| testRealm.swift:52:12:52:12 | myPassword : | semmle.label | myPassword : | -| testRealm.swift:59:2:59:2 | [post] g | semmle.label | [post] g | -| testRealm.swift:59:2:59:2 | [post] g [data] : | semmle.label | [post] g [data] : | -| testRealm.swift:59:11:59:11 | myPassword : | semmle.label | myPassword : | +| testRealm.swift:27:6:27:6 | value : | semmle.label | value : | +| testRealm.swift:41:2:41:2 | [post] a | semmle.label | [post] a | +| testRealm.swift:41:2:41:2 | [post] a [data] : | semmle.label | [post] a [data] : | +| testRealm.swift:41:11:41:11 | myPassword : | semmle.label | myPassword : | +| testRealm.swift:49:2:49:2 | [post] c | semmle.label | [post] c | +| testRealm.swift:49:2:49:2 | [post] c [data] : | semmle.label | [post] c [data] : | +| testRealm.swift:49:11:49:11 | myPassword : | semmle.label | myPassword : | +| testRealm.swift:59:2:59:3 | [post] ...! | semmle.label | [post] ...! | +| testRealm.swift:59:2:59:3 | [post] ...! [data] : | semmle.label | [post] ...! [data] : | +| testRealm.swift:59:12:59:12 | myPassword : | semmle.label | myPassword : | +| testRealm.swift:66:2:66:2 | [post] g | semmle.label | [post] g | +| testRealm.swift:66:2:66:2 | [post] g [data] : | semmle.label | [post] g [data] : | +| testRealm.swift:66:11:66:11 | myPassword : | semmle.label | myPassword : | subpaths | testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : | | testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : | @@ -449,10 +449,10 @@ subpaths | testCoreData2.swift:98:18:98:18 | d [value] : | testCoreData2.swift:70:9:70:9 | self [value] : | file://:0:0:0:0 | .value : | testCoreData2.swift:98:18:98:20 | .value : | | testCoreData2.swift:104:18:104:18 | e : | testCoreData2.swift:70:9:70:9 | self : | file://:0:0:0:0 | .value : | testCoreData2.swift:104:18:104:20 | .value : | | testCoreData2.swift:105:18:105:18 | e : | testCoreData2.swift:71:9:71:9 | self : | file://:0:0:0:0 | .value2 : | testCoreData2.swift:105:18:105:20 | .value2 : | -| testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:34:2:34:2 | [post] a [data] : | -| testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:42:2:42:2 | [post] c [data] : | -| testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:52:2:52:3 | [post] ...! [data] : | -| testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:16:6:16:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:59:2:59:2 | [post] g [data] : | +| testRealm.swift:41:11:41:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:41:2:41:2 | [post] a [data] : | +| testRealm.swift:49:11:49:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:49:2:49:2 | [post] c [data] : | +| testRealm.swift:59:12:59:12 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:59:2:59:3 | [post] ...! [data] : | +| testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:66:2:66:2 | [post] g [data] : | #select | testCoreData2.swift:37:2:37:2 | obj | testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:37:16:37:16 | bankAccountNo : | bankAccountNo | | testCoreData2.swift:39:2:39:2 | obj | testCoreData2.swift:39:28:39:28 | bankAccountNo : | testCoreData2.swift:39:2:39:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:39:28:39:28 | bankAccountNo : | bankAccountNo | @@ -542,7 +542,7 @@ subpaths | testGRDB.swift:208:80:208:89 | [...] | testGRDB.swift:208:81:208:81 | password : | testGRDB.swift:208:80:208:89 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:208:81:208:81 | password : | password | | testGRDB.swift:210:84:210:93 | [...] | testGRDB.swift:210:85:210:85 | password : | testGRDB.swift:210:84:210:93 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:210:85:210:85 | password : | password | | testGRDB.swift:212:98:212:107 | [...] | testGRDB.swift:212:99:212:99 | password : | testGRDB.swift:212:98:212:107 | [...] | This operation stores '[...]' in a database. It may contain unencrypted sensitive data from $@. | testGRDB.swift:212:99:212:99 | password : | password | -| testRealm.swift:34:2:34:2 | a | testRealm.swift:34:11:34:11 | myPassword : | testRealm.swift:34:2:34:2 | [post] a | This operation stores 'a' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:34:11:34:11 | myPassword : | myPassword | -| testRealm.swift:42:2:42:2 | c | testRealm.swift:42:11:42:11 | myPassword : | testRealm.swift:42:2:42:2 | [post] c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:42:11:42:11 | myPassword : | myPassword | -| testRealm.swift:52:2:52:3 | ...! | testRealm.swift:52:12:52:12 | myPassword : | testRealm.swift:52:2:52:3 | [post] ...! | This operation stores '...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:52:12:52:12 | myPassword : | myPassword | -| testRealm.swift:59:2:59:2 | g | testRealm.swift:59:11:59:11 | myPassword : | testRealm.swift:59:2:59:2 | [post] g | This operation stores 'g' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:11:59:11 | myPassword : | myPassword | +| testRealm.swift:41:2:41:2 | a | testRealm.swift:41:11:41:11 | myPassword : | testRealm.swift:41:2:41:2 | [post] a | This operation stores 'a' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:41:11:41:11 | myPassword : | myPassword | +| testRealm.swift:49:2:49:2 | c | testRealm.swift:49:11:49:11 | myPassword : | testRealm.swift:49:2:49:2 | [post] c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:49:11:49:11 | myPassword : | myPassword | +| testRealm.swift:59:2:59:3 | ...! | testRealm.swift:59:12:59:12 | myPassword : | testRealm.swift:59:2:59:3 | [post] ...! | This operation stores '...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:12:59:12 | myPassword : | myPassword | +| testRealm.swift:66:2:66:2 | g | testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:66:2:66:2 | [post] g | This operation stores 'g' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:66:11:66:11 | myPassword : | myPassword | diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected index 4f0e89775e4..261bdf78e70 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected @@ -111,10 +111,10 @@ | testGRDB.swift:208:81:208:81 | password | label:password, type:credential | | testGRDB.swift:210:85:210:85 | password | label:password, type:credential | | testGRDB.swift:212:99:212:99 | password | label:password, type:credential | -| testRealm.swift:34:11:34:11 | myPassword | label:myPassword, type:credential | -| testRealm.swift:42:11:42:11 | myPassword | label:myPassword, type:credential | -| testRealm.swift:52:12:52:12 | myPassword | label:myPassword, type:credential | -| testRealm.swift:59:11:59:11 | myPassword | label:myPassword, type:credential | +| testRealm.swift:41:11:41:11 | myPassword | label:myPassword, type:credential | +| testRealm.swift:49:11:49:11 | myPassword | label:myPassword, type:credential | +| testRealm.swift:59:12:59:12 | myPassword | label:myPassword, type:credential | +| testRealm.swift:66:11:66:11 | myPassword | label:myPassword, type:credential | | testSend.swift:29:19:29:19 | passwordPlain | label:passwordPlain, type:credential | | testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential | | testSend.swift:45:13:45:13 | password | label:password, type:credential | diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift index 61ed4d9c2b6..3475a61531a 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift @@ -10,12 +10,6 @@ class RealmSwiftObject { typealias Object = RealmSwiftObject -class MyRealmSwiftObject : RealmSwiftObject { - override init() { data = "" } - - var data: String -} - class Realm { func add(_ object: Object, update: UpdatePolicy = .error) {} @@ -27,6 +21,19 @@ class Realm { // --- tests --- +class MyRealmSwiftObject : RealmSwiftObject { + override init() { data = "" } + + var data: String +} + + + + + + + + func test1(realm : Realm, myPassword : String, myHashedPassword : String) { // add objects (within a transaction) ... From daa8141414ed76eae2e7a606ff7373e4403cdfa3 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 20 Jan 2023 17:49:21 +0000 Subject: [PATCH 085/141] Swift: Add test case. --- .../Security/CWE-311/SensitiveExprs.expected | 3 +++ .../Security/CWE-311/testRealm.swift | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected index 261bdf78e70..ef794d4004a 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/SensitiveExprs.expected @@ -111,10 +111,13 @@ | testGRDB.swift:208:81:208:81 | password | label:password, type:credential | | testGRDB.swift:210:85:210:85 | password | label:password, type:credential | | testGRDB.swift:212:99:212:99 | password | label:password, type:credential | +| testRealm.swift:31:20:31:20 | .password | label:password, type:credential | | testRealm.swift:41:11:41:11 | myPassword | label:myPassword, type:credential | | testRealm.swift:49:11:49:11 | myPassword | label:myPassword, type:credential | | testRealm.swift:59:12:59:12 | myPassword | label:myPassword, type:credential | | testRealm.swift:66:11:66:11 | myPassword | label:myPassword, type:credential | +| testRealm.swift:73:2:73:4 | .password | label:password, type:credential | +| testRealm.swift:73:15:73:15 | myPassword | label:myPassword, type:credential | | testSend.swift:29:19:29:19 | passwordPlain | label:passwordPlain, type:credential | | testSend.swift:33:19:33:19 | passwordPlain | label:passwordPlain, type:credential | | testSend.swift:45:13:45:13 | password | label:password, type:credential | diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift index 3475a61531a..87a1530ea63 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift @@ -27,14 +27,14 @@ class MyRealmSwiftObject : RealmSwiftObject { var data: String } +class MyRealmSwiftObject2 : Object { + override init() { password = "" } + var username: String? + var password: String? +} - - - - - -func test1(realm : Realm, myPassword : String, myHashedPassword : String) { +func test1(realm : Realm, myUsername: String, myPassword : String, myHashedPassword : String) { // add objects (within a transaction) ... let a = MyRealmSwiftObject() @@ -65,6 +65,13 @@ func test1(realm : Realm, myPassword : String, myHashedPassword : String) { g.data = "" // GOOD (not sensitive) g.data = myPassword // BAD g.data = "" // GOOD (not sensitive) + + // MyRealmSwiftObject2... + + let h = MyRealmSwiftObject2() + h.username = myUsername // GOOD (not sensitive) + h.password = myPassword // BAD [NOT DETECTED] + realm.add(h) } // limitation: its possible to configure a Realm DB to be stored encrypted, if this is done correctly From 684408a493eee62e6e7bd9a664d294742d5ac3a3 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 30 Mar 2023 11:20:35 -0400 Subject: [PATCH 086/141] Fix StringFormat import --- .../src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql | 1 + 1 file changed, 1 insertion(+) diff --git a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql index 1b6adf1ade7..fc5af977a33 100644 --- a/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql +++ b/java/ql/src/Security/CWE/CWE-134/ExternallyControlledFormatString.ql @@ -12,6 +12,7 @@ import java import semmle.code.java.security.ExternallyControlledFormatStringQuery +import semmle.code.java.StringFormat import ExternallyControlledFormatStringFlow::PathGraph from From 03078603bf6fa8e4c8783f7adbb65c0fad0450f9 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 30 Mar 2023 11:24:33 -0400 Subject: [PATCH 087/141] Reinstate private markers on additional predicates --- .../code/java/security/UnsafeDeserializationQuery.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index b6d78b6318e..af998cdc6b7 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -75,7 +75,7 @@ private module SafeKryoConfig implements DataFlow::ConfigSig { * Holds when a functional expression is used to create a `KryoPool.Builder`. * Eg. `new KryoPool.Builder(() -> new Kryo())` */ - additional predicate stepKryoPoolBuilderFactoryArgToConstructor( + private predicate stepKryoPoolBuilderFactoryArgToConstructor( DataFlow::Node node1, DataFlow::Node node2 ) { exists(ConstructorCall cc, FunctionalExpr fe | @@ -90,7 +90,7 @@ private module SafeKryoConfig implements DataFlow::ConfigSig { * Holds when a `KryoPool.run` is called to use a `Kryo` instance. * Eg. `pool.run(kryo -> ...)` */ - additional predicate stepKryoPoolRunMethodAccessQualifierToFunctionalArgument( + private predicate stepKryoPoolRunMethodAccessQualifierToFunctionalArgument( DataFlow::Node node1, DataFlow::Node node2 ) { exists(MethodAccess ma | @@ -103,7 +103,7 @@ private module SafeKryoConfig implements DataFlow::ConfigSig { /** * Holds when a `KryoPool.Builder` method is called fluently. */ - additional predicate stepKryoPoolBuilderChainMethod(DataFlow::Node node1, DataFlow::Node node2) { + private predicate stepKryoPoolBuilderChainMethod(DataFlow::Node node1, DataFlow::Node node2) { exists(MethodAccess ma | ma.getMethod() instanceof KryoPoolBuilderMethod and ma = node2.asExpr() and @@ -114,7 +114,7 @@ private module SafeKryoConfig implements DataFlow::ConfigSig { /** * Holds when a `KryoPool.borrow` method is called. */ - additional predicate stepKryoPoolBorrowMethod(DataFlow::Node node1, DataFlow::Node node2) { + private predicate stepKryoPoolBorrowMethod(DataFlow::Node node1, DataFlow::Node node2) { exists(MethodAccess ma | ma.getMethod() = any(Method m | m.getDeclaringType() instanceof KryoPool and m.hasName("borrow")) and From ac218ba08ba7937a88ce597dcafc8d4fba9afc2f Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Thu, 30 Mar 2023 22:03:05 -0400 Subject: [PATCH 088/141] Replace private classes with one method to predicates --- .../security/UnsafeDeserializationQuery.qll | 132 +++++++++--------- 1 file changed, 63 insertions(+), 69 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index af998cdc6b7..0d03ec40117 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -223,76 +223,72 @@ class UnsafeDeserializationSink extends DataFlow::ExprNode { MethodAccess getMethodAccess() { unsafeDeserialization(result, this.getExpr()) } } -/** A sanitizer for unsafe deserialization */ -private class UnsafeDeserializationSanitizer extends DataFlow::Node { - UnsafeDeserializationSanitizer() { - exists(ClassInstanceExpr cie | - cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and - cie = this.asExpr() and - SafeJsonIoFlow::flowToExpr(cie.getArgument(1)) - ) - or - exists(MethodAccess ma | - ma.getMethod() instanceof JsonIoJsonToJavaMethod and - ma.getArgument(0) = this.asExpr() and - SafeJsonIoFlow::flowToExpr(ma.getArgument(1)) - ) - or - exists(MethodAccess ma | - // Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears - // to be called with an explicit class argument limiting those types that can - // be instantiated during deserialization. - ma.getMethod() instanceof JoddJsonParseMethod and +/** Holds if `node` is a sanitizer for unsafe deserialization */ +private predicate isUnsafeDeserializationSanitizer(DataFlow::Node node) { + exists(ClassInstanceExpr cie | + cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader and + cie = node.asExpr() and + SafeJsonIoFlow::flowToExpr(cie.getArgument(1)) + ) + or + exists(MethodAccess ma | + ma.getMethod() instanceof JsonIoJsonToJavaMethod and + ma.getArgument(0) = node.asExpr() and + SafeJsonIoFlow::flowToExpr(ma.getArgument(1)) + ) + or + exists(MethodAccess ma | + // Sanitize the input to jodd.json.JsonParser.parse et al whenever it appears + // to be called with an explicit class argument limiting those types that can + // be instantiated during deserialization. + ma.getMethod() instanceof JoddJsonParseMethod and + ma.getArgument(1).getType() instanceof TypeClass and + not ma.getArgument(1) instanceof NullLiteral and + not ma.getArgument(1).getType().getName() = ["Class", "Class"] and + node.asExpr() = ma.getAnArgument() + ) + or + exists(MethodAccess ma | + // Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears + // to be called with an explicit class argument limiting those types that can + // be instantiated during deserialization, or if the deserializer has already been + // configured to use a specified root class. + ma.getMethod() instanceof FlexjsonDeserializeMethod and + node.asExpr() = ma.getAnArgument() and + ( ma.getArgument(1).getType() instanceof TypeClass and not ma.getArgument(1) instanceof NullLiteral and - not ma.getArgument(1).getType().getName() = ["Class", "Class"] and - this.asExpr() = ma.getAnArgument() + not ma.getArgument(1).getType().getName() = ["Class", "Class"] + or + isSafeFlexjsonDeserializer(ma.getQualifier()) ) - or - exists(MethodAccess ma | - // Sanitize the input to flexjson.JSONDeserializer.deserialize whenever it appears - // to be called with an explicit class argument limiting those types that can - // be instantiated during deserialization, or if the deserializer has already been - // configured to use a specified root class. - ma.getMethod() instanceof FlexjsonDeserializeMethod and - this.asExpr() = ma.getAnArgument() and - ( - ma.getArgument(1).getType() instanceof TypeClass and - not ma.getArgument(1) instanceof NullLiteral and - not ma.getArgument(1).getType().getName() = ["Class", "Class"] - or - isSafeFlexjsonDeserializer(ma.getQualifier()) - ) - ) - } + ) } /** Taint step for Unsafe deserialization */ -private class UnsafeDeserializationAdditionalTaintStep extends Unit { - predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - exists(ClassInstanceExpr cie | - cie.getArgument(0) = pred.asExpr() and - cie = succ.asExpr() and - ( - cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or - cie.getConstructor().getDeclaringType() instanceof YamlBeansReader or - cie.getConstructor().getDeclaringType().getAnAncestor() instanceof UnsafeHessianInput or - cie.getConstructor().getDeclaringType() instanceof BurlapInput - ) +private predicate isUnsafeDeserializationTaintStep(DataFlow::Node pred, DataFlow::Node succ) { + exists(ClassInstanceExpr cie | + cie.getArgument(0) = pred.asExpr() and + cie = succ.asExpr() and + ( + cie.getConstructor().getDeclaringType() instanceof JsonIoJsonReader or + cie.getConstructor().getDeclaringType() instanceof YamlBeansReader or + cie.getConstructor().getDeclaringType().getAnAncestor() instanceof UnsafeHessianInput or + cie.getConstructor().getDeclaringType() instanceof BurlapInput ) - or - exists(MethodAccess ma | - ma.getMethod() instanceof BurlapInputInitMethod and - ma.getArgument(0) = pred.asExpr() and - ma.getQualifier() = succ.asExpr() - ) - or - createJacksonJsonParserStep(pred, succ) - or - createJacksonTreeNodeStep(pred, succ) - or - intentFlowsToParcel(pred, succ) - } + ) + or + exists(MethodAccess ma | + ma.getMethod() instanceof BurlapInputInitMethod and + ma.getArgument(0) = pred.asExpr() and + ma.getQualifier() = succ.asExpr() + ) + or + createJacksonJsonParserStep(pred, succ) + or + createJacksonTreeNodeStep(pred, succ) + or + intentFlowsToParcel(pred, succ) } /** @@ -308,12 +304,10 @@ deprecated class UnsafeDeserializationConfig extends TaintTracking::Configuratio override predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink } override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) { - any(UnsafeDeserializationAdditionalTaintStep s).isAdditionalTaintStep(pred, succ) + isUnsafeDeserializationTaintStep(pred, succ) } - override predicate isSanitizer(DataFlow::Node node) { - node instanceof UnsafeDeserializationSanitizer - } + override predicate isSanitizer(DataFlow::Node node) { isUnsafeDeserializationSanitizer(node) } } /** Tracks flows from remote user input to a deserialization sink. */ @@ -323,10 +317,10 @@ private module UnsafeDeserializationConfig implements DataFlow::ConfigSig { predicate isSink(DataFlow::Node sink) { sink instanceof UnsafeDeserializationSink } predicate isAdditionalFlowStep(DataFlow::Node pred, DataFlow::Node succ) { - any(UnsafeDeserializationAdditionalTaintStep s).isAdditionalTaintStep(pred, succ) + isUnsafeDeserializationTaintStep(pred, succ) } - predicate isBarrier(DataFlow::Node node) { node instanceof UnsafeDeserializationSanitizer } + predicate isBarrier(DataFlow::Node node) { isUnsafeDeserializationSanitizer(node) } } module UnsafeDeserializationFlow = TaintTracking::Global; From 01280aee67b467f1fc160724df16d24310643347 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 31 Mar 2023 08:48:57 +0100 Subject: [PATCH 089/141] Swift: Add missing import. --- swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll | 1 + 1 file changed, 1 insertion(+) diff --git a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll index ab4743dadeb..6917f8ea209 100644 --- a/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll +++ b/swift/ql/lib/codeql/swift/dataflow/ExternalFlow.qll @@ -99,6 +99,7 @@ private module Frameworks { private import codeql.swift.security.CleartextStorageDatabaseExtensions private import codeql.swift.security.PathInjectionExtensions private import codeql.swift.security.PredicateInjectionExtensions + private import codeql.swift.security.StringLengthConflationExtensions } /** From 33b4d2d6531d62f6716d4ea05dc57777795568e7 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Fri, 31 Mar 2023 10:02:11 +0200 Subject: [PATCH 090/141] Swift: add `SuccessfullyExtractedLines` query This counts how many lines we have extracted some entity in. If we test changes in this, we can have a more fine grained look into how much we actually extract than looking at the extracted files. --- .../src/diagnostics/SuccessfullyExtractedLines.ql | 15 +++++++++++++++ .../SuccessfullyExtractedLines.expected | 1 + .../Diagnostics/SuccessfullyExtractedLines.qlref | 1 + .../ql/test/query-tests/Diagnostics/ignored.swift | 3 +++ swift/ql/test/query-tests/Diagnostics/main.swift | 6 ++++++ 5 files changed, 26 insertions(+) create mode 100644 swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql create mode 100644 swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.expected create mode 100644 swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.qlref create mode 100644 swift/ql/test/query-tests/Diagnostics/ignored.swift diff --git a/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql b/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql new file mode 100644 index 00000000000..1cc9d985155 --- /dev/null +++ b/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql @@ -0,0 +1,15 @@ +/** + * @name Successfully extracted lines + * @description Count all lines in source code in which something was extracted. + * @kind metric + * @id swift/diagnostics/successfully-extracted-lines + * @tags summary + */ + +import swift + +select count(File f, int line | + exists(Location loc | + not loc instanceof UnknownLocation and loc.getFile() = f and loc.getStartLine() = line + ) + ) diff --git a/swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.expected b/swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.expected new file mode 100644 index 00000000000..b5a514b9ffa --- /dev/null +++ b/swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.expected @@ -0,0 +1 @@ +| 4 | diff --git a/swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.qlref b/swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.qlref new file mode 100644 index 00000000000..26996e64988 --- /dev/null +++ b/swift/ql/test/query-tests/Diagnostics/SuccessfullyExtractedLines.qlref @@ -0,0 +1 @@ +diagnostics/SuccessfullyExtractedLines.ql diff --git a/swift/ql/test/query-tests/Diagnostics/ignored.swift b/swift/ql/test/query-tests/Diagnostics/ignored.swift new file mode 100644 index 00000000000..f488af7e837 --- /dev/null +++ b/swift/ql/test/query-tests/Diagnostics/ignored.swift @@ -0,0 +1,3 @@ +//codeql-extractor-env: CODEQL_EXTRACTOR_SWIFT_RUN_UNDER=true + +func not_compiled() {} diff --git a/swift/ql/test/query-tests/Diagnostics/main.swift b/swift/ql/test/query-tests/Diagnostics/main.swift index e69de29bb2d..92d0406caac 100644 --- a/swift/ql/test/query-tests/Diagnostics/main.swift +++ b/swift/ql/test/query-tests/Diagnostics/main.swift @@ -0,0 +1,6 @@ + + +// a comment + + +func foo() {} From 6f86cb1c1b02b1e7385c09d12c67b38f015b10af Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 29 Mar 2023 13:38:32 +0200 Subject: [PATCH 091/141] C#: Add interface definition and add more testcases. --- .../dataflow/operators/Operator.cs | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/csharp/ql/test/library-tests/dataflow/operators/Operator.cs b/csharp/ql/test/library-tests/dataflow/operators/Operator.cs index 164b1e84525..946a3b676cf 100644 --- a/csharp/ql/test/library-tests/dataflow/operators/Operator.cs +++ b/csharp/ql/test/library-tests/dataflow/operators/Operator.cs @@ -4,12 +4,22 @@ public class Operators static void Sink(object o) { } static T Source(object source) => throw null; - public class C + public interface I where T : I + { + static virtual T operator *(T x, T y) => x; + static abstract T operator /(T x, T y); + static abstract T operator checked /(T x, T y); + } + + public class C : I { public static C operator +(C x, C y) => x; public static C operator checked -(C x, C y) => y; public static C operator -(C x, C y) => x; + + public static C operator /(C x, C y) => y; + public static C operator checked /(C x, C y) => y; } public void M1() @@ -35,4 +45,43 @@ public class Operators var z = checked(x - y); Sink(z); // $ hasValueFlow=6 } + + public void M4Aux(T x, T y) where T : I + { + var z = x * y; + Sink(z); // $ hasValueFlow=7 + } + + public void M4() + { + var x = Source(7); + var y = Source(8); + M4Aux(x, y); + } + + public void M5Aux(T x, T y) where T : I + { + var z = x / y; + Sink(z); // $ hasValueFlow=10 + } + + public void M5() + { + var x = Source(9); + var y = Source(10); + M5Aux(x, y); + } + + public void M6Aux(T x, T y) where T : I + { + var z = checked(x / y); + Sink(z); // $ hasValueFlow=12 + } + + public void M6() + { + var x = Source(11); + var y = Source(12); + M6Aux(x, y); + } } \ No newline at end of file From f792bf09d30dc825aa28b50e0d0f7ae440132cb0 Mon Sep 17 00:00:00 2001 From: Michael Nebel Date: Wed, 29 Mar 2023 14:38:10 +0200 Subject: [PATCH 092/141] C#: Update expected test output. --- .../dataflow/operators/operatorFlow.expected | 249 ++++++++++++------ 1 file changed, 174 insertions(+), 75 deletions(-) diff --git a/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected index 33f8c4a03e6..c5c80bf9f44 100644 --- a/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected +++ b/csharp/ql/test/library-tests/dataflow/operators/operatorFlow.expected @@ -1,80 +1,179 @@ failures edges -| Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | -| Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | -| Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | -| Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | -| Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | -| Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | -| Operator.cs:17:17:17:28 | call to method Source : C | Operator.cs:19:17:19:17 | access to local variable x : C | -| Operator.cs:17:17:17:28 | call to method Source : C | Operator.cs:19:17:19:17 | access to local variable x : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:19:17:19:21 | call to operator + : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:19:17:19:21 | call to operator + : C | -| Operator.cs:19:17:19:21 | call to operator + : C | Operator.cs:20:14:20:14 | access to local variable z | -| Operator.cs:19:17:19:21 | call to operator + : C | Operator.cs:20:14:20:14 | access to local variable z | -| Operator.cs:25:17:25:28 | call to method Source : C | Operator.cs:27:27:27:27 | access to local variable x : C | -| Operator.cs:25:17:25:28 | call to method Source : C | Operator.cs:27:27:27:27 | access to local variable x : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:27:27:27:31 | call to operator - : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:27:27:27:31 | call to operator - : C | -| Operator.cs:27:27:27:31 | call to operator - : C | Operator.cs:28:14:28:14 | access to local variable z | -| Operator.cs:27:27:27:31 | call to operator - : C | Operator.cs:28:14:28:14 | access to local variable z | -| Operator.cs:34:17:34:28 | call to method Source : C | Operator.cs:35:29:35:29 | access to local variable y : C | -| Operator.cs:34:17:34:28 | call to method Source : C | Operator.cs:35:29:35:29 | access to local variable y : C | -| Operator.cs:35:25:35:29 | call to operator checked - : C | Operator.cs:36:14:36:14 | access to local variable z | -| Operator.cs:35:25:35:29 | call to operator checked - : C | Operator.cs:36:14:36:14 | access to local variable z | -| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | +| Operator.cs:9:39:9:39 | x : C | Operator.cs:9:50:9:50 | access to parameter x : C | +| Operator.cs:9:39:9:39 | x : C | Operator.cs:9:50:9:50 | access to parameter x : C | +| Operator.cs:16:38:16:38 | x : C | Operator.cs:16:49:16:49 | access to parameter x : C | +| Operator.cs:16:38:16:38 | x : C | Operator.cs:16:49:16:49 | access to parameter x : C | +| Operator.cs:18:51:18:51 | y : C | Operator.cs:18:57:18:57 | access to parameter y : C | +| Operator.cs:18:51:18:51 | y : C | Operator.cs:18:57:18:57 | access to parameter y : C | +| Operator.cs:19:38:19:38 | x : C | Operator.cs:19:49:19:49 | access to parameter x : C | +| Operator.cs:19:38:19:38 | x : C | Operator.cs:19:49:19:49 | access to parameter x : C | +| Operator.cs:21:43:21:43 | y : C | Operator.cs:21:49:21:49 | access to parameter y : C | +| Operator.cs:21:43:21:43 | y : C | Operator.cs:21:49:21:49 | access to parameter y : C | +| Operator.cs:22:51:22:51 | y : C | Operator.cs:22:57:22:57 | access to parameter y : C | +| Operator.cs:22:51:22:51 | y : C | Operator.cs:22:57:22:57 | access to parameter y : C | +| Operator.cs:27:17:27:28 | call to method Source : C | Operator.cs:29:17:29:17 | access to local variable x : C | +| Operator.cs:27:17:27:28 | call to method Source : C | Operator.cs:29:17:29:17 | access to local variable x : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | Operator.cs:16:38:16:38 | x : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | Operator.cs:16:38:16:38 | x : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | Operator.cs:29:17:29:21 | call to operator + : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | Operator.cs:29:17:29:21 | call to operator + : C | +| Operator.cs:29:17:29:21 | call to operator + : C | Operator.cs:30:14:30:14 | access to local variable z | +| Operator.cs:29:17:29:21 | call to operator + : C | Operator.cs:30:14:30:14 | access to local variable z | +| Operator.cs:35:17:35:28 | call to method Source : C | Operator.cs:37:27:37:27 | access to local variable x : C | +| Operator.cs:35:17:35:28 | call to method Source : C | Operator.cs:37:27:37:27 | access to local variable x : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | Operator.cs:19:38:19:38 | x : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | Operator.cs:19:38:19:38 | x : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | Operator.cs:37:27:37:31 | call to operator - : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | Operator.cs:37:27:37:31 | call to operator - : C | +| Operator.cs:37:27:37:31 | call to operator - : C | Operator.cs:38:14:38:14 | access to local variable z | +| Operator.cs:37:27:37:31 | call to operator - : C | Operator.cs:38:14:38:14 | access to local variable z | +| Operator.cs:44:17:44:28 | call to method Source : C | Operator.cs:45:29:45:29 | access to local variable y : C | +| Operator.cs:44:17:44:28 | call to method Source : C | Operator.cs:45:29:45:29 | access to local variable y : C | +| Operator.cs:45:25:45:29 | call to operator checked - : C | Operator.cs:46:14:46:14 | access to local variable z | +| Operator.cs:45:25:45:29 | call to operator checked - : C | Operator.cs:46:14:46:14 | access to local variable z | +| Operator.cs:45:29:45:29 | access to local variable y : C | Operator.cs:18:51:18:51 | y : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | Operator.cs:18:51:18:51 | y : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | Operator.cs:45:25:45:29 | call to operator checked - : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | Operator.cs:45:25:45:29 | call to operator checked - : C | +| Operator.cs:49:28:49:28 | x : C | Operator.cs:51:17:51:17 | access to parameter x : C | +| Operator.cs:49:28:49:28 | x : C | Operator.cs:51:17:51:17 | access to parameter x : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | Operator.cs:9:39:9:39 | x : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | Operator.cs:9:39:9:39 | x : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | Operator.cs:51:17:51:21 | call to operator * : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | Operator.cs:51:17:51:21 | call to operator * : C | +| Operator.cs:51:17:51:21 | call to operator * : C | Operator.cs:52:14:52:14 | (...) ... | +| Operator.cs:51:17:51:21 | call to operator * : C | Operator.cs:52:14:52:14 | (...) ... | +| Operator.cs:57:17:57:28 | call to method Source : C | Operator.cs:59:15:59:15 | access to local variable x : C | +| Operator.cs:57:17:57:28 | call to method Source : C | Operator.cs:59:15:59:15 | access to local variable x : C | +| Operator.cs:59:15:59:15 | access to local variable x : C | Operator.cs:49:28:49:28 | x : C | +| Operator.cs:59:15:59:15 | access to local variable x : C | Operator.cs:49:28:49:28 | x : C | +| Operator.cs:62:33:62:33 | y : C | Operator.cs:64:21:64:21 | access to parameter y : C | +| Operator.cs:62:33:62:33 | y : C | Operator.cs:64:21:64:21 | access to parameter y : C | +| Operator.cs:64:17:64:21 | call to operator / : C | Operator.cs:65:14:65:14 | (...) ... | +| Operator.cs:64:17:64:21 | call to operator / : C | Operator.cs:65:14:65:14 | (...) ... | +| Operator.cs:64:21:64:21 | access to parameter y : C | Operator.cs:21:43:21:43 | y : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | Operator.cs:21:43:21:43 | y : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | Operator.cs:64:17:64:21 | call to operator / : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | Operator.cs:64:17:64:21 | call to operator / : C | +| Operator.cs:71:17:71:29 | call to method Source : C | Operator.cs:72:18:72:18 | access to local variable y : C | +| Operator.cs:71:17:71:29 | call to method Source : C | Operator.cs:72:18:72:18 | access to local variable y : C | +| Operator.cs:72:18:72:18 | access to local variable y : C | Operator.cs:62:33:62:33 | y : C | +| Operator.cs:72:18:72:18 | access to local variable y : C | Operator.cs:62:33:62:33 | y : C | +| Operator.cs:75:33:75:33 | y : C | Operator.cs:77:29:77:29 | access to parameter y : C | +| Operator.cs:75:33:75:33 | y : C | Operator.cs:77:29:77:29 | access to parameter y : C | +| Operator.cs:77:25:77:29 | call to operator checked / : C | Operator.cs:78:14:78:14 | (...) ... | +| Operator.cs:77:25:77:29 | call to operator checked / : C | Operator.cs:78:14:78:14 | (...) ... | +| Operator.cs:77:29:77:29 | access to parameter y : C | Operator.cs:22:51:22:51 | y : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | Operator.cs:22:51:22:51 | y : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | Operator.cs:77:25:77:29 | call to operator checked / : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | Operator.cs:77:25:77:29 | call to operator checked / : C | +| Operator.cs:84:17:84:29 | call to method Source : C | Operator.cs:85:18:85:18 | access to local variable y : C | +| Operator.cs:84:17:84:29 | call to method Source : C | Operator.cs:85:18:85:18 | access to local variable y : C | +| Operator.cs:85:18:85:18 | access to local variable y : C | Operator.cs:75:33:75:33 | y : C | +| Operator.cs:85:18:85:18 | access to local variable y : C | Operator.cs:75:33:75:33 | y : C | nodes -| Operator.cs:9:38:9:38 | x : C | semmle.label | x : C | -| Operator.cs:9:38:9:38 | x : C | semmle.label | x : C | -| Operator.cs:9:49:9:49 | access to parameter x : C | semmle.label | access to parameter x : C | -| Operator.cs:9:49:9:49 | access to parameter x : C | semmle.label | access to parameter x : C | -| Operator.cs:11:51:11:51 | y : C | semmle.label | y : C | -| Operator.cs:11:51:11:51 | y : C | semmle.label | y : C | -| Operator.cs:11:57:11:57 | access to parameter y : C | semmle.label | access to parameter y : C | -| Operator.cs:11:57:11:57 | access to parameter y : C | semmle.label | access to parameter y : C | -| Operator.cs:12:38:12:38 | x : C | semmle.label | x : C | -| Operator.cs:12:38:12:38 | x : C | semmle.label | x : C | -| Operator.cs:12:49:12:49 | access to parameter x : C | semmle.label | access to parameter x : C | -| Operator.cs:12:49:12:49 | access to parameter x : C | semmle.label | access to parameter x : C | -| Operator.cs:17:17:17:28 | call to method Source : C | semmle.label | call to method Source : C | -| Operator.cs:17:17:17:28 | call to method Source : C | semmle.label | call to method Source : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | semmle.label | access to local variable x : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | semmle.label | access to local variable x : C | -| Operator.cs:19:17:19:21 | call to operator + : C | semmle.label | call to operator + : C | -| Operator.cs:19:17:19:21 | call to operator + : C | semmle.label | call to operator + : C | -| Operator.cs:20:14:20:14 | access to local variable z | semmle.label | access to local variable z | -| Operator.cs:20:14:20:14 | access to local variable z | semmle.label | access to local variable z | -| Operator.cs:25:17:25:28 | call to method Source : C | semmle.label | call to method Source : C | -| Operator.cs:25:17:25:28 | call to method Source : C | semmle.label | call to method Source : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | semmle.label | access to local variable x : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | semmle.label | access to local variable x : C | -| Operator.cs:27:27:27:31 | call to operator - : C | semmle.label | call to operator - : C | -| Operator.cs:27:27:27:31 | call to operator - : C | semmle.label | call to operator - : C | -| Operator.cs:28:14:28:14 | access to local variable z | semmle.label | access to local variable z | -| Operator.cs:28:14:28:14 | access to local variable z | semmle.label | access to local variable z | -| Operator.cs:34:17:34:28 | call to method Source : C | semmle.label | call to method Source : C | -| Operator.cs:34:17:34:28 | call to method Source : C | semmle.label | call to method Source : C | -| Operator.cs:35:25:35:29 | call to operator checked - : C | semmle.label | call to operator checked - : C | -| Operator.cs:35:25:35:29 | call to operator checked - : C | semmle.label | call to operator checked - : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | semmle.label | access to local variable y : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | semmle.label | access to local variable y : C | -| Operator.cs:36:14:36:14 | access to local variable z | semmle.label | access to local variable z | -| Operator.cs:36:14:36:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:9:39:9:39 | x : C | semmle.label | x : C | +| Operator.cs:9:39:9:39 | x : C | semmle.label | x : C | +| Operator.cs:9:50:9:50 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:9:50:9:50 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:16:38:16:38 | x : C | semmle.label | x : C | +| Operator.cs:16:38:16:38 | x : C | semmle.label | x : C | +| Operator.cs:16:49:16:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:16:49:16:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:18:51:18:51 | y : C | semmle.label | y : C | +| Operator.cs:18:51:18:51 | y : C | semmle.label | y : C | +| Operator.cs:18:57:18:57 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:18:57:18:57 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:19:38:19:38 | x : C | semmle.label | x : C | +| Operator.cs:19:38:19:38 | x : C | semmle.label | x : C | +| Operator.cs:19:49:19:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:19:49:19:49 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:21:43:21:43 | y : C | semmle.label | y : C | +| Operator.cs:21:43:21:43 | y : C | semmle.label | y : C | +| Operator.cs:21:49:21:49 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:21:49:21:49 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:22:51:22:51 | y : C | semmle.label | y : C | +| Operator.cs:22:51:22:51 | y : C | semmle.label | y : C | +| Operator.cs:22:57:22:57 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:22:57:22:57 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:27:17:27:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:27:17:27:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:29:17:29:21 | call to operator + : C | semmle.label | call to operator + : C | +| Operator.cs:29:17:29:21 | call to operator + : C | semmle.label | call to operator + : C | +| Operator.cs:30:14:30:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:30:14:30:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:35:17:35:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:35:17:35:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:37:27:37:31 | call to operator - : C | semmle.label | call to operator - : C | +| Operator.cs:37:27:37:31 | call to operator - : C | semmle.label | call to operator - : C | +| Operator.cs:38:14:38:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:38:14:38:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:44:17:44:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:44:17:44:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:45:25:45:29 | call to operator checked - : C | semmle.label | call to operator checked - : C | +| Operator.cs:45:25:45:29 | call to operator checked - : C | semmle.label | call to operator checked - : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:46:14:46:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:46:14:46:14 | access to local variable z | semmle.label | access to local variable z | +| Operator.cs:49:28:49:28 | x : C | semmle.label | x : C | +| Operator.cs:49:28:49:28 | x : C | semmle.label | x : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | semmle.label | access to parameter x : C | +| Operator.cs:51:17:51:21 | call to operator * : C | semmle.label | call to operator * : C | +| Operator.cs:51:17:51:21 | call to operator * : C | semmle.label | call to operator * : C | +| Operator.cs:52:14:52:14 | (...) ... | semmle.label | (...) ... | +| Operator.cs:52:14:52:14 | (...) ... | semmle.label | (...) ... | +| Operator.cs:57:17:57:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:57:17:57:28 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:59:15:59:15 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:59:15:59:15 | access to local variable x : C | semmle.label | access to local variable x : C | +| Operator.cs:62:33:62:33 | y : C | semmle.label | y : C | +| Operator.cs:62:33:62:33 | y : C | semmle.label | y : C | +| Operator.cs:64:17:64:21 | call to operator / : C | semmle.label | call to operator / : C | +| Operator.cs:64:17:64:21 | call to operator / : C | semmle.label | call to operator / : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:65:14:65:14 | (...) ... | semmle.label | (...) ... | +| Operator.cs:65:14:65:14 | (...) ... | semmle.label | (...) ... | +| Operator.cs:71:17:71:29 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:71:17:71:29 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:72:18:72:18 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:72:18:72:18 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:75:33:75:33 | y : C | semmle.label | y : C | +| Operator.cs:75:33:75:33 | y : C | semmle.label | y : C | +| Operator.cs:77:25:77:29 | call to operator checked / : C | semmle.label | call to operator checked / : C | +| Operator.cs:77:25:77:29 | call to operator checked / : C | semmle.label | call to operator checked / : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | semmle.label | access to parameter y : C | +| Operator.cs:78:14:78:14 | (...) ... | semmle.label | (...) ... | +| Operator.cs:78:14:78:14 | (...) ... | semmle.label | (...) ... | +| Operator.cs:84:17:84:29 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:84:17:84:29 | call to method Source : C | semmle.label | call to method Source : C | +| Operator.cs:85:18:85:18 | access to local variable y : C | semmle.label | access to local variable y : C | +| Operator.cs:85:18:85:18 | access to local variable y : C | semmle.label | access to local variable y : C | subpaths -| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | Operator.cs:19:17:19:21 | call to operator + : C | -| Operator.cs:19:17:19:17 | access to local variable x : C | Operator.cs:9:38:9:38 | x : C | Operator.cs:9:49:9:49 | access to parameter x : C | Operator.cs:19:17:19:21 | call to operator + : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | Operator.cs:27:27:27:31 | call to operator - : C | -| Operator.cs:27:27:27:27 | access to local variable x : C | Operator.cs:12:38:12:38 | x : C | Operator.cs:12:49:12:49 | access to parameter x : C | Operator.cs:27:27:27:31 | call to operator - : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | -| Operator.cs:35:29:35:29 | access to local variable y : C | Operator.cs:11:51:11:51 | y : C | Operator.cs:11:57:11:57 | access to parameter y : C | Operator.cs:35:25:35:29 | call to operator checked - : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | Operator.cs:16:38:16:38 | x : C | Operator.cs:16:49:16:49 | access to parameter x : C | Operator.cs:29:17:29:21 | call to operator + : C | +| Operator.cs:29:17:29:17 | access to local variable x : C | Operator.cs:16:38:16:38 | x : C | Operator.cs:16:49:16:49 | access to parameter x : C | Operator.cs:29:17:29:21 | call to operator + : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | Operator.cs:19:38:19:38 | x : C | Operator.cs:19:49:19:49 | access to parameter x : C | Operator.cs:37:27:37:31 | call to operator - : C | +| Operator.cs:37:27:37:27 | access to local variable x : C | Operator.cs:19:38:19:38 | x : C | Operator.cs:19:49:19:49 | access to parameter x : C | Operator.cs:37:27:37:31 | call to operator - : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | Operator.cs:18:51:18:51 | y : C | Operator.cs:18:57:18:57 | access to parameter y : C | Operator.cs:45:25:45:29 | call to operator checked - : C | +| Operator.cs:45:29:45:29 | access to local variable y : C | Operator.cs:18:51:18:51 | y : C | Operator.cs:18:57:18:57 | access to parameter y : C | Operator.cs:45:25:45:29 | call to operator checked - : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | Operator.cs:9:39:9:39 | x : C | Operator.cs:9:50:9:50 | access to parameter x : C | Operator.cs:51:17:51:21 | call to operator * : C | +| Operator.cs:51:17:51:17 | access to parameter x : C | Operator.cs:9:39:9:39 | x : C | Operator.cs:9:50:9:50 | access to parameter x : C | Operator.cs:51:17:51:21 | call to operator * : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | Operator.cs:21:43:21:43 | y : C | Operator.cs:21:49:21:49 | access to parameter y : C | Operator.cs:64:17:64:21 | call to operator / : C | +| Operator.cs:64:21:64:21 | access to parameter y : C | Operator.cs:21:43:21:43 | y : C | Operator.cs:21:49:21:49 | access to parameter y : C | Operator.cs:64:17:64:21 | call to operator / : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | Operator.cs:22:51:22:51 | y : C | Operator.cs:22:57:22:57 | access to parameter y : C | Operator.cs:77:25:77:29 | call to operator checked / : C | +| Operator.cs:77:29:77:29 | access to parameter y : C | Operator.cs:22:51:22:51 | y : C | Operator.cs:22:57:22:57 | access to parameter y : C | Operator.cs:77:25:77:29 | call to operator checked / : C | #select -| Operator.cs:20:14:20:14 | access to local variable z | Operator.cs:17:17:17:28 | call to method Source : C | Operator.cs:20:14:20:14 | access to local variable z | $@ | Operator.cs:17:17:17:28 | call to method Source : C | call to method Source : C | -| Operator.cs:28:14:28:14 | access to local variable z | Operator.cs:25:17:25:28 | call to method Source : C | Operator.cs:28:14:28:14 | access to local variable z | $@ | Operator.cs:25:17:25:28 | call to method Source : C | call to method Source : C | -| Operator.cs:36:14:36:14 | access to local variable z | Operator.cs:34:17:34:28 | call to method Source : C | Operator.cs:36:14:36:14 | access to local variable z | $@ | Operator.cs:34:17:34:28 | call to method Source : C | call to method Source : C | +| Operator.cs:30:14:30:14 | access to local variable z | Operator.cs:27:17:27:28 | call to method Source : C | Operator.cs:30:14:30:14 | access to local variable z | $@ | Operator.cs:27:17:27:28 | call to method Source : C | call to method Source : C | +| Operator.cs:38:14:38:14 | access to local variable z | Operator.cs:35:17:35:28 | call to method Source : C | Operator.cs:38:14:38:14 | access to local variable z | $@ | Operator.cs:35:17:35:28 | call to method Source : C | call to method Source : C | +| Operator.cs:46:14:46:14 | access to local variable z | Operator.cs:44:17:44:28 | call to method Source : C | Operator.cs:46:14:46:14 | access to local variable z | $@ | Operator.cs:44:17:44:28 | call to method Source : C | call to method Source : C | +| Operator.cs:52:14:52:14 | (...) ... | Operator.cs:57:17:57:28 | call to method Source : C | Operator.cs:52:14:52:14 | (...) ... | $@ | Operator.cs:57:17:57:28 | call to method Source : C | call to method Source : C | +| Operator.cs:65:14:65:14 | (...) ... | Operator.cs:71:17:71:29 | call to method Source : C | Operator.cs:65:14:65:14 | (...) ... | $@ | Operator.cs:71:17:71:29 | call to method Source : C | call to method Source : C | +| Operator.cs:78:14:78:14 | (...) ... | Operator.cs:84:17:84:29 | call to method Source : C | Operator.cs:78:14:78:14 | (...) ... | $@ | Operator.cs:84:17:84:29 | call to method Source : C | call to method Source : C | From bc698546e59585a7aaf0cdcb2112734218f34b19 Mon Sep 17 00:00:00 2001 From: Paolo Tranquilli Date: Fri, 31 Mar 2023 10:32:40 +0200 Subject: [PATCH 093/141] Swift: specify treatment for multi-line things --- swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql b/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql index 1cc9d985155..59b1d5bc8bc 100644 --- a/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql +++ b/swift/ql/src/diagnostics/SuccessfullyExtractedLines.ql @@ -1,6 +1,6 @@ /** * @name Successfully extracted lines - * @description Count all lines in source code in which something was extracted. + * @description Count all lines in source code in which something was extracted. Entities spanning multiple lines like multi-line strings or comments only contribute one line to this count. * @kind metric * @id swift/diagnostics/successfully-extracted-lines * @tags summary From 209aebad612ffd20980ba5d4248bc14990d54d66 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 11:10:40 +0200 Subject: [PATCH 094/141] Ruby: Update HttpClients.ql not assume all predicates have results --- .../http_clients/HttpClients.expected | 362 ++++++++++++++---- .../frameworks/http_clients/HttpClients.ql | 14 +- 2 files changed, 289 insertions(+), 87 deletions(-) diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected index eae7e9b76a5..697cdd751dd 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected +++ b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected @@ -1,80 +1,282 @@ -| Excon.rb:3:9:3:40 | call to get | Excon | Excon.rb:3:19:3:39 | "http://example.com/" | Excon.rb:4:1:4:10 | call to body | -| Excon.rb:6:9:6:60 | call to post | Excon | Excon.rb:6:20:6:40 | "http://example.com/" | Excon.rb:7:1:7:10 | call to body | -| Excon.rb:9:9:9:59 | call to put | Excon | Excon.rb:9:19:9:39 | "http://example.com/" | Excon.rb:10:1:10:10 | call to body | -| Excon.rb:12:9:12:61 | call to patch | Excon | Excon.rb:12:21:12:41 | "http://example.com/" | Excon.rb:13:1:13:10 | call to body | -| Excon.rb:15:9:15:43 | call to delete | Excon | Excon.rb:15:22:15:42 | "http://example.com/" | Excon.rb:16:1:16:10 | call to body | -| Excon.rb:18:9:18:41 | call to head | Excon | Excon.rb:18:20:18:40 | "http://example.com/" | Excon.rb:19:1:19:10 | call to body | -| Excon.rb:21:9:21:44 | call to options | Excon | Excon.rb:21:23:21:43 | "http://example.com/" | Excon.rb:22:1:22:10 | call to body | -| Excon.rb:24:9:24:42 | call to trace | Excon | Excon.rb:24:21:24:41 | "http://example.com/" | Excon.rb:25:1:25:10 | call to body | -| Excon.rb:28:9:28:34 | call to get | Excon | Excon.rb:27:25:27:44 | "http://example.com" | Excon.rb:29:1:29:10 | call to body | -| Excon.rb:28:9:28:34 | call to get | Excon | Excon.rb:28:31:28:33 | "/" | Excon.rb:29:1:29:10 | call to body | -| Excon.rb:31:10:31:39 | call to post | Excon | Excon.rb:27:25:27:44 | "http://example.com" | Excon.rb:32:1:32:11 | call to body | -| Excon.rb:31:10:31:39 | call to post | Excon | Excon.rb:31:33:31:38 | "/foo" | Excon.rb:32:1:32:11 | call to body | -| Excon.rb:35:9:35:34 | call to get | Excon | Excon.rb:34:37:34:56 | "http://example.com" | Excon.rb:36:1:36:10 | call to body | -| Excon.rb:35:9:35:34 | call to get | Excon | Excon.rb:35:31:35:33 | "/" | Excon.rb:36:1:36:10 | call to body | -| Excon.rb:38:10:38:39 | call to post | Excon | Excon.rb:34:37:34:56 | "http://example.com" | Excon.rb:39:1:39:11 | call to body | -| Excon.rb:38:10:38:39 | call to post | Excon | Excon.rb:38:33:38:38 | "/foo" | Excon.rb:39:1:39:11 | call to body | -| Faraday.rb:3:9:3:42 | call to get | Faraday | Faraday.rb:3:21:3:41 | "http://example.com/" | Faraday.rb:4:1:4:10 | call to body | -| Faraday.rb:6:9:6:62 | call to post | Faraday | Faraday.rb:6:22:6:42 | "http://example.com/" | Faraday.rb:7:1:7:10 | call to body | -| Faraday.rb:9:9:9:61 | call to put | Faraday | Faraday.rb:9:21:9:41 | "http://example.com/" | Faraday.rb:10:1:10:10 | call to body | -| Faraday.rb:12:9:12:63 | call to patch | Faraday | Faraday.rb:12:23:12:43 | "http://example.com/" | Faraday.rb:13:1:13:10 | call to body | -| Faraday.rb:15:9:15:45 | call to delete | Faraday | Faraday.rb:15:24:15:44 | "http://example.com/" | Faraday.rb:16:1:16:10 | call to body | -| Faraday.rb:18:9:18:43 | call to head | Faraday | Faraday.rb:18:22:18:42 | "http://example.com/" | Faraday.rb:19:1:19:10 | call to body | -| Faraday.rb:24:9:24:44 | call to trace | Faraday | Faraday.rb:24:23:24:43 | "http://example.com/" | Faraday.rb:25:1:25:10 | call to body | -| Faraday.rb:28:9:28:27 | call to get | Faraday | Faraday.rb:27:26:27:45 | "http://example.com" | Faraday.rb:29:1:29:10 | call to body | -| Faraday.rb:28:9:28:27 | call to get | Faraday | Faraday.rb:28:24:28:26 | "/" | Faraday.rb:29:1:29:10 | call to body | -| Faraday.rb:31:10:31:46 | call to post | Faraday | Faraday.rb:27:26:27:45 | "http://example.com" | Faraday.rb:32:1:32:11 | call to body | -| Faraday.rb:31:10:31:46 | call to post | Faraday | Faraday.rb:31:26:31:31 | "/foo" | Faraday.rb:32:1:32:11 | call to body | -| Faraday.rb:35:10:35:28 | call to get | Faraday | Faraday.rb:34:26:34:50 | Pair | Faraday.rb:36:1:36:11 | call to body | -| Faraday.rb:35:10:35:28 | call to get | Faraday | Faraday.rb:34:31:34:50 | "http://example.com" | Faraday.rb:36:1:36:11 | call to body | -| Faraday.rb:35:10:35:28 | call to get | Faraday | Faraday.rb:35:25:35:27 | "/" | Faraday.rb:36:1:36:11 | call to body | -| Faraday.rb:39:10:39:28 | call to get | Faraday | Faraday.rb:38:38:38:63 | Pair | Faraday.rb:40:1:40:11 | call to body | -| Faraday.rb:39:10:39:28 | call to get | Faraday | Faraday.rb:38:43:38:63 | "https://example.com" | Faraday.rb:40:1:40:11 | call to body | -| Faraday.rb:39:10:39:28 | call to get | Faraday | Faraday.rb:39:25:39:27 | "/" | Faraday.rb:40:1:40:11 | call to body | -| HttpClient.rb:3:9:3:45 | call to get | HTTPClient | HttpClient.rb:3:24:3:44 | "http://example.com/" | HttpClient.rb:4:1:4:10 | call to body | -| HttpClient.rb:6:9:6:65 | call to post | HTTPClient | HttpClient.rb:6:25:6:45 | "http://example.com/" | HttpClient.rb:7:1:7:13 | call to content | -| HttpClient.rb:9:9:9:64 | call to put | HTTPClient | HttpClient.rb:9:24:9:44 | "http://example.com/" | HttpClient.rb:10:1:10:15 | call to http_body | -| HttpClient.rb:12:9:12:48 | call to delete | HTTPClient | HttpClient.rb:12:27:12:47 | "http://example.com/" | HttpClient.rb:13:1:13:10 | call to dump | -| HttpClient.rb:15:9:15:46 | call to head | HTTPClient | HttpClient.rb:15:25:15:45 | "http://example.com/" | HttpClient.rb:16:1:16:10 | call to body | -| HttpClient.rb:18:9:18:49 | call to options | HTTPClient | HttpClient.rb:18:28:18:48 | "http://example.com/" | HttpClient.rb:19:1:19:13 | call to content | -| HttpClient.rb:21:9:21:47 | call to trace | HTTPClient | HttpClient.rb:21:26:21:46 | "http://example.com/" | HttpClient.rb:22:1:22:15 | call to http_body | -| HttpClient.rb:24:9:24:53 | call to get_content | HTTPClient | HttpClient.rb:24:32:24:52 | "http://example.com/" | HttpClient.rb:24:9:24:53 | call to get_content | -| HttpClient.rb:26:10:26:74 | call to post_content | HTTPClient | HttpClient.rb:26:34:26:54 | "http://example.com/" | HttpClient.rb:26:10:26:74 | call to post_content | -| Httparty.rb:5:1:5:35 | call to get | HTTParty | Httparty.rb:5:14:5:34 | "http://example.com/" | Httparty.rb:5:1:5:35 | call to get | -| Httparty.rb:7:1:7:55 | call to post | HTTParty | Httparty.rb:7:15:7:35 | "http://example.com/" | Httparty.rb:7:1:7:55 | call to post | -| Httparty.rb:9:1:9:54 | call to put | HTTParty | Httparty.rb:9:14:9:34 | "http://example.com/" | Httparty.rb:9:1:9:54 | call to put | -| Httparty.rb:11:1:11:56 | call to patch | HTTParty | Httparty.rb:11:16:11:36 | "http://example.com/" | Httparty.rb:11:1:11:56 | call to patch | -| Httparty.rb:15:9:15:46 | call to delete | HTTParty | Httparty.rb:15:25:15:45 | "http://example.com/" | Httparty.rb:16:1:16:10 | call to body | -| Httparty.rb:18:9:18:44 | call to head | HTTParty | Httparty.rb:18:23:18:43 | "http://example.com/" | Httparty.rb:19:1:19:10 | call to body | -| Httparty.rb:21:9:21:47 | call to options | HTTParty | Httparty.rb:21:26:21:46 | "http://example.com/" | Httparty.rb:22:1:22:10 | call to body | -| NetHttp.rb:4:1:4:18 | call to get | Net::HTTP | NetHttp.rb:4:15:4:17 | uri | NetHttp.rb:4:1:4:18 | call to get | -| NetHttp.rb:6:8:6:50 | call to post | Net::HTTP | NetHttp.rb:6:23:6:36 | call to parse | NetHttp.rb:7:1:7:9 | call to body | -| NetHttp.rb:6:8:6:50 | call to post | Net::HTTP | NetHttp.rb:6:23:6:36 | call to parse | NetHttp.rb:8:1:8:14 | call to read_body | -| NetHttp.rb:6:8:6:50 | call to post | Net::HTTP | NetHttp.rb:6:23:6:36 | call to parse | NetHttp.rb:9:1:9:11 | call to entity | -| NetHttp.rb:13:6:13:17 | call to get | Net::HTTP | NetHttp.rb:11:21:11:41 | "https://example.com" | NetHttp.rb:18:1:18:7 | call to body | -| NetHttp.rb:13:6:13:17 | call to get | Net::HTTP | NetHttp.rb:13:14:13:16 | "/" | NetHttp.rb:18:1:18:7 | call to body | -| NetHttp.rb:14:6:14:18 | call to post | Net::HTTP | NetHttp.rb:11:21:11:41 | "https://example.com" | NetHttp.rb:19:1:19:12 | call to read_body | -| NetHttp.rb:14:6:14:18 | call to post | Net::HTTP | NetHttp.rb:14:15:14:17 | "/" | NetHttp.rb:19:1:19:12 | call to read_body | -| NetHttp.rb:15:6:15:17 | call to put | Net::HTTP | NetHttp.rb:11:21:11:41 | "https://example.com" | NetHttp.rb:20:1:20:9 | call to entity | -| NetHttp.rb:15:6:15:17 | call to put | Net::HTTP | NetHttp.rb:15:14:15:16 | "/" | NetHttp.rb:20:1:20:9 | call to entity | -| NetHttp.rb:24:3:24:33 | call to get | Net::HTTP | NetHttp.rb:24:17:24:22 | domain | NetHttp.rb:27:1:27:28 | call to body | -| NetHttp.rb:24:3:24:33 | call to get | Net::HTTP | NetHttp.rb:24:29:24:32 | path | NetHttp.rb:27:1:27:28 | call to body | -| OpenURI.rb:3:9:3:41 | call to open | OpenURI | OpenURI.rb:3:21:3:40 | "http://example.com" | OpenURI.rb:4:1:4:10 | call to read | -| OpenURI.rb:6:9:6:34 | call to open | OpenURI | OpenURI.rb:6:14:6:33 | "http://example.com" | OpenURI.rb:7:1:7:15 | call to readlines | -| OpenURI.rb:9:9:9:38 | call to open | OpenURI | OpenURI.rb:9:18:9:37 | "http://example.com" | OpenURI.rb:10:1:10:10 | call to read | -| OpenURI.rb:15:9:15:47 | call to open_uri | OpenURI | OpenURI.rb:15:26:15:46 | "https://example.com" | OpenURI.rb:16:1:16:10 | call to read | -| RestClient.rb:3:9:3:45 | call to get | RestClient | RestClient.rb:3:24:3:44 | "http://example.com/" | RestClient.rb:4:1:4:10 | call to body | -| RestClient.rb:6:9:6:59 | call to post | RestClient | RestClient.rb:6:25:6:44 | "http://example.com" | RestClient.rb:7:1:7:10 | call to body | -| RestClient.rb:9:9:9:58 | call to put | RestClient | RestClient.rb:9:24:9:43 | "http://example.com" | RestClient.rb:10:1:10:10 | call to body | -| RestClient.rb:12:9:12:60 | call to patch | RestClient | RestClient.rb:12:26:12:45 | "http://example.com" | RestClient.rb:13:1:13:10 | call to body | -| RestClient.rb:15:9:15:47 | call to delete | RestClient | RestClient.rb:15:27:15:46 | "http://example.com" | RestClient.rb:16:1:16:10 | call to body | -| RestClient.rb:18:9:18:45 | call to head | RestClient | RestClient.rb:18:25:18:44 | "http://example.com" | RestClient.rb:19:1:19:10 | call to body | -| RestClient.rb:21:9:21:48 | call to options | RestClient | RestClient.rb:21:28:21:47 | "http://example.com" | RestClient.rb:22:1:22:10 | call to body | -| RestClient.rb:28:9:28:85 | call to execute | RestClient | RestClient.rb:28:56:28:84 | "http://example.com/resource" | RestClient.rb:29:1:29:10 | call to body | -| Typhoeus.rb:3:9:3:43 | call to get | Typhoeus | Typhoeus.rb:3:22:3:42 | "http://example.com/" | Typhoeus.rb:4:1:4:10 | call to body | -| Typhoeus.rb:6:9:6:63 | call to post | Typhoeus | Typhoeus.rb:6:23:6:43 | "http://example.com/" | Typhoeus.rb:7:1:7:10 | call to body | -| Typhoeus.rb:9:9:9:62 | call to put | Typhoeus | Typhoeus.rb:9:22:9:42 | "http://example.com/" | Typhoeus.rb:10:1:10:10 | call to body | -| Typhoeus.rb:12:9:12:64 | call to patch | Typhoeus | Typhoeus.rb:12:24:12:44 | "http://example.com/" | Typhoeus.rb:13:1:13:10 | call to body | -| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus | Typhoeus.rb:15:25:15:45 | "http://example.com/" | Typhoeus.rb:16:1:16:10 | call to body | -| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus | Typhoeus.rb:18:23:18:43 | "http://example.com/" | Typhoeus.rb:19:1:19:10 | call to body | -| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus | Typhoeus.rb:21:26:21:46 | "http://example.com/" | Typhoeus.rb:22:1:22:10 | call to body | +httpRequests +| Excon.rb:3:9:3:40 | call to get | +| Excon.rb:6:9:6:60 | call to post | +| Excon.rb:9:9:9:59 | call to put | +| Excon.rb:12:9:12:61 | call to patch | +| Excon.rb:15:9:15:43 | call to delete | +| Excon.rb:18:9:18:41 | call to head | +| Excon.rb:21:9:21:44 | call to options | +| Excon.rb:24:9:24:42 | call to trace | +| Excon.rb:28:9:28:34 | call to get | +| Excon.rb:31:10:31:39 | call to post | +| Excon.rb:35:9:35:34 | call to get | +| Excon.rb:38:10:38:39 | call to post | +| Faraday.rb:3:9:3:42 | call to get | +| Faraday.rb:6:9:6:62 | call to post | +| Faraday.rb:9:9:9:61 | call to put | +| Faraday.rb:12:9:12:63 | call to patch | +| Faraday.rb:15:9:15:45 | call to delete | +| Faraday.rb:18:9:18:43 | call to head | +| Faraday.rb:24:9:24:44 | call to trace | +| Faraday.rb:28:9:28:27 | call to get | +| Faraday.rb:31:10:31:46 | call to post | +| Faraday.rb:35:10:35:28 | call to get | +| Faraday.rb:39:10:39:28 | call to get | +| HttpClient.rb:3:9:3:45 | call to get | +| HttpClient.rb:6:9:6:65 | call to post | +| HttpClient.rb:9:9:9:64 | call to put | +| HttpClient.rb:12:9:12:48 | call to delete | +| HttpClient.rb:15:9:15:46 | call to head | +| HttpClient.rb:18:9:18:49 | call to options | +| HttpClient.rb:21:9:21:47 | call to trace | +| HttpClient.rb:24:9:24:53 | call to get_content | +| HttpClient.rb:26:10:26:74 | call to post_content | +| Httparty.rb:5:1:5:35 | call to get | +| Httparty.rb:7:1:7:55 | call to post | +| Httparty.rb:9:1:9:54 | call to put | +| Httparty.rb:11:1:11:56 | call to patch | +| Httparty.rb:15:9:15:46 | call to delete | +| Httparty.rb:18:9:18:44 | call to head | +| Httparty.rb:21:9:21:47 | call to options | +| NetHttp.rb:4:1:4:18 | call to get | +| NetHttp.rb:6:8:6:50 | call to post | +| NetHttp.rb:13:6:13:17 | call to get | +| NetHttp.rb:14:6:14:18 | call to post | +| NetHttp.rb:15:6:15:17 | call to put | +| NetHttp.rb:24:3:24:33 | call to get | +| OpenURI.rb:3:9:3:41 | call to open | +| OpenURI.rb:6:9:6:34 | call to open | +| OpenURI.rb:9:9:9:38 | call to open | +| OpenURI.rb:12:9:12:45 | call to open | +| OpenURI.rb:15:9:15:47 | call to open_uri | +| RestClient.rb:3:9:3:45 | call to get | +| RestClient.rb:6:9:6:59 | call to post | +| RestClient.rb:9:9:9:58 | call to put | +| RestClient.rb:12:9:12:60 | call to patch | +| RestClient.rb:15:9:15:47 | call to delete | +| RestClient.rb:18:9:18:45 | call to head | +| RestClient.rb:21:9:21:48 | call to options | +| RestClient.rb:25:9:25:21 | call to get | +| RestClient.rb:28:9:28:85 | call to execute | +| Typhoeus.rb:3:9:3:43 | call to get | +| Typhoeus.rb:6:9:6:63 | call to post | +| Typhoeus.rb:9:9:9:62 | call to put | +| Typhoeus.rb:12:9:12:64 | call to patch | +| Typhoeus.rb:15:9:15:46 | call to delete | +| Typhoeus.rb:18:9:18:44 | call to head | +| Typhoeus.rb:21:9:21:47 | call to options | +getFramework +| Excon.rb:3:9:3:40 | call to get | Excon | +| Excon.rb:6:9:6:60 | call to post | Excon | +| Excon.rb:9:9:9:59 | call to put | Excon | +| Excon.rb:12:9:12:61 | call to patch | Excon | +| Excon.rb:15:9:15:43 | call to delete | Excon | +| Excon.rb:18:9:18:41 | call to head | Excon | +| Excon.rb:21:9:21:44 | call to options | Excon | +| Excon.rb:24:9:24:42 | call to trace | Excon | +| Excon.rb:28:9:28:34 | call to get | Excon | +| Excon.rb:31:10:31:39 | call to post | Excon | +| Excon.rb:35:9:35:34 | call to get | Excon | +| Excon.rb:38:10:38:39 | call to post | Excon | +| Faraday.rb:3:9:3:42 | call to get | Faraday | +| Faraday.rb:6:9:6:62 | call to post | Faraday | +| Faraday.rb:9:9:9:61 | call to put | Faraday | +| Faraday.rb:12:9:12:63 | call to patch | Faraday | +| Faraday.rb:15:9:15:45 | call to delete | Faraday | +| Faraday.rb:18:9:18:43 | call to head | Faraday | +| Faraday.rb:24:9:24:44 | call to trace | Faraday | +| Faraday.rb:28:9:28:27 | call to get | Faraday | +| Faraday.rb:31:10:31:46 | call to post | Faraday | +| Faraday.rb:35:10:35:28 | call to get | Faraday | +| Faraday.rb:39:10:39:28 | call to get | Faraday | +| HttpClient.rb:3:9:3:45 | call to get | HTTPClient | +| HttpClient.rb:6:9:6:65 | call to post | HTTPClient | +| HttpClient.rb:9:9:9:64 | call to put | HTTPClient | +| HttpClient.rb:12:9:12:48 | call to delete | HTTPClient | +| HttpClient.rb:15:9:15:46 | call to head | HTTPClient | +| HttpClient.rb:18:9:18:49 | call to options | HTTPClient | +| HttpClient.rb:21:9:21:47 | call to trace | HTTPClient | +| HttpClient.rb:24:9:24:53 | call to get_content | HTTPClient | +| HttpClient.rb:26:10:26:74 | call to post_content | HTTPClient | +| Httparty.rb:5:1:5:35 | call to get | HTTParty | +| Httparty.rb:7:1:7:55 | call to post | HTTParty | +| Httparty.rb:9:1:9:54 | call to put | HTTParty | +| Httparty.rb:11:1:11:56 | call to patch | HTTParty | +| Httparty.rb:15:9:15:46 | call to delete | HTTParty | +| Httparty.rb:18:9:18:44 | call to head | HTTParty | +| Httparty.rb:21:9:21:47 | call to options | HTTParty | +| NetHttp.rb:4:1:4:18 | call to get | Net::HTTP | +| NetHttp.rb:6:8:6:50 | call to post | Net::HTTP | +| NetHttp.rb:13:6:13:17 | call to get | Net::HTTP | +| NetHttp.rb:14:6:14:18 | call to post | Net::HTTP | +| NetHttp.rb:15:6:15:17 | call to put | Net::HTTP | +| NetHttp.rb:24:3:24:33 | call to get | Net::HTTP | +| OpenURI.rb:3:9:3:41 | call to open | OpenURI | +| OpenURI.rb:6:9:6:34 | call to open | OpenURI | +| OpenURI.rb:9:9:9:38 | call to open | OpenURI | +| OpenURI.rb:12:9:12:45 | call to open | OpenURI | +| OpenURI.rb:15:9:15:47 | call to open_uri | OpenURI | +| RestClient.rb:3:9:3:45 | call to get | RestClient | +| RestClient.rb:6:9:6:59 | call to post | RestClient | +| RestClient.rb:9:9:9:58 | call to put | RestClient | +| RestClient.rb:12:9:12:60 | call to patch | RestClient | +| RestClient.rb:15:9:15:47 | call to delete | RestClient | +| RestClient.rb:18:9:18:45 | call to head | RestClient | +| RestClient.rb:21:9:21:48 | call to options | RestClient | +| RestClient.rb:25:9:25:21 | call to get | RestClient | +| RestClient.rb:28:9:28:85 | call to execute | RestClient | +| Typhoeus.rb:3:9:3:43 | call to get | Typhoeus | +| Typhoeus.rb:6:9:6:63 | call to post | Typhoeus | +| Typhoeus.rb:9:9:9:62 | call to put | Typhoeus | +| Typhoeus.rb:12:9:12:64 | call to patch | Typhoeus | +| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus | +| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus | +| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus | +getResponseBody +| Excon.rb:3:9:3:40 | call to get | Excon.rb:4:1:4:10 | call to body | +| Excon.rb:6:9:6:60 | call to post | Excon.rb:7:1:7:10 | call to body | +| Excon.rb:9:9:9:59 | call to put | Excon.rb:10:1:10:10 | call to body | +| Excon.rb:12:9:12:61 | call to patch | Excon.rb:13:1:13:10 | call to body | +| Excon.rb:15:9:15:43 | call to delete | Excon.rb:16:1:16:10 | call to body | +| Excon.rb:18:9:18:41 | call to head | Excon.rb:19:1:19:10 | call to body | +| Excon.rb:21:9:21:44 | call to options | Excon.rb:22:1:22:10 | call to body | +| Excon.rb:24:9:24:42 | call to trace | Excon.rb:25:1:25:10 | call to body | +| Excon.rb:28:9:28:34 | call to get | Excon.rb:29:1:29:10 | call to body | +| Excon.rb:31:10:31:39 | call to post | Excon.rb:32:1:32:11 | call to body | +| Excon.rb:35:9:35:34 | call to get | Excon.rb:36:1:36:10 | call to body | +| Excon.rb:38:10:38:39 | call to post | Excon.rb:39:1:39:11 | call to body | +| Faraday.rb:3:9:3:42 | call to get | Faraday.rb:4:1:4:10 | call to body | +| Faraday.rb:6:9:6:62 | call to post | Faraday.rb:7:1:7:10 | call to body | +| Faraday.rb:9:9:9:61 | call to put | Faraday.rb:10:1:10:10 | call to body | +| Faraday.rb:12:9:12:63 | call to patch | Faraday.rb:13:1:13:10 | call to body | +| Faraday.rb:15:9:15:45 | call to delete | Faraday.rb:16:1:16:10 | call to body | +| Faraday.rb:18:9:18:43 | call to head | Faraday.rb:19:1:19:10 | call to body | +| Faraday.rb:24:9:24:44 | call to trace | Faraday.rb:25:1:25:10 | call to body | +| Faraday.rb:28:9:28:27 | call to get | Faraday.rb:29:1:29:10 | call to body | +| Faraday.rb:31:10:31:46 | call to post | Faraday.rb:32:1:32:11 | call to body | +| Faraday.rb:35:10:35:28 | call to get | Faraday.rb:36:1:36:11 | call to body | +| Faraday.rb:39:10:39:28 | call to get | Faraday.rb:40:1:40:11 | call to body | +| HttpClient.rb:3:9:3:45 | call to get | HttpClient.rb:4:1:4:10 | call to body | +| HttpClient.rb:6:9:6:65 | call to post | HttpClient.rb:7:1:7:13 | call to content | +| HttpClient.rb:9:9:9:64 | call to put | HttpClient.rb:10:1:10:15 | call to http_body | +| HttpClient.rb:12:9:12:48 | call to delete | HttpClient.rb:13:1:13:10 | call to dump | +| HttpClient.rb:15:9:15:46 | call to head | HttpClient.rb:16:1:16:10 | call to body | +| HttpClient.rb:18:9:18:49 | call to options | HttpClient.rb:19:1:19:13 | call to content | +| HttpClient.rb:21:9:21:47 | call to trace | HttpClient.rb:22:1:22:15 | call to http_body | +| HttpClient.rb:24:9:24:53 | call to get_content | HttpClient.rb:24:9:24:53 | call to get_content | +| HttpClient.rb:26:10:26:74 | call to post_content | HttpClient.rb:26:10:26:74 | call to post_content | +| Httparty.rb:5:1:5:35 | call to get | Httparty.rb:5:1:5:35 | call to get | +| Httparty.rb:7:1:7:55 | call to post | Httparty.rb:7:1:7:55 | call to post | +| Httparty.rb:9:1:9:54 | call to put | Httparty.rb:9:1:9:54 | call to put | +| Httparty.rb:11:1:11:56 | call to patch | Httparty.rb:11:1:11:56 | call to patch | +| Httparty.rb:15:9:15:46 | call to delete | Httparty.rb:16:1:16:10 | call to body | +| Httparty.rb:18:9:18:44 | call to head | Httparty.rb:19:1:19:10 | call to body | +| Httparty.rb:21:9:21:47 | call to options | Httparty.rb:22:1:22:10 | call to body | +| NetHttp.rb:4:1:4:18 | call to get | NetHttp.rb:4:1:4:18 | call to get | +| NetHttp.rb:6:8:6:50 | call to post | NetHttp.rb:7:1:7:9 | call to body | +| NetHttp.rb:6:8:6:50 | call to post | NetHttp.rb:8:1:8:14 | call to read_body | +| NetHttp.rb:6:8:6:50 | call to post | NetHttp.rb:9:1:9:11 | call to entity | +| NetHttp.rb:13:6:13:17 | call to get | NetHttp.rb:18:1:18:7 | call to body | +| NetHttp.rb:14:6:14:18 | call to post | NetHttp.rb:19:1:19:12 | call to read_body | +| NetHttp.rb:15:6:15:17 | call to put | NetHttp.rb:20:1:20:9 | call to entity | +| NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:27:1:27:28 | call to body | +| OpenURI.rb:3:9:3:41 | call to open | OpenURI.rb:4:1:4:10 | call to read | +| OpenURI.rb:6:9:6:34 | call to open | OpenURI.rb:7:1:7:15 | call to readlines | +| OpenURI.rb:9:9:9:38 | call to open | OpenURI.rb:10:1:10:10 | call to read | +| OpenURI.rb:12:9:12:45 | call to open | OpenURI.rb:13:1:13:10 | call to read | +| OpenURI.rb:15:9:15:47 | call to open_uri | OpenURI.rb:16:1:16:10 | call to read | +| RestClient.rb:3:9:3:45 | call to get | RestClient.rb:4:1:4:10 | call to body | +| RestClient.rb:6:9:6:59 | call to post | RestClient.rb:7:1:7:10 | call to body | +| RestClient.rb:9:9:9:58 | call to put | RestClient.rb:10:1:10:10 | call to body | +| RestClient.rb:12:9:12:60 | call to patch | RestClient.rb:13:1:13:10 | call to body | +| RestClient.rb:15:9:15:47 | call to delete | RestClient.rb:16:1:16:10 | call to body | +| RestClient.rb:18:9:18:45 | call to head | RestClient.rb:19:1:19:10 | call to body | +| RestClient.rb:21:9:21:48 | call to options | RestClient.rb:22:1:22:10 | call to body | +| RestClient.rb:25:9:25:21 | call to get | RestClient.rb:26:1:26:10 | call to body | +| RestClient.rb:28:9:28:85 | call to execute | RestClient.rb:29:1:29:10 | call to body | +| Typhoeus.rb:3:9:3:43 | call to get | Typhoeus.rb:4:1:4:10 | call to body | +| Typhoeus.rb:6:9:6:63 | call to post | Typhoeus.rb:7:1:7:10 | call to body | +| Typhoeus.rb:9:9:9:62 | call to put | Typhoeus.rb:10:1:10:10 | call to body | +| Typhoeus.rb:12:9:12:64 | call to patch | Typhoeus.rb:13:1:13:10 | call to body | +| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus.rb:16:1:16:10 | call to body | +| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus.rb:19:1:19:10 | call to body | +| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus.rb:22:1:22:10 | call to body | +getAUrlPart +| Excon.rb:3:9:3:40 | call to get | Excon.rb:3:19:3:39 | "http://example.com/" | +| Excon.rb:6:9:6:60 | call to post | Excon.rb:6:20:6:40 | "http://example.com/" | +| Excon.rb:9:9:9:59 | call to put | Excon.rb:9:19:9:39 | "http://example.com/" | +| Excon.rb:12:9:12:61 | call to patch | Excon.rb:12:21:12:41 | "http://example.com/" | +| Excon.rb:15:9:15:43 | call to delete | Excon.rb:15:22:15:42 | "http://example.com/" | +| Excon.rb:18:9:18:41 | call to head | Excon.rb:18:20:18:40 | "http://example.com/" | +| Excon.rb:21:9:21:44 | call to options | Excon.rb:21:23:21:43 | "http://example.com/" | +| Excon.rb:24:9:24:42 | call to trace | Excon.rb:24:21:24:41 | "http://example.com/" | +| Excon.rb:28:9:28:34 | call to get | Excon.rb:27:25:27:44 | "http://example.com" | +| Excon.rb:28:9:28:34 | call to get | Excon.rb:28:31:28:33 | "/" | +| Excon.rb:31:10:31:39 | call to post | Excon.rb:27:25:27:44 | "http://example.com" | +| Excon.rb:31:10:31:39 | call to post | Excon.rb:31:33:31:38 | "/foo" | +| Excon.rb:35:9:35:34 | call to get | Excon.rb:34:37:34:56 | "http://example.com" | +| Excon.rb:35:9:35:34 | call to get | Excon.rb:35:31:35:33 | "/" | +| Excon.rb:38:10:38:39 | call to post | Excon.rb:34:37:34:56 | "http://example.com" | +| Excon.rb:38:10:38:39 | call to post | Excon.rb:38:33:38:38 | "/foo" | +| Faraday.rb:3:9:3:42 | call to get | Faraday.rb:3:21:3:41 | "http://example.com/" | +| Faraday.rb:6:9:6:62 | call to post | Faraday.rb:6:22:6:42 | "http://example.com/" | +| Faraday.rb:9:9:9:61 | call to put | Faraday.rb:9:21:9:41 | "http://example.com/" | +| Faraday.rb:12:9:12:63 | call to patch | Faraday.rb:12:23:12:43 | "http://example.com/" | +| Faraday.rb:15:9:15:45 | call to delete | Faraday.rb:15:24:15:44 | "http://example.com/" | +| Faraday.rb:18:9:18:43 | call to head | Faraday.rb:18:22:18:42 | "http://example.com/" | +| Faraday.rb:24:9:24:44 | call to trace | Faraday.rb:24:23:24:43 | "http://example.com/" | +| Faraday.rb:28:9:28:27 | call to get | Faraday.rb:27:26:27:45 | "http://example.com" | +| Faraday.rb:28:9:28:27 | call to get | Faraday.rb:28:24:28:26 | "/" | +| Faraday.rb:31:10:31:46 | call to post | Faraday.rb:27:26:27:45 | "http://example.com" | +| Faraday.rb:31:10:31:46 | call to post | Faraday.rb:31:26:31:31 | "/foo" | +| Faraday.rb:35:10:35:28 | call to get | Faraday.rb:34:26:34:50 | Pair | +| Faraday.rb:35:10:35:28 | call to get | Faraday.rb:34:31:34:50 | "http://example.com" | +| Faraday.rb:35:10:35:28 | call to get | Faraday.rb:35:25:35:27 | "/" | +| Faraday.rb:39:10:39:28 | call to get | Faraday.rb:38:38:38:63 | Pair | +| Faraday.rb:39:10:39:28 | call to get | Faraday.rb:38:43:38:63 | "https://example.com" | +| Faraday.rb:39:10:39:28 | call to get | Faraday.rb:39:25:39:27 | "/" | +| HttpClient.rb:3:9:3:45 | call to get | HttpClient.rb:3:24:3:44 | "http://example.com/" | +| HttpClient.rb:6:9:6:65 | call to post | HttpClient.rb:6:25:6:45 | "http://example.com/" | +| HttpClient.rb:9:9:9:64 | call to put | HttpClient.rb:9:24:9:44 | "http://example.com/" | +| HttpClient.rb:12:9:12:48 | call to delete | HttpClient.rb:12:27:12:47 | "http://example.com/" | +| HttpClient.rb:15:9:15:46 | call to head | HttpClient.rb:15:25:15:45 | "http://example.com/" | +| HttpClient.rb:18:9:18:49 | call to options | HttpClient.rb:18:28:18:48 | "http://example.com/" | +| HttpClient.rb:21:9:21:47 | call to trace | HttpClient.rb:21:26:21:46 | "http://example.com/" | +| HttpClient.rb:24:9:24:53 | call to get_content | HttpClient.rb:24:32:24:52 | "http://example.com/" | +| HttpClient.rb:26:10:26:74 | call to post_content | HttpClient.rb:26:34:26:54 | "http://example.com/" | +| Httparty.rb:5:1:5:35 | call to get | Httparty.rb:5:14:5:34 | "http://example.com/" | +| Httparty.rb:7:1:7:55 | call to post | Httparty.rb:7:15:7:35 | "http://example.com/" | +| Httparty.rb:9:1:9:54 | call to put | Httparty.rb:9:14:9:34 | "http://example.com/" | +| Httparty.rb:11:1:11:56 | call to patch | Httparty.rb:11:16:11:36 | "http://example.com/" | +| Httparty.rb:15:9:15:46 | call to delete | Httparty.rb:15:25:15:45 | "http://example.com/" | +| Httparty.rb:18:9:18:44 | call to head | Httparty.rb:18:23:18:43 | "http://example.com/" | +| Httparty.rb:21:9:21:47 | call to options | Httparty.rb:21:26:21:46 | "http://example.com/" | +| NetHttp.rb:4:1:4:18 | call to get | NetHttp.rb:4:15:4:17 | uri | +| NetHttp.rb:6:8:6:50 | call to post | NetHttp.rb:6:23:6:36 | call to parse | +| NetHttp.rb:13:6:13:17 | call to get | NetHttp.rb:11:21:11:41 | "https://example.com" | +| NetHttp.rb:13:6:13:17 | call to get | NetHttp.rb:13:14:13:16 | "/" | +| NetHttp.rb:14:6:14:18 | call to post | NetHttp.rb:11:21:11:41 | "https://example.com" | +| NetHttp.rb:14:6:14:18 | call to post | NetHttp.rb:14:15:14:17 | "/" | +| NetHttp.rb:15:6:15:17 | call to put | NetHttp.rb:11:21:11:41 | "https://example.com" | +| NetHttp.rb:15:6:15:17 | call to put | NetHttp.rb:15:14:15:16 | "/" | +| NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:24:17:24:22 | domain | +| NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:24:29:24:32 | path | +| OpenURI.rb:3:9:3:41 | call to open | OpenURI.rb:3:21:3:40 | "http://example.com" | +| OpenURI.rb:6:9:6:34 | call to open | OpenURI.rb:6:14:6:33 | "http://example.com" | +| OpenURI.rb:9:9:9:38 | call to open | OpenURI.rb:9:18:9:37 | "http://example.com" | +| OpenURI.rb:15:9:15:47 | call to open_uri | OpenURI.rb:15:26:15:46 | "https://example.com" | +| RestClient.rb:3:9:3:45 | call to get | RestClient.rb:3:24:3:44 | "http://example.com/" | +| RestClient.rb:6:9:6:59 | call to post | RestClient.rb:6:25:6:44 | "http://example.com" | +| RestClient.rb:9:9:9:58 | call to put | RestClient.rb:9:24:9:43 | "http://example.com" | +| RestClient.rb:12:9:12:60 | call to patch | RestClient.rb:12:26:12:45 | "http://example.com" | +| RestClient.rb:15:9:15:47 | call to delete | RestClient.rb:15:27:15:46 | "http://example.com" | +| RestClient.rb:18:9:18:45 | call to head | RestClient.rb:18:25:18:44 | "http://example.com" | +| RestClient.rb:21:9:21:48 | call to options | RestClient.rb:21:28:21:47 | "http://example.com" | +| RestClient.rb:28:9:28:85 | call to execute | RestClient.rb:28:56:28:84 | "http://example.com/resource" | +| Typhoeus.rb:3:9:3:43 | call to get | Typhoeus.rb:3:22:3:42 | "http://example.com/" | +| Typhoeus.rb:6:9:6:63 | call to post | Typhoeus.rb:6:23:6:43 | "http://example.com/" | +| Typhoeus.rb:9:9:9:62 | call to put | Typhoeus.rb:9:22:9:42 | "http://example.com/" | +| Typhoeus.rb:12:9:12:64 | call to patch | Typhoeus.rb:12:24:12:44 | "http://example.com/" | +| Typhoeus.rb:15:9:15:46 | call to delete | Typhoeus.rb:15:25:15:45 | "http://example.com/" | +| Typhoeus.rb:18:9:18:44 | call to head | Typhoeus.rb:18:23:18:43 | "http://example.com/" | +| Typhoeus.rb:21:9:21:47 | call to options | Typhoeus.rb:21:26:21:46 | "http://example.com/" | diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql index 0bcc883c364..7ccc8efbbde 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql +++ b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.ql @@ -1,10 +1,10 @@ import codeql.ruby.Concepts import codeql.ruby.DataFlow -query predicate httpRequests( - Http::Client::Request r, string framework, DataFlow::Node urlPart, DataFlow::Node responseBody -) { - r.getFramework() = framework and - r.getAUrlPart() = urlPart and - r.getResponseBody() = responseBody -} +query predicate httpRequests(Http::Client::Request r) { any() } + +query string getFramework(Http::Client::Request req) { result = req.getFramework() } + +query DataFlow::Node getResponseBody(Http::Client::Request req) { result = req.getResponseBody() } + +query DataFlow::Node getAUrlPart(Http::Client::Request req) { result = req.getAUrlPart() } From e366ba1d7c0351d2cae81dcbacc8475c53197b90 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 11:33:39 +0200 Subject: [PATCH 095/141] JS: Use RST syntax for link in docs --- .../customizing-library-models-for-javascript.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst b/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst index a50b6b11a85..d8a9e15faf5 100644 --- a/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst +++ b/docs/codeql/codeql-language-guides/customizing-library-models-for-javascript.rst @@ -30,7 +30,7 @@ The CodeQL library for JavaScript exposes the following extensible predicates: - **typeModel**\(type1, type2, path) - **summaryModel**\(type, path, input, output, kind) -See the [CLI documentation for how to load and use data extensions in a CodeQL evaluation run](https://docs.google.com/document/d/14IYCHX8wWuU-HTvJ2gPSdXQKHKYbWCHQKOgn8oLaa80/edit#heading=h.m0v53lpi6w2n) (internal access required). +See the `CLI documentation for how to load and use data extensions in a CodeQL evaluation run `__ (internal access required). We'll explain how to use these using a few examples, and provide some reference material at the end of this article. From 33b041242d5308de061dba599fbe28845235463a Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Thu, 30 Mar 2023 16:00:55 +0100 Subject: [PATCH 096/141] Swift: Recognize Core Data + Realm sources via type aliases. --- .../lib/codeql/swift/elements/type/Type.qll | 20 +++++++++++++++++++ .../CleartextStorageDatabaseExtensions.qll | 4 ++-- .../CleartextStorageDatabaseQuery.qll | 6 +++--- .../CWE-311/CleartextStorageDatabase.expected | 13 ++++++++++++ .../Security/CWE-311/testRealm.swift | 2 +- 5 files changed, 39 insertions(+), 6 deletions(-) diff --git a/swift/ql/lib/codeql/swift/elements/type/Type.qll b/swift/ql/lib/codeql/swift/elements/type/Type.qll index b59da586b63..d543121ef4e 100644 --- a/swift/ql/lib/codeql/swift/elements/type/Type.qll +++ b/swift/ql/lib/codeql/swift/elements/type/Type.qll @@ -1,4 +1,6 @@ private import codeql.swift.generated.type.Type +private import codeql.swift.elements.type.NominalType +private import codeql.swift.elements.type.TypeAliasType class Type extends Generated::Type { override string toString() { result = this.getName() } @@ -11,4 +13,22 @@ class Type extends Generated::Type { * ``` */ Type getUnderlyingType() { result = this } + + /** + * Gets any base type of this type, or the result of resolving a typedef. For + * example in the following code, `C` has base type `B` which has underlying + * type `A`. Thus, `getABaseOrAliasedType*` can be used to discover the + * relationship between `C` and `A`. + * ``` + * class A {} + * + * typealias B = A + * + * class C : B {} + * ``` + */ + Type getABaseOrAliasedType() { + result = this.(NominalType).getABaseType() or + result = this.(TypeAliasType).getAliasedType() + } } diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll index e8529ff5d06..0bb20e9b8fb 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll @@ -49,7 +49,7 @@ private class CoreDataStore extends CleartextStorageDatabaseSink { // with `coreDataObj.data` is a sink. // (ideally this would be only members with the `@NSManaged` attribute) exists(NominalType t, Expr e | - t.getABaseType*().getName() = "NSManagedObject" and + t.getABaseOrAliasedType*().getName() = "NSManagedObject" and this.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = e and e.getFullyConverted().getType() = t and not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl @@ -67,7 +67,7 @@ private class RealmStore extends CleartextStorageDatabaseSink instanceof DataFlo // example in `realmObj.data = sensitive` the post-update node corresponding // with `realmObj.data` is a sink. exists(NominalType t, Expr e | - t.getABaseType*().getName() = "RealmSwiftObject" and + t.getABaseOrAliasedType*().getName() = "RealmSwiftObject" and this.getPreUpdateNode().asExpr() = e and e.getFullyConverted().getType() = t and not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll index e77f7f523bd..acf88255473 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll @@ -37,9 +37,9 @@ class CleartextStorageConfig extends TaintTracking::Configuration { // flow out from fields of an `NSManagedObject` or `RealmSwiftObject` at the sink, // for example in `realmObj.data = sensitive`. isSink(node) and - exists(ClassOrStructDecl cd, Decl cx | - cd.getABaseTypeDecl*().getName() = ["NSManagedObject", "RealmSwiftObject"] and - cx.asNominalTypeDecl() = cd and + exists(NominalTypeDecl d, Decl cx | + d.getType().getABaseOrAliasedType*().getName() = ["NSManagedObject", "RealmSwiftObject"] and + cx.asNominalTypeDecl() = d and c.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember() ) or diff --git a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected index 4d6cc43192f..52c9a9e6bc7 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected +++ b/swift/ql/test/query-tests/Security/CWE-311/CleartextStorageDatabase.expected @@ -2,6 +2,7 @@ edges | file://:0:0:0:0 | self [value] : | file://:0:0:0:0 | .value : | | file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [data] : | | file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | +| file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [password] : | | file://:0:0:0:0 | value : | file://:0:0:0:0 | [post] self [value] : | | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | value : | | testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : | testCoreData2.swift:37:2:37:2 | [post] obj | @@ -169,6 +170,7 @@ edges | testGRDB.swift:210:85:210:85 | password : | testGRDB.swift:210:84:210:93 | [...] | | testGRDB.swift:212:99:212:99 | password : | testGRDB.swift:212:98:212:107 | [...] | | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | value : | +| testRealm.swift:34:6:34:6 | value : | file://:0:0:0:0 | value : | | testRealm.swift:41:2:41:2 | [post] a [data] : | testRealm.swift:41:2:41:2 | [post] a | | testRealm.swift:41:11:41:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | | testRealm.swift:41:11:41:11 | myPassword : | testRealm.swift:41:2:41:2 | [post] a [data] : | @@ -181,17 +183,22 @@ edges | testRealm.swift:66:2:66:2 | [post] g [data] : | testRealm.swift:66:2:66:2 | [post] g | | testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | | testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:66:2:66:2 | [post] g [data] : | +| testRealm.swift:73:2:73:2 | [post] h [password] : | testRealm.swift:73:2:73:2 | [post] h | +| testRealm.swift:73:15:73:15 | myPassword : | testRealm.swift:34:6:34:6 | value : | +| testRealm.swift:73:15:73:15 | myPassword : | testRealm.swift:73:2:73:2 | [post] h [password] : | nodes | file://:0:0:0:0 | .value2 : | semmle.label | .value2 : | | file://:0:0:0:0 | .value : | semmle.label | .value : | | file://:0:0:0:0 | .value : | semmle.label | .value : | | file://:0:0:0:0 | [post] self [data] : | semmle.label | [post] self [data] : | | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | semmle.label | [post] self [notStoredBankAccountNumber] : | +| file://:0:0:0:0 | [post] self [password] : | semmle.label | [post] self [password] : | | file://:0:0:0:0 | [post] self [value] : | semmle.label | [post] self [value] : | | file://:0:0:0:0 | self [value] : | semmle.label | self [value] : | | file://:0:0:0:0 | value : | semmle.label | value : | | file://:0:0:0:0 | value : | semmle.label | value : | | file://:0:0:0:0 | value : | semmle.label | value : | +| file://:0:0:0:0 | value : | semmle.label | value : | | testCoreData2.swift:23:13:23:13 | value : | semmle.label | value : | | testCoreData2.swift:37:2:37:2 | [post] obj | semmle.label | [post] obj | | testCoreData2.swift:37:2:37:2 | [post] obj [myValue] : | semmle.label | [post] obj [myValue] : | @@ -422,6 +429,7 @@ nodes | testGRDB.swift:212:98:212:107 | [...] | semmle.label | [...] | | testGRDB.swift:212:99:212:99 | password : | semmle.label | password : | | testRealm.swift:27:6:27:6 | value : | semmle.label | value : | +| testRealm.swift:34:6:34:6 | value : | semmle.label | value : | | testRealm.swift:41:2:41:2 | [post] a | semmle.label | [post] a | | testRealm.swift:41:2:41:2 | [post] a [data] : | semmle.label | [post] a [data] : | | testRealm.swift:41:11:41:11 | myPassword : | semmle.label | myPassword : | @@ -434,6 +442,9 @@ nodes | testRealm.swift:66:2:66:2 | [post] g | semmle.label | [post] g | | testRealm.swift:66:2:66:2 | [post] g [data] : | semmle.label | [post] g [data] : | | testRealm.swift:66:11:66:11 | myPassword : | semmle.label | myPassword : | +| testRealm.swift:73:2:73:2 | [post] h | semmle.label | [post] h | +| testRealm.swift:73:2:73:2 | [post] h [password] : | semmle.label | [post] h [password] : | +| testRealm.swift:73:15:73:15 | myPassword : | semmle.label | myPassword : | subpaths | testCoreData2.swift:43:35:43:35 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:43:2:43:2 | [post] obj [notStoredBankAccountNumber] : | | testCoreData2.swift:52:41:52:41 | bankAccountNo : | testCoreData2.swift:23:13:23:13 | value : | file://:0:0:0:0 | [post] self [notStoredBankAccountNumber] : | testCoreData2.swift:52:2:52:10 | [post] ...? [notStoredBankAccountNumber] : | @@ -453,6 +464,7 @@ subpaths | testRealm.swift:49:11:49:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:49:2:49:2 | [post] c [data] : | | testRealm.swift:59:12:59:12 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:59:2:59:3 | [post] ...! [data] : | | testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:27:6:27:6 | value : | file://:0:0:0:0 | [post] self [data] : | testRealm.swift:66:2:66:2 | [post] g [data] : | +| testRealm.swift:73:15:73:15 | myPassword : | testRealm.swift:34:6:34:6 | value : | file://:0:0:0:0 | [post] self [password] : | testRealm.swift:73:2:73:2 | [post] h [password] : | #select | testCoreData2.swift:37:2:37:2 | obj | testCoreData2.swift:37:16:37:16 | bankAccountNo : | testCoreData2.swift:37:2:37:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:37:16:37:16 | bankAccountNo : | bankAccountNo | | testCoreData2.swift:39:2:39:2 | obj | testCoreData2.swift:39:28:39:28 | bankAccountNo : | testCoreData2.swift:39:2:39:2 | [post] obj | This operation stores 'obj' in a database. It may contain unencrypted sensitive data from $@. | testCoreData2.swift:39:28:39:28 | bankAccountNo : | bankAccountNo | @@ -546,3 +558,4 @@ subpaths | testRealm.swift:49:2:49:2 | c | testRealm.swift:49:11:49:11 | myPassword : | testRealm.swift:49:2:49:2 | [post] c | This operation stores 'c' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:49:11:49:11 | myPassword : | myPassword | | testRealm.swift:59:2:59:3 | ...! | testRealm.swift:59:12:59:12 | myPassword : | testRealm.swift:59:2:59:3 | [post] ...! | This operation stores '...!' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:59:12:59:12 | myPassword : | myPassword | | testRealm.swift:66:2:66:2 | g | testRealm.swift:66:11:66:11 | myPassword : | testRealm.swift:66:2:66:2 | [post] g | This operation stores 'g' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:66:11:66:11 | myPassword : | myPassword | +| testRealm.swift:73:2:73:2 | h | testRealm.swift:73:15:73:15 | myPassword : | testRealm.swift:73:2:73:2 | [post] h | This operation stores 'h' in a database. It may contain unencrypted sensitive data from $@. | testRealm.swift:73:15:73:15 | myPassword : | myPassword | diff --git a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift index 87a1530ea63..8bcf9ce83f5 100644 --- a/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift +++ b/swift/ql/test/query-tests/Security/CWE-311/testRealm.swift @@ -70,7 +70,7 @@ func test1(realm : Realm, myUsername: String, myPassword : String, myHashedPassw let h = MyRealmSwiftObject2() h.username = myUsername // GOOD (not sensitive) - h.password = myPassword // BAD [NOT DETECTED] + h.password = myPassword // BAD realm.add(h) } From 302013a7fd95124babb25b82f59599d4b13ff99f Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 27 Jan 2023 16:20:54 +0000 Subject: [PATCH 097/141] Swift: Add a test for Type.getABaseOrAliasedType. --- .../type/nominaltype/nominaltype.expected | 20 +++++++++---------- .../elements/type/nominaltype/nominaltype.ql | 2 ++ .../type/nominaltype/nominaltypedecl.expected | 2 +- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected index 0eb3c363ee8..08a3b86b7b3 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected @@ -1,13 +1,13 @@ | nominaltype.swift:35:6:35:6 | a | A | A | | -| nominaltype.swift:36:6:36:6 | a_alias | A_alias | A | getAliasedType:A | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | A? | getAliasedType:A? | -| nominaltype.swift:38:6:38:6 | b1 | B1 | B1 | getABaseType:A | -| nominaltype.swift:39:6:39:6 | b2 | B2 | B2 | getABaseType:A_alias | -| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1 | getAliasedType:B1 | -| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | B2 | getAliasedType:B2 | +| nominaltype.swift:36:6:36:6 | a_alias | A_alias | A | getABaseOrAliasedType:A, getAliasedType:A | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | Optional | getABaseOrAliasedType:Optional, getAliasedType:Optional | +| nominaltype.swift:38:6:38:6 | b1 | B1 | B1 | getABaseOrAliasedType:A, getABaseType:A | +| nominaltype.swift:39:6:39:6 | b2 | B2 | B2 | getABaseOrAliasedType:A_alias, getABaseType:A_alias | +| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1 | getABaseOrAliasedType:B1, getAliasedType:B1 | +| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | B2 | getABaseOrAliasedType:B2, getAliasedType:B2 | | nominaltype.swift:42:6:42:6 | p | P | P | | | nominaltype.swift:43:6:43:6 | p_alias | P_alias | P_alias | | -| nominaltype.swift:44:6:44:6 | c1 | C1 | C1 | getABaseType:P | -| nominaltype.swift:45:6:45:6 | c2 | C2 | C2 | getABaseType:P_alias | -| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | C1 | getAliasedType:C1 | -| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | C2 | getAliasedType:C2 | +| nominaltype.swift:44:6:44:6 | c1 | C1 | C1 | getABaseOrAliasedType:P, getABaseType:P | +| nominaltype.swift:45:6:45:6 | c2 | C2 | C2 | getABaseOrAliasedType:P_alias, getABaseType:P_alias | +| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | C1 | getABaseOrAliasedType:C1, getAliasedType:C1 | +| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | C2 | getABaseOrAliasedType:C2, getAliasedType:C2 | diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql index f5e01a8022b..a8384f4afbf 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql @@ -4,6 +4,8 @@ string describe(Type t) { result = "getAliasedType:" + t.(TypeAliasType).getAliasedType() or result = "getABaseType:" + t.(NominalType).getABaseType() + or + result = "getABaseOrAliasedType:" + t.getABaseOrAliasedType() } from VarDecl v, Type t diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected index 612b031f54e..0d75db4b0e0 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected @@ -1,6 +1,6 @@ | nominaltype.swift:35:6:35:6 | a | A | | | nominaltype.swift:36:6:36:6 | a_alias | A_alias | getAliasedType:A | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | getAliasedType:A? | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | getAliasedType:Optional | | nominaltype.swift:38:6:38:6 | b1 | B1 | getABaseType:A | | nominaltype.swift:39:6:39:6 | b2 | B2 | getABaseType:A_alias | | nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | getAliasedType:B1 | From 4a06b81429ea764a8e6339dc075a43aa00d96f59 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 12:03:14 +0200 Subject: [PATCH 098/141] JS: Use API graphs in CryptoJS --- .../javascript/frameworks/CryptoLibraries.qll | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 8e788151f97..93a526c01b3 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -291,13 +291,13 @@ private module CryptoJS { * ``` */ - exists(DataFlow::SourceNode mod, DataFlow::PropRead propRead | - mod = DataFlow::moduleImport("crypto-js") and - propRead = mod.getAPropertyRead("algo").getAPropertyRead() and - this = propRead.getAMemberCall("create") and - algorithmName = propRead.getPropertyName() and - not isStrongPasswordHashingAlgorithm(algorithmName) - ) + this = + API::moduleImport("crypto-js") + .getMember("algo") + .getMember(algorithmName) + .getMember("create") + .getACall() and + not isStrongPasswordHashingAlgorithm(algorithmName) } CryptographicAlgorithm getAlgorithm() { result.matchesName(algorithmName) } From 40530ae14de85e490adcc43ab8e2fa73b0aa5eba Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 12:04:56 +0200 Subject: [PATCH 099/141] JS: Simplfy with set literal --- .../ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 93a526c01b3..705758ff46a 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -321,10 +321,7 @@ private module CryptoJS { */ private API::Node getAlgorithmNode(CryptographicAlgorithm algorithm) { exists(string algorithmName | algorithm.matchesName(algorithmName) | - exists(API::Node mod | mod = API::moduleImport("crypto-js") | - result = mod.getMember(algorithmName) or - result = mod.getMember("Hmac" + algorithmName) // they prefix Hmac - ) + result = API::moduleImport("crypto-js").getMember([algorithmName, "Hmac" + algorithmName]) or result = API::moduleImport("crypto-js/" + algorithmName) ) From 504a0f811227f823e25cc1fc38afeb4ddf22de49 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 11:10:47 +0200 Subject: [PATCH 100/141] Ruby: Add test where response body is not referenced --- ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb b/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb index 12333be9f4e..608b46ece9a 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb +++ b/ruby/ql/test/library-tests/frameworks/http_clients/NetHttp.rb @@ -25,3 +25,5 @@ def get(domain, path) end get("example.com", "/").body + +Net::HTTP.post(uri, "some_body") # note: response body not accessed From c699afd07f2be35c782f3a392c5cff73d36b7d72 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 11:07:21 +0200 Subject: [PATCH 101/141] Ruby: instantiate NetHttpRequest even if body is not accessed --- .../ruby/frameworks/http_clients/NetHttp.qll | 14 +++++++++----- .../frameworks/http_clients/HttpClients.expected | 7 +++++++ 2 files changed, 16 insertions(+), 5 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll index fbe27b6884c..eac0a928a1b 100644 --- a/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll +++ b/ruby/ql/lib/codeql/ruby/frameworks/http_clients/NetHttp.qll @@ -21,8 +21,8 @@ private import codeql.ruby.dataflow.internal.DataFlowImplForHttpClientLibraries */ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode { private DataFlow::CallNode request; - private DataFlow::Node responseBody; private API::Node requestNode; + private boolean returnsResponseBody; NetHttpRequest() { exists(string method | @@ -32,12 +32,12 @@ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode { // Net::HTTP.get(...) method = "get" and requestNode = API::getTopLevelMember("Net").getMember("HTTP").getReturn(method) and - responseBody = request + returnsResponseBody = true or // Net::HTTP.post(...).body method in ["post", "post_form"] and requestNode = API::getTopLevelMember("Net").getMember("HTTP").getReturn(method) and - responseBody = requestNode.getAMethodCall(["body", "read_body", "entity"]) + returnsResponseBody = false or // Net::HTTP.new(..).get(..).body method in [ @@ -45,7 +45,7 @@ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode { "post", "post2", "request_post", "request" ] and requestNode = API::getTopLevelMember("Net").getMember("HTTP").getInstance().getReturn(method) and - responseBody = requestNode.getAMethodCall(["body", "read_body", "entity"]) + returnsResponseBody = false ) } @@ -64,7 +64,11 @@ class NetHttpRequest extends Http::Client::Request::Range, DataFlow::CallNode { ) } - override DataFlow::Node getResponseBody() { result = responseBody } + override DataFlow::Node getResponseBody() { + if returnsResponseBody = true + then result = this + else result = requestNode.getAMethodCall(["body", "read_body", "entity"]) + } /** Gets the value that controls certificate validation, if any. */ DataFlow::Node getCertificateValidationControllingValue() { diff --git a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected index 697cdd751dd..50d8303925f 100644 --- a/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected +++ b/ruby/ql/test/library-tests/frameworks/http_clients/HttpClients.expected @@ -43,7 +43,9 @@ httpRequests | NetHttp.rb:13:6:13:17 | call to get | | NetHttp.rb:14:6:14:18 | call to post | | NetHttp.rb:15:6:15:17 | call to put | +| NetHttp.rb:16:6:16:19 | call to patch | | NetHttp.rb:24:3:24:33 | call to get | +| NetHttp.rb:29:1:29:32 | call to post | | OpenURI.rb:3:9:3:41 | call to open | | OpenURI.rb:6:9:6:34 | call to open | | OpenURI.rb:9:9:9:38 | call to open | @@ -110,7 +112,9 @@ getFramework | NetHttp.rb:13:6:13:17 | call to get | Net::HTTP | | NetHttp.rb:14:6:14:18 | call to post | Net::HTTP | | NetHttp.rb:15:6:15:17 | call to put | Net::HTTP | +| NetHttp.rb:16:6:16:19 | call to patch | Net::HTTP | | NetHttp.rb:24:3:24:33 | call to get | Net::HTTP | +| NetHttp.rb:29:1:29:32 | call to post | Net::HTTP | | OpenURI.rb:3:9:3:41 | call to open | OpenURI | | OpenURI.rb:6:9:6:34 | call to open | OpenURI | | OpenURI.rb:9:9:9:38 | call to open | OpenURI | @@ -259,8 +263,11 @@ getAUrlPart | NetHttp.rb:14:6:14:18 | call to post | NetHttp.rb:14:15:14:17 | "/" | | NetHttp.rb:15:6:15:17 | call to put | NetHttp.rb:11:21:11:41 | "https://example.com" | | NetHttp.rb:15:6:15:17 | call to put | NetHttp.rb:15:14:15:16 | "/" | +| NetHttp.rb:16:6:16:19 | call to patch | NetHttp.rb:11:21:11:41 | "https://example.com" | +| NetHttp.rb:16:6:16:19 | call to patch | NetHttp.rb:16:16:16:18 | "/" | | NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:24:17:24:22 | domain | | NetHttp.rb:24:3:24:33 | call to get | NetHttp.rb:24:29:24:32 | path | +| NetHttp.rb:29:1:29:32 | call to post | NetHttp.rb:29:16:29:18 | uri | | OpenURI.rb:3:9:3:41 | call to open | OpenURI.rb:3:21:3:40 | "http://example.com" | | OpenURI.rb:6:9:6:34 | call to open | OpenURI.rb:6:14:6:33 | "http://example.com" | | OpenURI.rb:9:9:9:38 | call to open | OpenURI.rb:9:18:9:37 | "http://example.com" | From 04c09a73a9dc773fa34f7d275e9354cd8fdc3e61 Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Fri, 31 Mar 2023 12:40:19 +0100 Subject: [PATCH 102/141] Java: Add .md extension to changenote file --- .../{2023-03-22-expanded-args => 2023-03-22-expanded-args.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename java/ql/lib/change-notes/{2023-03-22-expanded-args => 2023-03-22-expanded-args.md} (100%) diff --git a/java/ql/lib/change-notes/2023-03-22-expanded-args b/java/ql/lib/change-notes/2023-03-22-expanded-args.md similarity index 100% rename from java/ql/lib/change-notes/2023-03-22-expanded-args rename to java/ql/lib/change-notes/2023-03-22-expanded-args.md From 3d85c4f19ce50ef47a76d28ef76318f4f786fa4a Mon Sep 17 00:00:00 2001 From: Ian Lynagh Date: Fri, 31 Mar 2023 12:46:10 +0100 Subject: [PATCH 103/141] Java: Add another change note --- java/ql/lib/change-notes/2023-03-31-compilation-names.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 java/ql/lib/change-notes/2023-03-31-compilation-names.md diff --git a/java/ql/lib/change-notes/2023-03-31-compilation-names.md b/java/ql/lib/change-notes/2023-03-31-compilation-names.md new file mode 100644 index 00000000000..c581a585199 --- /dev/null +++ b/java/ql/lib/change-notes/2023-03-31-compilation-names.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* The filenames embedded in `Compilation.toString()` now use `/` as the path separator on all platforms. From 8d9b96b776a3724acbb51414c9850c052b17e19c Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Thu, 30 Mar 2023 17:22:00 +0200 Subject: [PATCH 104/141] C++: Drop the bit size restriction in `typeBound` and use `float` --- .../semantic/analysis/RangeAnalysisStage.qll | 23 +++---- .../SimpleRangeAnalysis_tests.cpp | 62 +++++++++---------- 2 files changed, 41 insertions(+), 44 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll index 330251be09d..c544dec893f 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll @@ -78,18 +78,15 @@ import experimental.semmle.code.cpp.semantic.SemanticLocation /** * Holds if `typ` is a small integral type with the given lower and upper bounds. */ -private predicate typeBound(SemIntegerType typ, int lowerbound, int upperbound) { +private predicate typeBound(SemIntegerType typ, float lowerbound, float upperbound) { exists(int bitSize | bitSize = typ.getByteSize() * 8 | - bitSize < 32 and - ( - if typ.isSigned() - then ( - upperbound = 1.bitShiftLeft(bitSize - 1) - 1 and - lowerbound = -upperbound - 1 - ) else ( - lowerbound = 0 and - upperbound = 1.bitShiftLeft(bitSize) - 1 - ) + if typ.isSigned() + then ( + upperbound = 2.pow(bitSize - 1) - 1 and + lowerbound = -upperbound - 1 + ) else ( + lowerbound = 0 and + upperbound = 2.pow(bitSize) - 1 ) ) } @@ -286,10 +283,10 @@ module RangeStage Bounds, LangSig LangParam, UtilSig< } /** Gets the lower bound of the resulting type. */ - int getLowerBound() { typeBound(getTrackedType(this), result, _) } + float getLowerBound() { typeBound(getTrackedType(this), result, _) } /** Gets the upper bound of the resulting type. */ - int getUpperBound() { typeBound(getTrackedType(this), _, result) } + float getUpperBound() { typeBound(getTrackedType(this), _, result) } } private module SignAnalysisInstantiated = SignAnalysis; // TODO: will this cause reevaluation if it's instantiated with the same DeltaSig and UtilParam multiple times? diff --git a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp index 7103d5962fb..19c9b47d670 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp +++ b/cpp/ql/test/library-tests/ir/range-analysis/SimpleRangeAnalysis_tests.cpp @@ -566,11 +566,11 @@ unsigned int test_ternary01(unsigned int x) { y1 = x < 100 ? (range(x), x) : // $ range=<=99 (range(x), 10); // $ range=>=100 - range(y1); + range(y1); // $ range=<=99 y2 = x >= 100 ? (range(x), 10) : // $ range=>=100 (range(x), x); // $ range=<=99 - range(y2); + range(y2); // $ range=<=99 y3 = 0; y4 = 0; y5 = 0; @@ -580,14 +580,14 @@ unsigned int test_ternary01(unsigned int x) { if (x < 300) { range(x); // $ range=<=299 y3 = x ?: - (range(x), 5); // y3 < 300 - range(y3); + (range(x), 5); + range(y3); // $ range=<=299 y4 = x ?: - (range(x), 500); // y4 <= 500 - range(y4); + (range(x), 500); + range(y4); // $ range=<=500 y5 = (x+1) ?: (range(x), 500); // $ range===-1 - range(y5); // y5 <= 300 + range(y5); // $ range=<=500 y6 = ((unsigned char)(x+1)) ?: (range(x), 5); // $ range=<=299 range(y6); // y6 < 256 @@ -608,11 +608,11 @@ unsigned int test_ternary02(unsigned int x) { y1 = x > 100 ? (range(x), x) : // $ range=>=101 (range(x), 110); // $ range=<=100 - range(y1); // y1 > 100 + range(y1); // $ range=>=101 y2 = x <= 100 ? (range(x), 110) : // $ range=<=100 (range(x), x); // $ range=>=101 - range(y2); // y2 > 100 + range(y2); // $ range=>=101 y3 = 1000; y4 = 1000; y5 = 1000; @@ -620,15 +620,15 @@ unsigned int test_ternary02(unsigned int x) { range(x); // $ range=>=300 y3 = (x-300) ?: (range(x), 5); // $ range===300 - range(y3); // y3 >= 0 + range(y3); // $ range=>=0 y4 = (x-200) ?: (range(x), 5); // $ range=<=200 range=>=300 - range(y4); // y4 >= 100 + range(y4); // $ SPURIOUS: range=>=5 MISSING: range=>=100 y5 = ((unsigned char)(x-200)) ?: (range(x), 5); // $ range=>=300 range(y5); // y6 >= 0 } - range(y1 + y2 + y3 + y4 + y5); // $ MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0" + range(y1 + y2 + y3 + y4 + y5); // $ range=">=call to range+207" MISSING: range=">=... = ...:... ? ... : ...+0" range=">=call to range+0" return y1 + y2 + y3 + y4 + y5; } @@ -640,14 +640,14 @@ unsigned int test_comma01(unsigned int x) { unsigned int y1; unsigned int y2; y1 = (++y, y); - range(y1); // $ range="==... ? ... : ...+1" + range(y1); // $ range=<=101 range="==... ? ... : ...+1" y2 = (y++, - range(y), // $ range="==++ ...:... = ...+1" range="==... ? ... : ...+2" + range(y), // $ range=<=102 range="==++ ...:... = ...+1" range="==... ? ... : ...+2" y += 3, - range(y), // $ range="==++ ...:... = ...+4" range="==... +++3" range="==... ? ... : ...+5" + range(y), // $ range=<=105 range="==++ ...:... = ...+4" range="==... +++3" range="==... ? ... : ...+5" y); - range(y2); // $ range="==++ ...:... = ...+4" range="==... +++3" range="==... ? ... : ...+5" - range(y1 + y2); // $ MISSING: range=">=++ ...:... = ...+5" range=">=... +++4" range=">=... += ...:... = ...+1" range=">=... ? ... : ...+6" + range(y2); // $ range=<=105 range="==++ ...:... = ...+4" range="==... +++3" range="==... ? ... : ...+5" + range(y1 + y2); // $ range=<=206 range="<=... ? ... : ...+106" MISSING: range=">=++ ...:... = ...+5" range=">=... +++4" range=">=... += ...:... = ...+1" range=">=... ? ... : ...+6" return y1 + y2; } @@ -683,27 +683,27 @@ int test_unsigned_mult01(unsigned int a, unsigned b) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=5 int r = a*b; // 15 .. 253 - range(r); + range(r); // $ range=>=15 range=<=253 total += r; - range(total); // $ MISSING: range=>=1 + range(total); // $ range=>=15 range=<=253 } if (3 <= a && a <= 11 && 0 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=0 int r = a*b; // 0 .. 253 - range(r); + range(r); // $ range=>=0 range=<=253 total += r; - range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 + range(total); // $ range=>=0 range=<=506 range=">=(unsigned int)...+0" range="<=(unsigned int)...+253" } if (3 <= a && a <= 11 && 13 <= b && b <= 23) { range(a); // $ range=<=11 range=>=3 range(b); // $ range=<=23 range=>=13 int r = a*b; // 39 .. 253 - range(r); + range(r); // $ range=>=39 range=<=253 total += r; - range(total); // $ MISSING: range=">=(unsigned int)...+1" range=>=1 + range(total); // $ range=>=39 range=<=759 range=">=(unsigned int)...+39" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253" } - range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 + range(total); // $ range=>=0 range=<=759 range=">=(unsigned int)...+0" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253" return total; } @@ -713,25 +713,25 @@ int test_unsigned_mult02(unsigned b) { if (5 <= b && b <= 23) { range(b); // $ range=<=23 range=>=5 int r = 11*b; // 55 .. 253 - range(r); + range(r); // $ range=>=55 range=<=253 total += r; - range(total); // $ MISSING: range=>=1 + range(total); // $ range=>=55 range=<=253 } if (0 <= b && b <= 23) { range(b); // $ range=<=23 range=>=0 int r = 11*b; // 0 .. 253 - range(r); + range(r); // $ range=>=0 range=<=253 total += r; - range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 + range(total); // $ range=>=0 range=<=506 range=">=(unsigned int)...+0" range="<=(unsigned int)...+253" } if (13 <= b && b <= 23) { range(b); // $ range=<=23 range=>=13 int r = 11*b; // 143 .. 253 - range(r); + range(r); // $ range=>=143 range=<=253 total += r; - range(total); // $ MISSING: range=">=(unsigned int)...+1" range=>=1 + range(total); // $ range=>=143 range=<=759 range=">=(unsigned int)...+143" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253" } - range(total); // $ MISSING: range=">=(unsigned int)...+0" range=>=0 + range(total); // $ range=>=0 range=<=759 range=">=(unsigned int)...+0" range="<=(unsigned int)...+506" range="<=(unsigned int)...+253" return total; } From 64cf27ab875371dbb74deea87e9a7c4c36dfd369 Mon Sep 17 00:00:00 2001 From: Asger F Date: Fri, 31 Mar 2023 12:50:21 +0200 Subject: [PATCH 105/141] JS: Modernize crypto libraries --- .../javascript/frameworks/CryptoLibraries.qll | 144 +++++++----------- 1 file changed, 59 insertions(+), 85 deletions(-) diff --git a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll index 705758ff46a..2fab10eacac 100644 --- a/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll +++ b/javascript/ql/lib/semmle/javascript/frameworks/CryptoLibraries.qll @@ -149,7 +149,7 @@ private module BrowserIdCrypto { * A model of the Node.js builtin crypto library. */ private module NodeJSCrypto { - private class InstantiatedAlgorithm extends DataFlow::CallNode { + private class InstantiatedAlgorithm extends API::CallNode { private string algorithmName; InstantiatedAlgorithm() { @@ -166,11 +166,11 @@ private module NodeJSCrypto { * Also matches `createHash`, `createHmac`, `createSign` instead of `createCipher`. */ - exists(DataFlow::SourceNode mod | - mod = DataFlow::moduleImport("crypto") and - this = mod.getAMemberCall("create" + ["Hash", "Hmac", "Sign", "Cipher"]) and - algorithmName = this.getArgument(0).getStringValue() - ) + this = + API::moduleImport("crypto") + .getMember("create" + ["Hash", "Hmac", "Sign", "Cipher"]) + .getACall() and + algorithmName = this.getArgument(0).getStringValue() } CryptographicAlgorithm getAlgorithm() { result.matchesName(algorithmName) } @@ -197,13 +197,12 @@ private module NodeJSCrypto { // crypto.generateKeyPair(type, options, callback) // crypto.generateKeyPairSync(type, options) // crypto.generateKeySync(type, options) - exists(DataFlow::SourceNode mod, string keyType | + exists(string keyType | keyType = "Key" and symmetric = true or keyType = "KeyPair" and symmetric = false | - mod = DataFlow::moduleImport("crypto") and - this = mod.getAMemberCall("generate" + keyType + ["", "Sync"]) + this = API::moduleImport("crypto").getMember("generate" + keyType + ["", "Sync"]).getACall() ) } @@ -249,17 +248,15 @@ private module NodeJSCrypto { private class Key extends CryptographicKey { Key() { - exists(InstantiatedAlgorithm instantiation, string name | - name = "setPrivateKey" or - name = "sign" - | - this = instantiation.getAMethodCall(name).getArgument(0) - ) + this = + any(InstantiatedAlgorithm i) + .getReturn() + .getMember(["setPrivateKey", "sign"]) + .getParameter(0) + .asSink() or - exists(DataFlow::SourceNode mod, string name, DataFlow::InvokeNode call, int index | - mod = DataFlow::moduleImport("crypto") and - call = mod.getAMemberCall(name) and - this = call.getArgument(index) + exists(string name, int index | + this = API::moduleImport("crypto").getMember(name).getACall().getArgument(index) | index = 0 and (name = "privateDecrypt" or name = "privateEncrypt") @@ -497,13 +494,12 @@ private module TweetNaCl { * Also matches the "hash" method name, and the "nacl-fast" module. */ - exists(DataFlow::SourceNode mod, string name | + exists(string name | name = "hash" and algorithm.matchesName("SHA512") or name = "sign" and algorithm.matchesName("ed25519") | - (mod = DataFlow::moduleImport("nacl") or mod = DataFlow::moduleImport("nacl-fast")) and - this = mod.getAMemberCall(name) and + this = API::moduleImport(["nacl", "nacl-fast"]).getMember(name).getACall() and super.getArgument(0) = input ) } @@ -529,17 +525,13 @@ private module HashJs { */ private DataFlow::CallNode getAlgorithmNode(CryptographicAlgorithm algorithm) { exists(string algorithmName | algorithm.matchesName(algorithmName) | - result = DataFlow::moduleMember("hash.js", algorithmName).getACall() + result = API::moduleImport("hash.js").getMember(algorithmName).getACall() or - exists(DataFlow::SourceNode mod | - mod = DataFlow::moduleImport("hash.js/lib/hash/" + algorithmName) - or - exists(string size | - mod = DataFlow::moduleImport("hash.js/lib/hash/sha/" + size) and - algorithmName = "SHA" + size - ) - | - result = mod.getACall() + result = API::moduleImport("hash.js/lib/hash/" + algorithmName).getACall() + or + exists(string size | + result = API::moduleImport("hash.js/lib/hash/sha/" + size).getACall() and + algorithmName = "SHA" + size ) ) } @@ -579,10 +571,7 @@ private module HashJs { * A model of the forge library. */ private module Forge { - private DataFlow::SourceNode getAnImportNode() { - result = DataFlow::moduleImport("forge") or - result = DataFlow::moduleImport("node-forge") - } + private API::Node getAnImportNode() { result = API::moduleImport(["forge", "node-forge"]) } abstract private class Cipher extends DataFlow::CallNode { abstract CryptographicAlgorithm getAlgorithm(); @@ -594,14 +583,14 @@ private module Forge { private string blockModeString; KeyCipher() { - exists(DataFlow::SourceNode mod, string algorithmName | - mod = getAnImportNode() and - algorithm.matchesName(algorithmName) - | - exists(string createName, string cipherName, string cipherPrefix | + exists(string algorithmName | algorithm.matchesName(algorithmName) | + exists(string cipherName, string cipherPrefix | // `require('forge').cipher.createCipher("3DES-CBC").update("secret", "key");` - (createName = "createCipher" or createName = "createDecipher") and - this = mod.getAPropertyRead("cipher").getAMemberCall(createName) and + this = + getAnImportNode() + .getMember("cipher") + .getMember(["createCipher", "createDecipher"]) + .getACall() and this.getArgument(0).mayHaveStringValue(cipherName) and cipherName = cipherPrefix + "-" + blockModeString and blockModeString = ["CBC", "CFB", "CTR", "ECB", "GCM", "OFB"] and @@ -610,13 +599,13 @@ private module Forge { ) or // `require("forge").rc2.createEncryptionCipher("key").update("secret");` - exists(string createName | - createName = "createEncryptionCipher" or createName = "createDecryptionCipher" - | - this = mod.getAPropertyRead(algorithmName).getAMemberCall(createName) and - key = this.getArgument(0) and - blockModeString = algorithmName - ) + this = + getAnImportNode() + .getMember(algorithmName) + .getMember(["createEncryptionCipher", "createDecryptionCipher"]) + .getACall() and + key = this.getArgument(0) and + blockModeString = algorithmName ) } @@ -637,10 +626,7 @@ private module Forge { exists(string algorithmName | algorithm.matchesName(algorithmName) | // require("forge").md.md5.create().update('The quick brown fox jumps over the lazy dog'); this = - getAnImportNode() - .getAPropertyRead("md") - .getAPropertyRead(algorithmName) - .getAMemberCall("create") + getAnImportNode().getMember("md").getMember(algorithmName).getMember("create").getACall() ) } @@ -676,15 +662,17 @@ private module Forge { // var cipher = forge.rc2.createEncryptionCipher(key, 128); this = getAnImportNode() - .getAPropertyRead(any(string s | algorithm.matchesName(s))) - .getAMemberCall("createEncryptionCipher") + .getMember(any(string s | algorithm.matchesName(s))) + .getMember("createEncryptionCipher") + .getACall() or // var key = forge.random.getBytesSync(16); // var cipher = forge.cipher.createCipher('AES-CBC', key); this = getAnImportNode() - .getAPropertyRead("cipher") - .getAMemberCall(["createCipher", "createDecipher"]) and + .getMember("cipher") + .getMember(["createCipher", "createDecipher"]) + .getACall() and algorithm.matchesName(this.getArgument(0).getStringValue()) } @@ -713,12 +701,9 @@ private module Md5 { Apply() { // `require("md5")("message");` - exists(DataFlow::SourceNode mod | - mod = DataFlow::moduleImport("md5") and - algorithm.matchesName("MD5") and - this = mod.getACall() and - super.getArgument(0) = input - ) + algorithm.matchesName("MD5") and + this = API::moduleImport("md5").getACall() and + super.getArgument(0) = input } override DataFlow::Node getAnInput() { result = input } @@ -740,21 +725,12 @@ private module Bcrypt { Apply() { // `require("bcrypt").hash(password);` with minor naming variations - exists(DataFlow::SourceNode mod, string moduleName, string methodName | - algorithm.matchesName("BCRYPT") and - ( - moduleName = "bcrypt" or - moduleName = "bcryptjs" or - moduleName = "bcrypt-nodejs" - ) and - ( - methodName = "hash" or - methodName = "hashSync" - ) and - mod = DataFlow::moduleImport(moduleName) and - this = mod.getAMemberCall(methodName) and - super.getArgument(0) = input - ) + algorithm.matchesName("BCRYPT") and + this = + API::moduleImport(["bcrypt", "bcryptjs", "bcrypt-nodejs"]) + .getMember(["hash", "hashSync"]) + .getACall() and + super.getArgument(0) = input } override DataFlow::Node getAnInput() { result = input } @@ -776,13 +752,11 @@ private module Hasha { Apply() { // `require('hasha')('unicorn', { algorithm: "md5" });` - exists(DataFlow::SourceNode mod, string algorithmName, DataFlow::Node algorithmNameNode | - mod = DataFlow::moduleImport("hasha") and - this = mod.getACall() and + exists(string algorithmName | + this = API::moduleImport("hasha").getACall() and super.getArgument(0) = input and algorithm.matchesName(algorithmName) and - super.getOptionArgument(1, "algorithm") = algorithmNameNode and - algorithmNameNode.mayHaveStringValue(algorithmName) + super.getOptionArgument(1, "algorithm").mayHaveStringValue(algorithmName) ) } @@ -800,7 +774,7 @@ private module Hasha { */ private module ExpressJwt { private class Key extends CryptographicKey { - Key() { this = DataFlow::moduleMember("express-jwt", "sign").getACall().getArgument(1) } + Key() { this = API::moduleImport("express-jwt").getMember("sign").getACall().getArgument(1) } } } From 8a805bb7a3ad210995a6312e81e3603a63832fe1 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 31 Mar 2023 13:54:04 +0100 Subject: [PATCH 106/141] Swift: Replace getABaseOrAliasedType with slightly more sophisticated getABaseType. --- .../swift/elements/type/NominalType.qll | 2 +- .../lib/codeql/swift/elements/type/Type.qll | 16 ++++++--------- .../swift/elements/type/TypeAliasType.qll | 2 ++ .../CleartextStorageDatabaseExtensions.qll | 4 ++-- .../CleartextStorageDatabaseQuery.qll | 2 +- .../type/nominaltype/nominaltype.expected | 20 +++++++++---------- .../elements/type/nominaltype/nominaltype.ql | 4 +--- 7 files changed, 23 insertions(+), 27 deletions(-) diff --git a/swift/ql/lib/codeql/swift/elements/type/NominalType.qll b/swift/ql/lib/codeql/swift/elements/type/NominalType.qll index 9e1c4a9a8c0..4abc15e30f2 100644 --- a/swift/ql/lib/codeql/swift/elements/type/NominalType.qll +++ b/swift/ql/lib/codeql/swift/elements/type/NominalType.qll @@ -3,7 +3,7 @@ private import codeql.swift.elements.decl.NominalTypeDecl private import codeql.swift.elements.type.Type class NominalType extends Generated::NominalType { - Type getABaseType() { result = this.getDeclaration().(NominalTypeDecl).getABaseType() } + override Type getABaseType() { result = this.getDeclaration().(NominalTypeDecl).getABaseType() } NominalType getADerivedType() { result.getABaseType() = this } diff --git a/swift/ql/lib/codeql/swift/elements/type/Type.qll b/swift/ql/lib/codeql/swift/elements/type/Type.qll index d543121ef4e..43cf1759127 100644 --- a/swift/ql/lib/codeql/swift/elements/type/Type.qll +++ b/swift/ql/lib/codeql/swift/elements/type/Type.qll @@ -15,20 +15,16 @@ class Type extends Generated::Type { Type getUnderlyingType() { result = this } /** - * Gets any base type of this type, or the result of resolving a typedef. For - * example in the following code, `C` has base type `B` which has underlying - * type `A`. Thus, `getABaseOrAliasedType*` can be used to discover the - * relationship between `C` and `A`. + * Gets any base type of this type. For a `typealias`, this is a base type + * of the aliased type. For example in the following code, both `B` and + * `B_alias` have base type `A`. * ``` * class A {} * - * typealias B = A + * class B : A {} * - * class C : B {} + * typealias B_alias = B * ``` */ - Type getABaseOrAliasedType() { - result = this.(NominalType).getABaseType() or - result = this.(TypeAliasType).getAliasedType() - } + Type getABaseType() { none() } } diff --git a/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll b/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll index b7b3045d9e0..d6d5e8acfce 100644 --- a/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll +++ b/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll @@ -13,4 +13,6 @@ class TypeAliasType extends Generated::TypeAliasType { Type getAliasedType() { result = this.getDecl().getAliasedType() } override Type getUnderlyingType() { result = this.getAliasedType().getUnderlyingType() } + + override Type getABaseType() { result = getAliasedType().getABaseType() } } diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll index 0bb20e9b8fb..c1e3e62d6f4 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseExtensions.qll @@ -49,7 +49,7 @@ private class CoreDataStore extends CleartextStorageDatabaseSink { // with `coreDataObj.data` is a sink. // (ideally this would be only members with the `@NSManaged` attribute) exists(NominalType t, Expr e | - t.getABaseOrAliasedType*().getName() = "NSManagedObject" and + t.getABaseType*().getUnderlyingType().getName() = "NSManagedObject" and this.(DataFlow::PostUpdateNode).getPreUpdateNode().asExpr() = e and e.getFullyConverted().getType() = t and not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl @@ -67,7 +67,7 @@ private class RealmStore extends CleartextStorageDatabaseSink instanceof DataFlo // example in `realmObj.data = sensitive` the post-update node corresponding // with `realmObj.data` is a sink. exists(NominalType t, Expr e | - t.getABaseOrAliasedType*().getName() = "RealmSwiftObject" and + t.getABaseType*().getUnderlyingType().getName() = "RealmSwiftObject" and this.getPreUpdateNode().asExpr() = e and e.getFullyConverted().getType() = t and not e.(DeclRefExpr).getDecl() instanceof SelfParamDecl diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll index acf88255473..c64322f4351 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll @@ -38,7 +38,7 @@ class CleartextStorageConfig extends TaintTracking::Configuration { // for example in `realmObj.data = sensitive`. isSink(node) and exists(NominalTypeDecl d, Decl cx | - d.getType().getABaseOrAliasedType*().getName() = ["NSManagedObject", "RealmSwiftObject"] and + d.getType().getABaseType*().getUnderlyingType().getName() = ["NSManagedObject", "RealmSwiftObject"] and cx.asNominalTypeDecl() = d and c.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember() ) diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected index 08a3b86b7b3..e28a65ab92b 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected @@ -1,13 +1,13 @@ | nominaltype.swift:35:6:35:6 | a | A | A | | -| nominaltype.swift:36:6:36:6 | a_alias | A_alias | A | getABaseOrAliasedType:A, getAliasedType:A | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | Optional | getABaseOrAliasedType:Optional, getAliasedType:Optional | -| nominaltype.swift:38:6:38:6 | b1 | B1 | B1 | getABaseOrAliasedType:A, getABaseType:A | -| nominaltype.swift:39:6:39:6 | b2 | B2 | B2 | getABaseOrAliasedType:A_alias, getABaseType:A_alias | -| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1 | getABaseOrAliasedType:B1, getAliasedType:B1 | -| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | B2 | getABaseOrAliasedType:B2, getAliasedType:B2 | +| nominaltype.swift:36:6:36:6 | a_alias | A_alias | A | getAliasedType:A | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | Optional | getAliasedType:Optional | +| nominaltype.swift:38:6:38:6 | b1 | B1 | B1 | getABaseType:A | +| nominaltype.swift:39:6:39:6 | b2 | B2 | B2 | getABaseType:A_alias | +| nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1 | getABaseType:A, getAliasedType:B1 | +| nominaltype.swift:41:6:41:6 | b2_alias | B2_alias | B2 | getABaseType:A_alias, getAliasedType:B2 | | nominaltype.swift:42:6:42:6 | p | P | P | | | nominaltype.swift:43:6:43:6 | p_alias | P_alias | P_alias | | -| nominaltype.swift:44:6:44:6 | c1 | C1 | C1 | getABaseOrAliasedType:P, getABaseType:P | -| nominaltype.swift:45:6:45:6 | c2 | C2 | C2 | getABaseOrAliasedType:P_alias, getABaseType:P_alias | -| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | C1 | getABaseOrAliasedType:C1, getAliasedType:C1 | -| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | C2 | getABaseOrAliasedType:C2, getAliasedType:C2 | +| nominaltype.swift:44:6:44:6 | c1 | C1 | C1 | getABaseType:P | +| nominaltype.swift:45:6:45:6 | c2 | C2 | C2 | getABaseType:P_alias | +| nominaltype.swift:46:6:46:6 | c1_alias | C1_alias | C1 | getABaseType:P, getAliasedType:C1 | +| nominaltype.swift:47:6:47:6 | c2_alias | C2_alias | C2 | getABaseType:P_alias, getAliasedType:C2 | diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql index a8384f4afbf..c0ab33423bf 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.ql @@ -3,9 +3,7 @@ import swift string describe(Type t) { result = "getAliasedType:" + t.(TypeAliasType).getAliasedType() or - result = "getABaseType:" + t.(NominalType).getABaseType() - or - result = "getABaseOrAliasedType:" + t.getABaseOrAliasedType() + result = "getABaseType:" + t.getABaseType() } from VarDecl v, Type t From b3e0c494354e440579e094b36fd23b89f4f76518 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:03:01 +0100 Subject: [PATCH 107/141] Swift: Remove unnecessary imports. --- swift/ql/lib/codeql/swift/elements/type/Type.qll | 2 -- 1 file changed, 2 deletions(-) diff --git a/swift/ql/lib/codeql/swift/elements/type/Type.qll b/swift/ql/lib/codeql/swift/elements/type/Type.qll index 43cf1759127..ec72e8aa9fd 100644 --- a/swift/ql/lib/codeql/swift/elements/type/Type.qll +++ b/swift/ql/lib/codeql/swift/elements/type/Type.qll @@ -1,6 +1,4 @@ private import codeql.swift.generated.type.Type -private import codeql.swift.elements.type.NominalType -private import codeql.swift.elements.type.TypeAliasType class Type extends Generated::Type { override string toString() { result = this.getName() } From c88bea7080008ac5a631141493a9722a4d7f912d Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:29:49 +0100 Subject: [PATCH 108/141] Update swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll Co-authored-by: Mathias Vorreiter Pedersen --- swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll b/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll index d6d5e8acfce..1d8e8fb1fd2 100644 --- a/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll +++ b/swift/ql/lib/codeql/swift/elements/type/TypeAliasType.qll @@ -14,5 +14,5 @@ class TypeAliasType extends Generated::TypeAliasType { override Type getUnderlyingType() { result = this.getAliasedType().getUnderlyingType() } - override Type getABaseType() { result = getAliasedType().getABaseType() } + override Type getABaseType() { result = this.getAliasedType().getABaseType() } } From 91f6b0ba4f9468b108e87d453f0a64d76e6af9a4 Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 31 Mar 2023 15:50:15 +0100 Subject: [PATCH 109/141] Swift: Correct test expectations. --- .../elements/type/nominaltype/nominaltype.expected | 2 +- .../elements/type/nominaltype/nominaltypedecl.expected | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected index e28a65ab92b..dc37626854f 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltype.expected @@ -1,6 +1,6 @@ | nominaltype.swift:35:6:35:6 | a | A | A | | | nominaltype.swift:36:6:36:6 | a_alias | A_alias | A | getAliasedType:A | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | Optional | getAliasedType:Optional | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | A? | getAliasedType:A? | | nominaltype.swift:38:6:38:6 | b1 | B1 | B1 | getABaseType:A | | nominaltype.swift:39:6:39:6 | b2 | B2 | B2 | getABaseType:A_alias | | nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | B1 | getABaseType:A, getAliasedType:B1 | diff --git a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected index 0d75db4b0e0..612b031f54e 100644 --- a/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected +++ b/swift/ql/test/library-tests/elements/type/nominaltype/nominaltypedecl.expected @@ -1,6 +1,6 @@ | nominaltype.swift:35:6:35:6 | a | A | | | nominaltype.swift:36:6:36:6 | a_alias | A_alias | getAliasedType:A | -| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | getAliasedType:Optional | +| nominaltype.swift:37:6:37:6 | a_optional_alias | A_optional_alias | getAliasedType:A? | | nominaltype.swift:38:6:38:6 | b1 | B1 | getABaseType:A | | nominaltype.swift:39:6:39:6 | b2 | B2 | getABaseType:A_alias | | nominaltype.swift:40:6:40:6 | b1_alias | B1_alias | getAliasedType:B1 | From 800411cd81803133a64c04307213fc561d507360 Mon Sep 17 00:00:00 2001 From: Ed Minnix Date: Fri, 31 Mar 2023 10:55:17 -0400 Subject: [PATCH 110/141] More replacing of single-predicate classes to predicate --- .../security/UnsafeDeserializationQuery.qll | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll index 0d03ec40117..7e995e5cbaf 100644 --- a/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll +++ b/java/ql/lib/semmle/code/java/security/UnsafeDeserializationQuery.qll @@ -399,12 +399,10 @@ private class UnsafeTypeSink extends DataFlow::Node { } } -private class UnsafeTypeAdditionalTaintStep extends Unit { - predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - resolveClassStep(fromNode, toNode) or - looksLikeResolveClassStep(fromNode, toNode) or - intentFlowsToParcel(fromNode, toNode) - } +private predicate isUnsafeTypeAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { + resolveClassStep(fromNode, toNode) or + looksLikeResolveClassStep(fromNode, toNode) or + intentFlowsToParcel(fromNode, toNode) } /** @@ -427,7 +425,7 @@ deprecated class UnsafeTypeConfig extends TaintTracking2::Configuration { * or at least looks like resolving a class. */ override predicate isAdditionalTaintStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - any(UnsafeTypeAdditionalTaintStep s).isAdditionalTaintStep(fromNode, toNode) + isUnsafeTypeAdditionalTaintStep(fromNode, toNode) } } @@ -447,7 +445,7 @@ module UnsafeTypeConfig implements DataFlow::ConfigSig { * or at least looks like resolving a class. */ predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - any(UnsafeTypeAdditionalTaintStep s).isAdditionalTaintStep(fromNode, toNode) + isUnsafeTypeAdditionalTaintStep(fromNode, toNode) } } @@ -488,18 +486,18 @@ private module EnableJacksonDefaultTypingConfig implements DataFlow::ConfigSig { module EnableJacksonDefaultTypingFlow = DataFlow::Global; /** Dataflow step that creates an `ObjectMapper` via a builder. */ -private class ObjectMapperBuilderAdditionalFlowStep extends Unit { - predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - exists(MethodAccess ma, Method m | m = ma.getMethod() | - m.getDeclaringType() instanceof MapperBuilder and - m.getReturnType() - .(RefType) - .hasQualifiedName("com.fasterxml.jackson.databind.json", - ["JsonMapper$Builder", "JsonMapper"]) and - fromNode.asExpr() = ma.getQualifier() and - ma = toNode.asExpr() - ) - } +private predicate isObjectMapperBuilderAdditionalFlowStep( + DataFlow::Node fromNode, DataFlow::Node toNode +) { + exists(MethodAccess ma, Method m | m = ma.getMethod() | + m.getDeclaringType() instanceof MapperBuilder and + m.getReturnType() + .(RefType) + .hasQualifiedName("com.fasterxml.jackson.databind.json", + ["JsonMapper$Builder", "JsonMapper"]) and + fromNode.asExpr() = ma.getQualifier() and + ma = toNode.asExpr() + ) } /** @@ -524,7 +522,7 @@ deprecated class SafeObjectMapperConfig extends DataFlow2::Configuration { * that configures or creates an `ObjectMapper` via a builder. */ override predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - any(ObjectMapperBuilderAdditionalFlowStep s).isAdditionalFlowStep(fromNode, toNode) + isObjectMapperBuilderAdditionalFlowStep(fromNode, toNode) } } @@ -544,7 +542,7 @@ module SafeObjectMapperConfig implements DataFlow::ConfigSig { * that configures or creates an `ObjectMapper` via a builder. */ predicate isAdditionalFlowStep(DataFlow::Node fromNode, DataFlow::Node toNode) { - any(ObjectMapperBuilderAdditionalFlowStep s).isAdditionalFlowStep(fromNode, toNode) + isObjectMapperBuilderAdditionalFlowStep(fromNode, toNode) } } From 7f69fe6e8c6c7a8c6c2ed1ff865792d1cab4324c Mon Sep 17 00:00:00 2001 From: Geoffrey White <40627776+geoffw0@users.noreply.github.com> Date: Fri, 31 Mar 2023 16:32:49 +0100 Subject: [PATCH 111/141] Swift: Autoformat. --- .../codeql/swift/security/CleartextStorageDatabaseQuery.qll | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll index c64322f4351..70b71606fcd 100644 --- a/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll +++ b/swift/ql/lib/codeql/swift/security/CleartextStorageDatabaseQuery.qll @@ -38,7 +38,8 @@ class CleartextStorageConfig extends TaintTracking::Configuration { // for example in `realmObj.data = sensitive`. isSink(node) and exists(NominalTypeDecl d, Decl cx | - d.getType().getABaseType*().getUnderlyingType().getName() = ["NSManagedObject", "RealmSwiftObject"] and + d.getType().getABaseType*().getUnderlyingType().getName() = + ["NSManagedObject", "RealmSwiftObject"] and cx.asNominalTypeDecl() = d and c.getAReadContent().(DataFlow::Content::FieldContent).getField() = cx.getAMember() ) From f6dc9e2a3587558060f2fa5e58957402097eac42 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 14:47:52 +0000 Subject: [PATCH 112/141] Fix accidental over-modelling of k8s Secret DeepCopy --- go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll index ee860e762a2..847e033e0c5 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll @@ -23,7 +23,7 @@ module K8sIoApiCoreV1 { } override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) { - inp.isReceiver() and outp = outp + inp.isReceiver() and outp = output } } From a113b8e8a4e07da0c0b428ab06b78b6181956ad9 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 14:40:40 +0000 Subject: [PATCH 113/141] No need for singleton set --- go/ql/src/experimental/CWE-327/CryptoLibraries.qll | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go/ql/src/experimental/CWE-327/CryptoLibraries.qll b/go/ql/src/experimental/CWE-327/CryptoLibraries.qll index 6db266273b5..ea087507177 100644 --- a/go/ql/src/experimental/CWE-327/CryptoLibraries.qll +++ b/go/ql/src/experimental/CWE-327/CryptoLibraries.qll @@ -203,7 +203,7 @@ class Des extends CryptographicOperation, DataFlow::CallNode { * Models cryptographic operations of the `crypto/rc4` package. */ class Rc4 extends CryptographicOperation, DataFlow::CallNode { - Rc4() { this.getTarget().hasQualifiedName("crypto/rc4", ["NewCipher"]) } + Rc4() { this.getTarget().hasQualifiedName("crypto/rc4", "NewCipher") } override Expr getInput() { result = this.getArgument(0).asExpr() } From 7a2520096287c314549179ad8ca0a4216e3759c9 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 14:28:38 +0000 Subject: [PATCH 114/141] Remove fields which are only used in char pred --- .../go/dataflow/internal/DataFlowNodes.qll | 20 ++++----- go/ql/lib/semmle/go/frameworks/Beego.qll | 45 +++++++++---------- go/ql/lib/semmle/go/frameworks/Echo.qll | 6 +-- .../semmle/go/frameworks/K8sIoApiCoreV1.qll | 8 ++-- go/ql/lib/semmle/go/frameworks/Revel.qll | 4 +- .../semmle/go/frameworks/stdlib/NetHttp.qll | 3 +- .../src/experimental/frameworks/CleverGo.qll | 10 ++--- go/ql/src/experimental/frameworks/Fiber.qll | 10 ++--- 8 files changed, 45 insertions(+), 61 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index 715330f87d9..23751641d5d 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -61,9 +61,8 @@ module Private { /** A data flow node that represents the output of a call. */ class OutNode extends Node { DataFlow::CallNode call; - int i; - OutNode() { this = call.getResult(i) } + OutNode() { this = call.getResult(_) } /** Gets the underlying call. */ DataFlowCall getCall() { result = call.asExpr() } @@ -753,13 +752,14 @@ module Public { * of the function. */ class ResultNode extends InstructionNode { - FuncDef fd; int i; ResultNode() { - exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i)) - or - insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i)) + exists(FuncDef fd | + exists(IR::ReturnInstruction ret | ret.getRoot() = fd | insn = ret.getResult(i)) + or + insn.(IR::ReadResultInstruction).reads(fd.getResultVar(i)) + ) } /** Gets the index of this result among all results of the function. */ @@ -1112,12 +1112,12 @@ module Public { */ class RangeElementNode extends Node { DataFlow::Node base; - IR::ExtractTupleElementInstruction extract; RangeElementNode() { - this.asInstruction() = extract and - extract.extractsElement(_, 1) and - extract.getBase().(IR::GetNextEntryInstruction).getDomain() = base.asInstruction() + exists(IR::ExtractTupleElementInstruction extract | extract = this.asInstruction() | + extract.extractsElement(_, 1) and + extract.getBase().(IR::GetNextEntryInstruction).getDomain() = base.asInstruction() + ) } /** Gets the data-flow node representing the base from which the element is read. */ diff --git a/go/ql/lib/semmle/go/frameworks/Beego.qll b/go/ql/lib/semmle/go/frameworks/Beego.qll index 85334e83ab8..d76ac8f23a1 100644 --- a/go/ql/lib/semmle/go/frameworks/Beego.qll +++ b/go/ql/lib/semmle/go/frameworks/Beego.qll @@ -51,13 +51,9 @@ module Beego { */ private class BeegoInputSource extends UntrustedFlowSource::Range { string methodName; - FunctionOutput output; BeegoInputSource() { - exists(DataFlow::MethodCallNode c | this = output.getExitNode(c) | - c.getTarget().hasQualifiedName(contextPackagePath(), "BeegoInput", methodName) - ) and - ( + exists(FunctionOutput output | methodName = "Bind" and output.isParameter(0) or @@ -66,6 +62,10 @@ module Beego { "URI", "URL", "UserAgent" ] and output.isResult(0) + | + exists(DataFlow::MethodCallNode c | this = output.getExitNode(c) | + c.getTarget().hasQualifiedName(contextPackagePath(), "BeegoInput", methodName) + ) ) } @@ -81,16 +81,8 @@ module Beego { * `beego.Controller` sources of untrusted data. */ private class BeegoControllerSource extends UntrustedFlowSource::Range { - string methodName; - FunctionOutput output; - BeegoControllerSource() { - exists(DataFlow::MethodCallNode c | - c.getTarget().hasQualifiedName(packagePath(), "Controller", methodName) - | - this = output.getExitNode(c) - ) and - ( + exists(string methodName, FunctionOutput output | methodName = "ParseForm" and output.isParameter(0) or @@ -99,6 +91,12 @@ module Beego { or methodName = "GetFile" and output.isResult(1) + | + exists(DataFlow::MethodCallNode c | + c.getTarget().hasQualifiedName(packagePath(), "Controller", methodName) + | + this = output.getExitNode(c) + ) ) } } @@ -225,10 +223,8 @@ module Beego { } private class ContextResponseBody extends Http::ResponseBody::Range { - string name; - ContextResponseBody() { - exists(Method m | m.hasQualifiedName(contextPackagePath(), "Context", name) | + exists(Method m, string name | m.hasQualifiedName(contextPackagePath(), "Context", name) | name = "Abort" and this = m.getACall().getArgument(1) or name = "WriteString" and this = m.getACall().getArgument(0) @@ -326,16 +322,17 @@ module Beego { } private class RedirectMethods extends Http::Redirect::Range, DataFlow::CallNode { - string package; string className; RedirectMethods() { - ( - package = packagePath() and className = "Controller" - or - package = contextPackagePath() and className = "Context" - ) and - this = any(Method m | m.hasQualifiedName(package, className, "Redirect")).getACall() + exists(string package | + ( + package = packagePath() and className = "Controller" + or + package = contextPackagePath() and className = "Context" + ) and + this = any(Method m | m.hasQualifiedName(package, className, "Redirect")).getACall() + ) } override DataFlow::Node getUrl() { diff --git a/go/ql/lib/semmle/go/frameworks/Echo.qll b/go/ql/lib/semmle/go/frameworks/Echo.qll index c4d243b504c..2fde621cf44 100644 --- a/go/ql/lib/semmle/go/frameworks/Echo.qll +++ b/go/ql/lib/semmle/go/frameworks/Echo.qll @@ -43,17 +43,15 @@ private module Echo { * Models of `Context.Get/Set`. `Context` behaves like a map, with corresponding taint propagation. */ private class ContextMapModels extends TaintTracking::FunctionModel, Method { - string methodName; FunctionInput input; FunctionOutput output; ContextMapModels() { - ( + exists(string methodName | this.hasQualifiedName(packagePath(), "Context", methodName) | methodName = "Get" and input.isReceiver() and output.isResult() or methodName = "Set" and input.isParameter(1) and output.isReceiver() - ) and - this.hasQualifiedName(packagePath(), "Context", methodName) + ) } override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) { diff --git a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll index 847e033e0c5..02df3b4c766 100644 --- a/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll +++ b/go/ql/lib/semmle/go/frameworks/K8sIoApiCoreV1.qll @@ -10,16 +10,16 @@ module K8sIoApiCoreV1 { string packagePath() { result = package("k8s.io/api", "core/v1") } private class SecretDeepCopy extends TaintTracking::FunctionModel, Method { - string methodName; FunctionOutput output; SecretDeepCopy() { - ( + exists(string methodName | methodName in ["DeepCopy", "DeepCopyObject"] and output.isResult() or methodName = "DeepCopyInto" and output.isParameter(0) - ) and - this.hasQualifiedName(packagePath(), ["Secret", "SecretList"], methodName) + | + this.hasQualifiedName(packagePath(), ["Secret", "SecretList"], methodName) + ) } override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) { diff --git a/go/ql/lib/semmle/go/frameworks/Revel.qll b/go/ql/lib/semmle/go/frameworks/Revel.qll index e5090a50caa..c23cf87fba2 100644 --- a/go/ql/lib/semmle/go/frameworks/Revel.qll +++ b/go/ql/lib/semmle/go/frameworks/Revel.qll @@ -201,11 +201,9 @@ module Revel { private class RevelHeaderMethods extends TaintTracking::FunctionModel { FunctionInput input; FunctionOutput output; - string name; RevelHeaderMethods() { - this.(Method).hasQualifiedName(packagePath(), "RevelHeader", name) and - ( + exists(string name | this.(Method).hasQualifiedName(packagePath(), "RevelHeader", name) | name = ["Add", "Set"] and input.isParameter([0, 1]) and output.isReceiver() or name = ["Get", "GetAll"] and input.isReceiver() and output.isResult() diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll index 965fbeca4fb..ced661cba64 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll @@ -57,13 +57,12 @@ module NetHttp { } private class MapWrite extends Http::HeaderWrite::Range, DataFlow::Node { - Write write; DataFlow::Node index; DataFlow::Node rhs; MapWrite() { this.getType().hasQualifiedName("net/http", "Header") and - write.writesElement(this, index, rhs) + any(Write write).writesElement(this, index, rhs) } override DataFlow::Node getName() { result = index } diff --git a/go/ql/src/experimental/frameworks/CleverGo.qll b/go/ql/src/experimental/frameworks/CleverGo.qll index d4d3fa441d2..4b39ea005fd 100644 --- a/go/ql/src/experimental/frameworks/CleverGo.qll +++ b/go/ql/src/experimental/frameworks/CleverGo.qll @@ -175,18 +175,14 @@ private module CleverGo { * Models HTTP redirects. */ private class HttpRedirect extends Http::Redirect::Range, DataFlow::CallNode { - string package; DataFlow::Node urlNode; HttpRedirect() { // HTTP redirect models for package: clevergo.tech/clevergo@v0.5.2 - package = packagePath() and // Receiver type: Context - ( - // signature: func (*Context) Redirect(code int, url string) error - this = any(Method m | m.hasQualifiedName(package, "Context", "Redirect")).getACall() and - urlNode = this.getArgument(1) - ) + // signature: func (*Context) Redirect(code int, url string) error + this = any(Method m | m.hasQualifiedName(packagePath(), "Context", "Redirect")).getACall() and + urlNode = this.getArgument(1) } override DataFlow::Node getUrl() { result = urlNode } diff --git a/go/ql/src/experimental/frameworks/Fiber.qll b/go/ql/src/experimental/frameworks/Fiber.qll index 2a4a2285702..cfc65afdc1c 100644 --- a/go/ql/src/experimental/frameworks/Fiber.qll +++ b/go/ql/src/experimental/frameworks/Fiber.qll @@ -130,18 +130,14 @@ private module Fiber { * Models HTTP redirects. */ private class Redirect extends Http::Redirect::Range, DataFlow::CallNode { - string package; DataFlow::Node urlNode; Redirect() { // HTTP redirect models for package: github.com/gofiber/fiber@v1.14.6 - package = fiberPackagePath() and // Receiver type: Ctx - ( - // signature: func (*Ctx) Redirect(location string, status ...int) - this = any(Method m | m.hasQualifiedName(package, "Ctx", "Redirect")).getACall() and - urlNode = this.getArgument(0) - ) + // signature: func (*Ctx) Redirect(location string, status ...int) + this = any(Method m | m.hasQualifiedName(fiberPackagePath(), "Ctx", "Redirect")).getACall() and + urlNode = this.getArgument(0) } override DataFlow::Node getUrl() { result = urlNode } From 513409e082fadf58b905f278dedac04fb7a84479 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 14:40:08 +0000 Subject: [PATCH 115/141] Fix formatting of QLDocs --- go/ql/lib/printAst.ql | 4 ++-- go/ql/lib/semmle/go/Concepts.qll | 4 ++-- go/ql/lib/semmle/go/Files.qll | 2 +- go/ql/lib/semmle/go/PrintAst.ql | 2 +- go/ql/lib/semmle/go/PrintAst.qll | 2 +- go/ql/lib/semmle/go/Scopes.qll | 2 +- go/ql/lib/semmle/go/StringOps.qll | 2 +- go/ql/lib/semmle/go/Types.qll | 4 ++-- .../dataflow/barrierguardutil/RegexpCheck.qll | 2 +- .../go/security/InsecureFeatureFlag.qll | 2 +- .../go/security/SafeUrlFlowCustomizations.qll | 2 +- .../semmle/go/security/UnsafeUnzipSymlink.qll | 4 ++-- .../go/security/ZipSlipCustomizations.qll | 2 +- .../InconsistentCode/WrappedErrorAlwaysNil.ql | 3 ++- go/ql/src/RedundantCode/Clones.qll | 2 +- .../CWE-295/DisabledCertificateCheck.ql | 2 +- .../Security/CWE-326/InsufficientKeySize.ql | 3 ++- go/ql/src/Security/CWE-327/InsecureTLS.ql | 9 ++++---- .../src/experimental/CWE-1004/AuthCookie.qll | 21 ++++++++++++------- .../experimental/CWE-327/CryptoLibraries.qll | 8 +++---- .../CWE-79/HTMLTemplateEscapingPassthrough.ql | 2 +- go/ql/src/experimental/CWE-918/SSRF.qll | 6 +++--- .../diagnostics/Diagnostics.ql | 2 +- 23 files changed, 51 insertions(+), 41 deletions(-) diff --git a/go/ql/lib/printAst.ql b/go/ql/lib/printAst.ql index 9d6d5c2d7b9..1ea2c9548d5 100644 --- a/go/ql/lib/printAst.ql +++ b/go/ql/lib/printAst.ql @@ -12,12 +12,12 @@ import semmle.go.PrintAst import ideContextual /** - * The source file to generate an AST from. + * Gets the source file to generate an AST from. */ external string selectedSourceFile(); /** - * Hook to customize the functions printed by this query. + * A hook to customize the functions printed by this query. */ class Cfg extends PrintAstConfiguration { override predicate shouldPrintFunction(FuncDecl func) { shouldPrintFile(func.getFile()) } diff --git a/go/ql/lib/semmle/go/Concepts.qll b/go/ql/lib/semmle/go/Concepts.qll index c6043ae46b3..2fb4e35d94b 100644 --- a/go/ql/lib/semmle/go/Concepts.qll +++ b/go/ql/lib/semmle/go/Concepts.qll @@ -115,7 +115,7 @@ module FileSystemAccess { /** A function that escapes meta-characters to prevent injection attacks. */ class EscapeFunction extends Function instanceof EscapeFunction::Range { /** - * The context that this function escapes for. + * Gets the context that this function escapes for. * * Currently, this can be "js", "html", or "url". */ @@ -132,7 +132,7 @@ module EscapeFunction { */ abstract class Range extends Function { /** - * The context that this function escapes for. + * Gets the context that this function escapes for. * * Currently, this can be `js', `html', or `url'. */ diff --git a/go/ql/lib/semmle/go/Files.qll b/go/ql/lib/semmle/go/Files.qll index b261b935318..11d7d337a41 100644 --- a/go/ql/lib/semmle/go/Files.qll +++ b/go/ql/lib/semmle/go/Files.qll @@ -181,7 +181,7 @@ class Folder extends Container, @folder { override string getURL() { result = "folder://" + this.getAbsolutePath() } } -/** Any file, including files that have not been extracted but are referred to as locations for errors. */ +/** A file, including files that have not been extracted but are referred to as locations for errors. */ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent, GoModExprParent, DeclParent, ScopeNode { diff --git a/go/ql/lib/semmle/go/PrintAst.ql b/go/ql/lib/semmle/go/PrintAst.ql index 23b6b123b06..6e0c1ce06f3 100644 --- a/go/ql/lib/semmle/go/PrintAst.ql +++ b/go/ql/lib/semmle/go/PrintAst.ql @@ -9,7 +9,7 @@ import go import PrintAst /** - * Hook to customize the functions printed by this query. + * A hook to customize the functions printed by this query. */ class Cfg extends PrintAstConfiguration { override predicate shouldPrintFunction(FuncDecl func) { any() } diff --git a/go/ql/lib/semmle/go/PrintAst.qll b/go/ql/lib/semmle/go/PrintAst.qll index cf28be44f49..b15144ade97 100644 --- a/go/ql/lib/semmle/go/PrintAst.qll +++ b/go/ql/lib/semmle/go/PrintAst.qll @@ -5,7 +5,7 @@ import go /** - * Hook to customize the files and functions printed by this module. + * A hook to customize the files and functions printed by this module. * * For an AstNode to be printed, it always requires `shouldPrintFile(f)` to hold * for its containing file `f`, and additionally requires `shouldPrintFunction(fun)` diff --git a/go/ql/lib/semmle/go/Scopes.qll b/go/ql/lib/semmle/go/Scopes.qll index 385b52028d9..28a32fe3de5 100644 --- a/go/ql/lib/semmle/go/Scopes.qll +++ b/go/ql/lib/semmle/go/Scopes.qll @@ -602,7 +602,7 @@ private newtype TCallable = TFuncLitCallable(FuncLit l) /** - * This is either a `Function` or a `FuncLit`, because of limitations of both + * A `Function` or a `FuncLit`. We do it this way because of limitations of both * `Function` and `FuncDef`: * - `Function` is an entity, and therefore does not include function literals, and * - `FuncDef` is an AST node, and so is not extracted for functions from external libraries. diff --git a/go/ql/lib/semmle/go/StringOps.qll b/go/ql/lib/semmle/go/StringOps.qll index c3dc8fdb18d..db86f3864f7 100644 --- a/go/ql/lib/semmle/go/StringOps.qll +++ b/go/ql/lib/semmle/go/StringOps.qll @@ -581,7 +581,7 @@ module StringOps { } /** - * One of the operands in a string concatenation. + * An operand in a string concatenation. * * See `ConcatenationElement` for more information. */ diff --git a/go/ql/lib/semmle/go/Types.qll b/go/ql/lib/semmle/go/Types.qll index ea522b2e11e..026b009aa3f 100644 --- a/go/ql/lib/semmle/go/Types.qll +++ b/go/ql/lib/semmle/go/Types.qll @@ -172,7 +172,7 @@ class InvalidType extends @invalidtype, Type { /** A basic type. */ class BasicType extends @basictype, Type { } -/** Either the normal or literal boolean type */ +/** The normal boolean type or the literal boolean type */ class BoolType extends @booltype, BasicType { } /** The `bool` type of a non-literal expression */ @@ -317,7 +317,7 @@ class Complex128Type extends @complex128type, ComplexType { override string getName() { result = "complex128" } } -/** Either the normal or literal string type */ +/** The normal string type or the literal string type */ class StringType extends @stringtype, BasicType { } /** The `string` type of a non-literal expression */ diff --git a/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll b/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll index 47593dcf537..795ffb11c44 100644 --- a/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll +++ b/go/ql/lib/semmle/go/dataflow/barrierguardutil/RegexpCheck.qll @@ -5,7 +5,7 @@ import go /** - * A call to a regexp match function, considered as a barrier guard for sanitizing untrusted URLs. + * Holds if `resultNode` comes from a call to a regexp match function, considered as a barrier guard for sanitizing untrusted URLs. * * This is overapproximate: we do not attempt to reason about the correctness of the regexp. * diff --git a/go/ql/lib/semmle/go/security/InsecureFeatureFlag.qll b/go/ql/lib/semmle/go/security/InsecureFeatureFlag.qll index 0006a9e9546..855d7746cf2 100644 --- a/go/ql/lib/semmle/go/security/InsecureFeatureFlag.qll +++ b/go/ql/lib/semmle/go/security/InsecureFeatureFlag.qll @@ -71,7 +71,7 @@ module InsecureFeatureFlag { } /** - * Flags suggesting an optional feature, perhaps deliberately insecure. + * A flag suggesting an optional feature, perhaps deliberately insecure. */ class SecurityFeatureFlag extends FlagKind { SecurityFeatureFlag() { this = "securityFeature" } diff --git a/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll b/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll index dbdb96a10a7..ec567167487 100644 --- a/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll +++ b/go/ql/lib/semmle/go/security/SafeUrlFlowCustomizations.qll @@ -19,7 +19,7 @@ module SafeUrlFlow { /** An outgoing sanitizer edge for safe URL flow. */ abstract class SanitizerEdge extends DataFlow::Node { } - /** Standard library safe URL sources. */ + /** A standard library safe URL source. */ class StdlibSource extends Source, DataFlow::FieldReadNode { StdlibSource() { this.getField().hasQualifiedName("net/http", "Request", ["Host", "URL"]) } } diff --git a/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll b/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll index 976b3bc1c0e..6465917d705 100644 --- a/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll +++ b/go/ql/lib/semmle/go/security/UnsafeUnzipSymlink.qll @@ -14,7 +14,7 @@ module UnsafeUnzipSymlink { import UnsafeUnzipSymlinkCustomizations::UnsafeUnzipSymlink /** - * Taint-flow configuration tracking archive header fields flowing to a `path/filepath.EvalSymlinks` call. + * A taint-flow configuration tracking archive header fields flowing to a `path/filepath.EvalSymlinks` call. */ class EvalSymlinksConfiguration extends TaintTracking2::Configuration { EvalSymlinksConfiguration() { this = "Archive header field symlinks resolved" } @@ -41,7 +41,7 @@ module UnsafeUnzipSymlink { } /** - * Taint-flow configuration tracking archive header fields flowing to an `os.Symlink` call, + * A taint-flow configuration tracking archive header fields flowing to an `os.Symlink` call, * which never flow to a `path/filepath.EvalSymlinks` call. */ class SymlinkConfiguration extends TaintTracking::Configuration { diff --git a/go/ql/lib/semmle/go/security/ZipSlipCustomizations.qll b/go/ql/lib/semmle/go/security/ZipSlipCustomizations.qll index 4bc407f871d..276aae4c4db 100644 --- a/go/ql/lib/semmle/go/security/ZipSlipCustomizations.qll +++ b/go/ql/lib/semmle/go/security/ZipSlipCustomizations.qll @@ -61,7 +61,7 @@ module ZipSlip { } /** - * Excludes zipped file data from consideration for zip slip. + * A zipped file, excluded from for zip slip. */ class ZipFileOpen extends Sanitizer { ZipFileOpen() { diff --git a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql index 93889b0a23e..48df6a9297d 100644 --- a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql +++ b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql @@ -16,7 +16,8 @@ import go string packagePath() { result = package("github.com/pkg/errors", "") } /** - * An equality test which guarantees that an expression is always `nil`. + * Holds if `g` is an equality test which guarantees that the expression `e` is + * either `nil` or not `nil`, depending on `outcome`. */ predicate nilTestGuard(DataFlow::Node g, Expr e, boolean outcome) { exists(DataFlow::EqualityTestNode eq, DataFlow::Node otherNode | diff --git a/go/ql/src/RedundantCode/Clones.qll b/go/ql/src/RedundantCode/Clones.qll index e98ff754733..6a198b7a3cb 100644 --- a/go/ql/src/RedundantCode/Clones.qll +++ b/go/ql/src/RedundantCode/Clones.qll @@ -19,7 +19,7 @@ class HashableNode extends AstNode { } /** - * An opaque integer describing the type of this AST node. + * Gets an opaque integer describing the type of this AST node. */ int getKind() { exists(int baseKind | diff --git a/go/ql/src/Security/CWE-295/DisabledCertificateCheck.ql b/go/ql/src/Security/CWE-295/DisabledCertificateCheck.ql index e3132371d7d..ae83fbce8bc 100644 --- a/go/ql/src/Security/CWE-295/DisabledCertificateCheck.ql +++ b/go/ql/src/Security/CWE-295/DisabledCertificateCheck.ql @@ -38,7 +38,7 @@ predicate becomesPartOf(DataFlow::Node part, DataFlow::Node whole) { } /** - * Flags suggesting a deliberately insecure certificate setup. + * A flag suggesting a deliberately insecure certificate setup. */ class InsecureCertificateFlag extends FlagKind { InsecureCertificateFlag() { this = "insecureCertificate" } diff --git a/go/ql/src/Security/CWE-326/InsufficientKeySize.ql b/go/ql/src/Security/CWE-326/InsufficientKeySize.ql index 038a42b4971..f0485e91edd 100644 --- a/go/ql/src/Security/CWE-326/InsufficientKeySize.ql +++ b/go/ql/src/Security/CWE-326/InsufficientKeySize.ql @@ -14,7 +14,8 @@ import go import DataFlow::PathGraph /** - * RSA key length data flow tracking configuration. + * A data flow tracking configuration for tracking flow from RSA key length to + * calls to RSA key generation functions. */ class RsaKeyTrackingConfiguration extends DataFlow::Configuration { RsaKeyTrackingConfiguration() { this = "RsaKeyTrackingConfiguration" } diff --git a/go/ql/src/Security/CWE-327/InsecureTLS.ql b/go/ql/src/Security/CWE-327/InsecureTLS.ql index e067fa1a36a..854557e80dc 100644 --- a/go/ql/src/Security/CWE-327/InsecureTLS.ql +++ b/go/ql/src/Security/CWE-327/InsecureTLS.ql @@ -52,7 +52,8 @@ int getASecureTlsVersion() { int getATlsVersion() { result = getASecureTlsVersion() or isInsecureTlsVersion(result, _, _) } /** - * Flow of TLS versions into a `tls.Config` struct, to the `MinVersion` and `MaxVersion` fields. + * A taint-tracking configuration for tracking flow from TLS versions to the + * `tls.Config.MinVersion` and `tls.Config.MaxVersion` fields. */ class TlsVersionFlowConfig extends TaintTracking::Configuration { TlsVersionFlowConfig() { this = "TlsVersionFlowConfig" } @@ -152,8 +153,8 @@ predicate isInsecureTlsVersionFlow( } /** - * Flow of unsecure TLS cipher suites into a `tls.Config` struct, - * to the `CipherSuites` field. + * A taint-tracking configuration for tracking flow from insecure TLS cipher + * suites into a `tls.Config` struct, to the `CipherSuites` field. */ class TlsInsecureCipherSuitesFlowConfig extends TaintTracking::Configuration { TlsInsecureCipherSuitesFlowConfig() { this = "TlsInsecureCipherSuitesFlowConfig" } @@ -229,7 +230,7 @@ predicate isInsecureTlsCipherFlow(DataFlow::PathNode source, DataFlow::PathNode } /** - * Flags suggesting support for an old or legacy TLS version. + * A flag suggesting support for an old or legacy TLS version. * * We accept 'intermediate' because it appears to be common for TLS users * to define three profiles: modern, intermediate, legacy/old, perhaps based diff --git a/go/ql/src/experimental/CWE-1004/AuthCookie.qll b/go/ql/src/experimental/CWE-1004/AuthCookie.qll index 8a4bc8d2163..676249c7b8c 100644 --- a/go/ql/src/experimental/CWE-1004/AuthCookie.qll +++ b/go/ql/src/experimental/CWE-1004/AuthCookie.qll @@ -65,7 +65,8 @@ private class SetCookieSink extends DataFlow::Node { } /** - * Tracks sensitive name to `net/http.SetCookie`. + * A taint-tracking configuration for tracking flow from sensitive names to + * `net/http.SetCookie`. */ class NameToNetHttpCookieTrackingConfiguration extends TaintTracking::Configuration { NameToNetHttpCookieTrackingConfiguration() { this = "NameToNetHttpCookieTrackingConfiguration" } @@ -84,7 +85,8 @@ class NameToNetHttpCookieTrackingConfiguration extends TaintTracking::Configurat } /** - * Tracks `bool` assigned to `HttpOnly` that flows into `net/http.SetCookie`. + * A taint-tracking configuration for tracking flow from `bool` assigned to + * `HttpOnly` that flows into `net/http.SetCookie`. */ class BoolToNetHttpCookieTrackingConfiguration extends TaintTracking::Configuration { BoolToNetHttpCookieTrackingConfiguration() { this = "BoolToNetHttpCookieTrackingConfiguration" } @@ -105,7 +107,8 @@ class BoolToNetHttpCookieTrackingConfiguration extends TaintTracking::Configurat } /** - * Tracks `HttpOnly` set to `false` to `gin-gonic/gin.Context.SetCookie`. + * A taint-tracking configuration for tracking flow from `HttpOnly` set to + * `false` to `gin-gonic/gin.Context.SetCookie`. */ class BoolToGinSetCookieTrackingConfiguration extends DataFlow::Configuration { BoolToGinSetCookieTrackingConfiguration() { this = "BoolToGinSetCookieTrackingConfiguration" } @@ -125,7 +128,8 @@ class BoolToGinSetCookieTrackingConfiguration extends DataFlow::Configuration { } /** - * Tracks sensitive name to `gin-gonic/gin.Context.SetCookie`. + * A taint-tracking configuration for tracking flow from sensitive names to + * `gin-gonic/gin.Context.SetCookie`. */ private class NameToGinSetCookieTrackingConfiguration extends DataFlow2::Configuration { NameToGinSetCookieTrackingConfiguration() { this = "NameToGinSetCookieTrackingConfiguration" } @@ -164,7 +168,8 @@ private class GorillaStoreSaveSink extends DataFlow::Node { } /** - * Tracks from gorilla cookie store creation to `gorilla/sessions.Session.Save`. + * A taint-tracking configuration for tracking flow from gorilla cookie store + * creation to `gorilla/sessions.Session.Save`. */ class GorillaCookieStoreSaveTrackingConfiguration extends DataFlow::Configuration { GorillaCookieStoreSaveTrackingConfiguration() { @@ -194,7 +199,8 @@ class GorillaCookieStoreSaveTrackingConfiguration extends DataFlow::Configuratio } /** - * Tracks session options to `gorilla/sessions.Session.Save`. + * A taint-tracking configuration for tracking flow from session options to + * `gorilla/sessions.Session.Save`. */ class GorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configuration { GorillaSessionOptionsTrackingConfiguration() { @@ -219,7 +225,8 @@ class GorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configur } /** - * Tracks `bool` assigned to `HttpOnly` that flows into `gorilla/sessions.Session.Save`. + * A taint-tracking configuration for tracking flow from a `bool` assigned to + * `HttpOnly` to `gorilla/sessions.Session.Save`. */ class BoolToGorillaSessionOptionsTrackingConfiguration extends TaintTracking::Configuration { BoolToGorillaSessionOptionsTrackingConfiguration() { diff --git a/go/ql/src/experimental/CWE-327/CryptoLibraries.qll b/go/ql/src/experimental/CWE-327/CryptoLibraries.qll index ea087507177..5518067b668 100644 --- a/go/ql/src/experimental/CWE-327/CryptoLibraries.qll +++ b/go/ql/src/experimental/CWE-327/CryptoLibraries.qll @@ -161,7 +161,7 @@ abstract class CryptographicOperation extends DataFlow::Node { } /** - * Models cryptographic operations of the `crypto/md5` package. + * A cryptographic operation from the `crypto/md5` package. */ class Md5 extends CryptographicOperation, DataFlow::CallNode { Md5() { this.getTarget().hasQualifiedName("crypto/md5", ["New", "Sum"]) } @@ -174,7 +174,7 @@ class Md5 extends CryptographicOperation, DataFlow::CallNode { } /** - * Models cryptographic operations of the `crypto/sha1` package. + * A cryptographic operation from the `crypto/sha1` package. */ class Sha1 extends CryptographicOperation, DataFlow::CallNode { Sha1() { this.getTarget().hasQualifiedName("crypto/sha1", ["New", "Sum"]) } @@ -187,7 +187,7 @@ class Sha1 extends CryptographicOperation, DataFlow::CallNode { } /** - * Models cryptographic operations of the `crypto/des` package. + * A cryptographic operation from the `crypto/des` package. */ class Des extends CryptographicOperation, DataFlow::CallNode { Des() { this.getTarget().hasQualifiedName("crypto/des", ["NewCipher", "NewTripleDESCipher"]) } @@ -200,7 +200,7 @@ class Des extends CryptographicOperation, DataFlow::CallNode { } /** - * Models cryptographic operations of the `crypto/rc4` package. + * A cryptographic operation from the `crypto/rc4` package. */ class Rc4 extends CryptographicOperation, DataFlow::CallNode { Rc4() { this.getTarget().hasQualifiedName("crypto/rc4", "NewCipher") } diff --git a/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql b/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql index eb6c7668f06..fd5fccacbc6 100644 --- a/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql +++ b/go/ql/src/experimental/CWE-79/HTMLTemplateEscapingPassthrough.ql @@ -29,7 +29,7 @@ predicate flowsFromUntrustedToConversion( } /** - * Provides the names of the types that will not be escaped when passed to + * A name of a type that will not be escaped when passed to * a `html/template` template. */ class PassthroughTypeName extends string { diff --git a/go/ql/src/experimental/CWE-918/SSRF.qll b/go/ql/src/experimental/CWE-918/SSRF.qll index cf264c8c0b6..b6424511a21 100644 --- a/go/ql/src/experimental/CWE-918/SSRF.qll +++ b/go/ql/src/experimental/CWE-918/SSRF.qll @@ -132,7 +132,7 @@ module ServerSideRequestForgery { } /** - * If the tainted variable is a boolean or has numeric type is not possible to exploit a SSRF + * A value which has boolean or numeric type, considered as a sanitizer for SSRF. */ class NumSanitizer extends Sanitizer { NumSanitizer() { @@ -142,8 +142,8 @@ module ServerSideRequestForgery { } /** - * When we receive a body from a request, we can use certain tags on our struct's fields to hint - * the binding function to run some validations for that field. If these binding functions returns + * A body received from a request, where certain tags on our struct's fields have been used to hint + * to the binding function to run some validations for that field. If these binding functions returns * no error, then we consider these fields safe for SSRF. */ class BodySanitizer extends Sanitizer instanceof CheckedAlphanumericStructFieldRead { } diff --git a/go/ql/test/extractor-tests/diagnostics/Diagnostics.ql b/go/ql/test/extractor-tests/diagnostics/Diagnostics.ql index dd6bb45e6a0..ed6d8ac043d 100644 --- a/go/ql/test/extractor-tests/diagnostics/Diagnostics.ql +++ b/go/ql/test/extractor-tests/diagnostics/Diagnostics.ql @@ -44,7 +44,7 @@ class Diagnostic extends @diagnostic { } /** - * Wraps `Compilation`, removing the `.exe` suffixes from compilation descriptions + * A wrapper around a `Compilation`, removing the `.exe` suffixes from compilation descriptions * such that this test produces the same results on Windows and non-Windows platforms. */ class PlatformNeutralCompilation extends Compilation { From cf89b00f47f19d737791d2ba9eb3537189e8083d Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 14:51:44 +0000 Subject: [PATCH 116/141] Fix variable names in QLDocs --- go/ql/lib/semmle/go/dataflow/SSA.qll | 2 +- go/ql/lib/semmle/go/dependencies/Dependencies.qll | 2 +- go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql | 4 ++-- go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/go/ql/lib/semmle/go/dataflow/SSA.qll b/go/ql/lib/semmle/go/dataflow/SSA.qll index 54b49816391..97a9ac4e069 100644 --- a/go/ql/lib/semmle/go/dataflow/SSA.qll +++ b/go/ql/lib/semmle/go/dataflow/SSA.qll @@ -310,7 +310,7 @@ private newtype TSsaWithFields = TStep(SsaWithFields base, Field f) { exists(accessPathAux(base, f)) } /** - * Gets a representation of `nd` as an ssa-with-fields value if there is one. + * Gets a representation of `insn` as an ssa-with-fields value if there is one. */ private TSsaWithFields accessPath(IR::Instruction insn) { exists(SsaVariable v | insn = v.getAUse() | result = TRoot(v)) diff --git a/go/ql/lib/semmle/go/dependencies/Dependencies.qll b/go/ql/lib/semmle/go/dependencies/Dependencies.qll index 5fc746e6987..b0acaab5a9e 100644 --- a/go/ql/lib/semmle/go/dependencies/Dependencies.qll +++ b/go/ql/lib/semmle/go/dependencies/Dependencies.qll @@ -86,7 +86,7 @@ class GoModDependency extends Dependency, GoModRequireLine { } /** - * Holds if this require line originally states dependency `path` had version `ver`. + * Holds if this require line originally states dependency `path` had version `v`. * * The actual info of this dependency can change based on `replace` directives in the same go.mod * file, which replace a dependency with another one. diff --git a/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql b/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql index f19bee4b179..1a6739608ac 100644 --- a/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql +++ b/go/ql/src/Security/CWE-020/MissingRegexpAnchor.ql @@ -14,7 +14,7 @@ import go /** - * Holds if `src` is a pattern for a collection of alternatives where + * Holds if `re` is a pattern for a collection of alternatives where * only the first or last alternative is anchored, indicating a * precedence mistake explained by `msg`. * @@ -46,7 +46,7 @@ predicate isInterestingSemiAnchoredRegexpString(string re, string msg) { } /** - * Holds if `src` is an unanchored pattern for a URL, indicating a + * Holds if `re` is an unanchored pattern for a URL, indicating a * mistake explained by `msg`. */ bindingset[re] diff --git a/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql b/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql index 7b2dcb12fcf..53e7c0e8730 100644 --- a/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql +++ b/go/ql/src/experimental/CWE-942/CorsMisconfiguration.ql @@ -166,7 +166,7 @@ class FlowsFromUntrusted extends TaintTracking::Configuration { } /** - * Holds if the provided `dst` is also destination of a `UntrustedFlowSource`. + * Holds if the provided `allowOriginHW` is also destination of a `UntrustedFlowSource`. */ predicate flowsToGuardedByCheckOnUntrusted(AllowOriginHeaderWrite allowOriginHW) { exists(FlowsFromUntrusted cfg, DataFlow::Node sink, ControlFlow::ConditionGuardNode cgn | From 9ac0c57a3ebcd8ae0e35a50477957fd48293b068 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 15:15:19 +0000 Subject: [PATCH 117/141] Fix alert message to match style guide --- go/ql/lib/semmle/go/dependencies/Dependencies.qll | 4 +--- go/ql/src/Security/CWE-601/OpenUrlRedirect.ql | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go/ql/lib/semmle/go/dependencies/Dependencies.qll b/go/ql/lib/semmle/go/dependencies/Dependencies.qll index b0acaab5a9e..d8c8ee52d29 100644 --- a/go/ql/lib/semmle/go/dependencies/Dependencies.qll +++ b/go/ql/lib/semmle/go/dependencies/Dependencies.qll @@ -28,9 +28,7 @@ abstract class Dependency extends Locatable { */ abstract predicate relevantForFile(File file); - /** - * An import of this dependency. - */ + /** Gets an import of this dependency. */ ImportSpec getAnImport() { result.getPath().regexpMatch("\\Q" + this.getDepPath() + "\\E(/.*)?") and this.relevantForFile(result.getFile()) diff --git a/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql b/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql index 63c8b945ab3..d633161f916 100644 --- a/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql +++ b/go/ql/src/Security/CWE-601/OpenUrlRedirect.ql @@ -24,5 +24,5 @@ where // this excludes flow from safe parts of request URLs, for example the full URL when the // doing a redirect from `http://` to `https://` not scfg.hasFlow(_, sink.getNode()) -select sink.getNode(), source, sink, "Untrusted URL redirection depends on a $@.", source.getNode(), - "user-provided value" +select sink.getNode(), source, sink, "This path to an untrusted URL redirection depends on a $@.", + source.getNode(), "user-provided value" From 607e2817e5d47c7061d0b06ee024b5f1aa9331eb Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 16:41:05 +0000 Subject: [PATCH 118/141] Use `not A and B` instead of `if A then none() else B` --- go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll index a3f79d756cc..a1d14003031 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll @@ -1305,10 +1305,10 @@ module CFG { exists(Completion inner | lastNode(this.getBody(), last, inner) and not inner.isNormal() | if inner = Break(this.getLabel()) then cmpl = Done() - else - if inner = Continue(this.getLabel()) - then none() - else cmpl = inner + else ( + not inner = Continue(this.getLabel()) and + cmpl = inner + ) ) } } From 34bca0612ba38c375a71db98f52fc5443aed0586 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 16:44:41 +0000 Subject: [PATCH 119/141] Use _ for exists-variable that is only used once --- .../library-tests/semmle/go/frameworks/SQL/QueryString.ql | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql index d0b8848480c..c19fdfc9c3e 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql @@ -8,10 +8,10 @@ class SqlTest extends InlineExpectationsTest { override predicate hasActualResult(Location location, string element, string tag, string value) { tag = "query" and - exists(SQL::Query q, SQL::QueryString qs, int qsLine | qs = q.getAQueryString() | + exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and - qs.hasLocationInfo(_, qsLine, _, _, _) and + qs.hasLocationInfo(_, _, _, _, _) and element = q.toString() and value = qs.toString() ) From 5d93ed5f529edf4a52e35d3a4de0ac2a15418486 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 21:51:43 +0000 Subject: [PATCH 120/141] Remove redundant term It's hard to tell what the original intention was, but I don't think the location of qs should be the same as the location of q, so this term is redundant. --- go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql | 1 - 1 file changed, 1 deletion(-) diff --git a/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql b/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql index c19fdfc9c3e..9cde1ad1fbe 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql +++ b/go/ql/test/library-tests/semmle/go/frameworks/SQL/QueryString.ql @@ -11,7 +11,6 @@ class SqlTest extends InlineExpectationsTest { exists(SQL::Query q, SQL::QueryString qs | qs = q.getAQueryString() | q.hasLocationInfo(location.getFile().getAbsolutePath(), location.getStartLine(), location.getStartColumn(), location.getEndLine(), location.getEndColumn()) and - qs.hasLocationInfo(_, _, _, _, _) and element = q.toString() and value = qs.toString() ) From a9f297c03127768db5ccdbf8f49506700dba3d6e Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 16:47:43 +0000 Subject: [PATCH 121/141] Use set literal instead of a conjunction --- .../semmle/go/Packages/package.ql | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/Packages/package.ql b/go/ql/test/library-tests/semmle/go/Packages/package.ql index 41ee771ecdf..74644c44c0b 100644 --- a/go/ql/test/library-tests/semmle/go/Packages/package.ql +++ b/go/ql/test/library-tests/semmle/go/Packages/package.ql @@ -2,17 +2,18 @@ import go from string path where - ( - path = "github.com/nonexistent/v2/test" or // OK - path = "github.com/nonexistent/test" or // OK - path = "github.com/nonexistent//v//test" or // NOT OK - path = "github.com/nonexistent//v/test" or // NOT OK - path = "github.com/nonexistent/v//test" or // NOT OK - path = "github.com/nonexistent/v/asd/v2/test" or // NOT OK - path = "github.com/nonexistent/v/test" or // NOT OK - path = "github.com/nonexistent//v2//test" or // NOT OK - path = "github.com/nonexistent//v2/test" or // NOT OK - path = "github.com/nonexistent/v2//test" // NOT OK - ) and + path = + [ + "github.com/nonexistent/v2/test", // OK + "github.com/nonexistent/test", // OK + "github.com/nonexistent//v//test", // NOT OK + "github.com/nonexistent//v/test", // NOT OK + "github.com/nonexistent/v//test", // NOT OK + "github.com/nonexistent/v/asd/v2/test", // NOT OK + "github.com/nonexistent/v/test", // NOT OK + "github.com/nonexistent//v2//test", // NOT OK + "github.com/nonexistent//v2/test", // NOT OK + "github.com/nonexistent/v2//test" // NOT OK + ] and path = package("github.com/nonexistent", "test") select path From 4fa57bfb2da7adb96fc5d692ae813a4c578a99ea Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Fri, 17 Feb 2023 16:49:17 +0000 Subject: [PATCH 122/141] Use set literal instead of regex comparison --- go/ql/test/library-tests/semmle/go/Types/MethodCount.ql | 2 +- go/ql/test/library-tests/semmle/go/Types/Methods.ql | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/Types/MethodCount.ql b/go/ql/test/library-tests/semmle/go/Types/MethodCount.ql index b4d3d2663fd..d0d3ee09b43 100644 --- a/go/ql/test/library-tests/semmle/go/Types/MethodCount.ql +++ b/go/ql/test/library-tests/semmle/go/Types/MethodCount.ql @@ -1,5 +1,5 @@ import go from Type t -where t.getPackage().getName().regexpMatch("main|pkg1|pkg2") +where t.getPackage().getName() = ["main", "pkg1", "pkg2"] select t.pp(), strictcount(t.getMethod(_)) diff --git a/go/ql/test/library-tests/semmle/go/Types/Methods.ql b/go/ql/test/library-tests/semmle/go/Types/Methods.ql index 2204612f64a..d00ee5865f4 100644 --- a/go/ql/test/library-tests/semmle/go/Types/Methods.ql +++ b/go/ql/test/library-tests/semmle/go/Types/Methods.ql @@ -1,5 +1,5 @@ import go from Type t, string m -where t.getPackage().getName().regexpMatch("main|pkg1|pkg2") +where t.getPackage().getName() = ["main", "pkg1", "pkg2"] select t.pp(), m, t.getMethod(m) From 8e8ffb20a3bfb67cd66f7fc4be043dd3571c8162 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Sat, 18 Feb 2023 07:51:32 +0000 Subject: [PATCH 123/141] Accept test changes caused by alert message change --- .../go/frameworks/Beego/OpenRedirect.expected | 4 ++-- .../go/frameworks/Echo/OpenRedirect.expected | 4 ++-- .../go/frameworks/Revel/OpenRedirect.expected | 2 +- .../OpenUrlRedirect/OpenUrlRedirect.expected | 22 +++++++++---------- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected index 9a80d4698cc..ebdb44f02e2 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/OpenRedirect.expected @@ -8,5 +8,5 @@ nodes | test.go:312:20:312:34 | call to URL | semmle.label | call to URL | subpaths #select -| test.go:247:13:247:34 | call to GetString | test.go:247:13:247:34 | call to GetString | test.go:247:13:247:34 | call to GetString | Untrusted URL redirection depends on a $@. | test.go:247:13:247:34 | call to GetString | user-provided value | -| test.go:248:20:248:41 | call to GetString | test.go:248:20:248:41 | call to GetString | test.go:248:20:248:41 | call to GetString | Untrusted URL redirection depends on a $@. | test.go:248:20:248:41 | call to GetString | user-provided value | +| test.go:247:13:247:34 | call to GetString | test.go:247:13:247:34 | call to GetString | test.go:247:13:247:34 | call to GetString | This path to an untrusted URL redirection depends on a $@. | test.go:247:13:247:34 | call to GetString | user-provided value | +| test.go:248:20:248:41 | call to GetString | test.go:248:20:248:41 | call to GetString | test.go:248:20:248:41 | call to GetString | This path to an untrusted URL redirection depends on a $@. | test.go:248:20:248:41 | call to GetString | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected index 10ad0046423..5bdc5910dc3 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Echo/OpenRedirect.expected @@ -14,5 +14,5 @@ nodes | test.go:191:21:191:32 | call to String | semmle.label | call to String | subpaths #select -| test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param | test.go:171:20:171:24 | param | Untrusted URL redirection depends on a $@. | test.go:170:11:170:32 | call to Param | user-provided value | -| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param | test.go:180:20:180:28 | ...+... | Untrusted URL redirection depends on a $@. | test.go:176:11:176:32 | call to Param | user-provided value | +| test.go:171:20:171:24 | param | test.go:170:11:170:32 | call to Param | test.go:171:20:171:24 | param | This path to an untrusted URL redirection depends on a $@. | test.go:170:11:170:32 | call to Param | user-provided value | +| test.go:180:20:180:28 | ...+... | test.go:176:11:176:32 | call to Param | test.go:180:20:180:28 | ...+... | This path to an untrusted URL redirection depends on a $@. | test.go:176:11:176:32 | call to Param | user-provided value | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected index 77436c0d149..a2321bb16fa 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/OpenRedirect.expected @@ -5,4 +5,4 @@ nodes | EndToEnd.go:94:20:94:49 | call to Get | semmle.label | call to Get | subpaths #select -| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | Untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | +| EndToEnd.go:94:20:94:49 | call to Get | EndToEnd.go:94:20:94:27 | selection of Params | EndToEnd.go:94:20:94:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:94:20:94:27 | selection of Params | user-provided value | diff --git a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected index f7e2677efef..d4de75b2cc6 100644 --- a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected +++ b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/OpenUrlRedirect.expected @@ -112,14 +112,14 @@ nodes | stdlib.go:194:23:194:42 | call to EscapedPath | semmle.label | call to EscapedPath | subpaths #select -| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form | OpenUrlRedirect.go:10:23:10:42 | call to Get | Untrusted URL redirection depends on a $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | -| stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form | stdlib.go:15:30:15:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | -| stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form | stdlib.go:24:30:24:35 | target | Untrusted URL redirection depends on a $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | -| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form | stdlib.go:35:30:35:39 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | -| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form | stdlib.go:46:23:46:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | -| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form | stdlib.go:67:23:67:40 | ...+... | Untrusted URL redirection depends on a $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | -| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form | stdlib.go:92:23:92:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | -| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form | stdlib.go:152:23:152:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | -| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue | stdlib.go:184:23:184:28 | target | Untrusted URL redirection depends on a $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | -| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:192:23:192:33 | selection of Path | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | -| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:194:23:194:42 | call to EscapedPath | Untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| OpenUrlRedirect.go:10:23:10:42 | call to Get | OpenUrlRedirect.go:10:23:10:28 | selection of Form | OpenUrlRedirect.go:10:23:10:42 | call to Get | This path to an untrusted URL redirection depends on a $@. | OpenUrlRedirect.go:10:23:10:28 | selection of Form | user-provided value | +| stdlib.go:15:30:15:35 | target | stdlib.go:13:13:13:18 | selection of Form | stdlib.go:15:30:15:35 | target | This path to an untrusted URL redirection depends on a $@. | stdlib.go:13:13:13:18 | selection of Form | user-provided value | +| stdlib.go:24:30:24:35 | target | stdlib.go:22:13:22:18 | selection of Form | stdlib.go:24:30:24:35 | target | This path to an untrusted URL redirection depends on a $@. | stdlib.go:22:13:22:18 | selection of Form | user-provided value | +| stdlib.go:35:30:35:39 | ...+... | stdlib.go:31:13:31:18 | selection of Form | stdlib.go:35:30:35:39 | ...+... | This path to an untrusted URL redirection depends on a $@. | stdlib.go:31:13:31:18 | selection of Form | user-provided value | +| stdlib.go:46:23:46:28 | target | stdlib.go:44:13:44:18 | selection of Form | stdlib.go:46:23:46:28 | target | This path to an untrusted URL redirection depends on a $@. | stdlib.go:44:13:44:18 | selection of Form | user-provided value | +| stdlib.go:67:23:67:40 | ...+... | stdlib.go:64:13:64:18 | selection of Form | stdlib.go:67:23:67:40 | ...+... | This path to an untrusted URL redirection depends on a $@. | stdlib.go:64:13:64:18 | selection of Form | user-provided value | +| stdlib.go:92:23:92:28 | target | stdlib.go:89:13:89:18 | selection of Form | stdlib.go:92:23:92:28 | target | This path to an untrusted URL redirection depends on a $@. | stdlib.go:89:13:89:18 | selection of Form | user-provided value | +| stdlib.go:152:23:152:28 | target | stdlib.go:146:13:146:18 | selection of Form | stdlib.go:152:23:152:28 | target | This path to an untrusted URL redirection depends on a $@. | stdlib.go:146:13:146:18 | selection of Form | user-provided value | +| stdlib.go:184:23:184:28 | target | stdlib.go:182:13:182:33 | call to FormValue | stdlib.go:184:23:184:28 | target | This path to an untrusted URL redirection depends on a $@. | stdlib.go:182:13:182:33 | call to FormValue | user-provided value | +| stdlib.go:192:23:192:33 | selection of Path | stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:192:23:192:33 | selection of Path | This path to an untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | +| stdlib.go:194:23:194:42 | call to EscapedPath | stdlib.go:190:36:190:56 | call to FormValue | stdlib.go:194:23:194:42 | call to EscapedPath | This path to an untrusted URL redirection depends on a $@. | stdlib.go:190:36:190:56 | call to FormValue | user-provided value | From d0a77a8433d1f7227b485d4df166b9c629258429 Mon Sep 17 00:00:00 2001 From: Alexandre Boulgakov Date: Wed, 29 Mar 2023 17:14:41 +0100 Subject: [PATCH 124/141] C++: Support repeated initializers in dbscheme. --- cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll | 5 +++-- cpp/ql/lib/semmlecode.cpp.dbscheme | 14 ++++++++------ 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll b/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll index 93609763ec3..566e4675a9f 100644 --- a/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll +++ b/cpp/ql/lib/semmle/code/cpp/exprs/Literal.qll @@ -192,7 +192,8 @@ class ClassAggregateLiteral extends AggregateLiteral { */ Expr getFieldExpr(Field field) { field = classType.getAField() and - aggregate_field_init(underlyingElement(this), unresolveElement(result), unresolveElement(field)) + aggregate_field_init(underlyingElement(this), unresolveElement(result), unresolveElement(field), + _) } /** @@ -264,7 +265,7 @@ class ArrayOrVectorAggregateLiteral extends AggregateLiteral { * element `elementIndex`, if present. */ Expr getElementExpr(int elementIndex) { - aggregate_array_init(underlyingElement(this), unresolveElement(result), elementIndex) + aggregate_array_init(underlyingElement(this), unresolveElement(result), elementIndex, _) } /** diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme b/cpp/ql/lib/semmlecode.cpp.dbscheme index a5bb28ed29f..19887dbd333 100644 --- a/cpp/ql/lib/semmlecode.cpp.dbscheme +++ b/cpp/ql/lib/semmlecode.cpp.dbscheme @@ -1820,24 +1820,26 @@ new_array_allocated_type( /** * The field being initialized by an initializer expression within an aggregate - * initializer for a class/struct/union. + * initializer for a class/struct/union. Position is used to sort repeated initializers. */ -#keyset[aggregate, field] +#keyset[aggregate, position] aggregate_field_init( int aggregate: @aggregateliteral ref, int initializer: @expr ref, - int field: @membervariable ref + int field: @membervariable ref, + int position: int ref ); /** * The index of the element being initialized by an initializer expression - * within an aggregate initializer for an array. + * within an aggregate initializer for an array. Position is used to sort repeated initializers. */ -#keyset[aggregate, element_index] +#keyset[aggregate, position] aggregate_array_init( int aggregate: @aggregateliteral ref, int initializer: @expr ref, - int element_index: int ref + int element_index: int ref, + int position: int ref ); @ctorinit = @ctordirectinit From b5932debc09ee203943a53f5230bd6d52de304f1 Mon Sep 17 00:00:00 2001 From: Alexandre Boulgakov Date: Thu, 30 Mar 2023 16:11:02 +0100 Subject: [PATCH 125/141] C++: Add db upgrade and downgrade scripts for repeated initializers. --- .../old.dbscheme | 2212 +++++++++++++++++ .../semmlecode.cpp.dbscheme | 2210 ++++++++++++++++ .../upgrade.properties | 4 + .../aggregate_array_init.ql | 11 + .../aggregate_field_init.ql | 15 + .../old.dbscheme | 2210 ++++++++++++++++ .../semmlecode.cpp.dbscheme | 2212 +++++++++++++++++ .../upgrade.properties | 4 + 8 files changed, 8878 insertions(+) create mode 100644 cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/old.dbscheme create mode 100644 cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/semmlecode.cpp.dbscheme create mode 100644 cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties create mode 100644 cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_array_init.ql create mode 100644 cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_field_init.ql create mode 100644 cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/old.dbscheme create mode 100644 cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/semmlecode.cpp.dbscheme create mode 100644 cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/upgrade.properties diff --git a/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/old.dbscheme b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/old.dbscheme new file mode 100644 index 00000000000..19887dbd333 --- /dev/null +++ b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/old.dbscheme @@ -0,0 +1,2212 @@ + +/** + * 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 source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string 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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: 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 @macroinvocation.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_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type( + unique int id: @function ref, + int this_type: @type 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 +) +is_structured_binding(unique int id: @variable 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, + int enclosing : @element 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 +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function 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 = @errortype +| 2 = @unknowntype +| 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 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +| 40 = @decimal32 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +| 50 = @float128x // _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +; + +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 +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + 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, + 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 frontend. + 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 +| 4 = @attribute_arg_constant_expr +; + +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_constant( + unique int arg: @attribute_arg ref, + int constant: @expr 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 +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +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; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + 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 +); + +braced_initialisers( + int init: @initialiser 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 // frontend 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 +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + ; + +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. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref, + int position: int ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref, + int position: 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 ; + +@access = @varaccess | @routineexpr ; + +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 +| 37 = @stmt_co_return +; + +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_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt 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_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_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 +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_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 ; + +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/downgrades/19887dbd33327fb07d54251786e0cb2578539775/semmlecode.cpp.dbscheme b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..a5bb28ed29f --- /dev/null +++ b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/semmlecode.cpp.dbscheme @@ -0,0 +1,2210 @@ + +/** + * 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 source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string 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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: 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 @macroinvocation.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_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type( + unique int id: @function ref, + int this_type: @type 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 +) +is_structured_binding(unique int id: @variable 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, + int enclosing : @element 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 +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function 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 = @errortype +| 2 = @unknowntype +| 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 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +| 40 = @decimal32 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +| 50 = @float128x // _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +; + +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 +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + 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, + 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 frontend. + 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 +| 4 = @attribute_arg_constant_expr +; + +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_constant( + unique int arg: @attribute_arg ref, + int constant: @expr 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 +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +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; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + 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 +); + +braced_initialisers( + int init: @initialiser 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 // frontend 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 +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + ; + +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 ; + +@access = @varaccess | @routineexpr ; + +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 +| 37 = @stmt_co_return +; + +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_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt 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_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_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 +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_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 ; + +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/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties new file mode 100644 index 00000000000..3c45f644ceb --- /dev/null +++ b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties @@ -0,0 +1,4 @@ +description: Revert support for repeated initializers, which are allowed in C with designated initializers. +compatibility: backwards +aggregate_field_init.rel: reorder aggregate_field_init.rel (int aggregate, int initializer, int field, int position) aggregate initializer field +aggregate_array_init.rel: reorder aggregate_array_init.rel (int aggregate, int initializer, int element_index, int position) aggregate initializer element_index diff --git a/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_array_init.ql b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_array_init.ql new file mode 100644 index 00000000000..b8997aca069 --- /dev/null +++ b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_array_init.ql @@ -0,0 +1,11 @@ +class AggregateLiteral extends @aggregateliteral { + string toString() { none() } +} + +class Expr extends @expr { + string toString() { none() } +} + +from AggregateLiteral al, Expr init, int index, int position +where exprparents(init, position, al) and aggregate_array_init(al, init, index) +select al, init, index, position diff --git a/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_field_init.ql b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_field_init.ql new file mode 100644 index 00000000000..b784f88cf0c --- /dev/null +++ b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/aggregate_field_init.ql @@ -0,0 +1,15 @@ +class AggregateLiteral extends @aggregateliteral { + string toString() { none() } +} + +class Expr extends @expr { + string toString() { none() } +} + +class Field extends @membervariable { + string toString() { none() } +} + +from AggregateLiteral al, Expr init, Field field, int position +where exprparents(init, position, al) and aggregate_field_init(al, init, field) +select al, init, field, position diff --git a/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/old.dbscheme b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/old.dbscheme new file mode 100644 index 00000000000..a5bb28ed29f --- /dev/null +++ b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/old.dbscheme @@ -0,0 +1,2210 @@ + +/** + * 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 source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string 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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: 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 @macroinvocation.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_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type( + unique int id: @function ref, + int this_type: @type 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 +) +is_structured_binding(unique int id: @variable 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, + int enclosing : @element 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 +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function 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 = @errortype +| 2 = @unknowntype +| 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 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +| 40 = @decimal32 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +| 50 = @float128x // _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +; + +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 +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + 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, + 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 frontend. + 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 +| 4 = @attribute_arg_constant_expr +; + +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_constant( + unique int arg: @attribute_arg ref, + int constant: @expr 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 +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +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; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + 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 +); + +braced_initialisers( + int init: @initialiser 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 // frontend 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 +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + ; + +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 ; + +@access = @varaccess | @routineexpr ; + +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 +| 37 = @stmt_co_return +; + +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_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt 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_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_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 +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_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 ; + +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/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/semmlecode.cpp.dbscheme b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/semmlecode.cpp.dbscheme new file mode 100644 index 00000000000..19887dbd333 --- /dev/null +++ b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/semmlecode.cpp.dbscheme @@ -0,0 +1,2212 @@ + +/** + * 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 source location of the snapshot. + */ +sourceLocationPrefix(string prefix : string 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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ +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 +); + +files( + unique int id: @file, + string name: string ref +); + +folders( + unique int id: @folder, + string name: 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 @macroinvocation.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_function +| 2 = @constructor +| 3 = @destructor +| 4 = @conversion_function +| 5 = @operator +| 6 = @builtin_function // 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 +); + +/** + * If `function` is a coroutine, then this gives the `std::experimental::resumable_traits` + * instance associated with it, and the variables representing the `handle` and `promise` + * for it. + */ +coroutine( + unique int function: @function ref, + int traits: @type ref, + int handle: @variable ref, + int promise: @variable ref +); + +/** The `new` function used for allocating the coroutine state, if any. */ +coroutine_new( + unique int function: @function ref, + int new: @function ref +); + +/** The `delete` function used for deallocating the coroutine state, if any. */ +coroutine_delete( + unique int function: @function ref, + int delete: @function ref +); + +purefunctions(unique int id: @function ref); + +function_deleted(unique int id: @function ref); + +function_defaulted(unique int id: @function ref); + +member_function_this_type( + unique int id: @function ref, + int this_type: @type 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 +) +is_structured_binding(unique int id: @variable 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, + int enclosing : @element 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 +); + +orphaned_variables( + int var: @localvariable ref, + int function: @function 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 = @errortype +| 2 = @unknowntype +| 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 Microsoft-specific __int8 +// ... 21 Microsoft-specific __int16 +// ... 22 Microsoft-specific __int32 +// ... 23 Microsoft-specific __int64 +| 24 = @float +| 25 = @double +| 26 = @long_double +| 27 = @complex_float // C99-specific _Complex float +| 28 = @complex_double // C99-specific _Complex double +| 29 = @complex_long_double // C99-specific _Complex long double +| 30 = @imaginary_float // C99-specific _Imaginary float +| 31 = @imaginary_double // C99-specific _Imaginary double +| 32 = @imaginary_long_double // C99-specific _Imaginary long double +| 33 = @wchar_t // Microsoft-specific +| 34 = @decltype_nullptr // C++11 +| 35 = @int128 // __int128 +| 36 = @unsigned_int128 // unsigned __int128 +| 37 = @signed_int128 // signed __int128 +| 38 = @float128 // __float128 +| 39 = @complex_float128 // _Complex __float128 +| 40 = @decimal32 // _Decimal32 +| 41 = @decimal64 // _Decimal64 +| 42 = @decimal128 // _Decimal128 +| 43 = @char16_t +| 44 = @char32_t +| 45 = @std_float32 // _Float32 +| 46 = @float32x // _Float32x +| 47 = @std_float64 // _Float64 +| 48 = @float64x // _Float64x +| 49 = @std_float128 // _Float128 +| 50 = @float128x // _Float128x +| 51 = @char8_t +| 52 = @float16 // _Float16 +| 53 = @complex_float16 // _Complex _Float16 +; + +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 +); + +/** + * An instance of the C++11 `decltype` operator. For example: + * ``` + * int a; + * decltype(1+a) b; + * ``` + * Here `expr` is `1+a`. + * + * Sometimes an additional pair of parentheses around the expression + * would change the semantics of this decltype, e.g. + * ``` + * struct A { double x; }; + * const A* a = new A(); + * decltype( a->x ); // type is double + * decltype((a->x)); // type is const double& + * ``` + * (Please consult the C++11 standard for more details). + * `parentheses_would_change_meaning` is `true` iff that is the case. + */ +#keyset[id, expr] +decltypes( + 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, + 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 frontend. + 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 +| 4 = @attribute_arg_constant_expr +; + +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_constant( + unique int arg: @attribute_arg ref, + int constant: @expr 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 +); + +@conversion = @cast + | @array_to_pointer + | @parexpr + | @reference_to + | @ref_indirect + | @temp_init + ; + +/* +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; + +@prefix_crement_expr = @preincrexpr | @predecrexpr; + +@postfix_crement_expr = @postincrexpr | @postdecrexpr; + +@increment_expr = @preincrexpr | @postincrexpr; + +@decrement_expr = @predecrexpr | @postdecrexpr; + +@crement_expr = @increment_expr | @decrement_expr; + +@un_arith_op_expr = @arithnegexpr + | @unaryplusexpr + | @conjugation + | @realpartexpr + | @imagpartexpr + | @crement_expr + ; + +@un_bitwise_op_expr = @complementexpr; + +@un_log_op_expr = @notexpr; + +@un_op_expr = @address_of + | @indirect + | @un_arith_op_expr + | @un_bitwise_op_expr + | @builtinaddressof + | @vec_fill + | @un_log_op_expr + | @co_await + | @co_yield + ; + +@bin_log_op_expr = @andlogicalexpr | @orlogicalexpr; + +@cmp_op_expr = @eq_op_expr | @rel_op_expr; + +@eq_op_expr = @eqexpr | @neexpr; + +@rel_op_expr = @gtexpr + | @ltexpr + | @geexpr + | @leexpr + | @spaceshipexpr + ; + +@bin_bitwise_op_expr = @lshiftexpr + | @rshiftexpr + | @andexpr + | @orexpr + | @xorexpr + ; + +@p_arith_op_expr = @paddexpr + | @psubexpr + | @pdiffexpr + ; + +@bin_arith_op_expr = @addexpr + | @subexpr + | @mulexpr + | @divexpr + | @remexpr + | @jmulexpr + | @jdivexpr + | @fjaddexpr + | @jfaddexpr + | @fjsubexpr + | @jfsubexpr + | @minexpr + | @maxexpr + | @p_arith_op_expr + ; + +@bin_op_expr = @bin_arith_op_expr + | @bin_bitwise_op_expr + | @cmp_op_expr + | @bin_log_op_expr + ; + +@op_expr = @un_op_expr + | @bin_op_expr + | @assign_expr + | @conditionalexpr + ; + +@assign_arith_expr = @assignaddexpr + | @assignsubexpr + | @assignmulexpr + | @assigndivexpr + | @assignremexpr + ; + +@assign_bitwise_expr = @assignandexpr + | @assignorexpr + | @assignxorexpr + | @assignlshiftexpr + | @assignrshiftexpr + | @assignpaddexpr + | @assignpsubexpr + ; + +@assign_op_expr = @assign_arith_expr | @assign_bitwise_expr + +@assign_expr = @assignexpr | @assign_op_expr | @blockassignexpr + +/* + 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 +); + +braced_initialisers( + int init: @initialiser 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 // frontend 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 +| 326 = @spaceshipexpr +| 327 = @co_await +| 328 = @co_yield +| 329 = @temp_init +| 330 = @isassignable +| 331 = @isaggregate +| 332 = @hasuniqueobjectrepresentations +| 333 = @builtinbitcast +| 334 = @builtinshuffle +| 335 = @blockassignexpr +| 336 = @issame +| 337 = @isfunction +| 338 = @islayoutcompatible +| 339 = @ispointerinterconvertiblebaseof +| 340 = @isarray +| 341 = @arrayrank +| 342 = @arrayextent +| 343 = @isarithmetic +| 344 = @iscompletetype +| 345 = @iscompound +| 346 = @isconst +| 347 = @isfloatingpoint +| 348 = @isfundamental +| 349 = @isintegral +| 350 = @islvaluereference +| 351 = @ismemberfunctionpointer +| 352 = @ismemberobjectpointer +| 353 = @ismemberpointer +| 354 = @isobject +| 355 = @ispointer +| 356 = @isreference +| 357 = @isrvaluereference +| 358 = @isscalar +| 359 = @issigned +| 360 = @isunsigned +| 361 = @isvoid +| 362 = @isvolatile +; + +@var_args_expr = @vastartexpr + | @vaendexpr + | @vaargexpr + | @vacopyexpr + ; + +@builtin_op = @var_args_expr + | @noopexpr + | @offsetofexpr + | @intaddrexpr + | @hasassignexpr + | @hascopyexpr + | @hasnothrowassign + | @hasnothrowconstr + | @hasnothrowcopy + | @hastrivialassign + | @hastrivialconstr + | @hastrivialcopy + | @hastrivialdestructor + | @hasuserdestr + | @hasvirtualdestr + | @isabstractexpr + | @isbaseofexpr + | @isclassexpr + | @isconvtoexpr + | @isemptyexpr + | @isenumexpr + | @ispodexpr + | @ispolyexpr + | @isunionexpr + | @typescompexpr + | @builtinshufflevector + | @builtinconvertvector + | @builtinaddressof + | @istriviallyconstructibleexpr + | @isdestructibleexpr + | @isnothrowdestructibleexpr + | @istriviallydestructibleexpr + | @istriviallyassignableexpr + | @isnothrowassignableexpr + | @isstandardlayoutexpr + | @istriviallycopyableexpr + | @isliteraltypeexpr + | @hastrivialmoveconstructorexpr + | @hastrivialmoveassignexpr + | @hasnothrowmoveassignexpr + | @isconstructibleexpr + | @isnothrowconstructibleexpr + | @hasfinalizerexpr + | @isdelegateexpr + | @isinterfaceclassexpr + | @isrefarrayexpr + | @isrefclassexpr + | @issealedexpr + | @issimplevalueclassexpr + | @isvalueclassexpr + | @isfinalexpr + | @builtinchooseexpr + | @builtincomplex + | @isassignable + | @isaggregate + | @hasuniqueobjectrepresentations + | @builtinbitcast + | @builtinshuffle + | @issame + | @isfunction + | @islayoutcompatible + | @ispointerinterconvertiblebaseof + | @isarray + | @arrayrank + | @arrayextent + | @isarithmetic + | @iscompletetype + | @iscompound + | @isconst + | @isfloatingpoint + | @isfundamental + | @isintegral + | @islvaluereference + | @ismemberfunctionpointer + | @ismemberobjectpointer + | @ismemberpointer + | @isobject + | @ispointer + | @isreference + | @isrvaluereference + | @isscalar + | @issigned + | @isunsigned + | @isvoid + | @isvolatile + ; + +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. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_field_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int field: @membervariable ref, + int position: int ref +); + +/** + * The index of the element being initialized by an initializer expression + * within an aggregate initializer for an array. Position is used to sort repeated initializers. + */ +#keyset[aggregate, position] +aggregate_array_init( + int aggregate: @aggregateliteral ref, + int initializer: @expr ref, + int element_index: int ref, + int position: 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 ; + +@access = @varaccess | @routineexpr ; + +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 +| 37 = @stmt_co_return +; + +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_initialization( + unique int if_stmt: @stmt_if ref, + int init_id: @stmt 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_initialization( + unique int constexpr_if_stmt: @stmt_constexpr_if ref, + int init_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 +); + +switch_initialization( + unique int switch_stmt: @stmt_switch ref, + int init_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 ; + +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/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/upgrade.properties b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/upgrade.properties new file mode 100644 index 00000000000..7b58d536070 --- /dev/null +++ b/cpp/ql/lib/upgrades/a5bb28ed29f73855d64cc5f939cef977fa8fd19a/upgrade.properties @@ -0,0 +1,4 @@ +description: Support repeated initializers, which are allowed in C with designated initializers. +compatibility: full +aggregate_field_init.rel: run aggregate_field_init.qlo +aggregate_array_init.rel: run aggregate_array_init.qlo From e593f0f7b3572068c91344d90aa9ea2a217696f8 Mon Sep 17 00:00:00 2001 From: Alexandre Boulgakov Date: Fri, 31 Mar 2023 14:46:59 +0100 Subject: [PATCH 126/141] C++: Update database stats. --- cpp/ql/lib/semmlecode.cpp.dbscheme.stats | 7034 ++++++++++++---------- 1 file changed, 3757 insertions(+), 3277 deletions(-) diff --git a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats index 93bbbcd82d3..24253b0aeb5 100644 --- a/cpp/ql/lib/semmlecode.cpp.dbscheme.stats +++ b/cpp/ql/lib/semmlecode.cpp.dbscheme.stats @@ -2,7 +2,7 @@ @compilation - 9947 + 9948 @externalDataElement @@ -18,303 +18,303 @@ @location_stmt - 3813507 + 3813678 @location_default - 29670824 + 29769315 @location_expr - 13165934 + 13166528 @diagnostic - 72033 + 72036 @file - 122193 + 123102 @folder - 15274 + 15387 @macro_expansion - 33908240 + 33954616 @other_macro_reference - 839618 + 857985 @function - 4634561 + 4638253 @fun_decl - 4995588 + 5001965 @var_decl - 8393866 + 8416189 @type_decl - 3242758 + 3241228 @namespace_decl - 308849 + 308863 @using - 369357 + 369307 @static_assert - 130539 + 130544 @parameter - 6539671 + 6569654 @membervariable - 1052936 + 1052983 @globalvariable - 301270 + 301276 @localvariable - 581183 + 581207 @enumconstant - 241267 + 241278 @errortype - 462 + 466 @unknowntype - 462 + 466 @void - 462 + 466 @boolean - 462 + 466 @char - 462 + 466 @unsigned_char - 462 + 466 @signed_char - 462 + 466 @short - 462 + 466 @unsigned_short - 462 + 466 @signed_short - 462 + 466 @int - 462 + 466 @unsigned_int - 462 + 466 @signed_int - 462 + 466 @long - 462 + 466 @unsigned_long - 462 + 466 @signed_long - 462 + 466 @long_long - 462 + 466 @unsigned_long_long - 462 + 466 @signed_long_long - 462 + 466 @float - 462 + 466 @double - 462 + 466 @long_double - 462 + 466 @complex_float - 462 + 466 @complex_double - 462 + 466 @complex_long_double - 462 + 466 @imaginary_float - 462 + 466 @imaginary_double - 462 + 466 @imaginary_long_double - 462 + 466 @wchar_t - 462 + 466 @decltype_nullptr - 462 + 466 @int128 - 462 + 466 @unsigned_int128 - 462 + 466 @signed_int128 - 462 + 466 @float128 - 462 + 466 @complex_float128 - 462 + 466 @decimal32 - 462 + 466 @decimal64 - 462 + 466 @decimal128 - 462 + 466 @char16_t - 462 + 466 @char32_t - 462 + 466 @std_float32 - 462 + 466 @float32x - 462 + 466 @std_float64 - 462 + 466 @float64x - 462 + 466 @std_float128 - 462 + 466 @float128x - 462 + 466 @char8_t - 462 + 466 @float16 - 462 + 466 @complex_float16 - 462 + 466 @pointer - 565145 + 567483 @reference - 1747594 + 1747669 @type_with_specifiers - 1007634 + 1009066 @array - 109233 + 110046 @routineptr - 635444 + 635462 @rvalue_reference - 613466 + 613493 @gnu_vector @@ -330,47 +330,47 @@ @decltype - 28696 + 27045 @usertype - 5233032 + 5225787 @mangledname - 4996504 + 4988979 @type_mention - 4022409 + 4022590 @routinetype - 547131 + 547147 @ptrtomember - 37491 + 37770 @specifier - 24531 + 24713 @gnuattribute - 680858 + 685456 @stdattribute - 493040 + 492036 @alignas - 9719 + 9792 @declspec - 243696 + 243716 @msattribute @@ -378,15 +378,15 @@ @attribute_arg_token - 38879 + 39168 @attribute_arg_type - 462 + 466 @attribute_arg_constant_expr - 367506 + 370239 @attribute_arg_empty @@ -398,63 +398,63 @@ @derivation - 368247 + 368257 @frienddecl - 716101 + 716121 @comment - 8773481 + 8774227 @namespace - 12497 + 12123 @specialnamequalifyingelement - 462 + 466 @namequalifier - 1533160 + 1533233 @value - 10758747 + 10759232 @initialiser - 1699633 + 1699706 @lambdacapture - 27771 + 27977 @errorexpr - 46890 + 46892 @address_of - 438806 + 438815 @reference_to - 1592422 + 1592467 @indirect - 292157 + 292170 @ref_indirect - 1938618 + 1938672 @array_to_pointer - 1428562 + 1428626 @vacuous_destructor_call @@ -462,55 +462,55 @@ @parexpr - 3581772 + 3581934 @arithnegexpr - 650874 + 650875 @complementexpr - 27791 + 27792 @notexpr - 275965 + 275977 @postincrexpr - 61942 + 61944 @postdecrexpr - 41968 + 41970 @preincrexpr - 70456 + 70459 @predecrexpr - 26164 + 26165 @conditionalexpr - 656192 + 656221 @addexpr - 397731 + 397749 @subexpr - 340216 + 340231 @mulexpr - 305846 + 305860 @divexpr - 132945 + 132951 @remexpr @@ -518,75 +518,75 @@ @paddexpr - 86517 + 86521 @psubexpr - 49816 + 49819 @pdiffexpr - 35456 + 35459 @lshiftexpr - 565360 + 565385 @rshiftexpr - 140605 + 140612 @andexpr - 488242 + 488264 @orexpr - 145223 + 145229 @xorexpr - 54084 + 54087 @eqexpr - 469864 + 469885 @neexpr - 301187 + 301200 @gtexpr - 99050 + 99787 @ltexpr - 104605 + 101652 @geexpr - 59150 + 59152 @leexpr - 212171 + 212181 @assignexpr - 935392 + 935434 @assignaddexpr - 68222 + 68229 @assignsubexpr - 11180 + 11181 @assignmulexpr - 7146 + 7147 @assigndivexpr @@ -610,11 +610,11 @@ @assignorexpr - 23830 + 23831 @assignxorexpr - 21807 + 21808 @assignpaddexpr @@ -622,23 +622,23 @@ @andlogicalexpr - 249535 + 249546 @orlogicalexpr - 864670 + 864709 @commaexpr - 124044 + 124055 @subscriptexpr - 367589 + 367604 @callexpr - 303632 + 302160 @vastartexpr @@ -646,7 +646,7 @@ @vaendexpr - 2777 + 2797 @vacopyexpr @@ -654,15 +654,15 @@ @varaccess - 6019061 + 6019333 @thisaccess - 1126986 + 1127035 @new_expr - 47667 + 47668 @delete_expr @@ -670,11 +670,11 @@ @throw_expr - 21694 + 21695 @condition_decl - 42425 + 42427 @braced_init_list @@ -682,27 +682,27 @@ @type_id - 36482 + 36483 @runtime_sizeof - 295343 + 295357 @runtime_alignof - 49890 + 49891 @sizeof_pack - 5554 + 5595 @routineexpr - 2917109 + 2917246 @type_operand - 1126879 + 1126930 @isemptyexpr @@ -710,15 +710,15 @@ @ispodexpr - 633 + 634 @hastrivialdestructor - 462 + 466 @literal - 4406609 + 4406808 @aggregateliteral @@ -734,15 +734,15 @@ @ctordirectinit - 112975 + 112978 @ctorvirtualinit - 6512 + 6513 @ctorfieldinit - 201112 + 201118 @ctordelegatinginit @@ -750,7 +750,7 @@ @dtordirectdestruct - 41774 + 41776 @dtorvirtualdestruct @@ -758,19 +758,19 @@ @dtorfielddestruct - 41704 + 41705 @static_cast - 210924 + 210934 @reinterpret_cast - 30749 + 30752 @const_cast - 35247 + 35250 @dynamic_cast @@ -778,27 +778,27 @@ @c_style_cast - 4209396 + 4209495 @lambdaexpr - 21291 + 21449 @param_ref - 245644 + 245656 @istrivialexpr - 925 + 932 @istriviallycopyableexpr - 3702 + 3730 @isconstructibleexpr - 462 + 466 @isfinalexpr @@ -806,15 +806,15 @@ @noexceptexpr - 25736 + 25737 @builtinaddressof - 13301 + 13302 @temp_init - 826635 + 826674 @assume @@ -870,7 +870,7 @@ @assignpsubexpr - 1150 + 1151 @virtfunptrexpr @@ -882,11 +882,11 @@ @expr_stmt - 94230 + 94234 @offsetofexpr - 19959 + 19960 @hasassignexpr @@ -958,7 +958,7 @@ @typescompexpr - 562840 + 562865 @intaddrexpr @@ -966,7 +966,7 @@ @uuidof - 20119 + 20120 @foldexpr @@ -1022,7 +1022,7 @@ @isnothrowconstructibleexpr - 14433 + 14434 @hasfinalizerexpr @@ -1222,83 +1222,83 @@ @stmt_expr - 1483544 + 1483611 @stmt_if - 724702 + 724735 @stmt_while - 30109 + 30110 @stmt_label - 53053 + 53056 @stmt_return - 1285346 + 1284647 @stmt_block - 1423277 + 1423603 @stmt_end_test_while - 148625 + 148632 @stmt_for - 61453 + 61456 @stmt_switch_case - 209633 + 209643 @stmt_switch - 20752 + 20753 @stmt_try_block - 46919 + 46921 @stmt_decl - 606527 + 606553 @stmt_empty - 193316 + 193324 @stmt_continue - 22524 + 22525 @stmt_break - 102326 + 102331 @stmt_range_based_for - 8331 + 8393 @stmt_handler - 65311 + 65314 @stmt_constexpr_if - 52504 + 52508 @stmt_goto - 110506 + 110511 @stmt_asm - 109799 + 109804 @stmt_microsoft_try @@ -1314,7 +1314,7 @@ @stmt_assigned_goto - 9060 + 9061 @stmt_co_return @@ -1322,51 +1322,51 @@ @ppd_if - 661419 + 666338 @ppd_ifdef - 261049 + 262991 @ppd_ifndef - 264289 + 266255 @ppd_elif - 24994 + 25180 @ppd_else - 207358 + 208900 @ppd_endif - 1186758 + 1195584 @ppd_plain_include - 308723 + 311019 @ppd_define - 2433092 + 2433298 @ppd_undef - 257809 + 258328 @ppd_pragma - 311993 + 312020 @ppd_include_next - 1851 + 1865 @ppd_line - 27756 + 27757 @ppd_error @@ -1412,11 +1412,11 @@ compilations - 9947 + 9948 id - 9947 + 9948 cwd @@ -1434,7 +1434,7 @@ 1 2 - 9947 + 9948 @@ -1460,7 +1460,7 @@ compilation_args - 651465 + 651494 id @@ -1472,7 +1472,7 @@ arg - 34403 + 34405 @@ -1496,7 +1496,7 @@ 126 127 - 3861 + 3862 127 @@ -1710,7 +1710,7 @@ 1 2 - 32343 + 32344 2 @@ -1731,7 +1731,7 @@ 1 2 - 33199 + 33200 2 @@ -1746,7 +1746,7 @@ compilation_compiling_files - 11526 + 11527 id @@ -1874,7 +1874,7 @@ 1 2 - 1754 + 1755 2 @@ -1910,7 +1910,7 @@ 1 2 - 1754 + 1755 2 @@ -1972,7 +1972,7 @@ 1 2 - 9173 + 9174 2 @@ -1992,7 +1992,7 @@ compilation_time - 46107 + 46109 id @@ -2008,7 +2008,7 @@ seconds - 10290 + 10051 @@ -2089,43 +2089,53 @@ 3 4 - 598 + 678 4 5 - 398 + 319 - 5 + 6 8 - 159 + 119 8 - 9 - 79 + 10 + 119 10 11 - 279 + 79 - 12 - 17 + 11 + 12 159 + + 13 + 17 + 119 + 17 - 22 + 21 159 - 27 - 89 + 21 + 44 159 + + 55 + 89 + 79 + @@ -2140,7 +2150,7 @@ 1 2 - 1754 + 1755 2 @@ -2192,42 +2202,37 @@ 3 4 - 1156 + 1236 4 5 - 598 + 518 5 6 - 239 + 159 6 7 - 438 + 558 7 - 8 - 79 - - - 8 9 279 9 - 25 + 24 279 - 25 - 95 - 239 + 24 + 91 + 279 @@ -2283,13 +2288,13 @@ 39 - 125 - 126 + 120 + 121 39 - 133 - 134 + 129 + 130 39 @@ -2306,27 +2311,27 @@ 1 2 - 6102 + 5823 2 3 - 1874 + 2074 3 4 - 1276 + 917 4 6 - 797 + 917 6 40 - 239 + 319 @@ -2342,32 +2347,32 @@ 1 2 - 5344 + 5065 2 3 - 2113 + 1794 3 4 - 1116 + 1236 4 5 - 598 + 757 5 - 9 + 7 877 - 9 - 59 - 239 + 7 + 67 + 319 @@ -2383,12 +2388,12 @@ 1 2 - 10051 + 9892 2 - 4 - 239 + 3 + 159 @@ -2398,11 +2403,11 @@ diagnostic_for - 841590 + 841626 diagnostic - 72033 + 72036 compilation @@ -2433,7 +2438,7 @@ 2 3 - 59653 + 59655 254 @@ -2454,7 +2459,7 @@ 1 2 - 72033 + 72036 @@ -2470,7 +2475,7 @@ 1 2 - 72033 + 72036 @@ -2749,15 +2754,15 @@ compilation_finished - 9947 + 9948 id - 9947 + 9948 cpu_seconds - 8149 + 7838 elapsed_seconds @@ -2775,7 +2780,7 @@ 1 2 - 9947 + 9948 @@ -2791,7 +2796,7 @@ 1 2 - 9947 + 9948 @@ -2807,17 +2812,17 @@ 1 2 - 6881 + 6605 2 3 - 1037 + 853 3 - 16 - 230 + 12 + 380 @@ -2833,12 +2838,12 @@ 1 2 - 7873 + 7354 2 3 - 276 + 484 @@ -2859,11 +2864,6 @@ 2 3 - 11 - - - 3 - 4 23 @@ -2872,43 +2872,43 @@ 11 - 10 - 11 + 7 + 8 + 23 + + + 11 + 12 11 - 12 - 13 + 25 + 26 11 - 30 - 31 + 52 + 53 11 - 61 - 62 + 114 + 115 11 - 111 - 112 + 145 + 146 11 - 157 - 158 + 244 + 245 11 - 230 - 231 - 11 - - - 238 - 239 + 248 + 249 11 @@ -2930,11 +2930,6 @@ 2 3 - 11 - - - 3 - 4 23 @@ -2943,43 +2938,43 @@ 11 - 10 - 11 + 7 + 8 + 23 + + + 11 + 12 11 - 12 - 13 + 25 + 26 11 - 30 - 31 + 51 + 52 11 - 61 - 62 + 102 + 103 11 - 103 - 104 + 107 + 108 11 - 111 - 112 + 172 + 173 11 - 182 - 183 - 11 - - - 208 - 209 + 230 + 231 11 @@ -3206,11 +3201,11 @@ sourceLocationPrefix - 462 + 466 prefix - 462 + 466 @@ -4704,31 +4699,31 @@ locations_default - 29670824 + 29769315 id - 29670824 + 29769315 container - 137467 + 138490 startLine - 2080993 + 2092739 startColumn - 36565 + 36837 endLine - 2083770 + 2096936 endColumn - 47674 + 48028 @@ -4742,7 +4737,7 @@ 1 2 - 29670824 + 29769315 @@ -4758,7 +4753,7 @@ 1 2 - 29670824 + 29769315 @@ -4774,7 +4769,7 @@ 1 2 - 29670824 + 29769315 @@ -4790,7 +4785,7 @@ 1 2 - 29670824 + 29769315 @@ -4806,7 +4801,7 @@ 1 2 - 29670824 + 29769315 @@ -4822,67 +4817,67 @@ 1 2 - 15737 + 15854 2 12 - 10645 + 10724 13 20 - 11571 + 11657 21 36 - 11108 + 11191 36 55 - 11108 + 11191 55 77 - 10645 + 10724 77 102 - 10645 + 10724 102 149 - 10645 + 10724 149 227 - 11108 + 11191 228 350 - 10645 + 10724 - 351 + 352 604 - 10645 + 10724 630 1494 - 10645 + 10724 - 1925 + 1829 2380 - 2314 + 2331 @@ -4898,67 +4893,67 @@ 1 2 - 15737 + 15854 2 9 - 10645 + 10724 9 16 - 11571 + 11657 16 25 - 11108 + 11191 25 40 - 10645 + 10724 40 57 - 10645 + 10724 58 - 73 - 10645 + 72 + 10724 73 103 - 11108 + 11191 106 141 - 11571 + 11657 148 - 226 - 11108 + 225 + 10724 - 226 - 373 - 10645 + 225 + 360 + 10724 - 381 - 1456 - 10645 + 372 + 1255 + 10724 - 1464 - 1614 - 1388 + 1455 + 1569 + 1865 @@ -4974,214 +4969,214 @@ 1 2 - 15737 + 15854 2 4 - 8794 + 8393 4 5 - 7405 + 7927 5 6 - 7405 + 7460 6 8 - 11571 + 11191 8 13 - 12034 + 12123 13 - 18 - 11571 + 17 + 11191 - 18 - 26 - 12034 - - - 26 - 32 - 11108 - - - 32 - 40 - 10645 - - - 40 - 54 - 10645 - - - 54 - 67 - 10645 - - - 67 - 77 - 7868 - - - - - - - container - endLine - - - 12 - - - 1 - 2 - 15737 - - - 2 - 9 - 10645 - - - 9 - 16 - 11571 - - - 16 + 17 25 - 11108 + 11191 25 - 40 - 10645 - - - 40 - 57 - 10645 - - - 58 - 72 - 10645 - - - 72 - 98 - 10645 - - - 101 - 140 - 11571 - - - 140 - 224 - 10645 - - - 224 - 360 - 10645 - - - 364 - 1185 - 10645 - - - 1254 - 1611 - 2314 - - - - - - - container - endColumn - - - 12 - - - 1 - 2 - 15737 - - - 2 - 10 - 11108 - - - 10 - 14 - 10645 - - - 14 - 21 - 11108 - - - 22 31 - 11108 + 12123 31 39 - 12497 + 11191 + + + 39 + 54 + 11191 + + + 54 + 67 + 10724 + + + 67 + 77 + 7927 + + + + + + + container + endLine + + + 12 + + + 1 + 2 + 15854 + + + 2 + 9 + 10724 + + + 9 + 16 + 11657 + + + 16 + 25 + 11191 + + + 25 + 40 + 10724 + + + 40 + 57 + 10724 + + + 58 + 71 + 10724 + + + 72 + 98 + 10724 + + + 101 + 140 + 11657 + + + 140 + 222 + 10724 + + + 223 + 360 + 11191 + + + 372 + 1255 + 10724 + + + 1452 + 1566 + 1865 + + + + + + + container + endColumn + + + 12 + + + 1 + 2 + 15854 + + + 2 + 10 + 11191 + + + 10 + 14 + 10724 + + + 14 + 21 + 11191 + + + 22 + 31 + 11191 + + + 31 + 39 + 12590 39 48 - 11571 + 12123 48 - 55 - 10645 + 56 + 11657 - 55 - 63 - 11108 + 56 + 64 + 12123 - 63 - 70 - 11571 + 64 + 73 + 12123 - 70 - 77 - 12034 + 73 + 78 + 10724 - 77 + 78 90 - 8331 + 6994 @@ -5197,52 +5192,52 @@ 1 2 - 572088 + 583803 2 3 - 312426 + 314750 3 4 - 196250 + 192580 4 6 - 159221 + 161804 6 10 - 186993 + 183720 10 16 - 163387 + 162271 16 25 - 166164 + 167400 25 - 46 - 160610 + 45 + 157141 - 46 - 169 - 156907 + 45 + 160 + 157608 - 170 + 160 298 - 6942 + 11657 @@ -5258,42 +5253,42 @@ 1 2 - 855355 + 870109 2 3 - 275861 + 273716 3 5 - 189307 + 193046 5 8 - 178198 + 173462 8 - 12 - 159684 + 13 + 187917 - 12 - 18 - 163850 + 13 + 20 + 160872 - 18 - 39 - 157370 + 20 + 51 + 159473 - 39 + 51 298 - 101365 + 74141 @@ -5309,47 +5304,47 @@ 1 2 - 601710 + 614112 2 3 - 308261 + 310087 3 4 - 199953 + 198642 4 6 - 181901 + 182322 6 9 - 177736 + 173462 9 13 - 163850 + 162737 13 19 - 171256 + 173928 19 29 - 164313 + 165069 29 52 - 112010 + 112377 @@ -5365,22 +5360,22 @@ 1 2 - 1520939 + 1529919 2 3 - 345752 + 348323 3 5 - 161999 + 161804 5 16 - 52302 + 52691 @@ -5396,52 +5391,52 @@ 1 2 - 576716 + 588466 2 3 - 313352 + 316149 3 4 - 198564 + 195378 4 6 - 165701 + 167866 6 9 - 157833 + 158074 9 14 - 175421 + 170198 14 21 - 173570 + 174394 21 32 - 159684 + 163670 32 - 60 - 156444 + 63 + 157608 - 60 + 64 66 - 3702 + 932 @@ -5457,72 +5452,72 @@ 1 31 - 2777 + 2797 42 85 - 2777 + 2797 86 128 - 2777 + 2797 129 229 - 2777 + 2797 248 292 - 2777 + 2797 293 360 - 2777 + 2797 - 376 - 459 - 2777 + 373 + 456 + 2797 475 - 560 - 2777 + 565 + 2797 565 - 623 - 2777 + 619 + 2797 - 626 - 699 - 2777 + 622 + 689 + 2797 - 699 - 796 - 2777 + 695 + 793 + 2797 820 - 1568 - 2777 + 1563 + 2797 - 1705 - 5647 - 2777 + 1638 + 5626 + 2797 - 15306 - 15307 - 462 + 15295 + 15296 + 466 @@ -5538,67 +5533,67 @@ 1 18 - 2777 + 2797 23 35 - 3239 + 3264 38 43 - 2777 + 2797 44 61 - 2777 + 2797 65 73 - 2777 + 2797 73 84 - 3239 + 3264 84 - 97 - 3239 + 96 + 2797 - 98 + 96 101 - 2314 + 3264 101 105 - 3239 + 3264 - 106 - 111 - 2777 + 107 + 112 + 2797 - 111 - 123 - 2777 + 112 + 126 + 2797 - 127 - 154 - 2777 + 137 + 170 + 2797 - 169 + 195 298 - 1851 + 1398 @@ -5614,72 +5609,72 @@ 1 19 - 2777 + 2797 30 72 - 2777 + 2797 83 122 - 2777 + 2797 122 205 - 2777 + 2797 214 261 - 2777 + 2797 - 264 + 265 322 - 2777 + 2797 - 325 - 380 - 2777 + 322 + 379 + 2797 404 - 436 - 2777 + 430 + 2797 - 454 + 452 474 - 2777 + 2797 - 479 - 514 - 2777 + 478 + 505 + 2797 - 517 - 586 - 2777 + 511 + 583 + 2797 - 587 - 838 - 2777 + 584 + 836 + 2797 - 1116 - 2197 - 2777 + 1104 + 2196 + 2797 - 2387 - 2388 - 462 + 2381 + 2382 + 466 @@ -5695,72 +5690,72 @@ 1 19 - 2777 + 2797 30 72 - 2777 + 2797 83 122 - 2777 + 2797 122 205 - 2777 + 2797 214 261 - 2777 + 2797 - 264 + 265 322 - 2777 + 2797 - 325 + 322 380 - 2777 + 2797 404 - 436 - 2777 + 430 + 2797 - 454 + 452 474 - 2777 + 2797 - 478 - 513 - 2777 + 477 + 504 + 2797 - 520 - 585 - 2777 + 514 + 582 + 2797 - 587 - 837 - 2777 + 584 + 835 + 2797 - 1121 - 2205 - 2777 + 1109 + 2203 + 2797 - 2383 - 2384 - 462 + 2376 + 2377 + 466 @@ -5776,67 +5771,67 @@ 1 7 - 2777 + 2797 7 11 - 3239 + 3264 11 16 - 3239 + 3264 16 22 - 2777 + 2797 22 24 - 2314 + 3264 24 - 27 - 3239 + 28 + 2797 - 28 - 33 - 2777 + 29 + 34 + 3264 - 33 - 40 - 3239 + 34 + 41 + 3264 - 40 - 43 - 2777 + 41 + 46 + 2797 - 43 + 46 49 - 2777 + 1865 49 54 - 2777 + 2797 54 74 - 2777 + 2797 75 86 - 1851 + 1865 @@ -5852,52 +5847,52 @@ 1 2 - 579956 + 594062 2 3 - 306872 + 306823 3 4 - 196250 + 195844 4 6 - 159221 + 159007 6 10 - 186067 + 183254 10 16 - 161536 + 160872 16 25 - 168016 + 169732 25 45 - 157370 + 158074 45 160 - 157370 + 158074 160 298 - 11108 + 11191 @@ -5913,47 +5908,47 @@ 1 2 - 866926 + 885497 2 3 - 265215 + 260193 3 4 - 122193 + 124501 4 6 - 139782 + 140821 6 10 - 192547 + 184653 10 15 - 165239 + 168333 15 26 - 163387 + 163203 26 120 - 156907 + 158074 121 298 - 11571 + 11657 @@ -5969,22 +5964,22 @@ 1 2 - 1513997 + 1527588 2 3 - 343438 + 341329 3 5 - 169404 + 170664 5 10 - 56931 + 57354 @@ -6000,47 +5995,47 @@ 1 2 - 610967 + 625303 2 3 - 299466 + 300295 3 4 - 201804 + 201906 4 6 - 184216 + 183254 6 9 - 174496 + 170198 9 13 - 166627 + 166001 13 19 - 172181 + 174861 19 29 - 160147 + 160872 29 52 - 113862 + 114242 @@ -6056,52 +6051,52 @@ 1 2 - 586436 + 600590 2 3 - 305946 + 306823 3 4 - 196250 + 193979 4 6 - 169404 + 168799 6 9 - 154593 + 155743 9 14 - 171256 + 167866 14 21 - 177273 + 178125 21 32 - 161536 + 163203 32 60 - 157370 + 158074 60 65 - 3702 + 3730 @@ -6117,67 +6112,67 @@ 1 2 - 5091 + 5129 2 8 - 3702 + 3730 9 186 - 3702 + 3730 - 196 + 193 295 - 3702 + 3730 297 - 498 - 3702 + 495 + 3730 503 - 554 - 3702 + 555 + 3730 - 563 + 561 634 - 3702 + 3730 640 - 762 - 3702 + 758 + 4196 - 765 - 871 - 3702 + 768 + 877 + 3730 - 879 - 1081 - 3702 + 877 + 1076 + 3730 - 1083 - 1287 - 3702 + 1193 + 1290 + 3730 - 1311 - 1591 - 3702 + 1295 + 1686 + 3730 - 1689 - 2419 - 1851 + 1875 + 2418 + 1398 @@ -6193,67 +6188,67 @@ 1 2 - 5554 + 5595 2 - 6 - 3702 + 5 + 3730 - 6 + 5 65 - 3702 + 3730 70 100 - 3702 + 3730 100 111 - 3702 + 3730 112 122 - 3702 + 3730 122 134 - 3702 + 3730 139 152 - 3702 + 3730 152 160 - 3702 + 3730 160 171 - 3702 + 3730 171 175 - 3702 + 3730 176 192 - 3702 + 3730 207 298 - 1388 + 1398 @@ -6269,67 +6264,67 @@ 1 2 - 5554 + 5595 2 8 - 3702 + 3730 9 - 106 - 3702 + 105 + 3730 155 241 - 3702 + 3730 253 - 335 - 3702 + 336 + 3730 - 340 + 339 426 - 3702 + 3730 - 437 + 435 488 - 3702 + 3730 489 - 574 - 3702 + 572 + 3730 - 576 - 627 - 3702 + 573 + 623 + 3730 - 630 - 698 - 3702 + 628 + 696 + 4196 - 698 - 815 - 3702 + 701 + 816 + 3730 - 816 - 993 - 3702 + 836 + 1095 + 3730 - 1106 + 1163 1174 - 1388 + 932 @@ -6345,67 +6340,67 @@ 1 2 - 6017 + 6061 2 4 - 3702 + 3730 4 8 - 4165 + 4196 8 15 - 3702 + 3730 15 23 - 3702 + 3730 23 29 - 3702 + 3730 29 35 - 4165 + 4196 35 39 - 3239 + 3264 39 42 - 3702 + 3730 42 44 - 2777 + 2797 44 46 - 3702 + 3730 46 49 - 3702 + 3730 49 53 - 1388 + 1398 @@ -6421,67 +6416,67 @@ 1 2 - 5554 + 5595 2 8 - 3702 + 3730 9 156 - 3702 + 3730 159 240 - 3702 + 3730 251 - 334 - 3702 + 335 + 3730 - 342 + 341 430 - 3702 + 3730 - 435 + 433 490 - 3702 + 3730 490 - 575 - 3702 + 573 + 3730 - 575 - 626 - 3702 + 573 + 622 + 3730 - 630 - 701 - 3702 + 628 + 698 + 3730 - 701 - 811 - 3702 + 700 + 810 + 3730 - 813 - 992 - 3702 + 811 + 987 + 3730 - 1108 - 1181 - 1388 + 1096 + 1180 + 1398 @@ -6491,19 +6486,19 @@ locations_stmt - 3813507 + 3813678 id - 3813507 + 3813678 container - 3082 + 3083 startLine - 199837 + 199846 startColumn @@ -6511,7 +6506,7 @@ endLine - 194103 + 194112 endColumn @@ -6529,7 +6524,7 @@ 1 2 - 3813507 + 3813678 @@ -6545,7 +6540,7 @@ 1 2 - 3813507 + 3813678 @@ -6561,7 +6556,7 @@ 1 2 - 3813507 + 3813678 @@ -6577,7 +6572,7 @@ 1 2 - 3813507 + 3813678 @@ -6593,7 +6588,7 @@ 1 2 - 3813507 + 3813678 @@ -6994,37 +6989,37 @@ 1 2 - 21539 + 21540 2 3 - 15291 + 15292 3 4 - 12475 + 12476 4 6 - 14448 + 14449 6 8 - 12516 + 12517 8 11 - 16709 + 16710 11 16 - 17264 + 17265 16 @@ -7034,22 +7029,22 @@ 22 29 - 16976 + 16977 29 37 - 17367 + 17368 37 45 - 15085 + 15086 45 56 - 16175 + 16176 56 @@ -7070,7 +7065,7 @@ 1 2 - 22300 + 22301 2 @@ -7095,27 +7090,27 @@ 8 11 - 17572 + 17573 11 16 - 16360 + 16361 16 22 - 16216 + 16217 22 29 - 16956 + 16957 29 36 - 15990 + 15991 36 @@ -7125,7 +7120,7 @@ 44 54 - 15640 + 15641 54 @@ -7146,22 +7141,22 @@ 1 2 - 26821 + 26823 2 3 - 20840 + 20841 3 4 - 16812 + 16813 4 5 - 16072 + 16073 5 @@ -7171,22 +7166,22 @@ 6 7 - 19854 + 19855 7 8 - 22752 + 22753 8 9 - 20388 + 20389 9 10 - 15003 + 15004 10 @@ -7212,12 +7207,12 @@ 1 2 - 34590 + 34592 2 3 - 25794 + 25795 3 @@ -7227,7 +7222,7 @@ 4 5 - 16216 + 16217 5 @@ -7237,12 +7232,12 @@ 6 7 - 12023 + 12024 7 8 - 10173 + 10174 8 @@ -7252,7 +7247,7 @@ 9 10 - 10728 + 10729 10 @@ -7262,12 +7257,12 @@ 11 12 - 10173 + 10174 12 14 - 15784 + 15785 14 @@ -7288,27 +7283,27 @@ 1 2 - 22135 + 22136 2 3 - 16195 + 16196 3 4 - 12948 + 12949 4 6 - 16072 + 16073 6 8 - 14695 + 14696 8 @@ -7318,32 +7313,32 @@ 10 14 - 18292 + 18293 14 18 - 17017 + 17018 18 22 - 17572 + 17573 22 26 - 18497 + 18498 26 30 - 16380 + 16381 30 36 - 15229 + 15230 36 @@ -7734,12 +7729,12 @@ 1 2 - 17408 + 17409 2 3 - 14407 + 14408 3 @@ -7749,7 +7744,7 @@ 4 6 - 15599 + 15600 6 @@ -7759,12 +7754,12 @@ 8 11 - 15455 + 15456 11 15 - 14633 + 14634 15 @@ -7774,7 +7769,7 @@ 21 27 - 15414 + 15415 27 @@ -7784,17 +7779,17 @@ 34 42 - 15743 + 15744 42 52 - 16010 + 16011 52 130 - 14407 + 14408 @@ -7810,7 +7805,7 @@ 1 2 - 24951 + 24952 2 @@ -7820,47 +7815,47 @@ 3 4 - 12763 + 12764 4 6 - 15661 + 15662 6 8 - 15003 + 15004 8 11 - 15887 + 15888 11 16 - 17449 + 17450 16 20 - 14592 + 14593 20 26 - 17161 + 17162 26 32 - 16257 + 16258 32 39 - 14859 + 14860 39 @@ -7881,22 +7876,22 @@ 1 2 - 32473 + 32475 2 3 - 23759 + 23760 3 4 - 18456 + 18457 4 5 - 15147 + 15148 5 @@ -7911,32 +7906,32 @@ 7 8 - 11735 + 11736 8 9 - 10913 + 10914 9 10 - 10173 + 10174 10 12 - 17963 + 17964 12 15 - 17716 + 17717 15 100 - 10214 + 10215 @@ -7952,12 +7947,12 @@ 1 2 - 24951 + 24952 2 3 - 20388 + 20389 3 @@ -7967,7 +7962,7 @@ 4 5 - 17798 + 17799 5 @@ -7977,27 +7972,27 @@ 6 7 - 20429 + 20430 7 8 - 22423 + 22424 8 9 - 18744 + 18745 9 10 - 12927 + 12928 10 12 - 15024 + 15025 12 @@ -8018,12 +8013,12 @@ 1 2 - 24704 + 24705 2 3 - 16627 + 16628 3 @@ -8033,12 +8028,12 @@ 4 6 - 17819 + 17820 6 8 - 15332 + 15333 8 @@ -8048,32 +8043,32 @@ 10 13 - 14407 + 14408 13 16 - 15024 + 15025 16 19 - 14654 + 14655 19 22 - 14037 + 14038 22 26 - 17120 + 17121 26 31 - 15332 + 15333 31 @@ -8473,11 +8468,11 @@ locations_expr - 13165934 + 13166528 id - 13165934 + 13166528 container @@ -8485,7 +8480,7 @@ startLine - 191904 + 191913 startColumn @@ -8493,7 +8488,7 @@ endLine - 191883 + 191892 endColumn @@ -8511,7 +8506,7 @@ 1 2 - 13165934 + 13166528 @@ -8527,7 +8522,7 @@ 1 2 - 13165934 + 13166528 @@ -8543,7 +8538,7 @@ 1 2 - 13165934 + 13166528 @@ -8559,7 +8554,7 @@ 1 2 - 13165934 + 13166528 @@ -8575,7 +8570,7 @@ 1 2 - 13165934 + 13166528 @@ -8991,32 +8986,32 @@ 1 5 - 16113 + 16114 5 9 - 16483 + 16484 9 15 - 16031 + 16032 15 23 - 15106 + 15107 23 32 - 15147 + 15148 32 44 - 15003 + 15004 44 @@ -9026,17 +9021,17 @@ 60 80 - 14818 + 14819 80 103 - 14633 + 14634 103 130 - 14777 + 14778 130 @@ -9067,12 +9062,12 @@ 1 2 - 23512 + 23513 2 3 - 15620 + 15621 3 @@ -9082,27 +9077,27 @@ 4 6 - 16360 + 16361 6 8 - 13626 + 13627 8 11 - 16442 + 16443 11 16 - 17346 + 17347 16 21 - 16442 + 16443 21 @@ -9112,12 +9107,12 @@ 28 35 - 15805 + 15806 35 43 - 15846 + 15847 43 @@ -9138,12 +9133,12 @@ 1 4 - 15969 + 15970 4 7 - 17531 + 17532 7 @@ -9153,47 +9148,47 @@ 11 16 - 17408 + 17409 16 21 - 17511 + 17512 21 26 - 15065 + 15066 26 31 - 16175 + 16176 31 36 - 17716 + 17717 36 40 - 15702 + 15703 40 44 - 16298 + 16299 44 49 - 16894 + 16895 49 63 - 8940 + 8941 @@ -9209,17 +9204,17 @@ 1 2 - 101943 + 101948 2 3 - 44620 + 44622 3 4 - 27643 + 27645 4 @@ -9245,7 +9240,7 @@ 1 4 - 16956 + 16957 4 @@ -9255,32 +9250,32 @@ 7 11 - 16421 + 16422 11 16 - 16216 + 16217 16 21 - 16442 + 16443 21 27 - 16771 + 16772 27 33 - 16442 + 16443 33 38 - 14469 + 14470 38 @@ -9290,17 +9285,17 @@ 43 47 - 14695 + 14696 47 52 - 16771 + 16772 52 65 - 14448 + 14449 65 @@ -9711,37 +9706,37 @@ 5 9 - 16483 + 16484 9 15 - 15805 + 15806 15 23 - 15085 + 15086 23 32 - 15640 + 15641 32 44 - 14736 + 14737 44 60 - 14489 + 14490 60 80 - 15250 + 15251 80 @@ -9756,17 +9751,17 @@ 130 160 - 14880 + 14881 160 195 - 14551 + 14552 195 299 - 9536 + 9537 @@ -9782,12 +9777,12 @@ 1 2 - 23512 + 23513 2 3 - 15558 + 15559 3 @@ -9797,12 +9792,12 @@ 4 6 - 16051 + 16052 6 8 - 13482 + 13483 8 @@ -9817,7 +9812,7 @@ 15 20 - 16771 + 16772 20 @@ -9827,17 +9822,17 @@ 26 33 - 16051 + 16052 33 40 - 14633 + 14634 40 49 - 14592 + 14593 49 @@ -9858,22 +9853,22 @@ 1 2 - 95469 + 95473 2 3 - 50005 + 50007 3 4 - 29370 + 29371 4 6 - 15599 + 15600 6 @@ -9894,57 +9889,57 @@ 1 4 - 15825 + 15826 4 7 - 17449 + 17450 7 11 - 16483 + 16484 11 16 - 17346 + 17347 16 21 - 17305 + 17306 21 26 - 15147 + 15148 26 31 - 16298 + 16299 31 36 - 17675 + 17676 36 40 - 15291 + 15292 40 44 - 16442 + 16443 44 49 - 16976 + 16977 49 @@ -9965,17 +9960,17 @@ 1 4 - 17182 + 17183 4 7 - 16791 + 16792 7 11 - 16421 + 16422 11 @@ -9985,22 +9980,22 @@ 16 21 - 16010 + 16011 21 26 - 14510 + 14511 26 32 - 16154 + 16155 32 38 - 17490 + 17491 38 @@ -10010,12 +10005,12 @@ 43 47 - 14469 + 14470 47 52 - 16565 + 16566 52 @@ -10405,23 +10400,23 @@ numlines - 1383934 + 1382103 element_id - 1376992 + 1375109 num_lines - 100902 + 101652 num_code - 84239 + 84866 num_comment - 59245 + 59685 @@ -10435,12 +10430,12 @@ 1 2 - 1370049 + 1368114 2 3 - 6942 + 6994 @@ -10456,12 +10451,12 @@ 1 2 - 1370974 + 1369047 2 3 - 6017 + 6061 @@ -10477,7 +10472,7 @@ 1 2 - 1376992 + 1375109 @@ -10493,27 +10488,27 @@ 1 2 - 67576 + 68079 2 3 - 12034 + 12123 3 4 - 7405 + 7460 4 21 - 7868 + 7927 29 - 926 - 6017 + 921 + 6061 @@ -10529,27 +10524,27 @@ 1 2 - 69891 + 70410 2 3 - 12034 + 12123 3 4 - 8331 + 8393 4 6 - 9257 + 9325 6 7 - 1388 + 1398 @@ -10565,22 +10560,22 @@ 1 2 - 68965 + 69478 2 3 - 14811 + 14921 3 4 - 10645 + 10724 4 7 - 6479 + 6528 @@ -10596,27 +10591,27 @@ 1 2 - 52302 + 52691 2 3 - 14348 + 14455 3 5 - 6479 + 6528 5 42 - 6479 + 6528 44 - 927 - 4628 + 922 + 4662 @@ -10632,27 +10627,27 @@ 1 2 - 52302 + 52691 2 3 - 16662 + 16786 3 5 - 6017 + 6061 5 8 - 6479 + 6528 8 12 - 2777 + 2797 @@ -10668,27 +10663,27 @@ 1 2 - 52765 + 53157 2 3 - 15737 + 15854 3 5 - 7405 + 7460 5 7 - 5091 + 5129 7 10 - 3239 + 3264 @@ -10704,32 +10699,32 @@ 1 2 - 34251 + 34505 2 3 - 9257 + 9325 3 4 - 4165 + 4196 4 6 - 4628 + 4662 6 11 - 5091 + 5129 17 - 2622 - 1851 + 2596 + 1865 @@ -10745,32 +10740,32 @@ 1 2 - 34251 + 34505 2 3 - 9257 + 9325 3 4 - 4165 + 4196 4 6 - 4628 + 4662 6 8 - 4628 + 4662 10 38 - 2314 + 2331 @@ -10786,32 +10781,32 @@ 1 2 - 34251 + 34505 2 3 - 9257 + 9325 3 4 - 4165 + 4196 4 6 - 4628 + 4662 6 10 - 4628 + 4662 10 37 - 2314 + 2331 @@ -10821,11 +10816,11 @@ diagnostics - 72033 + 72036 id - 72033 + 72036 severity @@ -10841,7 +10836,7 @@ full_error_message - 62489 + 62491 location @@ -10859,7 +10854,7 @@ 1 2 - 72033 + 72036 @@ -10875,7 +10870,7 @@ 1 2 - 72033 + 72036 @@ -10891,7 +10886,7 @@ 1 2 - 72033 + 72036 @@ -10907,7 +10902,7 @@ 1 2 - 72033 + 72036 @@ -10923,7 +10918,7 @@ 1 2 - 72033 + 72036 @@ -11319,7 +11314,7 @@ 1 2 - 62477 + 62480 829 @@ -11340,7 +11335,7 @@ 1 2 - 62489 + 62491 @@ -11356,7 +11351,7 @@ 1 2 - 62489 + 62491 @@ -11372,7 +11367,7 @@ 1 2 - 62489 + 62491 @@ -11388,7 +11383,7 @@ 1 2 - 62489 + 62491 @@ -11498,15 +11493,15 @@ files - 122193 + 123102 id - 122193 + 123102 name - 122193 + 123102 @@ -11520,7 +11515,7 @@ 1 2 - 122193 + 123102 @@ -11536,7 +11531,7 @@ 1 2 - 122193 + 123102 @@ -11546,15 +11541,15 @@ folders - 15274 + 15387 id - 15274 + 15387 name - 15274 + 15387 @@ -11568,7 +11563,7 @@ 1 2 - 15274 + 15387 @@ -11584,7 +11579,7 @@ 1 2 - 15274 + 15387 @@ -11594,15 +11589,15 @@ containerparent - 136542 + 137557 parent - 15274 + 15387 child - 136542 + 137557 @@ -11616,32 +11611,32 @@ 1 2 - 6479 + 6528 2 3 - 3239 + 3264 3 5 - 1388 + 1398 5 12 - 1388 + 1398 23 28 - 1388 + 1398 40 67 - 1388 + 1398 @@ -11657,7 +11652,7 @@ 1 2 - 136542 + 137557 @@ -11667,11 +11662,11 @@ fileannotations - 5237780 + 5238006 id - 5002 + 5003 kind @@ -11679,11 +11674,11 @@ name - 55930 + 55932 value - 47019 + 47021 @@ -11702,7 +11697,7 @@ 2 3 - 4829 + 4830 @@ -11918,7 +11913,7 @@ 1 2 - 9048 + 9049 2 @@ -11989,7 +11984,7 @@ 1 2 - 55930 + 55932 @@ -12020,12 +12015,12 @@ 4 6 - 4610 + 4611 6 9 - 4218 + 4219 9 @@ -12035,7 +12030,7 @@ 14 17 - 4218 + 4219 17 @@ -12055,7 +12050,7 @@ 82 157 - 4195 + 4196 158 @@ -12126,7 +12121,7 @@ 266 321 - 3757 + 3758 322 @@ -12152,7 +12147,7 @@ 1 2 - 47007 + 47010 2 @@ -12183,7 +12178,7 @@ 5 8 - 3584 + 3585 8 @@ -12203,7 +12198,7 @@ 19 29 - 3584 + 3585 29 @@ -12243,15 +12238,15 @@ inmacroexpansion - 109604513 + 109609474 id - 17998714 + 17999527 inv - 2695879 + 2696000 @@ -12265,37 +12260,37 @@ 1 3 - 1579476 + 1579546 3 5 - 1076083 + 1076132 5 6 - 1182998 + 1183051 6 7 - 4812255 + 4812473 7 8 - 6375799 + 6376088 8 9 - 2601108 + 2601226 9 21 - 370992 + 371008 @@ -12311,57 +12306,57 @@ 1 2 - 377826 + 377842 2 3 - 543242 + 543265 3 4 - 350956 + 350972 4 7 - 200341 + 200350 7 8 - 206822 + 206832 8 9 - 241503 + 241514 9 10 - 2206 + 2207 10 11 - 324968 + 324983 11 337 - 224489 + 224500 339 423 - 206025 + 206034 423 7616 - 17496 + 17497 @@ -12371,15 +12366,15 @@ affectedbymacroexpansion - 35632303 + 35633915 id - 5148541 + 5148773 inv - 2780346 + 2780470 @@ -12393,37 +12388,37 @@ 1 2 - 2811453 + 2811579 2 3 - 559241 + 559267 3 4 - 264485 + 264497 4 5 - 564894 + 564919 5 12 - 391280 + 391297 12 50 - 406753 + 406771 50 9900 - 150433 + 150439 @@ -12439,67 +12434,67 @@ 1 4 - 228755 + 228764 4 7 - 231419 + 231430 7 9 - 220127 + 220137 9 12 - 250688 + 250699 12 13 - 333446 + 333461 13 14 - 165325 + 165332 14 15 - 298368 + 298382 15 16 - 121649 + 121654 16 17 - 276168 + 276181 17 18 - 146706 + 146713 18 20 - 251734 + 251745 20 25 - 208646 + 208656 25 109 - 47308 + 47310 @@ -12509,19 +12504,19 @@ macroinvocations - 34146427 + 34192813 id - 34146427 + 34192813 macro_id - 81163 + 81166 location - 776449 + 776483 kind @@ -12539,7 +12534,7 @@ 1 2 - 34146427 + 34192813 @@ -12555,7 +12550,7 @@ 1 2 - 34146427 + 34192813 @@ -12571,7 +12566,7 @@ 1 2 - 34146427 + 34192813 @@ -12587,12 +12582,12 @@ 1 2 - 16645 + 16599 2 3 - 16979 + 16922 3 @@ -12602,22 +12597,22 @@ 4 5 - 5348 + 5383 5 8 - 5890 + 5809 8 13 - 6259 + 6236 13 26 - 6282 + 6328 26 @@ -12626,18 +12621,18 @@ 61 - 205 - 6132 + 200 + 6098 - 205 - 1780 - 6109 + 200 + 1697 + 6121 - 1780 - 168526 - 2144 + 1716 + 168807 + 2294 @@ -12653,17 +12648,17 @@ 1 2 - 43365 + 43367 2 3 - 10616 + 10617 3 4 - 5267 + 5268 4 @@ -12699,12 +12694,12 @@ 1 2 - 75307 + 75310 2 3 - 5855 + 5856 @@ -12720,37 +12715,37 @@ 1 2 - 288503 + 287189 2 3 - 173542 + 173515 3 4 - 72460 + 72935 4 5 - 61036 + 60981 5 9 - 71745 + 71656 9 21 - 59365 + 60186 21 - 244557 - 49797 + 244764 + 50018 @@ -12766,12 +12761,12 @@ 1 2 - 729303 + 729335 2 350 - 47146 + 47148 @@ -12787,7 +12782,7 @@ 1 2 - 776449 + 776483 @@ -12806,8 +12801,8 @@ 11 - 2941582 - 2941583 + 2945478 + 2945479 11 @@ -12860,15 +12855,15 @@ macroparent - 30546697 + 30581550 id - 30546697 + 30581550 parent_id - 23742230 + 23776789 @@ -12882,7 +12877,7 @@ 1 2 - 30546697 + 30581550 @@ -12898,17 +12893,17 @@ 1 2 - 18336209 + 18370535 2 3 - 4553733 + 4553929 3 88 - 852287 + 852324 @@ -12918,15 +12913,15 @@ macrolocationbind - 4036713 + 4036895 id - 2826088 + 2826216 location - 2017695 + 2017786 @@ -12940,22 +12935,22 @@ 1 2 - 2225864 + 2225964 2 3 - 340555 + 340571 3 7 - 230140 + 230151 7 57 - 29527 + 29529 @@ -12971,22 +12966,22 @@ 1 2 - 1608335 + 1608407 2 3 - 177385 + 177393 3 8 - 156613 + 156621 8 723 - 75360 + 75364 @@ -12996,11 +12991,11 @@ macro_argument_unexpanded - 86236355 + 86329774 invocation - 26718268 + 26761716 argument_index @@ -13008,7 +13003,7 @@ text - 325032 + 325046 @@ -13022,22 +13017,22 @@ 1 2 - 7569459 + 7582881 2 3 - 10882564 + 10899357 3 4 - 6258953 + 6268860 4 67 - 2007291 + 2010617 @@ -13053,22 +13048,22 @@ 1 2 - 7640455 + 7654526 2 3 - 11032487 + 11049010 3 4 - 6089388 + 6099011 4 67 - 1955937 + 1959168 @@ -13088,12 +13083,12 @@ 41432 - 174136 + 174417 57 - 717107 - 2317844 + 718224 + 2321513 34 @@ -13136,57 +13131,57 @@ 1 2 - 37325 + 35816 2 3 - 64644 + 62756 3 4 - 16979 + 19412 4 5 - 45786 + 44773 5 - 8 - 25521 + 7 + 24427 - 8 + 7 12 - 16218 + 18790 12 16 - 21855 + 22006 16 23 - 25671 + 25614 23 42 - 24506 + 24703 42 129 - 24391 + 24588 129 - 522100 - 22132 + 522415 + 22156 @@ -13202,12 +13197,12 @@ 1 2 - 235062 + 235073 2 3 - 79468 + 79472 3 @@ -13222,11 +13217,11 @@ macro_argument_expanded - 86236355 + 86329774 invocation - 26718268 + 26761716 argument_index @@ -13234,7 +13229,7 @@ text - 196977 + 196985 @@ -13248,22 +13243,22 @@ 1 2 - 7569459 + 7582881 2 3 - 10882564 + 10899357 3 4 - 6258953 + 6268860 4 67 - 2007291 + 2010617 @@ -13279,22 +13274,22 @@ 1 2 - 10891544 + 10908372 2 3 - 9380960 + 9395798 3 4 - 5309284 + 5318101 4 9 - 1136479 + 1139444 @@ -13314,12 +13309,12 @@ 41432 - 174136 + 174417 57 - 717107 - 2317844 + 718224 + 2321513 34 @@ -13362,62 +13357,62 @@ 1 2 - 22016 + 21234 2 3 - 39745 + 38295 3 4 - 8875 + 10340 4 5 - 16818 + 15712 5 6 - 3054 + 3539 6 7 - 22720 + 22352 7 - 10 - 16149 + 9 + 14847 - 10 - 15 - 15769 + 9 + 14 + 12622 - 15 - 27 - 14939 + 14 + 20 + 14986 - 27 - 73 - 14893 + 20 + 49 + 15666 - 73 - 361 - 14835 + 49 + 169 + 14790 - 363 - 1059615 - 7158 + 169 + 1060455 + 12599 @@ -13433,17 +13428,17 @@ 1 2 - 99687 + 99691 2 3 - 82580 + 82584 3 66 - 14708 + 14709 @@ -13453,19 +13448,19 @@ functions - 4634561 + 4638253 id - 4634561 + 4638253 name - 1902794 + 1916013 kind - 3239 + 3264 @@ -13479,7 +13474,7 @@ 1 2 - 4634561 + 4638253 @@ -13495,7 +13490,7 @@ 1 2 - 4634561 + 4638253 @@ -13511,22 +13506,22 @@ 1 2 - 1492705 + 1503340 2 3 - 151353 + 152479 3 5 - 149501 + 150147 5 - 1692 - 109233 + 1666 + 110046 @@ -13542,12 +13537,12 @@ 1 2 - 1902331 + 1915546 2 3 - 462 + 466 @@ -13563,37 +13558,37 @@ 6 7 - 462 + 466 64 65 - 462 + 466 173 174 - 462 + 466 195 196 - 462 + 466 - 1355 - 1356 - 462 + 1350 + 1351 + 466 - 2400 - 2401 - 462 + 2372 + 2373 + 466 - 5820 - 5821 - 462 + 5787 + 5788 + 466 @@ -13609,37 +13604,37 @@ 3 4 - 462 + 466 33 34 - 462 + 466 39 40 - 462 + 466 94 95 - 462 + 466 195 196 - 462 + 466 243 244 - 462 + 466 - 3505 - 3506 - 462 + 3503 + 3504 + 466 @@ -13649,15 +13644,15 @@ function_entry_point - 1158061 + 1156415 id - 1148341 + 1146623 entry_point - 1158061 + 1156415 @@ -13671,12 +13666,12 @@ 1 2 - 1138622 + 1136831 2 3 - 9719 + 9792 @@ -13692,7 +13687,7 @@ 1 2 - 1158061 + 1156415 @@ -13702,15 +13697,15 @@ function_return_type - 4639653 + 4643382 id - 4634561 + 4638253 return_type - 990971 + 984818 @@ -13724,12 +13719,12 @@ 1 2 - 4629470 + 4633124 2 3 - 5091 + 5129 @@ -13745,22 +13740,22 @@ 1 2 - 512842 + 510128 2 3 - 376763 + 373503 3 10 - 74519 + 75073 10 - 2513 - 26845 + 2512 + 26112 @@ -13778,7 +13773,7 @@ traits - 2 + 1 handle @@ -13846,9 +13841,9 @@ 12 - 1 - 2 - 2 + 2 + 3 + 1 @@ -13862,9 +13857,9 @@ 12 - 1 - 2 - 2 + 2 + 3 + 1 @@ -13878,9 +13873,9 @@ 12 - 1 - 2 - 2 + 2 + 3 + 1 @@ -14082,48 +14077,48 @@ purefunctions - 100048 + 100053 id - 100048 + 100053 function_deleted - 138393 + 137557 id - 138393 + 137557 function_defaulted - 73131 + 73674 id - 73131 + 73674 member_function_this_type - 553553 + 553568 id - 553553 + 553568 this_type - 189963 + 189968 @@ -14137,7 +14132,7 @@ 1 2 - 553553 + 553568 @@ -14153,22 +14148,22 @@ 1 2 - 68554 + 68556 2 3 - 45514 + 45516 3 4 - 30554 + 30555 4 5 - 15559 + 15560 5 @@ -14178,7 +14173,7 @@ 7 66 - 14183 + 14184 @@ -14188,27 +14183,27 @@ fun_decls - 5000679 + 5007094 id - 4995588 + 5001965 function - 4492002 + 4494634 type_id - 989582 + 983419 name - 1806058 + 1818557 location - 3404294 + 3416556 @@ -14222,7 +14217,7 @@ 1 2 - 4995588 + 5001965 @@ -14238,12 +14233,12 @@ 1 2 - 4990497 + 4996835 2 3 - 5091 + 5129 @@ -14259,7 +14254,7 @@ 1 2 - 4995588 + 5001965 @@ -14275,7 +14270,7 @@ 1 2 - 4995588 + 5001965 @@ -14291,17 +14286,17 @@ 1 2 - 4066639 + 4066107 2 3 - 353157 + 355784 3 7 - 72205 + 72742 @@ -14317,12 +14312,12 @@ 1 2 - 4452660 + 4454998 2 3 - 39342 + 39635 @@ -14338,7 +14333,7 @@ 1 2 - 4492002 + 4494634 @@ -14354,17 +14349,17 @@ 1 2 - 4122644 + 4122529 2 4 - 368432 + 371172 5 6 - 925 + 932 @@ -14380,22 +14375,22 @@ 1 2 - 438786 + 435521 2 3 - 438786 + 435987 3 8 - 74519 + 75073 8 - 2758 - 37491 + 2757 + 36837 @@ -14411,22 +14406,22 @@ 1 2 - 522099 + 519454 2 3 - 368432 + 365110 3 11 - 75908 + 75540 11 - 2474 - 23142 + 2473 + 23314 @@ -14442,17 +14437,17 @@ 1 2 - 862297 + 856120 2 5 - 88868 + 89528 5 821 - 38416 + 37770 @@ -14468,22 +14463,22 @@ 1 2 - 759544 + 752136 2 3 - 130987 + 131495 3 - 11 - 76833 + 10 + 74607 - 11 - 2029 - 22217 + 10 + 2028 + 25180 @@ -14499,27 +14494,27 @@ 1 2 - 1225175 + 1233821 2 3 - 265215 + 267188 3 4 - 79148 + 80203 4 6 - 136542 + 136624 6 - 1726 - 99976 + 1700 + 100720 @@ -14535,22 +14530,22 @@ 1 2 - 1402911 + 1412879 2 3 - 150427 + 151546 3 5 - 143484 + 144085 5 - 1676 - 109233 + 1650 + 110046 @@ -14566,17 +14561,17 @@ 1 2 - 1589442 + 1600796 2 4 - 132839 + 134293 4 - 938 - 83776 + 925 + 83467 @@ -14592,27 +14587,27 @@ 1 2 - 1246004 + 1254804 2 3 - 291598 + 293766 3 4 - 78222 + 79270 4 8 - 137004 + 137557 8 - 661 - 53228 + 651 + 53157 @@ -14628,17 +14623,17 @@ 1 2 - 2947457 + 2961450 2 4 - 297152 + 295165 4 55 - 159684 + 159939 @@ -14654,17 +14649,17 @@ 1 2 - 3014108 + 3028597 2 6 - 264289 + 261592 6 55 - 125896 + 126366 @@ -14680,12 +14675,12 @@ 1 2 - 3193695 + 3207655 2 - 27 - 210598 + 25 + 208900 @@ -14701,12 +14696,12 @@ 1 2 - 3231650 + 3245425 2 13 - 172644 + 171130 @@ -14716,22 +14711,22 @@ fun_def - 1932417 + 1934665 id - 1932417 + 1934665 fun_specialized - 25919 + 26112 id - 25919 + 26112 @@ -14749,15 +14744,15 @@ fun_decl_specifiers - 2890063 + 2903163 id - 1683401 + 1687527 name - 2777 + 2797 @@ -14771,17 +14766,17 @@ 1 2 - 495254 + 490544 2 3 - 1169633 + 1178331 3 4 - 18514 + 18651 @@ -14797,32 +14792,32 @@ 50 51 - 462 + 466 203 204 - 462 + 466 209 210 - 462 + 466 - 657 - 658 - 462 + 639 + 640 + 466 2561 2562 - 462 + 466 2564 2565 - 462 + 466 @@ -14953,26 +14948,26 @@ fun_decl_empty_throws - 1926863 + 1926738 fun_decl - 1926863 + 1926738 fun_decl_noexcept - 61185 + 61190 fun_decl - 61185 + 61190 constant - 61080 + 61086 @@ -14986,7 +14981,7 @@ 1 2 - 61185 + 61190 @@ -15002,7 +14997,7 @@ 1 2 - 60976 + 60981 2 @@ -15017,11 +15012,11 @@ fun_decl_empty_noexcept - 874794 + 869643 fun_decl - 874794 + 869643 @@ -15126,19 +15121,19 @@ param_decl_bind - 7337169 + 7373083 id - 7337169 + 7373083 index - 7868 + 7927 fun_decl - 4202718 + 4217187 @@ -15152,7 +15147,7 @@ 1 2 - 7337169 + 7373083 @@ -15168,7 +15163,7 @@ 1 2 - 7337169 + 7373083 @@ -15184,72 +15179,72 @@ 2 3 - 925 + 932 5 6 - 462 + 466 7 8 - 462 + 466 10 11 - 925 + 932 11 12 - 462 + 466 12 13 - 925 + 932 13 14 - 462 + 466 25 26 - 462 + 466 78 79 - 462 + 466 245 246 - 462 + 466 636 637 - 462 + 466 1713 1714 - 462 + 466 - 3991 - 3992 - 462 + 3987 + 3988 + 466 - 9080 - 9081 - 462 + 9044 + 9045 + 466 @@ -15265,72 +15260,72 @@ 2 3 - 925 + 932 5 6 - 462 + 466 7 8 - 462 + 466 10 11 - 925 + 932 11 12 - 462 + 466 12 13 - 925 + 932 13 14 - 462 + 466 25 26 - 462 + 466 78 79 - 462 + 466 245 246 - 462 + 466 636 637 - 462 + 466 1713 1714 - 462 + 466 - 3991 - 3992 - 462 + 3987 + 3988 + 466 - 9080 - 9081 - 462 + 9044 + 9045 + 466 @@ -15346,22 +15341,22 @@ 1 2 - 2355466 + 2358062 2 3 - 1054382 + 1060358 3 4 - 498494 + 502201 4 18 - 294375 + 296564 @@ -15377,22 +15372,22 @@ 1 2 - 2355466 + 2358062 2 3 - 1054382 + 1060358 3 4 - 498494 + 502201 4 18 - 294375 + 296564 @@ -15402,27 +15397,27 @@ var_decls - 8461442 + 8487066 id - 8393866 + 8416189 variable - 7390397 + 7405258 type_id - 2376757 + 2379045 name - 661881 + 666804 location - 5278855 + 5305524 @@ -15436,7 +15431,7 @@ 1 2 - 8393866 + 8416189 @@ -15452,12 +15447,12 @@ 1 2 - 8326289 + 8348110 2 3 - 67576 + 68079 @@ -15473,7 +15468,7 @@ 1 2 - 8393866 + 8416189 @@ -15489,7 +15484,12 @@ 1 2 - 8393866 + 8413391 + + + 2 + 3 + 2797 @@ -15505,17 +15505,17 @@ 1 2 - 6545688 + 6554266 2 3 - 692430 + 697579 3 7 - 152279 + 153411 @@ -15531,12 +15531,12 @@ 1 2 - 7220530 + 7234127 2 4 - 169867 + 171130 @@ -15552,12 +15552,12 @@ 1 2 - 7276072 + 7290083 2 3 - 114325 + 115175 @@ -15573,12 +15573,12 @@ 1 2 - 6849783 + 6860623 2 4 - 540614 + 544634 @@ -15594,27 +15594,27 @@ 1 2 - 1466323 + 1464171 2 3 - 507751 + 509196 3 4 - 97199 + 97922 4 7 - 185604 + 186984 7 - 780 - 119879 + 762 + 120770 @@ -15630,22 +15630,22 @@ 1 2 - 1598699 + 1597532 2 3 - 483220 + 484482 3 7 - 185141 + 186518 7 - 742 - 109696 + 724 + 110512 @@ -15661,17 +15661,17 @@ 1 2 - 1873172 + 1872181 2 3 - 382317 + 384694 3 128 - 121267 + 122169 @@ -15687,22 +15687,22 @@ 1 2 - 1700990 + 1700117 2 3 - 400369 + 401481 3 8 - 186993 + 188383 8 - 595 - 88405 + 592 + 89062 @@ -15718,37 +15718,37 @@ 1 2 - 338346 + 340862 2 3 - 86090 + 86731 3 4 - 48136 + 48494 4 6 - 51376 + 51758 6 12 - 51839 + 52225 12 33 - 49988 + 50360 34 - 3249 - 36102 + 3213 + 36371 @@ -15764,37 +15764,37 @@ 1 2 - 365655 + 368374 2 3 - 77296 + 77871 3 4 - 44896 + 45230 4 6 - 49062 + 49427 6 14 - 52765 + 53157 14 56 - 50451 + 50826 56 - 3166 - 21754 + 3130 + 21915 @@ -15810,27 +15810,27 @@ 1 2 - 453134 + 456504 2 3 - 93033 + 93725 3 5 - 46285 + 46629 5 19 - 50451 + 50826 19 - 1947 - 18977 + 1917 + 19118 @@ -15846,32 +15846,32 @@ 1 2 - 375837 + 378632 2 3 - 89793 + 90461 3 5 - 59245 + 59685 5 9 - 50913 + 51292 9 21 - 49988 + 50360 21 - 1020 - 36102 + 1010 + 36371 @@ -15887,17 +15887,17 @@ 1 2 - 4462842 + 4490903 2 3 - 541539 + 531111 3 - 1751 - 274472 + 1725 + 283508 @@ -15913,17 +15913,17 @@ 1 2 - 4860434 + 4879795 2 17 - 407311 + 415004 17 - 1747 - 11108 + 1721 + 10724 @@ -15939,12 +15939,12 @@ 1 2 - 4935880 + 4955801 2 - 1529 - 342975 + 1503 + 349722 @@ -15960,12 +15960,12 @@ 1 2 - 5274689 + 5296198 2 - 24 - 4165 + 6 + 9325 @@ -15975,26 +15975,26 @@ var_def - 4020816 + 4023674 id - 4020816 + 4023674 var_decl_specifiers - 329552 + 310553 id - 329552 + 310553 name - 1388 + 1398 @@ -16008,7 +16008,7 @@ 1 2 - 329552 + 310553 @@ -16024,17 +16024,17 @@ 15 16 - 462 + 466 66 67 - 462 + 466 - 631 - 632 - 462 + 585 + 586 + 466 @@ -16055,19 +16055,19 @@ type_decls - 3242758 + 3241228 id - 3242758 + 3241228 type_id - 3192770 + 3190868 location - 3164073 + 3162424 @@ -16081,7 +16081,7 @@ 1 2 - 3242758 + 3241228 @@ -16097,7 +16097,7 @@ 1 2 - 3242758 + 3241228 @@ -16113,12 +16113,12 @@ 1 2 - 3151576 + 3149368 2 5 - 41194 + 41500 @@ -16134,12 +16134,12 @@ 1 2 - 3151576 + 3149368 2 5 - 41194 + 41500 @@ -16155,12 +16155,12 @@ 1 2 - 3123804 + 3122322 2 20 - 40268 + 40101 @@ -16176,12 +16176,12 @@ 1 2 - 3123804 + 3122322 2 20 - 40268 + 40101 @@ -16191,45 +16191,45 @@ type_def - 2627162 + 2623851 id - 2627162 + 2623851 type_decl_top - 746121 + 742810 type_decl - 746121 + 742810 namespace_decls - 308849 + 308863 id - 308849 + 308863 namespace_id - 1415 + 1416 location - 308849 + 308863 bodylocation - 308849 + 308863 @@ -16243,7 +16243,7 @@ 1 2 - 308849 + 308863 @@ -16259,7 +16259,7 @@ 1 2 - 308849 + 308863 @@ -16275,7 +16275,7 @@ 1 2 - 308849 + 308863 @@ -16489,7 +16489,7 @@ 1 2 - 308849 + 308863 @@ -16505,7 +16505,7 @@ 1 2 - 308849 + 308863 @@ -16521,7 +16521,7 @@ 1 2 - 308849 + 308863 @@ -16537,7 +16537,7 @@ 1 2 - 308849 + 308863 @@ -16553,7 +16553,7 @@ 1 2 - 308849 + 308863 @@ -16569,7 +16569,7 @@ 1 2 - 308849 + 308863 @@ -16579,19 +16579,19 @@ usings - 369357 + 369307 id - 369357 + 369307 element_id - 313815 + 315216 location - 246238 + 247603 @@ -16605,7 +16605,7 @@ 1 2 - 369357 + 369307 @@ -16621,7 +16621,7 @@ 1 2 - 369357 + 369307 @@ -16637,17 +16637,17 @@ 1 2 - 260124 + 262991 2 3 - 52302 + 50826 3 5 - 1388 + 1398 @@ -16663,17 +16663,17 @@ 1 2 - 260124 + 262991 2 3 - 52302 + 50826 3 5 - 1388 + 1398 @@ -16689,22 +16689,22 @@ 1 2 - 200878 + 202372 2 4 - 11108 + 10724 4 5 - 31011 + 31241 5 11 - 3239 + 3264 @@ -16720,22 +16720,22 @@ 1 2 - 200878 + 202372 2 4 - 11108 + 10724 4 5 - 31011 + 31241 5 11 - 3239 + 3264 @@ -16745,7 +16745,7 @@ using_container - 476661 + 476682 parent @@ -16753,7 +16753,7 @@ child - 302243 + 302256 @@ -16767,7 +16767,7 @@ 1 2 - 3365 + 3366 2 @@ -16823,17 +16823,17 @@ 1 2 - 222924 + 222934 2 3 - 52817 + 52819 3 11 - 24322 + 24323 13 @@ -16848,19 +16848,19 @@ static_asserts - 130539 + 130544 id - 130539 + 130544 condition - 130539 + 130544 message - 29483 + 29484 location @@ -16882,7 +16882,7 @@ 1 2 - 130539 + 130544 @@ -16898,7 +16898,7 @@ 1 2 - 130539 + 130544 @@ -16914,7 +16914,7 @@ 1 2 - 130539 + 130544 @@ -16930,7 +16930,7 @@ 1 2 - 130539 + 130544 @@ -16946,7 +16946,7 @@ 1 2 - 130539 + 130544 @@ -16962,7 +16962,7 @@ 1 2 - 130539 + 130544 @@ -16978,7 +16978,7 @@ 1 2 - 130539 + 130544 @@ -16994,7 +16994,7 @@ 1 2 - 130539 + 130544 @@ -17010,7 +17010,7 @@ 1 2 - 21969 + 21970 2 @@ -17020,7 +17020,7 @@ 3 4 - 2768 + 2769 4 @@ -17051,7 +17051,7 @@ 1 2 - 21969 + 21970 2 @@ -17061,7 +17061,7 @@ 3 4 - 2768 + 2769 4 @@ -17092,7 +17092,7 @@ 1 2 - 27368 + 27370 2 @@ -17113,7 +17113,7 @@ 1 2 - 23385 + 23386 2 @@ -17149,7 +17149,7 @@ 1 2 - 3133 + 3134 2 @@ -17159,12 +17159,12 @@ 3 4 - 1308 + 1309 5 6 - 3624 + 3625 6 @@ -17205,7 +17205,7 @@ 1 2 - 3133 + 3134 2 @@ -17215,12 +17215,12 @@ 3 4 - 1308 + 1309 5 6 - 3624 + 3625 6 @@ -17271,7 +17271,7 @@ 3 4 - 6028 + 6029 4 @@ -17297,7 +17297,7 @@ 2 3 - 6116 + 6117 3 @@ -17466,23 +17466,23 @@ params - 6702132 + 6733324 id - 6539671 + 6569654 function - 3862057 + 3873993 index - 7868 + 7927 type_id - 2182821 + 2183667 @@ -17496,7 +17496,7 @@ 1 2 - 6539671 + 6569654 @@ -17512,7 +17512,7 @@ 1 2 - 6539671 + 6569654 @@ -17528,12 +17528,12 @@ 1 2 - 6417014 + 6446086 2 4 - 122656 + 123568 @@ -17549,22 +17549,22 @@ 1 2 - 2249935 + 2251746 2 3 - 946537 + 951711 3 4 - 426288 + 429459 4 18 - 239295 + 241075 @@ -17580,22 +17580,22 @@ 1 2 - 2249935 + 2251746 2 3 - 946537 + 951711 3 4 - 426288 + 429459 4 18 - 239295 + 241075 @@ -17611,22 +17611,22 @@ 1 2 - 2547551 + 2549710 2 3 - 819715 + 825811 3 4 - 343438 + 345992 4 12 - 151353 + 152479 @@ -17642,72 +17642,72 @@ 2 3 - 925 + 932 4 5 - 462 + 466 6 7 - 462 + 466 8 9 - 925 + 932 9 10 - 462 + 466 10 11 - 925 + 932 11 12 - 462 + 466 19 20 - 462 + 466 64 65 - 462 + 466 194 195 - 462 + 466 517 518 - 462 + 466 1438 1439 - 462 + 466 - 3483 - 3484 - 462 + 3479 + 3480 + 466 - 8344 - 8345 - 462 + 8308 + 8309 + 466 @@ -17723,72 +17723,72 @@ 2 3 - 925 + 932 4 5 - 462 + 466 6 7 - 462 + 466 8 9 - 925 + 932 9 10 - 462 + 466 10 11 - 925 + 932 11 12 - 462 + 466 19 20 - 462 + 466 64 65 - 462 + 466 194 195 - 462 + 466 517 518 - 462 + 466 1438 1439 - 462 + 466 - 3483 - 3484 - 462 + 3479 + 3480 + 466 - 8344 - 8345 - 462 + 8308 + 8309 + 466 @@ -17804,67 +17804,67 @@ 1 2 - 925 + 932 3 4 - 462 + 466 4 5 - 462 + 466 5 6 - 462 + 466 6 7 - 1388 + 1398 7 8 - 925 + 932 11 12 - 462 + 466 42 43 - 462 + 466 106 107 - 462 + 466 228 229 - 462 + 466 582 583 - 462 + 466 - 1275 - 1276 - 462 + 1271 + 1272 + 466 - 3632 - 3633 - 462 + 3599 + 3600 + 466 @@ -17880,22 +17880,22 @@ 1 2 - 1485300 + 1483289 2 3 - 439248 + 440184 3 8 - 168941 + 170198 8 - 520 - 89330 + 518 + 89995 @@ -17911,22 +17911,22 @@ 1 2 - 1705155 + 1702915 2 3 - 246701 + 248069 3 9 - 167090 + 168333 9 - 504 - 63873 + 502 + 64348 @@ -17942,17 +17942,17 @@ 1 2 - 1756995 + 1756539 2 3 - 347603 + 348323 3 13 - 78222 + 78804 @@ -17962,15 +17962,15 @@ overrides - 159972 + 159979 new - 125139 + 125145 old - 15109 + 15110 @@ -17984,12 +17984,12 @@ 1 2 - 90313 + 90317 2 3 - 34820 + 34821 3 @@ -18050,19 +18050,19 @@ membervariables - 1054731 + 1054778 id - 1052936 + 1052983 type_id - 327180 + 327195 name - 450865 + 450885 @@ -18076,7 +18076,7 @@ 1 2 - 1051221 + 1051268 2 @@ -18097,7 +18097,7 @@ 1 2 - 1052936 + 1052983 @@ -18113,17 +18113,17 @@ 1 2 - 242623 + 242634 2 3 - 51811 + 51813 3 10 - 25486 + 25487 10 @@ -18144,22 +18144,22 @@ 1 2 - 254828 + 254839 2 3 - 46386 + 46388 3 40 - 24569 + 24570 41 2031 - 1395 + 1396 @@ -18175,22 +18175,22 @@ 1 2 - 294833 + 294846 2 3 - 86391 + 86395 3 5 - 41121 + 41123 5 646 - 28518 + 28519 @@ -18206,17 +18206,17 @@ 1 2 - 367225 + 367242 2 3 - 51651 + 51654 3 650 - 31988 + 31989 @@ -18226,11 +18226,11 @@ globalvariables - 301278 + 301284 id - 301270 + 301276 type_id @@ -18238,7 +18238,7 @@ name - 294738 + 294744 @@ -18252,7 +18252,7 @@ 1 2 - 301262 + 301268 2 @@ -18273,7 +18273,7 @@ 1 2 - 301270 + 301276 @@ -18299,17 +18299,17 @@ 3 7 - 117 + 116 7 - 68 + 67 106 - 76 + 67 169440 - 50 + 51 @@ -18335,17 +18335,17 @@ 3 7 - 112 + 111 7 - 105 + 102 106 - 106 + 104 168448 - 42 + 43 @@ -18361,7 +18361,7 @@ 1 2 - 290721 + 290727 2 @@ -18382,7 +18382,7 @@ 1 2 - 294139 + 294145 2 @@ -18397,19 +18397,19 @@ localvariables - 581183 + 581207 id - 581183 + 581207 type_id - 37872 + 37873 name - 91323 + 91326 @@ -18423,7 +18423,7 @@ 1 2 - 581183 + 581207 @@ -18439,7 +18439,7 @@ 1 2 - 581183 + 581207 @@ -18455,7 +18455,7 @@ 1 2 - 21188 + 21189 2 @@ -18496,7 +18496,7 @@ 1 2 - 26975 + 26976 2 @@ -18532,7 +18532,7 @@ 1 2 - 57519 + 57522 2 @@ -18547,7 +18547,7 @@ 5 15 - 7041 + 7042 15 @@ -18568,7 +18568,7 @@ 1 2 - 77146 + 77150 2 @@ -18578,7 +18578,7 @@ 3 1486 - 6701 + 6702 @@ -18588,11 +18588,11 @@ autoderivation - 149355 + 149368 var - 149355 + 149368 derivation_type @@ -18610,7 +18610,7 @@ 1 2 - 149355 + 149368 @@ -18656,11 +18656,11 @@ orphaned_variables - 37893 + 37894 var - 37893 + 37894 function @@ -18678,7 +18678,7 @@ 1 2 - 37893 + 37894 @@ -18694,7 +18694,7 @@ 1 2 - 31225 + 31226 2 @@ -18709,19 +18709,19 @@ enumconstants - 241267 + 241278 id - 241267 + 241278 parent - 28478 + 28479 index - 10210 + 10211 type_id @@ -18729,11 +18729,11 @@ name - 240988 + 240998 location - 221204 + 221214 @@ -18747,7 +18747,7 @@ 1 2 - 241267 + 241278 @@ -18763,7 +18763,7 @@ 1 2 - 241267 + 241278 @@ -18779,7 +18779,7 @@ 1 2 - 241267 + 241278 @@ -18795,7 +18795,7 @@ 1 2 - 241267 + 241278 @@ -18811,7 +18811,7 @@ 1 2 - 241267 + 241278 @@ -18959,7 +18959,7 @@ 1 2 - 28478 + 28479 @@ -19046,7 +19046,7 @@ 2 3 - 4187 + 4188 3 @@ -19056,7 +19056,7 @@ 4 5 - 3868 + 3869 5 @@ -19071,7 +19071,7 @@ 7 8 - 1395 + 1396 8 @@ -19112,7 +19112,7 @@ 3 4 - 1754 + 1755 4 @@ -19168,7 +19168,7 @@ 3 4 - 1754 + 1755 4 @@ -19214,7 +19214,7 @@ 1 2 - 10210 + 10211 @@ -19240,7 +19240,7 @@ 3 4 - 1754 + 1755 4 @@ -19296,7 +19296,7 @@ 3 4 - 1754 + 1755 4 @@ -19422,7 +19422,7 @@ 1 2 - 240708 + 240719 2 @@ -19443,7 +19443,7 @@ 1 2 - 240708 + 240719 2 @@ -19464,7 +19464,7 @@ 1 2 - 240988 + 240998 @@ -19480,7 +19480,7 @@ 1 2 - 240988 + 240998 @@ -19496,7 +19496,7 @@ 1 2 - 240708 + 240719 2 @@ -19517,7 +19517,7 @@ 1 2 - 220446 + 220456 2 @@ -19538,7 +19538,7 @@ 1 2 - 221204 + 221214 @@ -19554,7 +19554,7 @@ 1 2 - 220446 + 220456 2 @@ -19575,7 +19575,7 @@ 1 2 - 221204 + 221214 @@ -19591,7 +19591,7 @@ 1 2 - 220446 + 220456 2 @@ -19606,31 +19606,31 @@ builtintypes - 22679 + 22848 id - 22679 + 22848 name - 22679 + 22848 kind - 22679 + 22848 size - 3239 + 3264 sign - 1388 + 1398 alignment - 2314 + 2331 @@ -19644,7 +19644,7 @@ 1 2 - 22679 + 22848 @@ -19660,7 +19660,7 @@ 1 2 - 22679 + 22848 @@ -19676,7 +19676,7 @@ 1 2 - 22679 + 22848 @@ -19692,7 +19692,7 @@ 1 2 - 22679 + 22848 @@ -19708,7 +19708,7 @@ 1 2 - 22679 + 22848 @@ -19724,7 +19724,7 @@ 1 2 - 22679 + 22848 @@ -19740,7 +19740,7 @@ 1 2 - 22679 + 22848 @@ -19756,7 +19756,7 @@ 1 2 - 22679 + 22848 @@ -19772,7 +19772,7 @@ 1 2 - 22679 + 22848 @@ -19788,7 +19788,7 @@ 1 2 - 22679 + 22848 @@ -19804,7 +19804,7 @@ 1 2 - 22679 + 22848 @@ -19820,7 +19820,7 @@ 1 2 - 22679 + 22848 @@ -19836,7 +19836,7 @@ 1 2 - 22679 + 22848 @@ -19852,7 +19852,7 @@ 1 2 - 22679 + 22848 @@ -19868,7 +19868,7 @@ 1 2 - 22679 + 22848 @@ -19884,32 +19884,32 @@ 1 2 - 462 + 466 3 4 - 462 + 466 5 6 - 462 + 466 7 8 - 462 + 466 10 11 - 925 + 932 13 14 - 462 + 466 @@ -19925,32 +19925,32 @@ 1 2 - 462 + 466 3 4 - 462 + 466 5 6 - 462 + 466 7 8 - 462 + 466 10 11 - 925 + 932 13 14 - 462 + 466 @@ -19966,32 +19966,32 @@ 1 2 - 462 + 466 3 4 - 462 + 466 5 6 - 462 + 466 7 8 - 462 + 466 10 11 - 925 + 932 13 14 - 462 + 466 @@ -20007,12 +20007,12 @@ 1 2 - 925 + 932 3 4 - 2314 + 2331 @@ -20028,12 +20028,12 @@ 1 2 - 1851 + 1865 2 3 - 1388 + 1398 @@ -20049,17 +20049,17 @@ 6 7 - 462 + 466 12 13 - 462 + 466 31 32 - 462 + 466 @@ -20075,17 +20075,17 @@ 6 7 - 462 + 466 12 13 - 462 + 466 31 32 - 462 + 466 @@ -20101,17 +20101,17 @@ 6 7 - 462 + 466 12 13 - 462 + 466 31 32 - 462 + 466 @@ -20127,12 +20127,12 @@ 5 6 - 925 + 932 7 8 - 462 + 466 @@ -20148,7 +20148,7 @@ 5 6 - 1388 + 1398 @@ -20164,27 +20164,27 @@ 6 7 - 462 + 466 8 9 - 462 + 466 10 11 - 462 + 466 12 13 - 462 + 466 13 14 - 462 + 466 @@ -20200,27 +20200,27 @@ 6 7 - 462 + 466 8 9 - 462 + 466 10 11 - 462 + 466 12 13 - 462 + 466 13 14 - 462 + 466 @@ -20236,27 +20236,27 @@ 6 7 - 462 + 466 8 9 - 462 + 466 10 11 - 462 + 466 12 13 - 462 + 466 13 14 - 462 + 466 @@ -20272,7 +20272,7 @@ 2 3 - 2314 + 2331 @@ -20288,7 +20288,7 @@ 3 4 - 2314 + 2331 @@ -20298,23 +20298,23 @@ derivedtypes - 4324912 + 4327233 id - 4324912 + 4327233 name - 2161067 + 2151026 kind - 2777 + 2797 type_id - 2666967 + 2670947 @@ -20328,7 +20328,7 @@ 1 2 - 4324912 + 4327233 @@ -20344,7 +20344,7 @@ 1 2 - 4324912 + 4327233 @@ -20360,7 +20360,7 @@ 1 2 - 4324912 + 4327233 @@ -20376,17 +20376,17 @@ 1 2 - 1901406 + 1889434 2 5 - 162924 + 164602 5 - 1167 - 96736 + 1165 + 96989 @@ -20402,12 +20402,12 @@ 1 2 - 2160141 + 2150094 2 3 - 925 + 932 @@ -20423,17 +20423,17 @@ 1 2 - 1901406 + 1889434 2 5 - 162924 + 164602 5 - 1149 - 96736 + 1147 + 96989 @@ -20449,32 +20449,32 @@ 236 237 - 462 + 466 - 1085 - 1086 - 462 + 1072 + 1073 + 466 - 1148 - 1149 - 462 + 1146 + 1147 + 466 - 1221 - 1222 - 462 + 1217 + 1218 + 466 - 2177 - 2178 - 462 + 2164 + 2165 + 466 - 3477 - 3478 - 462 + 3445 + 3446 + 466 @@ -20490,32 +20490,32 @@ 1 2 - 462 + 466 201 202 - 462 + 466 - 610 - 611 - 462 + 606 + 607 + 466 - 768 - 769 - 462 + 755 + 756 + 466 - 1136 - 1137 - 462 + 1123 + 1124 + 466 - 1955 - 1956 - 462 + 1929 + 1930 + 466 @@ -20531,32 +20531,32 @@ 84 85 - 462 + 466 - 1085 - 1086 - 462 + 1072 + 1073 + 466 - 1148 - 1149 - 462 + 1146 + 1147 + 466 - 1221 - 1222 - 462 + 1217 + 1218 + 466 - 2132 - 2133 - 462 + 2119 + 2120 + 466 - 3477 - 3478 - 462 + 3445 + 3446 + 466 @@ -20572,22 +20572,22 @@ 1 2 - 1649150 + 1652555 2 3 - 558202 + 561421 3 4 - 354083 + 351587 4 72 - 105530 + 105383 @@ -20603,22 +20603,22 @@ 1 2 - 1660259 + 1663746 2 3 - 550796 + 553960 3 4 - 351306 + 348789 4 72 - 104605 + 104450 @@ -20634,22 +20634,22 @@ 1 2 - 1653316 + 1656752 2 3 - 561905 + 565151 3 4 - 353157 + 350655 4 6 - 98588 + 98388 @@ -20659,19 +20659,19 @@ pointerishsize - 3208044 + 3208121 id - 3208044 + 3208121 size - 462 + 466 alignment - 462 + 466 @@ -20685,7 +20685,7 @@ 1 2 - 3208044 + 3208121 @@ -20701,7 +20701,7 @@ 1 2 - 3208044 + 3208121 @@ -20715,9 +20715,9 @@ 12 - 6931 - 6932 - 462 + 6880 + 6881 + 466 @@ -20733,7 +20733,7 @@ 1 2 - 462 + 466 @@ -20747,9 +20747,9 @@ 12 - 6931 - 6932 - 462 + 6880 + 6881 + 466 @@ -20765,7 +20765,7 @@ 1 2 - 462 + 466 @@ -20775,23 +20775,23 @@ arraysizes - 87479 + 88130 id - 87479 + 88130 num_elements - 31474 + 31708 bytesize - 32862 + 33107 alignment - 1851 + 1865 @@ -20805,7 +20805,7 @@ 1 2 - 87479 + 88130 @@ -20821,7 +20821,7 @@ 1 2 - 87479 + 88130 @@ -20837,7 +20837,7 @@ 1 2 - 87479 + 88130 @@ -20853,27 +20853,27 @@ 1 2 - 1851 + 1865 2 3 - 23605 + 23781 3 5 - 2777 + 2797 5 13 - 2777 + 2797 13 14 - 462 + 466 @@ -20889,17 +20889,17 @@ 1 2 - 26382 + 26578 2 3 - 2314 + 2331 3 7 - 2777 + 2797 @@ -20915,17 +20915,17 @@ 1 2 - 26382 + 26578 2 3 - 2777 + 2797 3 5 - 2314 + 2331 @@ -20941,27 +20941,27 @@ 1 2 - 1851 + 1865 2 3 - 23605 + 23781 3 4 - 3239 + 3264 4 6 - 2314 + 2331 7 16 - 1851 + 1865 @@ -20977,17 +20977,17 @@ 1 2 - 27308 + 27511 2 3 - 3702 + 3730 3 5 - 1851 + 1865 @@ -21003,17 +21003,17 @@ 1 2 - 27308 + 27511 2 3 - 4628 + 4662 4 5 - 925 + 932 @@ -21029,22 +21029,22 @@ 5 6 - 462 + 466 16 17 - 462 + 466 31 32 - 462 + 466 137 138 - 462 + 466 @@ -21060,17 +21060,17 @@ 4 5 - 462 + 466 7 8 - 925 + 932 68 69 - 462 + 466 @@ -21086,22 +21086,22 @@ 4 5 - 462 + 466 7 8 - 462 + 466 8 9 - 462 + 466 68 69 - 462 + 466 @@ -21111,15 +21111,15 @@ typedefbase - 1722257 + 1722355 id - 1722257 + 1722355 type_id - 809037 + 809095 @@ -21133,7 +21133,7 @@ 1 2 - 1722257 + 1722355 @@ -21149,22 +21149,22 @@ 1 2 - 629258 + 629309 2 3 - 85024 + 85028 3 6 - 63307 + 63310 6 5437 - 31446 + 31447 @@ -21174,19 +21174,19 @@ decltypes - 172572 + 172581 id - 17342 + 17343 expr - 172572 + 172581 base_type - 10353 + 10354 parentheses_would_change_meaning @@ -21250,7 +21250,7 @@ 1 2 - 17342 + 17343 @@ -21266,7 +21266,7 @@ 1 2 - 17342 + 17343 @@ -21282,7 +21282,7 @@ 1 2 - 172572 + 172581 @@ -21298,7 +21298,7 @@ 1 2 - 172572 + 172581 @@ -21314,7 +21314,7 @@ 1 2 - 172572 + 172581 @@ -21330,7 +21330,7 @@ 1 2 - 7522 + 7523 2 @@ -21361,7 +21361,7 @@ 2 3 - 6374 + 6375 3 @@ -21402,7 +21402,7 @@ 1 2 - 10353 + 10354 @@ -21460,19 +21460,19 @@ usertypes - 5233032 + 5225787 id - 5233032 + 5225787 name - 1352460 + 1348530 kind - 5091 + 5129 @@ -21486,7 +21486,7 @@ 1 2 - 5233032 + 5225787 @@ -21502,7 +21502,7 @@ 1 2 - 5233032 + 5225787 @@ -21518,27 +21518,27 @@ 1 2 - 983565 + 979689 2 3 - 154593 + 153411 3 7 - 104605 + 104916 7 - 80 - 102290 + 59 + 101186 - 80 - 886 - 7405 + 60 + 874 + 9325 @@ -21554,17 +21554,17 @@ 1 2 - 1212215 + 1207708 2 3 - 124970 + 125900 3 7 - 15274 + 14921 @@ -21580,57 +21580,57 @@ 6 7 - 462 + 466 10 11 - 462 + 466 26 27 - 462 + 466 124 125 - 462 + 466 - 136 - 137 - 462 + 135 + 136 + 466 - 664 - 665 - 462 + 663 + 664 + 466 - 861 - 862 - 462 + 853 + 854 + 466 - 963 - 964 - 462 + 959 + 960 + 466 - 1761 - 1762 - 462 + 1751 + 1752 + 466 - 1869 - 1870 - 462 + 1836 + 1837 + 466 - 4886 - 4887 - 462 + 4844 + 4845 + 466 @@ -21646,57 +21646,57 @@ 5 6 - 462 + 466 6 7 - 462 + 466 14 15 - 462 + 466 30 31 - 462 + 466 - 44 - 45 - 462 + 43 + 44 + 466 - 126 - 127 - 462 + 125 + 126 + 466 - 268 - 269 - 462 + 267 + 268 + 466 - 373 - 374 - 462 + 371 + 372 + 466 438 439 - 462 + 466 - 748 - 749 - 462 + 740 + 741 + 466 - 1213 - 1214 - 462 + 1194 + 1195 + 466 @@ -21706,19 +21706,19 @@ usertypesize - 1712098 + 1703381 id - 1712098 + 1703381 size - 13422 + 13522 alignment - 2314 + 2331 @@ -21732,7 +21732,7 @@ 1 2 - 1712098 + 1703381 @@ -21748,7 +21748,7 @@ 1 2 - 1712098 + 1703381 @@ -21764,47 +21764,47 @@ 1 2 - 3239 + 3264 2 3 - 4165 + 4196 3 4 - 462 + 466 4 5 - 925 + 932 6 8 - 925 + 932 9 15 - 925 + 932 37 84 - 925 + 932 92 163 - 925 + 932 - 748 - 2506 - 925 + 740 + 2468 + 932 @@ -21820,17 +21820,17 @@ 1 2 - 10182 + 10258 2 3 - 2777 + 2797 3 4 - 462 + 466 @@ -21846,27 +21846,27 @@ 2 3 - 462 + 466 6 7 - 462 + 466 184 185 - 462 + 466 254 255 - 462 + 466 - 3253 - 3254 - 462 + 3207 + 3208 + 466 @@ -21882,27 +21882,27 @@ 1 2 - 462 + 466 2 3 - 462 + 466 3 4 - 462 + 466 9 10 - 462 + 466 22 23 - 462 + 466 @@ -21912,26 +21912,26 @@ usertype_final - 9517 + 9518 id - 9517 + 9518 usertype_uuid - 36324 + 36325 id - 36324 + 36325 uuid - 35952 + 35954 @@ -21945,7 +21945,7 @@ 1 2 - 36324 + 36325 @@ -21961,7 +21961,7 @@ 1 2 - 35581 + 35583 2 @@ -21976,15 +21976,15 @@ mangled_name - 9469077 + 9465823 id - 9469077 + 9465823 mangled_name - 3926394 + 3945802 @@ -21998,7 +21998,7 @@ 1 2 - 9469077 + 9465823 @@ -22014,22 +22014,22 @@ 1 2 - 2838223 + 2852803 2 3 - 521637 + 523184 3 6 - 331866 + 333868 6 - 886 - 234667 + 874 + 235946 @@ -22039,59 +22039,59 @@ is_pod_class - 534124 + 534147 id - 534124 + 534147 is_standard_layout_class - 1259889 + 1251540 id - 1259889 + 1251540 is_complete - 1651927 + 1642763 id - 1651927 + 1642763 is_class_template - 398517 + 397751 id - 398517 + 397751 class_instantiation - 1092099 + 1092146 to - 1090866 + 1090913 from - 70258 + 70261 @@ -22105,7 +22105,7 @@ 1 2 - 1089725 + 1089772 2 @@ -22126,7 +22126,7 @@ 1 2 - 20818 + 20819 2 @@ -22176,11 +22176,11 @@ class_template_argument - 2918517 + 2918643 type_id - 1329537 + 1329594 index @@ -22188,7 +22188,7 @@ arg_type - 856517 + 856554 @@ -22202,27 +22202,27 @@ 1 2 - 544130 + 544154 2 3 - 404524 + 404541 3 4 - 235639 + 235649 4 7 - 121139 + 121144 7 113 - 24103 + 24104 @@ -22238,22 +22238,22 @@ 1 2 - 569824 + 569849 2 3 - 416293 + 416311 3 4 - 248826 + 248837 4 113 - 94592 + 94596 @@ -22361,27 +22361,27 @@ 1 2 - 533421 + 533444 2 3 - 179086 + 179094 3 4 - 51757 + 51759 4 10 - 64333 + 64336 10 10167 - 27918 + 27920 @@ -22397,17 +22397,17 @@ 1 2 - 755700 + 755733 2 3 - 82569 + 82572 3 22 - 18247 + 18248 @@ -22417,19 +22417,19 @@ class_template_argument_value - 494791 + 494274 type_id - 305946 + 304025 index - 1851 + 1865 arg_value - 494791 + 494274 @@ -22443,17 +22443,17 @@ 1 2 - 251329 + 249002 2 3 - 52765 + 53157 3 4 - 1851 + 1865 @@ -22469,22 +22469,22 @@ 1 2 - 191621 + 188850 2 3 - 80536 + 81135 3 4 - 12034 + 12123 4 9 - 21754 + 21915 @@ -22500,22 +22500,22 @@ 18 19 - 462 + 466 92 93 - 462 + 466 - 297 - 298 - 462 + 292 + 293 + 466 - 376 - 377 - 462 + 372 + 373 + 466 @@ -22531,22 +22531,22 @@ 19 20 - 462 + 466 124 125 - 462 + 466 - 413 - 414 - 462 + 408 + 409 + 466 - 513 - 514 - 462 + 509 + 510 + 466 @@ -22562,7 +22562,7 @@ 1 2 - 494791 + 494274 @@ -22578,7 +22578,7 @@ 1 2 - 494791 + 494274 @@ -22588,15 +22588,15 @@ is_proxy_class_for - 62948 + 62950 id - 62948 + 62950 templ_param_id - 62948 + 62950 @@ -22610,7 +22610,7 @@ 1 2 - 62948 + 62950 @@ -22626,7 +22626,7 @@ 1 2 - 62948 + 62950 @@ -22636,19 +22636,19 @@ type_mentions - 4022409 + 4022590 id - 4022409 + 4022590 type_id - 197871 + 197880 location - 3988945 + 3989125 kind @@ -22666,7 +22666,7 @@ 1 2 - 4022409 + 4022590 @@ -22682,7 +22682,7 @@ 1 2 - 4022409 + 4022590 @@ -22698,7 +22698,7 @@ 1 2 - 4022409 + 4022590 @@ -22714,12 +22714,12 @@ 1 2 - 97440 + 97444 2 3 - 21697 + 21698 3 @@ -22734,22 +22734,22 @@ 5 7 - 14358 + 14359 7 12 - 15834 + 15835 12 27 - 15156 + 15157 27 8555 - 14398 + 14399 @@ -22765,12 +22765,12 @@ 1 2 - 97440 + 97444 2 3 - 21697 + 21698 3 @@ -22785,22 +22785,22 @@ 5 7 - 14358 + 14359 7 12 - 15834 + 15835 12 27 - 15156 + 15157 27 8555 - 14398 + 14399 @@ -22816,7 +22816,7 @@ 1 2 - 197871 + 197880 @@ -22832,12 +22832,12 @@ 1 2 - 3955481 + 3955660 2 3 - 33463 + 33465 @@ -22853,12 +22853,12 @@ 1 2 - 3955481 + 3955660 2 3 - 33463 + 33465 @@ -22874,7 +22874,7 @@ 1 2 - 3988945 + 3989125 @@ -22932,26 +22932,26 @@ is_function_template - 1396431 + 1401221 id - 1396431 + 1401221 function_instantiation - 907017 + 907042 to - 907017 + 907042 from - 146177 + 146181 @@ -22965,7 +22965,7 @@ 1 2 - 907017 + 907042 @@ -22981,12 +22981,12 @@ 1 2 - 101332 + 101335 2 3 - 14430 + 14431 3 @@ -22996,7 +22996,7 @@ 6 21 - 12066 + 12067 22 @@ -23011,11 +23011,11 @@ function_template_argument - 2342255 + 2342320 function_id - 1338103 + 1338140 index @@ -23023,7 +23023,7 @@ arg_type - 304985 + 304993 @@ -23037,22 +23037,22 @@ 1 2 - 682935 + 682954 2 3 - 395380 + 395391 3 4 - 189010 + 189015 4 15 - 70777 + 70779 @@ -23068,22 +23068,22 @@ 1 2 - 700577 + 700596 2 3 - 405294 + 405305 3 4 - 168828 + 168833 4 9 - 63403 + 63405 @@ -23231,27 +23231,27 @@ 1 2 - 186999 + 187004 2 3 - 44668 + 44669 3 5 - 23286 + 23287 5 16 - 23533 + 23534 16 107 - 23039 + 23040 108 @@ -23272,12 +23272,12 @@ 1 2 - 274818 + 274826 2 4 - 26038 + 26039 4 @@ -23292,11 +23292,11 @@ function_template_argument_value - 363519 + 363529 function_id - 195149 + 195155 index @@ -23304,7 +23304,7 @@ arg_value - 360873 + 360883 @@ -23318,7 +23318,7 @@ 1 2 - 185764 + 185769 2 @@ -23339,12 +23339,12 @@ 1 2 - 178319 + 178324 2 31 - 15312 + 15313 32 @@ -23487,7 +23487,7 @@ 1 2 - 358227 + 358237 2 @@ -23508,7 +23508,7 @@ 1 2 - 360873 + 360883 @@ -23518,26 +23518,26 @@ is_variable_template - 47274 + 47278 id - 47274 + 47278 variable_instantiation - 168077 + 168091 to - 168077 + 168091 from - 25729 + 25731 @@ -23551,7 +23551,7 @@ 1 2 - 168077 + 168091 @@ -23567,7 +23567,7 @@ 1 2 - 14015 + 14016 2 @@ -23607,11 +23607,11 @@ variable_template_argument - 295468 + 295493 variable_id - 159709 + 159723 index @@ -23619,7 +23619,7 @@ arg_type - 165462 + 165476 @@ -23633,17 +23633,17 @@ 1 2 - 81894 + 81901 2 3 - 49575 + 49580 3 4 - 18826 + 18827 4 @@ -23664,22 +23664,22 @@ 1 2 - 85555 + 85562 2 3 - 51876 + 51881 3 4 - 13701 + 13702 4 17 - 8576 + 8577 @@ -23807,17 +23807,17 @@ 1 2 - 133353 + 133364 2 3 - 18094 + 18095 3 15 - 12446 + 12447 17 @@ -23838,12 +23838,12 @@ 1 2 - 149564 + 149577 2 3 - 13805 + 13807 3 @@ -23858,11 +23858,11 @@ variable_template_argument_value - 11818 + 11819 variable_id - 7739 + 7740 index @@ -23870,7 +23870,7 @@ arg_value - 11818 + 11819 @@ -23993,7 +23993,7 @@ 1 2 - 11818 + 11819 @@ -24009,7 +24009,7 @@ 1 2 - 11818 + 11819 @@ -24019,15 +24019,15 @@ routinetypes - 547131 + 547147 id - 547131 + 547147 return_type - 285756 + 285764 @@ -24041,7 +24041,7 @@ 1 2 - 547131 + 547147 @@ -24057,7 +24057,7 @@ 1 2 - 248991 + 248998 2 @@ -24067,7 +24067,7 @@ 3 3594 - 15418 + 15419 @@ -24077,19 +24077,19 @@ routinetypeargs - 975697 + 982953 routine - 420271 + 423397 index - 7868 + 7927 type_id - 224947 + 226620 @@ -24103,27 +24103,27 @@ 1 2 - 151353 + 152479 2 3 - 133302 + 134293 3 4 - 62948 + 63416 4 5 - 45359 + 45697 5 18 - 27308 + 27511 @@ -24139,27 +24139,27 @@ 1 2 - 180976 + 182322 2 3 - 132839 + 133827 3 4 - 58319 + 58753 4 5 - 33325 + 33573 5 11 - 14811 + 14921 @@ -24175,67 +24175,67 @@ 2 3 - 925 + 932 4 5 - 462 + 466 6 7 - 462 + 466 8 9 - 925 + 932 9 10 - 462 + 466 10 11 - 1388 + 1398 13 14 - 462 + 466 28 29 - 462 + 466 59 60 - 462 + 466 157 158 - 462 + 466 293 294 - 462 + 466 581 582 - 462 + 466 908 909 - 462 + 466 @@ -24251,57 +24251,57 @@ 1 2 - 925 + 932 3 4 - 925 + 932 4 5 - 1388 + 1398 5 6 - 925 + 932 6 7 - 925 + 932 10 11 - 462 + 466 14 15 - 462 + 466 47 48 - 462 + 466 90 91 - 462 + 466 176 177 - 462 + 466 347 348 - 462 + 466 @@ -24317,27 +24317,27 @@ 1 2 - 145336 + 146417 2 3 - 30548 + 30775 3 5 - 16662 + 16786 5 12 - 18051 + 18185 12 111 - 14348 + 14455 @@ -24353,22 +24353,22 @@ 1 2 - 171256 + 172529 2 3 - 30548 + 30775 3 6 - 18514 + 18651 6 14 - 4628 + 4662 @@ -24378,19 +24378,19 @@ ptrtomembers - 37491 + 37770 id - 37491 + 37770 type_id - 37491 + 37770 class_id - 15274 + 15387 @@ -24404,7 +24404,7 @@ 1 2 - 37491 + 37770 @@ -24420,7 +24420,7 @@ 1 2 - 37491 + 37770 @@ -24436,7 +24436,7 @@ 1 2 - 37491 + 37770 @@ -24452,7 +24452,7 @@ 1 2 - 37491 + 37770 @@ -24468,17 +24468,17 @@ 1 2 - 13422 + 13522 8 9 - 1388 + 1398 28 29 - 462 + 466 @@ -24494,17 +24494,17 @@ 1 2 - 13422 + 13522 8 9 - 1388 + 1398 28 29 - 462 + 466 @@ -24514,15 +24514,15 @@ specifiers - 24531 + 24713 id - 24531 + 24713 str - 24531 + 24713 @@ -24536,7 +24536,7 @@ 1 2 - 24531 + 24713 @@ -24552,7 +24552,7 @@ 1 2 - 24531 + 24713 @@ -24562,15 +24562,15 @@ typespecifiers - 1287198 + 1289776 type_id - 1269147 + 1271591 spec_id - 3702 + 3730 @@ -24584,12 +24584,12 @@ 1 2 - 1251095 + 1253405 2 3 - 18051 + 18185 @@ -24605,42 +24605,42 @@ 8 9 - 462 + 466 36 37 - 462 + 466 51 52 - 462 + 466 86 87 - 462 + 466 105 106 - 462 + 466 219 220 - 462 + 466 - 223 - 224 - 462 + 221 + 222 + 466 - 2053 - 2054 - 462 + 2040 + 2041 + 466 @@ -24650,11 +24650,11 @@ funspecifiers - 12433939 + 12434284 func_id - 3820608 + 3820714 spec_id @@ -24672,27 +24672,27 @@ 1 2 - 315076 + 315085 2 3 - 545967 + 545982 3 4 - 1150998 + 1151030 4 5 - 1559292 + 1559335 5 8 - 249273 + 249280 @@ -24808,15 +24808,15 @@ varspecifiers - 2310106 + 2243353 var_id - 1234895 + 1223562 spec_id - 3702 + 3730 @@ -24830,22 +24830,22 @@ 1 2 - 723904 + 729288 2 3 - 199953 + 202372 3 4 - 57856 + 58287 4 5 - 253181 + 233614 @@ -24861,42 +24861,42 @@ 112 113 - 462 + 466 315 316 - 462 + 466 - 414 - 415 - 462 + 416 + 417 + 466 - 560 - 561 - 462 + 514 + 515 + 466 - 692 - 693 - 462 + 646 + 647 + 466 + + + 686 + 687 + 466 700 701 - 462 + 466 - 732 - 733 - 462 - - - 1466 - 1467 - 462 + 1422 + 1423 + 466 @@ -24906,11 +24906,11 @@ attributes - 737259 + 736276 id - 737259 + 736276 kind @@ -24926,7 +24926,7 @@ location - 483417 + 483459 @@ -24940,7 +24940,7 @@ 1 2 - 737259 + 736276 @@ -24956,7 +24956,7 @@ 1 2 - 737259 + 736276 @@ -24972,7 +24972,7 @@ 1 2 - 737259 + 736276 @@ -24988,7 +24988,7 @@ 1 2 - 737259 + 736276 @@ -25012,8 +25012,8 @@ 104 - 4714 - 4715 + 4704 + 4705 104 @@ -25156,8 +25156,8 @@ 104 - 1053 - 1054 + 1043 + 1044 104 @@ -25300,8 +25300,8 @@ 104 - 7026 - 7027 + 7016 + 7017 104 @@ -25381,17 +25381,17 @@ 1 2 - 425056 + 425824 2 3 - 37443 + 36923 3 201 - 20918 + 20710 @@ -25407,7 +25407,7 @@ 1 2 - 483417 + 483459 @@ -25423,7 +25423,7 @@ 1 2 - 479129 + 479170 2 @@ -25444,7 +25444,7 @@ 1 2 - 483417 + 483459 @@ -25454,27 +25454,27 @@ attribute_args - 406849 + 409874 id - 406849 + 409874 kind - 1388 + 1398 attribute - 295764 + 297963 index - 1388 + 1398 location - 324923 + 327340 @@ -25488,7 +25488,7 @@ 1 2 - 406849 + 409874 @@ -25504,7 +25504,7 @@ 1 2 - 406849 + 409874 @@ -25520,7 +25520,7 @@ 1 2 - 406849 + 409874 @@ -25536,7 +25536,7 @@ 1 2 - 406849 + 409874 @@ -25552,17 +25552,17 @@ 1 2 - 462 + 466 84 85 - 462 + 466 794 795 - 462 + 466 @@ -25578,17 +25578,17 @@ 1 2 - 462 + 466 84 85 - 462 + 466 606 607 - 462 + 466 @@ -25604,12 +25604,12 @@ 1 2 - 925 + 932 3 4 - 462 + 466 @@ -25625,17 +25625,17 @@ 1 2 - 462 + 466 54 55 - 462 + 466 674 675 - 462 + 466 @@ -25651,17 +25651,17 @@ 1 2 - 214301 + 215895 2 3 - 51839 + 52225 3 4 - 29622 + 29842 @@ -25677,12 +25677,12 @@ 1 2 - 271695 + 273716 2 3 - 24068 + 24247 @@ -25698,17 +25698,17 @@ 1 2 - 214301 + 215895 2 3 - 51839 + 52225 3 4 - 29622 + 29842 @@ -25724,17 +25724,17 @@ 1 2 - 214301 + 215895 2 3 - 51839 + 52225 3 4 - 29622 + 29842 @@ -25750,17 +25750,17 @@ 64 65 - 462 + 466 176 177 - 462 + 466 639 640 - 462 + 466 @@ -25776,12 +25776,12 @@ 1 2 - 925 + 932 3 4 - 462 + 466 @@ -25797,17 +25797,17 @@ 64 65 - 462 + 466 176 177 - 462 + 466 639 640 - 462 + 466 @@ -25823,17 +25823,17 @@ 34 35 - 462 + 466 140 141 - 462 + 466 528 529 - 462 + 466 @@ -25849,22 +25849,22 @@ 1 2 - 276786 + 278845 2 3 - 23142 + 23314 3 9 - 24531 + 24713 17 18 - 462 + 466 @@ -25880,12 +25880,12 @@ 1 2 - 312426 + 314750 2 3 - 12497 + 12590 @@ -25901,22 +25901,22 @@ 1 2 - 276786 + 278845 2 3 - 23142 + 23314 3 9 - 24531 + 24713 17 18 - 462 + 466 @@ -25932,7 +25932,7 @@ 1 2 - 324923 + 327340 @@ -25942,15 +25942,15 @@ attribute_arg_value - 38879 + 39168 arg - 38879 + 39168 value - 15737 + 15854 @@ -25964,7 +25964,7 @@ 1 2 - 38879 + 39168 @@ -25980,12 +25980,12 @@ 1 2 - 14348 + 14455 2 34 - 1388 + 1398 @@ -25995,15 +25995,15 @@ attribute_arg_type - 462 + 466 arg - 462 + 466 type_id - 462 + 466 @@ -26017,7 +26017,7 @@ 1 2 - 462 + 466 @@ -26033,7 +26033,7 @@ 1 2 - 462 + 466 @@ -26043,15 +26043,15 @@ attribute_arg_constant - 367506 + 370239 arg - 367506 + 370239 constant - 367506 + 370239 @@ -26065,7 +26065,7 @@ 1 2 - 367506 + 370239 @@ -26081,7 +26081,7 @@ 1 2 - 367506 + 370239 @@ -26144,15 +26144,15 @@ typeattributes - 85973 + 84934 type_id - 62022 + 62027 spec_id - 85973 + 84934 @@ -26166,17 +26166,17 @@ 1 2 - 55014 + 56065 2 - 3 - 5124 + 4 + 4288 - 3 + 12 13 - 1882 + 1673 @@ -26192,7 +26192,7 @@ 1 2 - 85973 + 84934 @@ -26202,15 +26202,15 @@ funcattributes - 647729 + 651416 func_id - 592401 + 442981 spec_id - 647729 + 651416 @@ -26224,12 +26224,22 @@ 1 2 - 554330 + 334334 2 - 7 - 38070 + 3 + 65281 + + + 3 + 6 + 34972 + + + 6 + 9 + 8393 @@ -26245,7 +26255,7 @@ 1 2 - 647729 + 651416 @@ -26361,15 +26371,15 @@ unspecifiedtype - 10141141 + 10137757 type_id - 10141141 + 10137757 unspecified_type_id - 6821549 + 6813527 @@ -26383,7 +26393,7 @@ 1 2 - 10141141 + 10137757 @@ -26399,17 +26409,17 @@ 1 2 - 4593830 + 4583230 2 3 - 1991662 + 1993418 3 - 147 - 236055 + 145 + 236878 @@ -26419,11 +26429,11 @@ member - 4925739 + 4925876 parent - 618791 + 618808 index @@ -26431,7 +26441,7 @@ child - 4880436 + 4880571 @@ -26445,42 +26455,42 @@ 1 3 - 18911 + 18912 3 4 - 320333 + 320342 4 5 - 38281 + 38283 5 7 - 53136 + 53137 7 10 - 52924 + 52925 10 15 - 50313 + 50314 15 24 - 49607 + 49609 24 251 - 35282 + 35283 @@ -26496,42 +26506,42 @@ 1 3 - 18911 + 18912 3 4 - 320262 + 320271 4 5 - 38317 + 38318 5 7 - 53241 + 53243 7 10 - 53277 + 53278 10 15 - 49925 + 49926 15 24 - 49678 + 49679 24 255 - 35177 + 35178 @@ -26689,7 +26699,7 @@ 1 2 - 4880436 + 4880571 @@ -26705,12 +26715,12 @@ 1 2 - 4836508 + 4836643 2 8 - 43927 + 43928 @@ -26720,15 +26730,15 @@ enclosingfunction - 121346 + 121352 child - 121346 + 121352 parent - 69278 + 69281 @@ -26742,7 +26752,7 @@ 1 2 - 121346 + 121352 @@ -26758,12 +26768,12 @@ 1 2 - 36575 + 36577 2 3 - 21521 + 21522 3 @@ -26783,15 +26793,15 @@ derivations - 368247 + 368257 derivation - 368247 + 368257 sub - 347712 + 347722 index @@ -26799,11 +26809,11 @@ super - 203864 + 203870 location - 38211 + 38212 @@ -26817,7 +26827,7 @@ 1 2 - 368247 + 368257 @@ -26833,7 +26843,7 @@ 1 2 - 368247 + 368257 @@ -26849,7 +26859,7 @@ 1 2 - 368247 + 368257 @@ -26865,7 +26875,7 @@ 1 2 - 368247 + 368257 @@ -26881,12 +26891,12 @@ 1 2 - 332541 + 332550 2 7 - 15171 + 15172 @@ -26902,12 +26912,12 @@ 1 2 - 332541 + 332550 2 7 - 15171 + 15172 @@ -26923,12 +26933,12 @@ 1 2 - 332541 + 332550 2 7 - 15171 + 15172 @@ -26944,12 +26954,12 @@ 1 2 - 332541 + 332550 2 7 - 15171 + 15172 @@ -27094,12 +27104,12 @@ 1 2 - 196525 + 196531 2 1216 - 7338 + 7339 @@ -27115,12 +27125,12 @@ 1 2 - 196525 + 196531 2 1216 - 7338 + 7339 @@ -27136,7 +27146,7 @@ 1 2 - 203405 + 203411 2 @@ -27157,7 +27167,7 @@ 1 2 - 200265 + 200271 2 @@ -27250,7 +27260,7 @@ 1 2 - 38211 + 38212 @@ -27266,7 +27276,7 @@ 1 2 - 31119 + 31120 2 @@ -27291,11 +27301,11 @@ derspecifiers - 370152 + 370163 der_id - 367859 + 367869 spec_id @@ -27313,7 +27323,7 @@ 1 2 - 365566 + 365576 2 @@ -27359,11 +27369,11 @@ direct_base_offsets - 338927 + 338936 der_id - 338927 + 338936 offset @@ -27381,7 +27391,7 @@ 1 2 - 338927 + 338936 @@ -27723,23 +27733,23 @@ frienddecls - 716101 + 716121 id - 716101 + 716121 type_id - 42445 + 42446 decl_id - 70283 + 70285 location - 6350 + 6351 @@ -27753,7 +27763,7 @@ 1 2 - 716101 + 716121 @@ -27769,7 +27779,7 @@ 1 2 - 716101 + 716121 @@ -27785,7 +27795,7 @@ 1 2 - 716101 + 716121 @@ -27913,7 +27923,7 @@ 1 2 - 40998 + 40999 2 @@ -27934,7 +27944,7 @@ 1 2 - 40540 + 40541 2 @@ -27980,7 +27990,7 @@ 1 2 - 40540 + 40541 2 @@ -28026,7 +28036,7 @@ 1 2 - 69613 + 69615 2 @@ -28104,19 +28114,19 @@ comments - 8773481 + 8774227 id - 8773481 + 8774227 contents - 3339997 + 3340281 location - 8773481 + 8774227 @@ -28130,7 +28140,7 @@ 1 2 - 8773481 + 8774227 @@ -28146,7 +28156,7 @@ 1 2 - 8773481 + 8774227 @@ -28162,17 +28172,17 @@ 1 2 - 3055511 + 3055770 2 7 - 250912 + 250934 7 32784 - 33573 + 33576 @@ -28188,17 +28198,17 @@ 1 2 - 3055511 + 3055770 2 7 - 250912 + 250934 7 32784 - 33573 + 33576 @@ -28214,7 +28224,7 @@ 1 2 - 8773481 + 8774227 @@ -28230,7 +28240,7 @@ 1 2 - 8773481 + 8774227 @@ -28240,15 +28250,15 @@ commentbinding - 3095107 + 3089682 id - 2450351 + 2444793 element - 3019199 + 3013209 @@ -28262,12 +28272,12 @@ 1 2 - 2369352 + 2367854 2 97 - 80999 + 76938 @@ -28283,12 +28293,12 @@ 1 2 - 2943291 + 2936736 2 3 - 75908 + 76472 @@ -28298,15 +28308,15 @@ exprconv - 7021833 + 7022151 converted - 7021833 + 7022151 conversion - 7021833 + 7022151 @@ -28320,7 +28330,7 @@ 1 2 - 7021833 + 7022151 @@ -28336,7 +28346,7 @@ 1 2 - 7021833 + 7022151 @@ -28346,22 +28356,22 @@ compgenerated - 8328174 + 8328406 id - 8328174 + 8328406 synthetic_destructor_call - 144282 + 144289 element - 111735 + 111741 i @@ -28369,7 +28379,7 @@ destructor_call - 129058 + 129064 @@ -28383,7 +28393,7 @@ 1 2 - 92037 + 92041 2 @@ -28409,7 +28419,7 @@ 1 2 - 92037 + 92041 2 @@ -28587,7 +28597,7 @@ 1 2 - 127019 + 127025 2 @@ -28608,7 +28618,7 @@ 1 2 - 129058 + 129064 @@ -28618,15 +28628,15 @@ namespaces - 12497 + 12123 id - 12497 + 12123 name - 10182 + 9792 @@ -28640,7 +28650,7 @@ 1 2 - 12497 + 12123 @@ -28656,17 +28666,17 @@ 1 2 - 8794 + 8393 2 3 - 462 + 466 3 4 - 925 + 932 @@ -28676,26 +28686,26 @@ namespace_inline - 1388 + 1398 id - 1388 + 1398 namespacembrs - 2390180 + 2382776 parentid - 10645 + 10258 memberid - 2390180 + 2382776 @@ -28709,57 +28719,52 @@ 1 2 - 1851 + 1865 2 - 3 - 925 - - - 3 4 - 462 + 932 4 5 - 925 + 932 5 7 - 925 + 932 7 8 - 925 + 932 8 12 - 925 + 932 17 30 - 925 + 932 43 47 - 925 + 932 52 143 - 925 + 932 - 253 - 4520 - 925 + 255 + 4466 + 932 @@ -28775,7 +28780,7 @@ 1 2 - 2390180 + 2382776 @@ -28785,19 +28790,19 @@ exprparents - 14182800 + 14183439 expr_id - 14182800 + 14183439 child_index - 14633 + 14634 parent_id - 9437908 + 9438333 @@ -28811,7 +28816,7 @@ 1 2 - 14182800 + 14183439 @@ -28827,7 +28832,7 @@ 1 2 - 14182800 + 14183439 @@ -28945,17 +28950,17 @@ 1 2 - 5400330 + 5400574 2 3 - 3700403 + 3700570 3 712 - 337173 + 337189 @@ -28971,17 +28976,17 @@ 1 2 - 5400330 + 5400574 2 3 - 3700403 + 3700570 3 712 - 337173 + 337189 @@ -28991,22 +28996,22 @@ expr_isload - 4981532 + 4981760 expr_id - 4981532 + 4981760 conversionkinds - 4220624 + 4220723 expr_id - 4220624 + 4220723 kind @@ -29024,7 +29029,7 @@ 1 2 - 4220624 + 4220723 @@ -29063,8 +29068,8 @@ 1 - 4131034 - 4131035 + 4131133 + 4131134 1 @@ -29075,11 +29080,11 @@ iscall - 2950586 + 2950725 caller - 2950586 + 2950725 kind @@ -29097,7 +29102,7 @@ 1 2 - 2950586 + 2950725 @@ -29133,11 +29138,11 @@ numtemplatearguments - 396226 + 396237 expr_id - 396226 + 396237 num @@ -29155,7 +29160,7 @@ 1 2 - 396226 + 396237 @@ -29211,15 +29216,15 @@ specialnamequalifyingelements - 462 + 466 id - 462 + 466 name - 462 + 466 @@ -29233,7 +29238,7 @@ 1 2 - 462 + 466 @@ -29249,7 +29254,7 @@ 1 2 - 462 + 466 @@ -29259,23 +29264,23 @@ namequalifiers - 1533160 + 1533233 id - 1533160 + 1533233 qualifiableelement - 1533160 + 1533233 qualifyingelement - 83386 + 83409 location - 305907 + 305921 @@ -29289,7 +29294,7 @@ 1 2 - 1533160 + 1533233 @@ -29305,7 +29310,7 @@ 1 2 - 1533160 + 1533233 @@ -29321,7 +29326,7 @@ 1 2 - 1533160 + 1533233 @@ -29337,7 +29342,7 @@ 1 2 - 1533160 + 1533233 @@ -29353,7 +29358,7 @@ 1 2 - 1533160 + 1533233 @@ -29369,7 +29374,7 @@ 1 2 - 1533160 + 1533233 @@ -29385,12 +29390,12 @@ 1 2 - 46602 + 46624 2 3 - 20589 + 20590 3 @@ -29421,12 +29426,12 @@ 1 2 - 46602 + 46624 2 3 - 20589 + 20590 3 @@ -29457,12 +29462,12 @@ 1 2 - 50938 + 50960 2 3 - 19500 + 19501 3 @@ -29472,7 +29477,7 @@ 4 8 - 6275 + 6276 8 @@ -29493,32 +29498,32 @@ 1 2 - 98214 + 98218 2 3 - 27458 + 27460 3 4 - 45870 + 45872 4 6 - 14075 + 14076 6 7 - 98847 + 98852 7 790 - 21440 + 21441 @@ -29534,32 +29539,32 @@ 1 2 - 98214 + 98218 2 3 - 27458 + 27460 3 4 - 45870 + 45872 4 6 - 14075 + 14076 6 7 - 98847 + 98852 7 790 - 21440 + 21441 @@ -29575,22 +29580,22 @@ 1 2 - 134344 + 134350 2 3 - 56818 + 56820 3 4 - 105935 + 105940 4 143 - 8809 + 8810 @@ -29600,15 +29605,15 @@ varbind - 6019061 + 6019333 expr - 6019061 + 6019333 var - 767247 + 767282 @@ -29622,7 +29627,7 @@ 1 2 - 6019061 + 6019333 @@ -29638,52 +29643,52 @@ 1 2 - 126011 + 126016 2 3 - 137644 + 137650 3 4 - 106115 + 106120 4 5 - 85069 + 85073 5 6 - 61186 + 61189 6 7 - 48032 + 48034 7 9 - 59521 + 59524 9 13 - 59172 + 59175 13 28 - 58781 + 58784 28 5137 - 25711 + 25713 @@ -29693,15 +29698,15 @@ funbind - 2953714 + 2953853 expr - 2950903 + 2951042 fun - 533714 + 533740 @@ -29715,7 +29720,7 @@ 1 2 - 2948091 + 2948231 2 @@ -29736,27 +29741,27 @@ 1 2 - 329684 + 329699 2 3 - 82178 + 82182 3 4 - 31853 + 31855 4 7 - 48067 + 48070 7 158 - 40030 + 40031 159 @@ -29771,11 +29776,11 @@ expr_allocator - 46608 + 46609 expr - 46608 + 46609 func @@ -29797,7 +29802,7 @@ 1 2 - 46608 + 46609 @@ -29813,7 +29818,7 @@ 1 2 - 46608 + 46609 @@ -29897,11 +29902,11 @@ expr_deallocator - 55394 + 55395 expr - 55394 + 55395 func @@ -29923,7 +29928,7 @@ 1 2 - 55394 + 55395 @@ -29939,7 +29944,7 @@ 1 2 - 55394 + 55395 @@ -30044,15 +30049,15 @@ expr_cond_guard - 656192 + 656221 cond - 656192 + 656221 guard - 656192 + 656221 @@ -30066,7 +30071,7 @@ 1 2 - 656192 + 656221 @@ -30082,7 +30087,7 @@ 1 2 - 656192 + 656221 @@ -30092,15 +30097,15 @@ expr_cond_true - 656189 + 656219 cond - 656189 + 656219 true - 656189 + 656219 @@ -30114,7 +30119,7 @@ 1 2 - 656189 + 656219 @@ -30130,7 +30135,7 @@ 1 2 - 656189 + 656219 @@ -30140,15 +30145,15 @@ expr_cond_false - 656192 + 656221 cond - 656192 + 656221 false - 656192 + 656221 @@ -30162,7 +30167,7 @@ 1 2 - 656192 + 656221 @@ -30178,7 +30183,7 @@ 1 2 - 656192 + 656221 @@ -30188,15 +30193,15 @@ values - 10758747 + 10759232 id - 10758747 + 10759232 str - 87858 + 87862 @@ -30210,7 +30215,7 @@ 1 2 - 10758747 + 10759232 @@ -30226,17 +30231,17 @@ 1 2 - 59403 + 59406 2 3 - 12367 + 12368 3 6 - 6920 + 6921 6 @@ -30256,15 +30261,15 @@ valuetext - 4757155 + 4757293 id - 4757155 + 4757293 text - 703935 + 703959 @@ -30278,7 +30283,7 @@ 1 2 - 4757155 + 4757293 @@ -30294,21 +30299,21 @@ 1 2 - 527534 + 527546 2 3 - 102488 + 102496 3 7 - 56764 + 56768 7 - 425881 + 425884 17149 @@ -30319,15 +30324,15 @@ valuebind - 11192235 + 11192739 val - 10758747 + 10759232 expr - 11192235 + 11192739 @@ -30341,12 +30346,12 @@ 1 2 - 10347766 + 10348232 2 7 - 410981 + 410999 @@ -30362,7 +30367,7 @@ 1 2 - 11192235 + 11192739 @@ -30372,15 +30377,15 @@ fieldoffsets - 1052936 + 1052983 id - 1052936 + 1052983 byteoffset - 22654 + 22655 bitoffset @@ -30398,7 +30403,7 @@ 1 2 - 1052936 + 1052983 @@ -30414,7 +30419,7 @@ 1 2 - 1052936 + 1052983 @@ -30430,7 +30435,7 @@ 1 2 - 13002 + 13003 2 @@ -30476,7 +30481,7 @@ 1 2 - 21976 + 21977 2 @@ -30573,11 +30578,11 @@ bitfield - 20918 + 20919 id - 20918 + 20919 bits @@ -30599,7 +30604,7 @@ 1 2 - 20918 + 20919 @@ -30615,7 +30620,7 @@ 1 2 - 20918 + 20919 @@ -30759,23 +30764,23 @@ initialisers - 1699633 + 1699706 init - 1699633 + 1699706 var - 722291 + 722379 expr - 1699633 + 1699706 location - 391082 + 391099 @@ -30789,7 +30794,7 @@ 1 2 - 1699633 + 1699706 @@ -30805,7 +30810,7 @@ 1 2 - 1699633 + 1699706 @@ -30821,7 +30826,7 @@ 1 2 - 1699633 + 1699706 @@ -30837,17 +30842,17 @@ 1 2 - 634099 + 634183 2 16 - 31491 + 31492 16 25 - 56701 + 56703 @@ -30863,17 +30868,17 @@ 1 2 - 634099 + 634183 2 16 - 31491 + 31492 16 25 - 56701 + 56703 @@ -30889,7 +30894,7 @@ 1 2 - 722285 + 722373 2 @@ -30910,7 +30915,7 @@ 1 2 - 1699633 + 1699706 @@ -30926,7 +30931,7 @@ 1 2 - 1699633 + 1699706 @@ -30942,7 +30947,7 @@ 1 2 - 1699633 + 1699706 @@ -30958,22 +30963,22 @@ 1 2 - 318704 + 318718 2 3 - 23863 + 23864 3 15 - 30666 + 30667 15 111551 - 17847 + 17848 @@ -30989,17 +30994,17 @@ 1 2 - 341391 + 341406 2 4 - 35638 + 35639 4 - 12805 - 14052 + 12811 + 14053 @@ -31015,22 +31020,22 @@ 1 2 - 318704 + 318718 2 3 - 23863 + 23864 3 15 - 30666 + 30667 15 111551 - 17847 + 17848 @@ -31040,26 +31045,26 @@ braced_initialisers - 41632 + 41634 init - 41632 + 41634 expr_ancestor - 133354 + 133360 exp - 133354 + 133360 ancestor - 92928 + 92932 @@ -31073,7 +31078,7 @@ 1 2 - 133354 + 133360 @@ -31089,12 +31094,12 @@ 1 2 - 67112 + 67115 2 3 - 18431 + 18432 3 @@ -31114,11 +31119,11 @@ exprs - 18356809 + 18357636 id - 18356809 + 18357636 kind @@ -31126,7 +31131,7 @@ location - 3592504 + 3592604 @@ -31140,7 +31145,7 @@ 1 2 - 18356809 + 18357636 @@ -31156,7 +31161,7 @@ 1 2 - 18356809 + 18357636 @@ -31206,7 +31211,7 @@ 653 - 830 + 832 282 @@ -31296,8 +31301,8 @@ 282 - 468 - 1019 + 469 + 1020 282 @@ -31324,31 +31329,31 @@ 1 2 - 1941829 + 1941777 2 3 - 838392 + 838486 3 4 - 247121 + 247163 4 8 - 284556 + 284529 8 155 - 269490 + 269533 155 - 53479 + 53477 11114 @@ -31365,22 +31370,22 @@ 1 2 - 2392674 + 2392776 2 3 - 875968 + 875922 3 6 - 306925 + 306969 6 - 26 - 16935 + 25 + 16936 @@ -31390,15 +31395,15 @@ expr_types - 18411726 + 18412556 id - 18356809 + 18357636 typeid - 880959 + 881000 value_category @@ -31416,12 +31421,12 @@ 1 2 - 18301891 + 18302715 2 3 - 54917 + 54920 @@ -31437,7 +31442,7 @@ 1 2 - 18356809 + 18357636 @@ -31453,42 +31458,42 @@ 1 2 - 316756 + 316771 2 3 - 172216 + 172204 3 4 - 69369 + 69372 4 5 - 68261 + 68284 5 7 - 69765 + 69729 7 12 - 69864 + 69828 12 35 - 66875 + 66898 35 - 73135 - 47850 + 73134 + 47911 @@ -31504,12 +31509,12 @@ 1 2 - 757899 + 757935 2 3 - 111834 + 111840 3 @@ -31533,13 +31538,13 @@ 19 - 235367 - 235368 + 235356 + 235357 19 - 684712 - 684713 + 684721 + 684722 19 @@ -31576,11 +31581,11 @@ new_allocated_type - 47667 + 47668 expr - 47667 + 47668 type_id @@ -31598,7 +31603,7 @@ 1 2 - 47667 + 47668 @@ -31619,7 +31624,7 @@ 2 3 - 14924 + 14925 3 @@ -31711,6 +31716,10 @@ field 2156 + + position + 41 + @@ -31805,6 +31814,52 @@ + + aggregate + position + + + 12 + + + 1 + 2 + 6503 + + + 2 + 3 + 500733 + + + 3 + 4 + 11095 + + + 4 + 5 + 88743 + + + 5 + 12 + 49719 + + + 12 + 13 + 190968 + + + 13 + 42 + 192 + + + + + initializer aggregate @@ -31842,6 +31897,22 @@ + + initializer + position + + + 12 + + + 1 + 2 + 4005406 + + + + + field aggregate @@ -31964,6 +32035,195 @@ + + field + position + + + 12 + + + 1 + 2 + 2153 + + + 2 + 3 + 3 + + + + + + + position + aggregate + + + 12 + + + 2 + 3 + 13 + + + 3 + 4 + 5 + + + 49 + 50 + 3 + + + 50 + 51 + 5 + + + 72 + 193 + 3 + + + 191160 + 194827 + 3 + + + 194928 + 206244 + 3 + + + 217398 + 329623 + 3 + + + 340717 + 847954 + 3 + + + + + + + position + initializer + + + 12 + + + 2 + 3 + 13 + + + 3 + 4 + 5 + + + 49 + 50 + 3 + + + 50 + 51 + 5 + + + 72 + 193 + 3 + + + 191160 + 194827 + 3 + + + 194928 + 206244 + 3 + + + 217398 + 329623 + 3 + + + 340717 + 847954 + 3 + + + + + + + position + field + + + 12 + + + 1 + 2 + 13 + + + 2 + 3 + 5 + + + 3 + 4 + 3 + + + 4 + 5 + 5 + + + 6 + 11 + 3 + + + 14 + 27 + 3 + + + 33 + 66 + 3 + + + 90 + 174 + 3 + + + 248 + 655 + 3 + + + + + @@ -31982,6 +32242,10 @@ element_index 17485 + + position + 17485 + @@ -32096,6 +32360,62 @@ + + aggregate + position + + + 12 + + + 1 + 2 + 7521 + + + 2 + 3 + 7791 + + + 3 + 4 + 17335 + + + 4 + 5 + 8012 + + + 5 + 6 + 5810 + + + 6 + 8 + 5006 + + + 8 + 11 + 5381 + + + 11 + 22 + 4985 + + + 22 + 17486 + 3774 + + + + + initializer aggregate @@ -32128,6 +32448,22 @@ + + initializer + position + + + 12 + + + 1 + 2 + 730401 + + + + + element_index aggregate @@ -32240,19 +32576,163 @@ + + element_index + position + + + 12 + + + 1 + 2 + 17485 + + + + + + + position + aggregate + + + 12 + + + 1 + 2 + 6580 + + + 2 + 3 + 2653 + + + 3 + 5 + 1308 + + + 5 + 6 + 1488 + + + 7 + 9 + 1059 + + + 9 + 15 + 1388 + + + 15 + 27 + 1379 + + + 27 + 198 + 1316 + + + 202 + 65616 + 314 + + + + + + + position + initializer + + + 12 + + + 1 + 2 + 6580 + + + 2 + 3 + 2653 + + + 3 + 5 + 1308 + + + 5 + 6 + 1488 + + + 7 + 9 + 1059 + + + 9 + 15 + 1388 + + + 15 + 27 + 1379 + + + 27 + 198 + 1316 + + + 202 + 65616 + 314 + + + + + + + position + element_index + + + 12 + + + 1 + 2 + 17485 + + + + + condition_decl_bind - 42425 + 42427 expr - 42425 + 42427 decl - 42425 + 42427 @@ -32266,7 +32746,7 @@ 1 2 - 42425 + 42427 @@ -32282,7 +32762,7 @@ 1 2 - 42425 + 42427 @@ -32292,15 +32772,15 @@ typeid_bind - 36482 + 36483 expr - 36482 + 36483 type_id - 16406 + 16407 @@ -32314,7 +32794,7 @@ 1 2 - 36482 + 36483 @@ -32345,15 +32825,15 @@ uuidof_bind - 20119 + 20120 expr - 20119 + 20120 type_id - 19924 + 19925 @@ -32367,7 +32847,7 @@ 1 2 - 20119 + 20120 @@ -32383,7 +32863,7 @@ 1 2 - 19760 + 19761 2 @@ -32398,15 +32878,15 @@ sizeof_bind - 198852 + 198861 expr - 198852 + 198861 type_id - 8167 + 8168 @@ -32420,7 +32900,7 @@ 1 2 - 198852 + 198861 @@ -32529,19 +33009,19 @@ lambdas - 21291 + 21449 expr - 21291 + 21449 default_capture - 462 + 466 has_explicit_return_type - 462 + 466 @@ -32555,7 +33035,7 @@ 1 2 - 21291 + 21449 @@ -32571,7 +33051,7 @@ 1 2 - 21291 + 21449 @@ -32587,7 +33067,7 @@ 46 47 - 462 + 466 @@ -32603,7 +33083,7 @@ 1 2 - 462 + 466 @@ -32619,7 +33099,7 @@ 46 47 - 462 + 466 @@ -32635,7 +33115,7 @@ 1 2 - 462 + 466 @@ -32645,35 +33125,35 @@ lambda_capture - 27771 + 27977 id - 27771 + 27977 lambda - 20365 + 20517 index - 925 + 932 field - 27771 + 27977 captured_by_reference - 462 + 466 is_implicit - 462 + 466 location - 2777 + 2797 @@ -32687,7 +33167,7 @@ 1 2 - 27771 + 27977 @@ -32703,7 +33183,7 @@ 1 2 - 27771 + 27977 @@ -32719,7 +33199,7 @@ 1 2 - 27771 + 27977 @@ -32735,7 +33215,7 @@ 1 2 - 27771 + 27977 @@ -32751,7 +33231,7 @@ 1 2 - 27771 + 27977 @@ -32767,7 +33247,7 @@ 1 2 - 27771 + 27977 @@ -32783,12 +33263,12 @@ 1 2 - 12959 + 13056 2 3 - 7405 + 7460 @@ -32804,12 +33284,12 @@ 1 2 - 12959 + 13056 2 3 - 7405 + 7460 @@ -32825,12 +33305,12 @@ 1 2 - 12959 + 13056 2 3 - 7405 + 7460 @@ -32846,7 +33326,7 @@ 1 2 - 20365 + 20517 @@ -32862,7 +33342,7 @@ 1 2 - 20365 + 20517 @@ -32878,12 +33358,12 @@ 1 2 - 12959 + 13056 2 3 - 7405 + 7460 @@ -32899,12 +33379,12 @@ 16 17 - 462 + 466 44 45 - 462 + 466 @@ -32920,12 +33400,12 @@ 16 17 - 462 + 466 44 45 - 462 + 466 @@ -32941,12 +33421,12 @@ 16 17 - 462 + 466 44 45 - 462 + 466 @@ -32962,7 +33442,7 @@ 1 2 - 925 + 932 @@ -32978,7 +33458,7 @@ 1 2 - 925 + 932 @@ -32994,12 +33474,12 @@ 2 3 - 462 + 466 4 5 - 462 + 466 @@ -33015,7 +33495,7 @@ 1 2 - 27771 + 27977 @@ -33031,7 +33511,7 @@ 1 2 - 27771 + 27977 @@ -33047,7 +33527,7 @@ 1 2 - 27771 + 27977 @@ -33063,7 +33543,7 @@ 1 2 - 27771 + 27977 @@ -33079,7 +33559,7 @@ 1 2 - 27771 + 27977 @@ -33095,7 +33575,7 @@ 1 2 - 27771 + 27977 @@ -33111,7 +33591,7 @@ 60 61 - 462 + 466 @@ -33127,7 +33607,7 @@ 44 45 - 462 + 466 @@ -33143,7 +33623,7 @@ 2 3 - 462 + 466 @@ -33159,7 +33639,7 @@ 60 61 - 462 + 466 @@ -33175,7 +33655,7 @@ 1 2 - 462 + 466 @@ -33191,7 +33671,7 @@ 6 7 - 462 + 466 @@ -33207,7 +33687,7 @@ 60 61 - 462 + 466 @@ -33223,7 +33703,7 @@ 44 45 - 462 + 466 @@ -33239,7 +33719,7 @@ 2 3 - 462 + 466 @@ -33255,7 +33735,7 @@ 60 61 - 462 + 466 @@ -33271,7 +33751,7 @@ 1 2 - 462 + 466 @@ -33287,7 +33767,7 @@ 6 7 - 462 + 466 @@ -33303,12 +33783,12 @@ 8 9 - 1851 + 1865 14 15 - 925 + 932 @@ -33324,12 +33804,12 @@ 8 9 - 1851 + 1865 14 15 - 925 + 932 @@ -33345,7 +33825,7 @@ 1 2 - 2777 + 2797 @@ -33361,12 +33841,12 @@ 8 9 - 1851 + 1865 14 15 - 925 + 932 @@ -33382,7 +33862,7 @@ 1 2 - 2777 + 2797 @@ -33398,7 +33878,7 @@ 1 2 - 2777 + 2797 @@ -33524,11 +34004,11 @@ stmts - 4653237 + 4653633 id - 4653237 + 4653633 kind @@ -33536,7 +34016,7 @@ location - 2284887 + 2285081 @@ -33550,7 +34030,7 @@ 1 2 - 4653237 + 4653633 @@ -33566,7 +34046,7 @@ 1 2 - 4653237 + 4653633 @@ -33794,22 +34274,22 @@ 1 2 - 1890475 + 1890636 2 4 - 175816 + 175831 4 12 - 176026 + 176041 12 687 - 42568 + 42572 @@ -33825,12 +34305,12 @@ 1 2 - 2227676 + 2227865 2 8 - 57211 + 57215 @@ -33984,15 +34464,15 @@ if_then - 724702 + 724735 if_stmt - 724702 + 724735 then_id - 724702 + 724735 @@ -34006,7 +34486,7 @@ 1 2 - 724702 + 724735 @@ -34022,7 +34502,7 @@ 1 2 - 724702 + 724735 @@ -34032,15 +34512,15 @@ if_else - 184361 + 184369 if_stmt - 184361 + 184369 else_id - 184361 + 184369 @@ -34054,7 +34534,7 @@ 1 2 - 184361 + 184369 @@ -34070,7 +34550,7 @@ 1 2 - 184361 + 184369 @@ -34128,15 +34608,15 @@ constexpr_if_then - 52504 + 52508 constexpr_if_stmt - 52504 + 52508 then_id - 52504 + 52508 @@ -34150,7 +34630,7 @@ 1 2 - 52504 + 52508 @@ -34166,7 +34646,7 @@ 1 2 - 52504 + 52508 @@ -34176,15 +34656,15 @@ constexpr_if_else - 30854 + 30856 constexpr_if_stmt - 30854 + 30856 else_id - 30854 + 30856 @@ -34198,7 +34678,7 @@ 1 2 - 30854 + 30856 @@ -34214,7 +34694,7 @@ 1 2 - 30854 + 30856 @@ -34224,15 +34704,15 @@ while_body - 30109 + 30110 while_stmt - 30109 + 30110 body_id - 30109 + 30110 @@ -34246,7 +34726,7 @@ 1 2 - 30109 + 30110 @@ -34262,7 +34742,7 @@ 1 2 - 30109 + 30110 @@ -34272,15 +34752,15 @@ do_body - 148625 + 148632 do_stmt - 148625 + 148632 body_id - 148625 + 148632 @@ -34294,7 +34774,7 @@ 1 2 - 148625 + 148632 @@ -34310,7 +34790,7 @@ 1 2 - 148625 + 148632 @@ -34368,7 +34848,7 @@ switch_case - 209633 + 209643 switch_stmt @@ -34380,7 +34860,7 @@ case_id - 209633 + 209643 @@ -34608,7 +35088,7 @@ 1 2 - 209633 + 209643 @@ -34624,7 +35104,7 @@ 1 2 - 209633 + 209643 @@ -34634,15 +35114,15 @@ switch_body - 20752 + 20753 switch_stmt - 20752 + 20753 body_id - 20752 + 20753 @@ -34656,7 +35136,7 @@ 1 2 - 20752 + 20753 @@ -34672,7 +35152,7 @@ 1 2 - 20752 + 20753 @@ -34682,15 +35162,15 @@ for_initialization - 53314 + 53317 for_stmt - 53314 + 53317 init_id - 53314 + 53317 @@ -34704,7 +35184,7 @@ 1 2 - 53314 + 53317 @@ -34720,7 +35200,7 @@ 1 2 - 53314 + 53317 @@ -34730,15 +35210,15 @@ for_condition - 55575 + 55578 for_stmt - 55575 + 55578 condition_id - 55575 + 55578 @@ -34752,7 +35232,7 @@ 1 2 - 55575 + 55578 @@ -34768,7 +35248,7 @@ 1 2 - 55575 + 55578 @@ -34778,15 +35258,15 @@ for_update - 53417 + 53419 for_stmt - 53417 + 53419 update_id - 53417 + 53419 @@ -34800,7 +35280,7 @@ 1 2 - 53417 + 53419 @@ -34816,7 +35296,7 @@ 1 2 - 53417 + 53419 @@ -34826,15 +35306,15 @@ for_body - 61453 + 61456 for_stmt - 61453 + 61456 body_id - 61453 + 61456 @@ -34848,7 +35328,7 @@ 1 2 - 61453 + 61456 @@ -34864,7 +35344,7 @@ 1 2 - 61453 + 61456 @@ -34874,11 +35354,11 @@ stmtparents - 4056317 + 4056493 id - 4056317 + 4056493 index @@ -34886,7 +35366,7 @@ parent - 1721231 + 1721306 @@ -34900,7 +35380,7 @@ 1 2 - 4056317 + 4056493 @@ -34916,7 +35396,7 @@ 1 2 - 4056317 + 4056493 @@ -35054,27 +35534,27 @@ 1 2 - 988379 + 988422 2 3 - 373323 + 373339 3 4 - 105844 + 105849 4 6 - 111345 + 111349 6 17 - 129966 + 129972 17 @@ -35095,27 +35575,27 @@ 1 2 - 988379 + 988422 2 3 - 373323 + 373339 3 4 - 105844 + 105849 4 6 - 111345 + 111349 6 17 - 129966 + 129972 17 @@ -35130,22 +35610,22 @@ ishandler - 65311 + 65314 block - 65311 + 65314 stmt_decl_bind - 585113 + 585138 stmt - 544999 + 545022 num @@ -35153,7 +35633,7 @@ decl - 585008 + 585033 @@ -35167,12 +35647,12 @@ 1 2 - 524137 + 524159 2 19 - 20861 + 20862 @@ -35188,12 +35668,12 @@ 1 2 - 524137 + 524159 2 19 - 20861 + 20862 @@ -35391,7 +35871,7 @@ 1 2 - 584971 + 584995 2 @@ -35412,7 +35892,7 @@ 1 2 - 585008 + 585033 @@ -35422,11 +35902,11 @@ stmt_decl_entry_bind - 527572 + 527594 stmt - 487760 + 487781 num @@ -35434,7 +35914,7 @@ decl_entry - 527514 + 527536 @@ -35448,12 +35928,12 @@ 1 2 - 467163 + 467183 2 19 - 20596 + 20597 @@ -35469,12 +35949,12 @@ 1 2 - 467163 + 467183 2 19 - 20596 + 20597 @@ -35672,7 +36152,7 @@ 1 2 - 527493 + 527515 3 @@ -35693,7 +36173,7 @@ 1 2 - 527514 + 527536 @@ -35703,15 +36183,15 @@ blockscope - 1414946 + 1415210 block - 1414946 + 1415210 enclosing - 1300621 + 1300035 @@ -35725,7 +36205,7 @@ 1 2 - 1414946 + 1415210 @@ -35741,12 +36221,12 @@ 1 2 - 1235821 + 1234753 2 13 - 64799 + 65281 @@ -35756,19 +36236,19 @@ jumpinfo - 254032 + 254043 id - 254032 + 254043 str - 21155 + 21156 target - 53053 + 53056 @@ -35782,7 +36262,7 @@ 1 2 - 254032 + 254043 @@ -35798,7 +36278,7 @@ 1 2 - 254032 + 254043 @@ -35819,12 +36299,12 @@ 3 4 - 4246 + 4247 4 5 - 1565 + 1566 5 @@ -35860,7 +36340,7 @@ 1 2 - 16719 + 16720 2 @@ -35896,7 +36376,7 @@ 2 3 - 26432 + 26433 3 @@ -35932,7 +36412,7 @@ 1 2 - 53053 + 53056 @@ -35942,11 +36422,11 @@ preprocdirects - 4427322 + 4427698 id - 4427322 + 4427698 kind @@ -35954,7 +36434,7 @@ location - 4424811 + 4425187 @@ -35968,7 +36448,7 @@ 1 2 - 4427322 + 4427698 @@ -35984,7 +36464,7 @@ 1 2 - 4427322 + 4427698 @@ -36122,7 +36602,7 @@ 1 2 - 4424707 + 4425083 25 @@ -36143,7 +36623,7 @@ 1 2 - 4424811 + 4425187 @@ -36153,15 +36633,15 @@ preprocpair - 1419111 + 1429665 begin - 1186758 + 1195584 elseelifend - 1419111 + 1429665 @@ -36175,17 +36655,17 @@ 1 2 - 970143 + 977357 2 3 - 206433 + 207968 3 11 - 10182 + 10258 @@ -36201,7 +36681,7 @@ 1 2 - 1419111 + 1429665 @@ -36211,41 +36691,41 @@ preproctrue - 770652 + 766125 branch - 770652 + 766125 preprocfalse - 321683 + 331070 branch - 321683 + 331070 preproctext - 3569469 + 3569772 id - 3569469 + 3569772 head - 2589246 + 2589465 body - 1514472 + 1514601 @@ -36259,7 +36739,7 @@ 1 2 - 3569469 + 3569772 @@ -36275,7 +36755,7 @@ 1 2 - 3569469 + 3569772 @@ -36291,12 +36771,12 @@ 1 2 - 2442296 + 2442503 2 740 - 146949 + 146962 @@ -36312,12 +36792,12 @@ 1 2 - 2527119 + 2527333 2 5 - 62126 + 62132 @@ -36333,17 +36813,17 @@ 1 2 - 1370974 + 1371090 2 6 - 113585 + 113595 6 11572 - 29912 + 29915 @@ -36359,17 +36839,17 @@ 1 2 - 1374007 + 1374124 2 7 - 113899 + 113908 7 2959 - 26566 + 26568 @@ -36379,15 +36859,15 @@ includes - 310575 + 312885 id - 310575 + 312885 included - 116176 + 117040 @@ -36401,7 +36881,7 @@ 1 2 - 310575 + 312885 @@ -36417,32 +36897,32 @@ 1 2 - 60633 + 61084 2 3 - 21754 + 21915 3 4 - 12497 + 12590 4 6 - 10182 + 10258 6 14 - 8794 + 8859 14 47 - 2314 + 2331 @@ -36500,11 +36980,11 @@ link_parent - 38562230 + 38563300 element - 4878989 + 4879124 link_target @@ -36522,17 +37002,17 @@ 1 2 - 648887 + 648905 2 9 - 25932 + 25933 9 10 - 4204168 + 4204285 From ddd44b4c1314a9c1b13336fafff53a9b0598ff2c Mon Sep 17 00:00:00 2001 From: Alexandre Boulgakov Date: Fri, 31 Mar 2023 16:57:35 +0100 Subject: [PATCH 127/141] C++: Correct repeated initializers downgrade script compatibility to full. --- .../19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties index 3c45f644ceb..eab51f4d94d 100644 --- a/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties +++ b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties @@ -1,4 +1,4 @@ description: Revert support for repeated initializers, which are allowed in C with designated initializers. -compatibility: backwards +compatibility: full aggregate_field_init.rel: reorder aggregate_field_init.rel (int aggregate, int initializer, int field, int position) aggregate initializer field aggregate_array_init.rel: reorder aggregate_array_init.rel (int aggregate, int initializer, int element_index, int position) aggregate initializer element_index From 0b33d2685237e6027c34e292fdd9bb020e609cd1 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 31 Mar 2023 18:25:19 +0100 Subject: [PATCH 128/141] C++: Speed up non-linear recursion in GVN. --- .../gvn/internal/ValueNumberingInternal.qll | 71 +++++++++++++++---- 1 file changed, 58 insertions(+), 13 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll index 2dc735f49df..85a28fbc677 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -159,26 +159,56 @@ private predicate fieldAddressValueNumber( tvalueNumber(instr.getObjectAddress()) = objectAddress } +pragma[nomagic] +private predicate binaryValueNumber0( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, boolean isLeft, + TValueNumber valueNumber +) { + not instr instanceof PointerArithmeticInstruction and + instr.getEnclosingIRFunction() = irFunc and + instr.getOpcode() = opcode and + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate binaryValueNumber( BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand ) { - instr.getEnclosingIRFunction() = irFunc and - not instr instanceof PointerArithmeticInstruction and - instr.getOpcode() = opcode and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + binaryValueNumber0(instr, irFunc, opcode, true, leftOperand) and + binaryValueNumber0(instr, irFunc, opcode, false, rightOperand) } -private predicate pointerArithmeticValueNumber( +pragma[nomagic] +private predicate pointerArithmeticValueNumber0( PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, - TValueNumber leftOperand, TValueNumber rightOperand + boolean isLeft, TValueNumber valueNumber ) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getElementSize() = elementSize and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, + TValueNumber leftOperand, TValueNumber rightOperand +) { + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, true, leftOperand) and + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, false, rightOperand) } private predicate unaryValueNumber( @@ -203,14 +233,29 @@ private predicate inheritanceConversionValueNumber( unique( | | instr.getDerivedClass()) = derivedClass } +pragma[nomagic] +private predicate loadTotalOverlapValueNumber0( + LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber, + boolean isAddress +) { + instr.getEnclosingIRFunction() = irFunc and + instr.getResultIRType() = type and + ( + isAddress = true and + tvalueNumberOfOperand(instr.getSourceAddressOperand()) = valueNumber + or + isAddress = false and + tvalueNumber(instr.getSourceValueOperand().getAnyDef()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate loadTotalOverlapValueNumber( LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand, TValueNumber operand ) { - instr.getEnclosingIRFunction() = irFunc and - tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and - tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and - instr.getResultIRType() = type + loadTotalOverlapValueNumber0(instr, irFunc, type, operand, true) and + loadTotalOverlapValueNumber0(instr, irFunc, type, memOperand, false) } /** From 6638df1578b950843f0df071cd1a517aaaa4a8cf Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 31 Mar 2023 18:25:34 +0100 Subject: [PATCH 129/141] C++: Sync identical files. --- .../gvn/internal/ValueNumberingInternal.qll | 71 +++++++++++++++---- .../gvn/internal/ValueNumberingInternal.qll | 71 +++++++++++++++---- .../gvn/internal/ValueNumberingInternal.qll | 71 +++++++++++++++---- .../gvn/internal/ValueNumberingInternal.qll | 71 +++++++++++++++---- 4 files changed, 232 insertions(+), 52 deletions(-) diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 2dc735f49df..85a28fbc677 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -159,26 +159,56 @@ private predicate fieldAddressValueNumber( tvalueNumber(instr.getObjectAddress()) = objectAddress } +pragma[nomagic] +private predicate binaryValueNumber0( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, boolean isLeft, + TValueNumber valueNumber +) { + not instr instanceof PointerArithmeticInstruction and + instr.getEnclosingIRFunction() = irFunc and + instr.getOpcode() = opcode and + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate binaryValueNumber( BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand ) { - instr.getEnclosingIRFunction() = irFunc and - not instr instanceof PointerArithmeticInstruction and - instr.getOpcode() = opcode and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + binaryValueNumber0(instr, irFunc, opcode, true, leftOperand) and + binaryValueNumber0(instr, irFunc, opcode, false, rightOperand) } -private predicate pointerArithmeticValueNumber( +pragma[nomagic] +private predicate pointerArithmeticValueNumber0( PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, - TValueNumber leftOperand, TValueNumber rightOperand + boolean isLeft, TValueNumber valueNumber ) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getElementSize() = elementSize and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, + TValueNumber leftOperand, TValueNumber rightOperand +) { + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, true, leftOperand) and + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, false, rightOperand) } private predicate unaryValueNumber( @@ -203,14 +233,29 @@ private predicate inheritanceConversionValueNumber( unique( | | instr.getDerivedClass()) = derivedClass } +pragma[nomagic] +private predicate loadTotalOverlapValueNumber0( + LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber, + boolean isAddress +) { + instr.getEnclosingIRFunction() = irFunc and + instr.getResultIRType() = type and + ( + isAddress = true and + tvalueNumberOfOperand(instr.getSourceAddressOperand()) = valueNumber + or + isAddress = false and + tvalueNumber(instr.getSourceValueOperand().getAnyDef()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate loadTotalOverlapValueNumber( LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand, TValueNumber operand ) { - instr.getEnclosingIRFunction() = irFunc and - tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and - tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and - instr.getResultIRType() = type + loadTotalOverlapValueNumber0(instr, irFunc, type, operand, true) and + loadTotalOverlapValueNumber0(instr, irFunc, type, memOperand, false) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 2dc735f49df..85a28fbc677 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -159,26 +159,56 @@ private predicate fieldAddressValueNumber( tvalueNumber(instr.getObjectAddress()) = objectAddress } +pragma[nomagic] +private predicate binaryValueNumber0( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, boolean isLeft, + TValueNumber valueNumber +) { + not instr instanceof PointerArithmeticInstruction and + instr.getEnclosingIRFunction() = irFunc and + instr.getOpcode() = opcode and + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate binaryValueNumber( BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand ) { - instr.getEnclosingIRFunction() = irFunc and - not instr instanceof PointerArithmeticInstruction and - instr.getOpcode() = opcode and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + binaryValueNumber0(instr, irFunc, opcode, true, leftOperand) and + binaryValueNumber0(instr, irFunc, opcode, false, rightOperand) } -private predicate pointerArithmeticValueNumber( +pragma[nomagic] +private predicate pointerArithmeticValueNumber0( PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, - TValueNumber leftOperand, TValueNumber rightOperand + boolean isLeft, TValueNumber valueNumber ) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getElementSize() = elementSize and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, + TValueNumber leftOperand, TValueNumber rightOperand +) { + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, true, leftOperand) and + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, false, rightOperand) } private predicate unaryValueNumber( @@ -203,14 +233,29 @@ private predicate inheritanceConversionValueNumber( unique( | | instr.getDerivedClass()) = derivedClass } +pragma[nomagic] +private predicate loadTotalOverlapValueNumber0( + LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber, + boolean isAddress +) { + instr.getEnclosingIRFunction() = irFunc and + instr.getResultIRType() = type and + ( + isAddress = true and + tvalueNumberOfOperand(instr.getSourceAddressOperand()) = valueNumber + or + isAddress = false and + tvalueNumber(instr.getSourceValueOperand().getAnyDef()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate loadTotalOverlapValueNumber( LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand, TValueNumber operand ) { - instr.getEnclosingIRFunction() = irFunc and - tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and - tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and - instr.getResultIRType() = type + loadTotalOverlapValueNumber0(instr, irFunc, type, operand, true) and + loadTotalOverlapValueNumber0(instr, irFunc, type, memOperand, false) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll index 2dc735f49df..85a28fbc677 100644 --- a/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/raw/gvn/internal/ValueNumberingInternal.qll @@ -159,26 +159,56 @@ private predicate fieldAddressValueNumber( tvalueNumber(instr.getObjectAddress()) = objectAddress } +pragma[nomagic] +private predicate binaryValueNumber0( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, boolean isLeft, + TValueNumber valueNumber +) { + not instr instanceof PointerArithmeticInstruction and + instr.getEnclosingIRFunction() = irFunc and + instr.getOpcode() = opcode and + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate binaryValueNumber( BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand ) { - instr.getEnclosingIRFunction() = irFunc and - not instr instanceof PointerArithmeticInstruction and - instr.getOpcode() = opcode and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + binaryValueNumber0(instr, irFunc, opcode, true, leftOperand) and + binaryValueNumber0(instr, irFunc, opcode, false, rightOperand) } -private predicate pointerArithmeticValueNumber( +pragma[nomagic] +private predicate pointerArithmeticValueNumber0( PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, - TValueNumber leftOperand, TValueNumber rightOperand + boolean isLeft, TValueNumber valueNumber ) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getElementSize() = elementSize and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, + TValueNumber leftOperand, TValueNumber rightOperand +) { + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, true, leftOperand) and + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, false, rightOperand) } private predicate unaryValueNumber( @@ -203,14 +233,29 @@ private predicate inheritanceConversionValueNumber( unique( | | instr.getDerivedClass()) = derivedClass } +pragma[nomagic] +private predicate loadTotalOverlapValueNumber0( + LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber, + boolean isAddress +) { + instr.getEnclosingIRFunction() = irFunc and + instr.getResultIRType() = type and + ( + isAddress = true and + tvalueNumberOfOperand(instr.getSourceAddressOperand()) = valueNumber + or + isAddress = false and + tvalueNumber(instr.getSourceValueOperand().getAnyDef()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate loadTotalOverlapValueNumber( LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand, TValueNumber operand ) { - instr.getEnclosingIRFunction() = irFunc and - tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and - tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and - instr.getResultIRType() = type + loadTotalOverlapValueNumber0(instr, irFunc, type, operand, true) and + loadTotalOverlapValueNumber0(instr, irFunc, type, memOperand, false) } /** diff --git a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll index 2dc735f49df..85a28fbc677 100644 --- a/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll +++ b/csharp/ql/src/experimental/ir/implementation/unaliased_ssa/gvn/internal/ValueNumberingInternal.qll @@ -159,26 +159,56 @@ private predicate fieldAddressValueNumber( tvalueNumber(instr.getObjectAddress()) = objectAddress } +pragma[nomagic] +private predicate binaryValueNumber0( + BinaryInstruction instr, IRFunction irFunc, Opcode opcode, boolean isLeft, + TValueNumber valueNumber +) { + not instr instanceof PointerArithmeticInstruction and + instr.getEnclosingIRFunction() = irFunc and + instr.getOpcode() = opcode and + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate binaryValueNumber( BinaryInstruction instr, IRFunction irFunc, Opcode opcode, TValueNumber leftOperand, TValueNumber rightOperand ) { - instr.getEnclosingIRFunction() = irFunc and - not instr instanceof PointerArithmeticInstruction and - instr.getOpcode() = opcode and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + binaryValueNumber0(instr, irFunc, opcode, true, leftOperand) and + binaryValueNumber0(instr, irFunc, opcode, false, rightOperand) } -private predicate pointerArithmeticValueNumber( +pragma[nomagic] +private predicate pointerArithmeticValueNumber0( PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, - TValueNumber leftOperand, TValueNumber rightOperand + boolean isLeft, TValueNumber valueNumber ) { instr.getEnclosingIRFunction() = irFunc and instr.getOpcode() = opcode and instr.getElementSize() = elementSize and - tvalueNumber(instr.getLeft()) = leftOperand and - tvalueNumber(instr.getRight()) = rightOperand + ( + isLeft = true and + tvalueNumber(instr.getLeft()) = valueNumber + or + isLeft = false and + tvalueNumber(instr.getRight()) = valueNumber + ) +} + +pragma[assume_small_delta] +private predicate pointerArithmeticValueNumber( + PointerArithmeticInstruction instr, IRFunction irFunc, Opcode opcode, int elementSize, + TValueNumber leftOperand, TValueNumber rightOperand +) { + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, true, leftOperand) and + pointerArithmeticValueNumber0(instr, irFunc, opcode, elementSize, false, rightOperand) } private predicate unaryValueNumber( @@ -203,14 +233,29 @@ private predicate inheritanceConversionValueNumber( unique( | | instr.getDerivedClass()) = derivedClass } +pragma[nomagic] +private predicate loadTotalOverlapValueNumber0( + LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber valueNumber, + boolean isAddress +) { + instr.getEnclosingIRFunction() = irFunc and + instr.getResultIRType() = type and + ( + isAddress = true and + tvalueNumberOfOperand(instr.getSourceAddressOperand()) = valueNumber + or + isAddress = false and + tvalueNumber(instr.getSourceValueOperand().getAnyDef()) = valueNumber + ) +} + +pragma[assume_small_delta] private predicate loadTotalOverlapValueNumber( LoadTotalOverlapInstruction instr, IRFunction irFunc, IRType type, TValueNumber memOperand, TValueNumber operand ) { - instr.getEnclosingIRFunction() = irFunc and - tvalueNumber(instr.getAnOperand().(MemoryOperand).getAnyDef()) = memOperand and - tvalueNumberOfOperand(instr.getAnOperand().(AddressOperand)) = operand and - instr.getResultIRType() = type + loadTotalOverlapValueNumber0(instr, irFunc, type, operand, true) and + loadTotalOverlapValueNumber0(instr, irFunc, type, memOperand, false) } /** From e9615c57e9b01dab04b50972da46e8e3c90cab0c Mon Sep 17 00:00:00 2001 From: Porcupiney Hairs Date: Sat, 4 Mar 2023 03:11:13 +0530 Subject: [PATCH 130/141] Go: Add more JWT sinks This pull requests adds modelling for `katras/iris/v12/middleware/jwt`, `katras/jwt` and `gogf/gf-jwt` frameworks. --- .../experimental/CWE-321/HardcodedKeysLib.qll | 63 ++++++ .../CWE-321/HardcodedKeys.expected | 168 ++++++++++------ go/ql/test/experimental/CWE-321/go.mod | 72 ++++++- go/ql/test/experimental/CWE-321/main.go | 82 +++++++- .../vendor/github.com/gin-gonic/gin/stub.go | 5 +- .../vendor/github.com/gogf/gf-jwt/v2/stub.go | 90 +++++++++ .../github.com/golang-jwt/jwt/v4/stub.go | 10 +- .../iris-contrib/middleware/jwt/stub.go | 29 +++ .../kataras/iris/v12/middleware/jwt/stub.go | 81 ++++++++ .../vendor/github.com/kataras/jwt/stub.go | 105 ++++++++++ .../experimental/CWE-321/vendor/modules.txt | 190 +++++++++++++++++- 11 files changed, 814 insertions(+), 81 deletions(-) create mode 100644 go/ql/test/experimental/CWE-321/vendor/github.com/gogf/gf-jwt/v2/stub.go create mode 100644 go/ql/test/experimental/CWE-321/vendor/github.com/iris-contrib/middleware/jwt/stub.go create mode 100644 go/ql/test/experimental/CWE-321/vendor/github.com/kataras/iris/v12/middleware/jwt/stub.go create mode 100644 go/ql/test/experimental/CWE-321/vendor/github.com/kataras/jwt/stub.go diff --git a/go/ql/src/experimental/CWE-321/HardcodedKeysLib.qll b/go/ql/src/experimental/CWE-321/HardcodedKeysLib.qll index 5dc65a15098..12af9544b0e 100644 --- a/go/ql/src/experimental/CWE-321/HardcodedKeysLib.qll +++ b/go/ql/src/experimental/CWE-321/HardcodedKeysLib.qll @@ -79,6 +79,69 @@ module HardcodedKeys { } } + private class KatarasJwt extends Sink { + KatarasJwt() { + exists(string pkg | + pkg = package("github.com/kataras/jwt", "") and + ( + exists(DataFlow::MethodCallNode m | + // Model the `Register` method of the type `Keys` + // func (keys Keys) Register(alg Alg, kid string, pubKey PublicKey, privKey PrivateKey) + m.getTarget().hasQualifiedName(pkg, "Keys", "Register") + | + this = m.getArgument(3) + ) + or + exists(DataFlow::CallNode m, string names | + // Model the `Sign` method of the `SigningMethod` interface + // func Sign(alg Alg, key PrivateKey, claims interface{}, opts ...SignOption) ([]byte, error) + // func SignEncrypted(alg Alg, key PrivateKey, encrypt InjectFunc, claims interface{}, ...) ([]byte, error) + // func SignEncryptedWithHeader(alg Alg, key PrivateKey, encrypt InjectFunc, claims interface{}, ...) ([]byte, error) + // func SignWithHeader(alg Alg, key PrivateKey, claims interface{}, customHeader interface{}, ...) ([]byte, error) + m.getTarget().hasQualifiedName(pkg, names) and + names = ["Sign", "SignEncrypted", "SignEncryptedWithHeader", "SignWithHeader"] + | + this = m.getArgument(1) + ) + ) + ) + } + } + + private class IrisJwt extends Sink { + IrisJwt() { + exists(string pkg | + pkg = "github.com/kataras/iris/v12/middleware/jwt" and + ( + exists(DataFlow::CallNode m | + //func NewSigner(signatureAlg Alg, signatureKey interface{}, maxAge time.Duration) *Signer + m.getTarget().hasQualifiedName(pkg, "NewSigner") + | + this = m.getArgument(1) + ) + or + exists(Field f | + // Models the `key` field of the `Signer` type + // https://github.com/kataras/iris/blob/dccd57263617f5ca95d7621acfadf9dd37752dd6/middleware/jwt/signer.go#L17 + f.hasQualifiedName(pkg, "Signer", "Key") and + f.getAWrite().getRhs() = this + ) + ) + ) + } + } + + private class GogfJwtSign extends Sink { + GogfJwtSign() { + exists(Field f, string pkg | + pkg = package("github.com/gogf/gf-jwt", "") and + // https://github.com/gogf/gf-jwt/blob/40503f05bc0a2bcd7aeba550163112afbb5c221f/auth_jwt.go#L27 + f.hasQualifiedName(pkg, "GfJWTMiddleware", "Key") and + f.getAWrite().getRhs() = this + ) + } + } + private class GinJwtSign extends Sink { GinJwtSign() { exists(Field f | diff --git a/go/ql/test/experimental/CWE-321/HardcodedKeys.expected b/go/ql/test/experimental/CWE-321/HardcodedKeys.expected index fe0fb2d238d..873bb55b7c2 100644 --- a/go/ql/test/experimental/CWE-321/HardcodedKeys.expected +++ b/go/ql/test/experimental/CWE-321/HardcodedKeys.expected @@ -1,74 +1,126 @@ edges | HardcodedKeysBad.go:11:18:11:38 | type conversion | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | HardcodedKeysBad.go:11:18:11:38 | type conversion | -| main.go:25:18:25:31 | type conversion | main.go:34:28:34:39 | mySigningKey | -| main.go:25:25:25:30 | "key1" | main.go:25:18:25:31 | type conversion | -| main.go:42:23:42:28 | "key2" | main.go:42:16:42:29 | type conversion | -| main.go:60:9:60:22 | type conversion | main.go:61:44:61:46 | key | -| main.go:60:16:60:21 | `key3` | main.go:60:9:60:22 | type conversion | -| main.go:65:9:65:22 | type conversion | main.go:66:66:66:68 | key | -| main.go:65:16:65:21 | "key4" | main.go:65:9:65:22 | type conversion | -| main.go:69:10:69:23 | type conversion | main.go:74:15:74:18 | key2 | -| main.go:69:17:69:22 | "key5" | main.go:69:10:69:23 | type conversion | -| main.go:80:9:80:22 | type conversion | main.go:84:41:84:43 | key | -| main.go:80:16:80:21 | "key6" | main.go:80:9:80:22 | type conversion | -| main.go:89:10:89:23 | type conversion | main.go:91:66:91:69 | key2 | -| main.go:89:17:89:22 | "key7" | main.go:89:10:89:23 | type conversion | -| main.go:97:9:97:22 | type conversion | main.go:102:30:102:32 | key | -| main.go:97:16:97:21 | "key8" | main.go:97:9:97:22 | type conversion | -| main.go:106:15:106:28 | type conversion | main.go:107:16:107:24 | sharedKey | -| main.go:106:22:106:27 | "key9" | main.go:106:15:106:28 | type conversion | -| main.go:110:23:110:37 | type conversion | main.go:113:16:113:30 | sharedKeyglobal | -| main.go:110:30:110:36 | "key10" | main.go:110:23:110:37 | type conversion | +| main.go:33:18:33:31 | type conversion | main.go:42:28:42:39 | mySigningKey | +| main.go:33:25:33:30 | "key1" | main.go:33:18:33:31 | type conversion | +| main.go:50:23:50:28 | "key2" | main.go:50:16:50:29 | type conversion | +| main.go:68:9:68:22 | type conversion | main.go:69:44:69:46 | key | +| main.go:68:16:68:21 | `key3` | main.go:68:9:68:22 | type conversion | +| main.go:73:9:73:22 | type conversion | main.go:74:66:74:68 | key | +| main.go:73:16:73:21 | "key4" | main.go:73:9:73:22 | type conversion | +| main.go:77:10:77:23 | type conversion | main.go:82:15:82:18 | key2 | +| main.go:77:17:77:22 | "key5" | main.go:77:10:77:23 | type conversion | +| main.go:88:9:88:22 | type conversion | main.go:92:41:92:43 | key | +| main.go:88:16:88:21 | "key6" | main.go:88:9:88:22 | type conversion | +| main.go:97:10:97:23 | type conversion | main.go:99:66:99:69 | key2 | +| main.go:97:17:97:22 | "key7" | main.go:97:10:97:23 | type conversion | +| main.go:105:9:105:22 | type conversion | main.go:110:30:110:32 | key | +| main.go:105:16:105:21 | "key8" | main.go:105:9:105:22 | type conversion | +| main.go:114:15:114:28 | type conversion | main.go:115:16:115:24 | sharedKey | +| main.go:114:22:114:27 | "key9" | main.go:114:15:114:28 | type conversion | +| main.go:118:23:118:37 | type conversion | main.go:121:16:121:30 | sharedKeyglobal | +| main.go:118:30:118:36 | "key10" | main.go:118:23:118:37 | type conversion | +| main.go:127:27:127:33 | "key11" | main.go:127:20:127:34 | type conversion | +| main.go:142:14:142:28 | type conversion | main.go:144:39:144:46 | mySecret | +| main.go:142:21:142:27 | "key12" | main.go:142:14:142:28 | type conversion | +| main.go:149:14:149:28 | type conversion | main.go:153:11:153:18 | mySecret | +| main.go:149:21:149:27 | "key13" | main.go:149:14:149:28 | type conversion | +| main.go:160:12:160:26 | type conversion | main.go:161:34:161:39 | secret | +| main.go:160:19:160:25 | "key14" | main.go:160:12:160:26 | type conversion | +| main.go:166:12:166:26 | type conversion | main.go:167:32:167:37 | secret | +| main.go:166:19:166:25 | "key15" | main.go:166:12:166:26 | type conversion | +| main.go:172:12:172:26 | type conversion | main.go:173:41:173:46 | secret | +| main.go:172:19:172:25 | "key16" | main.go:172:12:172:26 | type conversion | +| main.go:178:12:178:26 | type conversion | main.go:179:51:179:56 | secret | +| main.go:178:19:178:25 | "key17" | main.go:178:12:178:26 | type conversion | +| main.go:184:12:184:26 | type conversion | main.go:185:42:185:47 | secret | +| main.go:184:19:184:25 | "key18" | main.go:184:12:184:26 | type conversion | +| main.go:190:12:190:26 | type conversion | main.go:193:33:193:38 | secret | +| main.go:190:19:190:25 | "key19" | main.go:190:12:190:26 | type conversion | | sanitizer.go:17:9:17:21 | type conversion | sanitizer.go:18:44:18:46 | key | | sanitizer.go:17:16:17:20 | `key` | sanitizer.go:17:9:17:21 | type conversion | nodes | HardcodedKeysBad.go:11:18:11:38 | type conversion | semmle.label | type conversion | | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | semmle.label | "AllYourBase" | | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | semmle.label | mySigningKey | -| main.go:25:18:25:31 | type conversion | semmle.label | type conversion | -| main.go:25:25:25:30 | "key1" | semmle.label | "key1" | -| main.go:34:28:34:39 | mySigningKey | semmle.label | mySigningKey | -| main.go:42:16:42:29 | type conversion | semmle.label | type conversion | -| main.go:42:23:42:28 | "key2" | semmle.label | "key2" | -| main.go:60:9:60:22 | type conversion | semmle.label | type conversion | -| main.go:60:16:60:21 | `key3` | semmle.label | `key3` | -| main.go:61:44:61:46 | key | semmle.label | key | -| main.go:65:9:65:22 | type conversion | semmle.label | type conversion | -| main.go:65:16:65:21 | "key4" | semmle.label | "key4" | -| main.go:66:66:66:68 | key | semmle.label | key | -| main.go:69:10:69:23 | type conversion | semmle.label | type conversion | -| main.go:69:17:69:22 | "key5" | semmle.label | "key5" | -| main.go:74:15:74:18 | key2 | semmle.label | key2 | -| main.go:80:9:80:22 | type conversion | semmle.label | type conversion | -| main.go:80:16:80:21 | "key6" | semmle.label | "key6" | -| main.go:84:41:84:43 | key | semmle.label | key | -| main.go:89:10:89:23 | type conversion | semmle.label | type conversion | -| main.go:89:17:89:22 | "key7" | semmle.label | "key7" | -| main.go:91:66:91:69 | key2 | semmle.label | key2 | -| main.go:97:9:97:22 | type conversion | semmle.label | type conversion | -| main.go:97:16:97:21 | "key8" | semmle.label | "key8" | -| main.go:102:30:102:32 | key | semmle.label | key | -| main.go:106:15:106:28 | type conversion | semmle.label | type conversion | -| main.go:106:22:106:27 | "key9" | semmle.label | "key9" | -| main.go:107:16:107:24 | sharedKey | semmle.label | sharedKey | -| main.go:110:23:110:37 | type conversion | semmle.label | type conversion | -| main.go:110:30:110:36 | "key10" | semmle.label | "key10" | -| main.go:113:16:113:30 | sharedKeyglobal | semmle.label | sharedKeyglobal | +| main.go:33:18:33:31 | type conversion | semmle.label | type conversion | +| main.go:33:25:33:30 | "key1" | semmle.label | "key1" | +| main.go:42:28:42:39 | mySigningKey | semmle.label | mySigningKey | +| main.go:50:16:50:29 | type conversion | semmle.label | type conversion | +| main.go:50:23:50:28 | "key2" | semmle.label | "key2" | +| main.go:68:9:68:22 | type conversion | semmle.label | type conversion | +| main.go:68:16:68:21 | `key3` | semmle.label | `key3` | +| main.go:69:44:69:46 | key | semmle.label | key | +| main.go:73:9:73:22 | type conversion | semmle.label | type conversion | +| main.go:73:16:73:21 | "key4" | semmle.label | "key4" | +| main.go:74:66:74:68 | key | semmle.label | key | +| main.go:77:10:77:23 | type conversion | semmle.label | type conversion | +| main.go:77:17:77:22 | "key5" | semmle.label | "key5" | +| main.go:82:15:82:18 | key2 | semmle.label | key2 | +| main.go:88:9:88:22 | type conversion | semmle.label | type conversion | +| main.go:88:16:88:21 | "key6" | semmle.label | "key6" | +| main.go:92:41:92:43 | key | semmle.label | key | +| main.go:97:10:97:23 | type conversion | semmle.label | type conversion | +| main.go:97:17:97:22 | "key7" | semmle.label | "key7" | +| main.go:99:66:99:69 | key2 | semmle.label | key2 | +| main.go:105:9:105:22 | type conversion | semmle.label | type conversion | +| main.go:105:16:105:21 | "key8" | semmle.label | "key8" | +| main.go:110:30:110:32 | key | semmle.label | key | +| main.go:114:15:114:28 | type conversion | semmle.label | type conversion | +| main.go:114:22:114:27 | "key9" | semmle.label | "key9" | +| main.go:115:16:115:24 | sharedKey | semmle.label | sharedKey | +| main.go:118:23:118:37 | type conversion | semmle.label | type conversion | +| main.go:118:30:118:36 | "key10" | semmle.label | "key10" | +| main.go:121:16:121:30 | sharedKeyglobal | semmle.label | sharedKeyglobal | +| main.go:127:20:127:34 | type conversion | semmle.label | type conversion | +| main.go:127:27:127:33 | "key11" | semmle.label | "key11" | +| main.go:142:14:142:28 | type conversion | semmle.label | type conversion | +| main.go:142:21:142:27 | "key12" | semmle.label | "key12" | +| main.go:144:39:144:46 | mySecret | semmle.label | mySecret | +| main.go:149:14:149:28 | type conversion | semmle.label | type conversion | +| main.go:149:21:149:27 | "key13" | semmle.label | "key13" | +| main.go:153:11:153:18 | mySecret | semmle.label | mySecret | +| main.go:160:12:160:26 | type conversion | semmle.label | type conversion | +| main.go:160:19:160:25 | "key14" | semmle.label | "key14" | +| main.go:161:34:161:39 | secret | semmle.label | secret | +| main.go:166:12:166:26 | type conversion | semmle.label | type conversion | +| main.go:166:19:166:25 | "key15" | semmle.label | "key15" | +| main.go:167:32:167:37 | secret | semmle.label | secret | +| main.go:172:12:172:26 | type conversion | semmle.label | type conversion | +| main.go:172:19:172:25 | "key16" | semmle.label | "key16" | +| main.go:173:41:173:46 | secret | semmle.label | secret | +| main.go:178:12:178:26 | type conversion | semmle.label | type conversion | +| main.go:178:19:178:25 | "key17" | semmle.label | "key17" | +| main.go:179:51:179:56 | secret | semmle.label | secret | +| main.go:184:12:184:26 | type conversion | semmle.label | type conversion | +| main.go:184:19:184:25 | "key18" | semmle.label | "key18" | +| main.go:185:42:185:47 | secret | semmle.label | secret | +| main.go:190:12:190:26 | type conversion | semmle.label | type conversion | +| main.go:190:19:190:25 | "key19" | semmle.label | "key19" | +| main.go:193:33:193:38 | secret | semmle.label | secret | | sanitizer.go:17:9:17:21 | type conversion | semmle.label | type conversion | | sanitizer.go:17:16:17:20 | `key` | semmle.label | `key` | | sanitizer.go:18:44:18:46 | key | semmle.label | key | subpaths #select | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | HardcodedKeysBad.go:19:28:19:39 | mySigningKey | $@ is used to sign a JWT token. | HardcodedKeysBad.go:11:25:11:37 | "AllYourBase" | Hardcoded String | -| main.go:34:28:34:39 | mySigningKey | main.go:25:25:25:30 | "key1" | main.go:34:28:34:39 | mySigningKey | $@ is used to sign a JWT token. | main.go:25:25:25:30 | "key1" | Hardcoded String | -| main.go:42:16:42:29 | type conversion | main.go:42:23:42:28 | "key2" | main.go:42:16:42:29 | type conversion | $@ is used to sign a JWT token. | main.go:42:23:42:28 | "key2" | Hardcoded String | -| main.go:61:44:61:46 | key | main.go:60:16:60:21 | `key3` | main.go:61:44:61:46 | key | $@ is used to sign a JWT token. | main.go:60:16:60:21 | `key3` | Hardcoded String | -| main.go:66:66:66:68 | key | main.go:65:16:65:21 | "key4" | main.go:66:66:66:68 | key | $@ is used to sign a JWT token. | main.go:65:16:65:21 | "key4" | Hardcoded String | -| main.go:74:15:74:18 | key2 | main.go:69:17:69:22 | "key5" | main.go:74:15:74:18 | key2 | $@ is used to sign a JWT token. | main.go:69:17:69:22 | "key5" | Hardcoded String | -| main.go:84:41:84:43 | key | main.go:80:16:80:21 | "key6" | main.go:84:41:84:43 | key | $@ is used to sign a JWT token. | main.go:80:16:80:21 | "key6" | Hardcoded String | -| main.go:91:66:91:69 | key2 | main.go:89:17:89:22 | "key7" | main.go:91:66:91:69 | key2 | $@ is used to sign a JWT token. | main.go:89:17:89:22 | "key7" | Hardcoded String | -| main.go:102:30:102:32 | key | main.go:97:16:97:21 | "key8" | main.go:102:30:102:32 | key | $@ is used to sign a JWT token. | main.go:97:16:97:21 | "key8" | Hardcoded String | -| main.go:107:16:107:24 | sharedKey | main.go:106:22:106:27 | "key9" | main.go:107:16:107:24 | sharedKey | $@ is used to sign a JWT token. | main.go:106:22:106:27 | "key9" | Hardcoded String | -| main.go:113:16:113:30 | sharedKeyglobal | main.go:110:30:110:36 | "key10" | main.go:113:16:113:30 | sharedKeyglobal | $@ is used to sign a JWT token. | main.go:110:30:110:36 | "key10" | Hardcoded String | +| main.go:42:28:42:39 | mySigningKey | main.go:33:25:33:30 | "key1" | main.go:42:28:42:39 | mySigningKey | $@ is used to sign a JWT token. | main.go:33:25:33:30 | "key1" | Hardcoded String | +| main.go:50:16:50:29 | type conversion | main.go:50:23:50:28 | "key2" | main.go:50:16:50:29 | type conversion | $@ is used to sign a JWT token. | main.go:50:23:50:28 | "key2" | Hardcoded String | +| main.go:69:44:69:46 | key | main.go:68:16:68:21 | `key3` | main.go:69:44:69:46 | key | $@ is used to sign a JWT token. | main.go:68:16:68:21 | `key3` | Hardcoded String | +| main.go:74:66:74:68 | key | main.go:73:16:73:21 | "key4" | main.go:74:66:74:68 | key | $@ is used to sign a JWT token. | main.go:73:16:73:21 | "key4" | Hardcoded String | +| main.go:82:15:82:18 | key2 | main.go:77:17:77:22 | "key5" | main.go:82:15:82:18 | key2 | $@ is used to sign a JWT token. | main.go:77:17:77:22 | "key5" | Hardcoded String | +| main.go:92:41:92:43 | key | main.go:88:16:88:21 | "key6" | main.go:92:41:92:43 | key | $@ is used to sign a JWT token. | main.go:88:16:88:21 | "key6" | Hardcoded String | +| main.go:99:66:99:69 | key2 | main.go:97:17:97:22 | "key7" | main.go:99:66:99:69 | key2 | $@ is used to sign a JWT token. | main.go:97:17:97:22 | "key7" | Hardcoded String | +| main.go:110:30:110:32 | key | main.go:105:16:105:21 | "key8" | main.go:110:30:110:32 | key | $@ is used to sign a JWT token. | main.go:105:16:105:21 | "key8" | Hardcoded String | +| main.go:115:16:115:24 | sharedKey | main.go:114:22:114:27 | "key9" | main.go:115:16:115:24 | sharedKey | $@ is used to sign a JWT token. | main.go:114:22:114:27 | "key9" | Hardcoded String | +| main.go:121:16:121:30 | sharedKeyglobal | main.go:118:30:118:36 | "key10" | main.go:121:16:121:30 | sharedKeyglobal | $@ is used to sign a JWT token. | main.go:118:30:118:36 | "key10" | Hardcoded String | +| main.go:127:20:127:34 | type conversion | main.go:127:27:127:33 | "key11" | main.go:127:20:127:34 | type conversion | $@ is used to sign a JWT token. | main.go:127:27:127:33 | "key11" | Hardcoded String | +| main.go:144:39:144:46 | mySecret | main.go:142:21:142:27 | "key12" | main.go:144:39:144:46 | mySecret | $@ is used to sign a JWT token. | main.go:142:21:142:27 | "key12" | Hardcoded String | +| main.go:153:11:153:18 | mySecret | main.go:149:21:149:27 | "key13" | main.go:153:11:153:18 | mySecret | $@ is used to sign a JWT token. | main.go:149:21:149:27 | "key13" | Hardcoded String | +| main.go:161:34:161:39 | secret | main.go:160:19:160:25 | "key14" | main.go:161:34:161:39 | secret | $@ is used to sign a JWT token. | main.go:160:19:160:25 | "key14" | Hardcoded String | +| main.go:167:32:167:37 | secret | main.go:166:19:166:25 | "key15" | main.go:167:32:167:37 | secret | $@ is used to sign a JWT token. | main.go:166:19:166:25 | "key15" | Hardcoded String | +| main.go:173:41:173:46 | secret | main.go:172:19:172:25 | "key16" | main.go:173:41:173:46 | secret | $@ is used to sign a JWT token. | main.go:172:19:172:25 | "key16" | Hardcoded String | +| main.go:179:51:179:56 | secret | main.go:178:19:178:25 | "key17" | main.go:179:51:179:56 | secret | $@ is used to sign a JWT token. | main.go:178:19:178:25 | "key17" | Hardcoded String | +| main.go:185:42:185:47 | secret | main.go:184:19:184:25 | "key18" | main.go:185:42:185:47 | secret | $@ is used to sign a JWT token. | main.go:184:19:184:25 | "key18" | Hardcoded String | +| main.go:193:33:193:38 | secret | main.go:190:19:190:25 | "key19" | main.go:193:33:193:38 | secret | $@ is used to sign a JWT token. | main.go:190:19:190:25 | "key19" | Hardcoded String | | sanitizer.go:18:44:18:46 | key | sanitizer.go:17:16:17:20 | `key` | sanitizer.go:18:44:18:46 | key | $@ is used to sign a JWT token. | sanitizer.go:17:16:17:20 | `key` | Hardcoded String | diff --git a/go/ql/test/experimental/CWE-321/go.mod b/go/ql/test/experimental/CWE-321/go.mod index 1f78c4037c0..68e45a0217b 100644 --- a/go/ql/test/experimental/CWE-321/go.mod +++ b/go/ql/test/experimental/CWE-321/go.mod @@ -6,14 +6,33 @@ require ( github.com/appleboy/gin-jwt/v2 v2.8.0 github.com/cristalhq/jwt/v3 v3.1.0 github.com/go-kit/kit v0.12.0 - github.com/golang-jwt/jwt/v4 v4.4.1 + github.com/gogf/gf-jwt/v2 v2.0.1 + github.com/golang-jwt/jwt/v4 v4.5.0 + github.com/iris-contrib/middleware/jwt v0.0.0-20230311205048-b568fe9b470f + github.com/kataras/iris/v12 v12.2.0 + github.com/kataras/jwt v0.1.8 github.com/lestrrat/go-jwx v0.9.1 github.com/square/go-jose/v3 v3.0.0-20200630053402-0a67ce9b0693 gopkg.in/square/go-jose.v2 v2.6.0 ) require ( + github.com/BurntSushi/toml v1.2.1 // indirect + github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 // indirect + github.com/CloudyKit/jet/v6 v6.2.0 // indirect + github.com/Joker/jade v1.1.3 // indirect + github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 // indirect + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/aymerick/douceur v0.2.0 // indirect + github.com/cespare/xxhash/v2 v2.1.2 // indirect + github.com/clbanning/mxj/v2 v2.5.5 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect + github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 // indirect + github.com/fatih/color v1.13.0 // indirect + github.com/fatih/structs v1.1.0 // indirect + github.com/flosch/pongo2/v4 v4.0.2 // indirect + github.com/fsnotify/fsnotify v1.5.4 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.7.7 // indirect github.com/go-kit/log v0.2.0 // indirect @@ -21,21 +40,58 @@ require ( github.com/go-playground/locales v0.13.0 // indirect github.com/go-playground/universal-translator v0.17.0 // indirect github.com/go-playground/validator/v10 v10.4.1 // indirect + github.com/go-redis/redis/v8 v8.11.5 // indirect + github.com/go-sql-driver/mysql v1.6.0 // indirect + github.com/gogf/gf/v2 v2.0.0-rc3 // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/gorilla/css v1.0.0 // indirect + github.com/gorilla/websocket v1.5.0 // indirect + github.com/grokify/html-strip-tags-go v0.0.1 // indirect + github.com/iris-contrib/schema v0.0.6 // indirect + github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/kataras/blocks v0.0.7 // indirect + github.com/kataras/golog v0.1.8 // indirect + github.com/kataras/pio v0.0.11 // indirect + github.com/kataras/sitemap v0.0.6 // indirect + github.com/kataras/tunnel v0.0.4 // indirect + github.com/klauspost/compress v1.16.0 // indirect github.com/leodido/go-urn v1.2.0 // indirect github.com/lestrrat/go-pdebug v0.0.0-20180220043741-569c97477ae8 // indirect - github.com/mattn/go-isatty v0.0.14 // indirect + github.com/mailgun/raymond/v2 v2.0.48 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/mattn/go-colorable v0.1.9 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-runewidth v0.0.9 // indirect + github.com/microcosm-cc/bluemonday v1.0.23 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect + github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/russross/blackfriday/v2 v2.1.0 // indirect + github.com/schollz/closestmatch v2.1.0+incompatible // indirect + github.com/sirupsen/logrus v1.8.1 // indirect + github.com/tdewolff/minify/v2 v2.12.4 // indirect + github.com/tdewolff/parse/v2 v2.6.4 // indirect github.com/ugorji/go/codec v1.1.7 // indirect - golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 // indirect - golang.org/x/net v0.0.0-20210917221730-978cfadd31cf // indirect - golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 // indirect - golang.org/x/text v0.3.7 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/yosssi/ace v0.0.5 // indirect + go.opentelemetry.io/otel v1.0.0 // indirect + go.opentelemetry.io/otel/sdk v1.0.0 // indirect + go.opentelemetry.io/otel/trace v1.0.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + golang.org/x/time v0.3.0 // indirect google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 // indirect google.golang.org/grpc v1.40.0 // indirect - google.golang.org/protobuf v1.27.1 // indirect - gopkg.in/yaml.v2 v2.2.8 // indirect + google.golang.org/protobuf v1.29.0 // indirect + gopkg.in/ini.v1 v1.67.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go/ql/test/experimental/CWE-321/main.go b/go/ql/test/experimental/CWE-321/main.go index 1e1f3ee45e4..d18dbf77203 100644 --- a/go/ql/test/experimental/CWE-321/main.go +++ b/go/ql/test/experimental/CWE-321/main.go @@ -1,13 +1,17 @@ package main //go:generate depstubber -vendor github.com/appleboy/gin-jwt/v2 GinJWTMiddleware New -//go:generate depstubber -vendor github.com/golang-jwt/jwt/v4 MapClaims,RegisteredClaims,SigningMethodRSA,SigningMethodHMAC,Token NewNumericDate,NewWithClaims +//go:generate depstubber -vendor github.com/golang-jwt/jwt/v4 MapClaims,RegisteredClaims,SigningMethodRSA,SigningMethodHMAC,Token NewNumericDate,NewWithClaims,New //go:generate depstubber -vendor github.com/gin-gonic/gin Context New //go:generate depstubber -vendor github.com/go-kit/kit/auth/jwt "" NewSigner //go:generate depstubber -vendor github.com/lestrrat/go-jwx/jwk "" New //go:generate depstubber -vendor github.com/square/go-jose/v3 Recipient NewEncrypter,NewSigner //go:generate depstubber -vendor gopkg.in/square/go-jose.v2 Recipient NewEncrypter,NewSigner //go:generate depstubber -vendor github.com/cristalhq/jwt/v3 Signer NewSignerHS,HS256 +//go:generate depstubber -vendor github.com/iris-contrib/middleware/jwt "" NewToken,NewTokenWithClaims +//go:generate depstubber -vendor github.com/kataras/iris/v12/middleware/jwt Signer,Verifier NewSigner,NewVerifier +//go:generate depstubber -vendor github.com/kataras/jwt Keys,Alg Sign,SignEncrypted,SignEncryptedWithHeader,SignWithHeader +//go:generate depstubber -vendor github.com/gogf/gf-jwt/v2 GfJWTMiddleware import ( "time" @@ -15,7 +19,11 @@ import ( jwt "github.com/appleboy/gin-jwt/v2" cristal "github.com/cristalhq/jwt/v3" gokit "github.com/go-kit/kit/auth/jwt" + gogf "github.com/gogf/gf-jwt/v2" gjwt "github.com/golang-jwt/jwt/v4" + iris "github.com/iris-contrib/middleware/jwt" + iris12 "github.com/kataras/iris/v12/middleware/jwt" + kataras "github.com/kataras/jwt" le "github.com/lestrrat/go-jwx/jwk" jose_v3 "github.com/square/go-jose/v3" jose_v2 "gopkg.in/square/go-jose.v2" @@ -113,6 +121,78 @@ func lejwt2() (interface{}, error) { return le.New(sharedKeyglobal) // BAD } +func gogfjwt() interface{} { + return &gogf.GfJWTMiddleware{ + Realm: "test zone", + Key: []byte("key11"), + Timeout: time.Minute * 5, + MaxRefresh: time.Minute * 5, + IdentityKey: "id", + TokenLookup: "header: Authorization, query: token, cookie: jwt", + TokenHeadName: "Bearer", + TimeFunc: time.Now, + Authenticator: nil, + Unauthorized: nil, + PayloadFunc: nil, + IdentityHandler: nil, + } +} + +func irisjwt() interface{} { + mySecret := []byte("key12") + token := iris.NewTokenWithClaims(nil, nil) + tokenString, _ := token.SignedString(mySecret) + return tokenString +} + +func iris12jwt2() interface{} { + mySecret := []byte("key13") + + s := &iris12.Signer{ + Alg: nil, + Key: mySecret, + MaxAge: 3 * time.Second, + } + return s +} + +func irisjwt3() interface{} { + secret := []byte("key14") + signer := iris12.NewSigner(nil, secret, 3*time.Second) + return signer +} + +func katarasJwt() interface{} { + secret := []byte("key15") + token, _ := kataras.Sign(nil, secret, nil, nil) + return token +} + +func katarasJwt2() interface{} { + secret := []byte("key16") + token, _ := kataras.SignEncrypted(nil, secret, nil, nil) + return token +} + +func katarasJwt3() interface{} { + secret := []byte("key17") + token, _ := kataras.SignEncryptedWithHeader(nil, secret, nil, nil, nil) + return token +} + +func katarasJwt4() interface{} { + secret := []byte("key18") + token, _ := kataras.SignWithHeader(nil, secret, nil, nil) + return token +} + +func katarasJwt5() { + secret := []byte("key19") + var keys kataras.Keys + var alg kataras.Alg + keys.Register(alg, "api", nil, secret) +} + func main() { return } diff --git a/go/ql/test/experimental/CWE-321/vendor/github.com/gin-gonic/gin/stub.go b/go/ql/test/experimental/CWE-321/vendor/github.com/gin-gonic/gin/stub.go index f941716f925..79c7a98ec0b 100644 --- a/go/ql/test/experimental/CWE-321/vendor/github.com/gin-gonic/gin/stub.go +++ b/go/ql/test/experimental/CWE-321/vendor/github.com/gin-gonic/gin/stub.go @@ -14,6 +14,7 @@ import ( multipart "mime/multipart" net "net" http "net/http" + template0 "text/template" time "time" ) @@ -388,7 +389,7 @@ type Engine struct { TrustedPlatform string MaxMultipartMemory int64 HTMLRender interface{} - FuncMap template.FuncMap + FuncMap template0.FuncMap } func (_ *Engine) Any(_ string, _ ...HandlerFunc) IRoutes { @@ -479,7 +480,7 @@ func (_ *Engine) SecureJsonPrefix(_ string) *Engine { func (_ *Engine) ServeHTTP(_ http.ResponseWriter, _ *http.Request) {} -func (_ *Engine) SetFuncMap(_ template.FuncMap) {} +func (_ *Engine) SetFuncMap(_ template0.FuncMap) {} func (_ *Engine) SetHTMLTemplate(_ *template.Template) {} diff --git a/go/ql/test/experimental/CWE-321/vendor/github.com/gogf/gf-jwt/v2/stub.go b/go/ql/test/experimental/CWE-321/vendor/github.com/gogf/gf-jwt/v2/stub.go new file mode 100644 index 00000000000..343b5f84dca --- /dev/null +++ b/go/ql/test/experimental/CWE-321/vendor/github.com/gogf/gf-jwt/v2/stub.go @@ -0,0 +1,90 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for github.com/gogf/gf-jwt/v2, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: github.com/gogf/gf-jwt/v2 (exports: GfJWTMiddleware; functions: ) + +// Package gf is a stub of github.com/gogf/gf-jwt/v2, generated by depstubber. +package gf + +import ( + context "context" + time "time" +) + +type GfJWTMiddleware struct { + Realm string + SigningAlgorithm string + Key []byte + KeyFunc func(interface{}) (interface{}, error) + Timeout time.Duration + MaxRefresh time.Duration + Authenticator func(context.Context) (interface{}, error) + Authorizator func(interface{}, context.Context) bool + PayloadFunc func(interface{}) MapClaims + Unauthorized func(context.Context, int, string) + IdentityHandler func(context.Context) interface{} + IdentityKey string + TokenLookup string + TokenHeadName string + TimeFunc func() time.Time + HTTPStatusMessageFunc func(error, context.Context) string + PrivKeyFile string + PrivKeyBytes []byte + PubKeyFile string + PrivateKeyPassphrase string + PubKeyBytes []byte + SendCookie bool + CookieMaxAge time.Duration + SecureCookie bool + CookieHTTPOnly bool + CookieDomain string + SendAuthorization bool + DisabledAbort bool + CookieName string + CacheAdapter interface{} +} + +func (_ *GfJWTMiddleware) CheckIfTokenExpire(_ context.Context) (interface{}, string, error) { + return nil, "", nil +} + +func (_ *GfJWTMiddleware) GetClaimsFromJWT(_ context.Context) (MapClaims, string, error) { + return nil, "", nil +} + +func (_ *GfJWTMiddleware) GetIdentity(_ context.Context) interface{} { + return nil +} + +func (_ *GfJWTMiddleware) GetPayload(_ context.Context) string { + return "" +} + +func (_ *GfJWTMiddleware) GetToken(_ context.Context) string { + return "" +} + +func (_ *GfJWTMiddleware) LoginHandler(_ context.Context) (string, time.Time) { + return "", time.Time{} +} + +func (_ *GfJWTMiddleware) LogoutHandler(_ context.Context) {} + +func (_ *GfJWTMiddleware) MiddlewareFunc() func(interface{}) { + return nil +} + +func (_ *GfJWTMiddleware) RefreshHandler(_ context.Context) (string, time.Time) { + return "", time.Time{} +} + +func (_ *GfJWTMiddleware) RefreshToken(_ context.Context) (string, time.Time, error) { + return "", time.Time{}, nil +} + +func (_ *GfJWTMiddleware) TokenGenerator(_ interface{}) (string, time.Time, error) { + return "", time.Time{}, nil +} + +type MapClaims map[string]interface{} diff --git a/go/ql/test/experimental/CWE-321/vendor/github.com/golang-jwt/jwt/v4/stub.go b/go/ql/test/experimental/CWE-321/vendor/github.com/golang-jwt/jwt/v4/stub.go index d83739d7fde..a64a6c31e32 100644 --- a/go/ql/test/experimental/CWE-321/vendor/github.com/golang-jwt/jwt/v4/stub.go +++ b/go/ql/test/experimental/CWE-321/vendor/github.com/golang-jwt/jwt/v4/stub.go @@ -2,7 +2,7 @@ // This is a simple stub for github.com/golang-jwt/jwt/v4, strictly for use in testing. // See the LICENSE file for information about the licensing of the original library. -// Source: github.com/golang-jwt/jwt/v4 (exports: MapClaims,RegisteredClaims,SigningMethodRSA,SigningMethodHMAC,Token; functions: NewNumericDate,NewWithClaims) +// Source: github.com/golang-jwt/jwt/v4 (exports: MapClaims,RegisteredClaims,SigningMethodRSA,SigningMethodHMAC,Token; functions: NewNumericDate,NewWithClaims,New) // Package jwt is a stub of github.com/golang-jwt/jwt/v4, generated by depstubber. package jwt @@ -52,6 +52,10 @@ func (_ MapClaims) VerifyNotBefore(_ int64, _ bool) bool { return false } +func New(_ SigningMethod) *Token { + return nil +} + func NewNumericDate(_ time.Time) *NumericDate { return nil } @@ -220,6 +224,10 @@ func (_ NumericDate) Zone() (string, int) { return "", 0 } +func (_ NumericDate) ZoneBounds() (time.Time, time.Time) { + return time.Time{}, time.Time{} +} + func (_ *NumericDate) GobDecode(_ []byte) error { return nil } diff --git a/go/ql/test/experimental/CWE-321/vendor/github.com/iris-contrib/middleware/jwt/stub.go b/go/ql/test/experimental/CWE-321/vendor/github.com/iris-contrib/middleware/jwt/stub.go new file mode 100644 index 00000000000..942d8731623 --- /dev/null +++ b/go/ql/test/experimental/CWE-321/vendor/github.com/iris-contrib/middleware/jwt/stub.go @@ -0,0 +1,29 @@ +// Package jwt is a stub of github.com/iris-contrib/middleware/jwt, manually generated. +package jwt + +import ( + gj "github.com/golang-jwt/jwt/v4" +) + +type ( + // Token for JWT. Different fields will be used depending on whether you're + // creating or parsing/verifying a token. + // + // A type alias for jwt.Token. + Token = gj.Token + // MapClaims type that uses the map[string]interface{} for JSON decoding + // This is the default claims type if you don't supply one + // + // A type alias for jwt.MapClaims. + MapClaims = gj.MapClaims + // Claims must just have a Valid method that determines + // if the token is invalid for any supported reason. + // + // A type alias for jwt.Claims. + Claims = gj.Claims +) + +var ( + NewToken = gj.New + NewTokenWithClaims = gj.NewWithClaims +) diff --git a/go/ql/test/experimental/CWE-321/vendor/github.com/kataras/iris/v12/middleware/jwt/stub.go b/go/ql/test/experimental/CWE-321/vendor/github.com/kataras/iris/v12/middleware/jwt/stub.go new file mode 100644 index 00000000000..750ed4a15ee --- /dev/null +++ b/go/ql/test/experimental/CWE-321/vendor/github.com/kataras/iris/v12/middleware/jwt/stub.go @@ -0,0 +1,81 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for github.com/kataras/iris/v12/middleware/jwt, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: github.com/kataras/iris/v12/middleware/jwt (exports: Signer,Verifier; functions: NewSigner,NewVerifier) + +// Package jwt is a stub of github.com/kataras/iris/v12/middleware/jwt, generated by depstubber. +package jwt + +import ( + time "time" +) + +type Blocklist interface { + Count() (int64, error) + Del(_ string) error + Has(_ string) (bool, error) + InvalidateToken(_ []byte, _ interface{}) error + ValidateToken(_ []byte, _ interface{}, _ error) error +} + +func NewSigner(_ interface{}, _ interface{}, _ time.Duration) *Signer { + return nil +} + +func NewVerifier(_ interface{}, _ interface{}, _ ...interface{}) *Verifier { + return nil +} + +type Signer struct { + Alg interface{} + Key interface{} + MaxAge time.Duration + Options []interface{} + Encrypt func([]byte) ([]byte, error) +} + +func (_ *Signer) NewTokenPair(_ interface{}, _ interface{}, _ time.Duration, _ ...interface{}) (interface{}, error) { + return nil, nil +} + +func (_ *Signer) Sign(_ interface{}, _ ...interface{}) ([]byte, error) { + return nil, nil +} + +func (_ *Signer) WithEncryption(_ []byte, _ []byte) *Signer { + return nil +} + +type TokenExtractor func(interface{}) string + +type Verifier struct { + Alg interface{} + Key interface{} + Decrypt func([]byte) ([]byte, error) + Extractors []TokenExtractor + Blocklist Blocklist + Validators []interface{} + ErrorHandler func(interface{}, error) + DisableContextUser bool +} + +func (_ *Verifier) RequestToken(_ interface{}) string { + return "" +} + +func (_ *Verifier) Verify(_ func() interface{}, _ ...interface{}) interface{} { + return nil +} + +func (_ *Verifier) VerifyToken(_ []byte, _ ...interface{}) (interface{}, error) { + return nil, nil +} + +func (_ *Verifier) WithDecryption(_ []byte, _ []byte) *Verifier { + return nil +} + +func (_ *Verifier) WithDefaultBlocklist() *Verifier { + return nil +} diff --git a/go/ql/test/experimental/CWE-321/vendor/github.com/kataras/jwt/stub.go b/go/ql/test/experimental/CWE-321/vendor/github.com/kataras/jwt/stub.go new file mode 100644 index 00000000000..ee94e737207 --- /dev/null +++ b/go/ql/test/experimental/CWE-321/vendor/github.com/kataras/jwt/stub.go @@ -0,0 +1,105 @@ +// Code generated by depstubber. DO NOT EDIT. +// This is a simple stub for github.com/kataras/jwt, strictly for use in testing. + +// See the LICENSE file for information about the licensing of the original library. +// Source: github.com/kataras/jwt (exports: Keys,Alg; functions: Sign,SignEncrypted,SignEncryptedWithHeader,SignWithHeader) + +// Package jwt is a stub of github.com/kataras/jwt, generated by depstubber. +package jwt + +import ( + time "time" +) + +type Alg interface { + Name() string + Sign(_ interface{}, _ []byte) ([]byte, error) + Verify(_ interface{}, _ []byte, _ []byte) error +} + +type Audience []string + +func (_ *Audience) UnmarshalJSON(_ []byte) error { + return nil +} + +type Claims struct { + NotBefore int64 + IssuedAt int64 + Expiry int64 + ID string + OriginID string + Issuer string + Subject string + Audience Audience +} + +func (_ Claims) Age() time.Duration { + return 0 +} + +func (_ Claims) ApplyClaims(_ *Claims) {} + +func (_ Claims) ExpiresAt() time.Time { + return time.Time{} +} + +func (_ Claims) Timeleft() time.Duration { + return 0 +} + +type InjectFunc func([]byte) ([]byte, error) + +type Key struct { + ID string + Alg Alg + Public interface{} + Private interface{} + MaxAge time.Duration + Encrypt InjectFunc + Decrypt InjectFunc +} + +type Keys map[string]*Key + +func (_ Keys) Get(_ string) (*Key, bool) { + return nil, false +} + +func (_ Keys) Register(_ Alg, _ string, _ interface{}, _ interface{}) {} + +func (_ Keys) SignToken(_ string, _ interface{}, _ ...SignOption) ([]byte, error) { + return nil, nil +} + +func (_ Keys) ValidateHeader(_ string, _ []byte) (Alg, interface{}, InjectFunc, error) { + return nil, nil, nil, nil +} + +func (_ Keys) VerifyToken(_ []byte, _ interface{}, _ ...TokenValidator) error { + return nil +} + +func Sign(_ Alg, _ interface{}, _ interface{}, _ ...SignOption) ([]byte, error) { + return nil, nil +} + +func SignEncrypted(_ Alg, _ interface{}, _ InjectFunc, _ interface{}, _ ...SignOption) ([]byte, error) { + return nil, nil +} + +func SignEncryptedWithHeader(_ Alg, _ interface{}, _ InjectFunc, _ interface{}, _ interface{}, _ ...SignOption) ([]byte, error) { + return nil, nil +} + +type SignOption interface { + ApplyClaims(_ *Claims) +} + +func SignWithHeader(_ Alg, _ interface{}, _ interface{}, _ interface{}, _ ...SignOption) ([]byte, error) { + return nil, nil +} + +type TokenValidator interface { + ValidateToken(_ []byte, _ Claims, _ error) error +} diff --git a/go/ql/test/experimental/CWE-321/vendor/modules.txt b/go/ql/test/experimental/CWE-321/vendor/modules.txt index 1a10cd454fb..61fe07b4540 100644 --- a/go/ql/test/experimental/CWE-321/vendor/modules.txt +++ b/go/ql/test/experimental/CWE-321/vendor/modules.txt @@ -4,15 +4,24 @@ github.com/appleboy/gin-jwt/v2 # github.com/cristalhq/jwt/v3 v3.1.0 ## explicit github.com/cristalhq/jwt/v3 -# github.com/gin-gonic/gin v1.7.7 -## explicit -github.com/gin-gonic/gin # github.com/go-kit/kit v0.12.0 ## explicit github.com/go-kit/kit -# github.com/golang-jwt/jwt/v4 v4.4.1 +# github.com/gogf/gf-jwt/v2 v2.0.1 +## explicit +github.com/gogf/gf-jwt/v2 +# github.com/golang-jwt/jwt/v4 v4.5.0 ## explicit github.com/golang-jwt/jwt/v4 +# github.com/iris-contrib/middleware/jwt v0.0.0-20230311205048-b568fe9b470f +## explicit +github.com/iris-contrib/middleware/jwt +# github.com/kataras/iris/v12 v12.2.0 +## explicit +github.com/kataras/iris/v12 +# github.com/kataras/jwt v0.1.8 +## explicit +github.com/kataras/jwt # github.com/lestrrat/go-jwx v0.9.1 ## explicit github.com/lestrrat/go-jwx @@ -22,12 +31,60 @@ github.com/square/go-jose/v3 # gopkg.in/square/go-jose.v2 v2.6.0 ## explicit gopkg.in/square/go-jose.v2 +# github.com/BurntSushi/toml v1.2.1 +## explicit +github.com/BurntSushi/toml +# github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53 +## explicit +github.com/CloudyKit/fastprinter +# github.com/CloudyKit/jet/v6 v6.2.0 +## explicit +github.com/CloudyKit/jet/v6 +# github.com/Joker/jade v1.1.3 +## explicit +github.com/Joker/jade +# github.com/Shopify/goreferrer v0.0.0-20220729165902-8cddb4f5de06 +## explicit +github.com/Shopify/goreferrer +# github.com/andybalholm/brotli v1.0.5 +## explicit +github.com/andybalholm/brotli +# github.com/aymerick/douceur v0.2.0 +## explicit +github.com/aymerick/douceur +# github.com/cespare/xxhash/v2 v2.1.2 +## explicit +github.com/cespare/xxhash/v2 +# github.com/clbanning/mxj/v2 v2.5.5 +## explicit +github.com/clbanning/mxj/v2 # github.com/davecgh/go-spew v1.1.1 ## explicit github.com/davecgh/go-spew +# github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f +## explicit +github.com/dgryski/go-rendezvous +# github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385 +## explicit +github.com/eknkc/amber +# github.com/fatih/color v1.13.0 +## explicit +github.com/fatih/color +# github.com/fatih/structs v1.1.0 +## explicit +github.com/fatih/structs +# github.com/flosch/pongo2/v4 v4.0.2 +## explicit +github.com/flosch/pongo2/v4 +# github.com/fsnotify/fsnotify v1.5.4 +## explicit +github.com/fsnotify/fsnotify # github.com/gin-contrib/sse v0.1.0 ## explicit github.com/gin-contrib/sse +# github.com/gin-gonic/gin v1.7.7 +## explicit +github.com/gin-gonic/gin # github.com/go-kit/log v0.2.0 ## explicit github.com/go-kit/log @@ -43,54 +100,165 @@ github.com/go-playground/universal-translator # github.com/go-playground/validator/v10 v10.4.1 ## explicit github.com/go-playground/validator/v10 +# github.com/go-redis/redis/v8 v8.11.5 +## explicit +github.com/go-redis/redis/v8 +# github.com/go-sql-driver/mysql v1.6.0 +## explicit +github.com/go-sql-driver/mysql +# github.com/gogf/gf/v2 v2.0.0-rc3 +## explicit +github.com/gogf/gf/v2 # github.com/golang/protobuf v1.5.2 ## explicit github.com/golang/protobuf +# github.com/golang/snappy v0.0.4 +## explicit +github.com/golang/snappy +# github.com/google/uuid v1.3.0 +## explicit +github.com/google/uuid +# github.com/gorilla/css v1.0.0 +## explicit +github.com/gorilla/css +# github.com/gorilla/websocket v1.5.0 +## explicit +github.com/gorilla/websocket +# github.com/grokify/html-strip-tags-go v0.0.1 +## explicit +github.com/grokify/html-strip-tags-go +# github.com/iris-contrib/schema v0.0.6 +## explicit +github.com/iris-contrib/schema +# github.com/josharian/intern v1.0.0 +## explicit +github.com/josharian/intern # github.com/json-iterator/go v1.1.12 ## explicit github.com/json-iterator/go +# github.com/kataras/blocks v0.0.7 +## explicit +github.com/kataras/blocks +# github.com/kataras/golog v0.1.8 +## explicit +github.com/kataras/golog +# github.com/kataras/pio v0.0.11 +## explicit +github.com/kataras/pio +# github.com/kataras/sitemap v0.0.6 +## explicit +github.com/kataras/sitemap +# github.com/kataras/tunnel v0.0.4 +## explicit +github.com/kataras/tunnel +# github.com/klauspost/compress v1.16.0 +## explicit +github.com/klauspost/compress # github.com/leodido/go-urn v1.2.0 ## explicit github.com/leodido/go-urn # github.com/lestrrat/go-pdebug v0.0.0-20180220043741-569c97477ae8 ## explicit github.com/lestrrat/go-pdebug -# github.com/mattn/go-isatty v0.0.14 +# github.com/mailgun/raymond/v2 v2.0.48 +## explicit +github.com/mailgun/raymond/v2 +# github.com/mailru/easyjson v0.7.7 +## explicit +github.com/mailru/easyjson +# github.com/mattn/go-colorable v0.1.9 +## explicit +github.com/mattn/go-colorable +# github.com/mattn/go-isatty v0.0.17 ## explicit github.com/mattn/go-isatty +# github.com/mattn/go-runewidth v0.0.9 +## explicit +github.com/mattn/go-runewidth +# github.com/microcosm-cc/bluemonday v1.0.23 +## explicit +github.com/microcosm-cc/bluemonday # github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd ## explicit github.com/modern-go/concurrent # github.com/modern-go/reflect2 v1.0.2 ## explicit github.com/modern-go/reflect2 +# github.com/olekukonko/tablewriter v0.0.5 +## explicit +github.com/olekukonko/tablewriter # github.com/pkg/errors v0.9.1 ## explicit github.com/pkg/errors +# github.com/russross/blackfriday/v2 v2.1.0 +## explicit +github.com/russross/blackfriday/v2 +# github.com/schollz/closestmatch v2.1.0+incompatible +## explicit +github.com/schollz/closestmatch +# github.com/sirupsen/logrus v1.8.1 +## explicit +github.com/sirupsen/logrus +# github.com/tdewolff/minify/v2 v2.12.4 +## explicit +github.com/tdewolff/minify/v2 +# github.com/tdewolff/parse/v2 v2.6.4 +## explicit +github.com/tdewolff/parse/v2 # github.com/ugorji/go/codec v1.1.7 ## explicit github.com/ugorji/go/codec -# golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 +# github.com/valyala/bytebufferpool v1.0.0 +## explicit +github.com/valyala/bytebufferpool +# github.com/vmihailenco/msgpack/v5 v5.3.5 +## explicit +github.com/vmihailenco/msgpack/v5 +# github.com/vmihailenco/tagparser/v2 v2.0.0 +## explicit +github.com/vmihailenco/tagparser/v2 +# github.com/yosssi/ace v0.0.5 +## explicit +github.com/yosssi/ace +# go.opentelemetry.io/otel v1.0.0 +## explicit +go.opentelemetry.io/otel +# go.opentelemetry.io/otel/sdk v1.0.0 +## explicit +go.opentelemetry.io/otel/sdk +# go.opentelemetry.io/otel/trace v1.0.0 +## explicit +go.opentelemetry.io/otel/trace +# golang.org/x/crypto v0.7.0 ## explicit golang.org/x/crypto -# golang.org/x/net v0.0.0-20210917221730-978cfadd31cf +# golang.org/x/net v0.8.0 ## explicit golang.org/x/net -# golang.org/x/sys v0.0.0-20210917161153-d61c044b1678 +# golang.org/x/sys v0.6.0 ## explicit golang.org/x/sys -# golang.org/x/text v0.3.7 +# golang.org/x/text v0.8.0 ## explicit golang.org/x/text +# golang.org/x/time v0.3.0 +## explicit +golang.org/x/time # google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4 ## explicit google.golang.org/genproto # google.golang.org/grpc v1.40.0 ## explicit google.golang.org/grpc -# google.golang.org/protobuf v1.27.1 +# google.golang.org/protobuf v1.29.0 ## explicit google.golang.org/protobuf -# gopkg.in/yaml.v2 v2.2.8 +# gopkg.in/ini.v1 v1.67.0 +## explicit +gopkg.in/ini.v1 +# gopkg.in/yaml.v2 v2.4.0 ## explicit gopkg.in/yaml.v2 +# gopkg.in/yaml.v3 v3.0.1 +## explicit +gopkg.in/yaml.v3 From e5700e07c7912e7b217ec1311b0a5b2ae9202a14 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Fri, 31 Mar 2023 21:33:28 +0100 Subject: [PATCH 131/141] C++: Fix join order in 'cpp/unsafe-strncat'. --- .../Memory Management/SuspiciousCallToStrncat.ql | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql index 0d46332a40a..37ad8fd7076 100644 --- a/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql +++ b/cpp/ql/src/Likely Bugs/Memory Management/SuspiciousCallToStrncat.ql @@ -48,11 +48,11 @@ predicate case1(FunctionCall fc, Expr sizeArg, VariableAccess destArg) { * Holds if `fc` is a call to `strncat` with size argument `sizeArg` and destination * argument `destArg`, and `sizeArg` computes the value `sizeof (dest) - strlen (dest)`. */ -predicate case2(FunctionCall fc, Expr sizeArg, VariableAccess destArg) { - interestingCallWithArgs(fc, sizeArg, destArg) and +predicate case2(FunctionCall fc, Expr sizeArg, Expr destArg) { + interestingCallWithArgs(fc, pragma[only_bind_into](sizeArg), pragma[only_bind_into](destArg)) and exists(SubExpr sub, int n | // The destination buffer is an array of size n - destArg.getUnspecifiedType().(ArrayType).getSize() = n and + pragma[only_bind_out](destArg.getUnspecifiedType().(ArrayType).getSize()) = n and // The size argument is equivalent to a subtraction globalValueNumber(sizeArg).getAnExpr() = sub and // ... where the left side of the subtraction is the constant n From e641505361f23e8120429796e268f8907ccea66c Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Fri, 31 Mar 2023 11:05:28 -0400 Subject: [PATCH 132/141] Fix partial path traversal Java example Again The original wouldn't compile, and the fix made by #11899 is sub-optimal. This keeps the entire comparision using the Java `Path` object, which is optimal. Signed-off-by: Jonathan Leitschuh --- .../src/Security/CWE/CWE-023/PartialPathTraversalBad.java | 2 +- .../src/Security/CWE/CWE-023/PartialPathTraversalGood.java | 6 ++++-- .../CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp | 7 +++---- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalBad.java b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalBad.java index e933679aa44..961d8c21c6b 100644 --- a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalBad.java +++ b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalBad.java @@ -1,7 +1,7 @@ public class PartialPathTraversalBad { public void example(File dir, File parent) throws IOException { if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath())) { - throw new IOException("Invalid directory: " + dir.getCanonicalPath()); + throw new IOException("Path traversal attempt: " + dir.getCanonicalPath()); } } } diff --git a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalGood.java b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalGood.java index baf4ef8545e..65392373a25 100644 --- a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalGood.java +++ b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalGood.java @@ -1,7 +1,9 @@ +import java.io.File; + public class PartialPathTraversalGood { public void example(File dir, File parent) throws IOException { - if (!dir.getCanonicalPath().startsWith(parent.getCanonicalPath() + File.separator)) { - throw new IOException("Invalid directory: " + dir.getCanonicalPath()); + if (!dir.toPath().normalize().startsWith(parent.toPath())) { + throw new IOException("Path traversal attempt: " + dir.getCanonicalPath()); } } } diff --git a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp index 7703f5c52ff..5338a98efc5 100644 --- a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp +++ b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp @@ -26,10 +26,9 @@ and not just children of parent, which is a security issue.

-In this example, the if statement checks if parent.getCanonicalPath() + File.separator -is a prefix of dir.getCanonicalPath(). Because parent.getCanonicalPath() + File.separator is -indeed slash-terminated, the user supplying dir can only access children of -parent, as desired. +In this example, the if statement checks if parent.toPath() +is a prefix of dir.normalize(). Because Path#startsWith will do the correct check that +dir is ia child children of parent, as desired.

From b9d409279bf38b8e3200c07d453ea1581a78b0fe Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Fri, 31 Mar 2023 15:17:56 -0400 Subject: [PATCH 133/141] Update java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp Co-authored-by: Tony Torralba --- .../CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp index 5338a98efc5..342d38ac5c2 100644 --- a/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp +++ b/java/ql/src/Security/CWE/CWE-023/PartialPathTraversalRemainder.inc.qhelp @@ -27,8 +27,8 @@ and not just children of parent, which is a security issue.

In this example, the if statement checks if parent.toPath() -is a prefix of dir.normalize(). Because Path#startsWith will do the correct check that -dir is ia child children of parent, as desired. +is a prefix of dir.normalize(). Because Path#startsWith does the correct check that +dir is a child of parent, users will not be able to access siblings of parent, as desired.

From 0d774a647ca4766f2db86163f3e6270d974a4969 Mon Sep 17 00:00:00 2001 From: Jonathan Leitschuh Date: Fri, 31 Mar 2023 11:05:28 -0400 Subject: [PATCH 134/141] Fix partial path traversal Java example Again The original wouldn't compile, and the fix made by #11899 is sub-optimal. This keeps the entire comparision using the Java `Path` object, which is optimal. Signed-off-by: Jonathan Leitschuh --- .../CWE-023/semmle/tests/PartialPathTraversalTest.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalTest.java b/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalTest.java index b7c0256d075..af0fd776de1 100644 --- a/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalTest.java +++ b/java/ql/test/query-tests/security/CWE-023/semmle/tests/PartialPathTraversalTest.java @@ -225,6 +225,12 @@ public class PartialPathTraversalTest { } } + public void doesNotFlagOptimalSafeVersion(File dir, File parent) throws IOException { + if (!dir.toPath().normalize().startsWith(parent.toPath())) { // Safe + throw new IOException("Path traversal attempt: " + dir.getCanonicalPath()); + } + } + public void doesNotFlag() { "hello".startsWith("goodbye"); } From 17bd9c12d7ac143f5c424e7d8e061fbbfa8ee4d8 Mon Sep 17 00:00:00 2001 From: Jeroen Ketema Date: Mon, 3 Apr 2023 09:25:19 +0200 Subject: [PATCH 135/141] JS: Fix qhelp after file rename --- .../ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp index 1efdbe694b1..f9e3a5b3857 100644 --- a/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp +++ b/javascript/ql/src/Security/CWE-916/InsufficientPasswordHash.qhelp @@ -37,7 +37,7 @@ the hash of a password.

- +

This is not secure, since the password can be efficiently @@ -46,7 +46,7 @@ algorithm:

- + From e8800a6dbaaf5cb6fb973d1d143f13028237e69d Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 3 Apr 2023 13:52:55 +0100 Subject: [PATCH 136/141] C++: Move the new range-analysis library out of experimental and into an 'internal' directory. --- .../rangeanalysis/new/SimpleRangeAnalysis.qll | 132 ++ .../new/internal/semantic/Semantic.qll | 7 + .../new/internal/semantic/SemanticBound.qll | 45 + .../new/internal/semantic/SemanticCFG.qll | 22 + .../new/internal/semantic/SemanticExpr.qll | 309 +++++ .../semantic/SemanticExprSpecific.qll | 450 ++++++ .../new/internal/semantic/SemanticGuard.qll | 65 + .../internal/semantic/SemanticLocation.qll | 23 + .../new/internal/semantic/SemanticOpcode.qll | 187 +++ .../new/internal/semantic/SemanticSSA.qll | 75 + .../new/internal/semantic/SemanticType.qll | 311 +++++ .../semantic/SemanticTypeSpecific.qll | 43 + .../new/internal/semantic/analysis/Bound.qll | 86 ++ .../semantic/analysis/ConstantAnalysis.qll | 31 + .../analysis/ConstantAnalysisSpecific.qll | 10 + .../internal/semantic/analysis/FloatDelta.qll | 20 + .../internal/semantic/analysis/IntDelta.qll | 29 + .../semantic/analysis/ModulusAnalysis.qll | 341 +++++ .../analysis/ModulusAnalysisSpecific.qll | 8 + .../semantic/analysis/RangeAnalysis.qll | 2 + .../semantic/analysis/RangeAnalysisImpl.qll | 107 ++ .../analysis/RangeAnalysisSpecific.qll | 92 ++ .../semantic/analysis/RangeAnalysisStage.qll | 1217 +++++++++++++++++ .../internal/semantic/analysis/RangeUtils.qll | 140 ++ .../new/internal/semantic/analysis/Sign.qll | 267 ++++ .../semantic/analysis/SignAnalysisCommon.qll | 510 +++++++ .../analysis/SignAnalysisSpecific.qll | 23 + 27 files changed, 4552 insertions(+) create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/SimpleRangeAnalysis.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/Semantic.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticBound.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticCFG.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExpr.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticLocation.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticOpcode.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticSSA.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticType.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticTypeSpecific.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Bound.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysis.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysisSpecific.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/FloatDelta.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/IntDelta.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysisSpecific.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysis.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisImpl.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisSpecific.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Sign.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisCommon.qll create mode 100644 cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisSpecific.qll diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/SimpleRangeAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/SimpleRangeAnalysis.qll new file mode 100644 index 00000000000..04cb8a5a3fa --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/SimpleRangeAnalysis.qll @@ -0,0 +1,132 @@ +/** + * Wrapper for the semantic range analysis library that mimics the + * interface of the simple range analysis library. + */ + +private import cpp +private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis + +/** + * Gets the lower bound of the expression. + * + * Note: expressions in C/C++ are often implicitly or explicitly cast to a + * different result type. Such casts can cause the value of the expression + * to overflow or to be truncated. This predicate computes the lower bound + * of the expression without including the effect of the casts. To compute + * the lower bound of the expression after all the casts have been applied, + * call `lowerBound` like this: + * + * `lowerBound(expr.getFullyConverted())` + */ +float lowerBound(Expr expr) { + exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound | + semBounded(getSemanticExpr(i), b, result, false, _) + ) +} + +/** + * Gets the upper bound of the expression. + * + * Note: expressions in C/C++ are often implicitly or explicitly cast to a + * different result type. Such casts can cause the value of the expression + * to overflow or to be truncated. This predicate computes the upper bound + * of the expression without including the effect of the casts. To compute + * the upper bound of the expression after all the casts have been applied, + * call `upperBound` like this: + * + * `upperBound(expr.getFullyConverted())` + */ +float upperBound(Expr expr) { + exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound | + semBounded(getSemanticExpr(i), b, result, true, _) + ) +} + +/** + * Holds if the upper bound of `expr` may have been widened. This means the + * upper bound is in practice likely to be overly wide. + */ +predicate upperBoundMayBeWidened(Expr e) { none() } + +/** + * Holds if `expr` has a provably empty range. For example: + * + * 10 < expr and expr < 5 + * + * The range of an expression can only be empty if it can never be + * executed. For example: + * + * ```cpp + * if (10 < x) { + * if (x < 5) { + * // Unreachable code + * return x; // x has an empty range: 10 < x && x < 5 + * } + * } + * ``` + */ +predicate exprWithEmptyRange(Expr expr) { lowerBound(expr) > upperBound(expr) } + +/** Holds if the definition might overflow negatively. */ +predicate defMightOverflowNegatively(RangeSsaDefinition def, StackVariable v) { none() } + +/** Holds if the definition might overflow positively. */ +predicate defMightOverflowPositively(RangeSsaDefinition def, StackVariable v) { none() } + +/** + * Holds if the definition might overflow (either positively or + * negatively). + */ +predicate defMightOverflow(RangeSsaDefinition def, StackVariable v) { + defMightOverflowNegatively(def, v) or + defMightOverflowPositively(def, v) +} + +/** + * Holds if the expression might overflow negatively. This predicate + * does not consider the possibility that the expression might overflow + * due to a conversion. + */ +predicate exprMightOverflowNegatively(Expr expr) { none() } + +/** + * Holds if the expression might overflow negatively. Conversions + * are also taken into account. For example the expression + * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than + * due to the addition. + */ +predicate convertedExprMightOverflowNegatively(Expr expr) { + exprMightOverflowNegatively(expr) or + convertedExprMightOverflowNegatively(expr.getConversion()) +} + +/** + * Holds if the expression might overflow positively. This predicate + * does not consider the possibility that the expression might overflow + * due to a conversion. + */ +predicate exprMightOverflowPositively(Expr expr) { none() } + +/** + * Holds if the expression might overflow positively. Conversions + * are also taken into account. For example the expression + * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than + * due to the addition. + */ +predicate convertedExprMightOverflowPositively(Expr expr) { + exprMightOverflowPositively(expr) or + convertedExprMightOverflowPositively(expr.getConversion()) +} + +/** + * Holds if the expression might overflow (either positively or + * negatively). The possibility that the expression might overflow + * due to an implicit or explicit cast is also considered. + */ +predicate convertedExprMightOverflow(Expr expr) { + convertedExprMightOverflowNegatively(expr) or + convertedExprMightOverflowPositively(expr) +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/Semantic.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/Semantic.qll new file mode 100644 index 00000000000..2238a8b6c94 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/Semantic.qll @@ -0,0 +1,7 @@ +import SemanticExpr +import SemanticBound +import SemanticSSA +import SemanticGuard +import SemanticCFG +import SemanticType +import SemanticOpcode diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticBound.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticBound.qll new file mode 100644 index 00000000000..a1814f659fc --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticBound.qll @@ -0,0 +1,45 @@ +/** + * Semantic wrapper around the language-specific bounds library. + */ + +private import SemanticExpr +private import SemanticExprSpecific::SemanticExprConfig as Specific +private import SemanticSSA +private import SemanticLocation + +/** + * A valid base for an expression bound. + * + * Can be either a variable (`SemSsaBound`) or zero (`SemZeroBound`). + */ +class SemBound instanceof Specific::Bound { + final string toString() { result = super.toString() } + + final SemLocation getLocation() { result = super.getLocation() } + + final SemExpr getExpr(int delta) { result = Specific::getBoundExpr(this, delta) } +} + +/** + * A bound that is a constant zero. + */ +class SemZeroBound extends SemBound { + SemZeroBound() { Specific::zeroBound(this) } +} + +/** + * A bound that is an SSA definition. + */ +class SemSsaBound extends SemBound { + /** + * The variables whose value is used as the bound. + * + * Can be multi-valued in some implementations. If so, all variables will be equivalent. + */ + SemSsaVariable var; + + SemSsaBound() { Specific::ssaBound(this, var) } + + /** Gets a variable whose value is used as the bound. */ + final SemSsaVariable getAVariable() { result = var } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticCFG.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticCFG.qll new file mode 100644 index 00000000000..333edc46b6e --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticCFG.qll @@ -0,0 +1,22 @@ +/** + * Semantic interface to the control flow graph. + */ + +private import Semantic +private import SemanticExprSpecific::SemanticExprConfig as Specific + +/** + * A basic block in the control-flow graph. + */ +class SemBasicBlock extends Specific::BasicBlock { + /** Holds if this block (transitively) dominates `otherblock`. */ + final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) } + + /** Holds if this block has dominance information. */ + final predicate hasDominanceInformation() { Specific::hasDominanceInformation(this) } + + /** Gets an expression that is evaluated in this basic block. */ + final SemExpr getAnExpr() { result.getBasicBlock() = this } + + final int getUniqueId() { result = Specific::getBasicBlockUniqueId(this) } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExpr.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExpr.qll new file mode 100644 index 00000000000..2ea958931da --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExpr.qll @@ -0,0 +1,309 @@ +/** + * Semantic interface for expressions. + */ + +private import Semantic +private import SemanticExprSpecific::SemanticExprConfig as Specific + +/** + * An language-neutral expression. + * + * The expression computes a value of type `getSemType()`. The actual computation is determined by + * the expression's opcode (`getOpcode()`). + */ +class SemExpr instanceof Specific::Expr { + final string toString() { result = super.toString() } + + final Specific::Location getLocation() { result = super.getLocation() } + + Opcode getOpcode() { result instanceof Opcode::Unknown } + + SemType getSemType() { result = Specific::getUnknownExprType(this) } + + final SemBasicBlock getBasicBlock() { result = Specific::getExprBasicBlock(this) } +} + +/** An expression with an opcode other than `Unknown`. */ +abstract private class SemKnownExpr extends SemExpr { + Opcode opcode; + SemType type; + + final override Opcode getOpcode() { result = opcode } + + final override SemType getSemType() { result = type } +} + +/** An expression that returns a literal value. */ +class SemLiteralExpr extends SemKnownExpr { + SemLiteralExpr() { + Specific::integerLiteral(this, type, _) and opcode instanceof Opcode::Constant + or + Specific::largeIntegerLiteral(this, type, _) and opcode instanceof Opcode::Constant + or + Specific::booleanLiteral(this, type, _) and opcode instanceof Opcode::Constant + or + Specific::floatingPointLiteral(this, type, _) and opcode instanceof Opcode::Constant + or + Specific::nullLiteral(this, type) and opcode instanceof Opcode::Constant + or + Specific::stringLiteral(this, type, _) and opcode instanceof Opcode::StringConstant + } +} + +/** An expression that returns a numeric literal value. */ +class SemNumericLiteralExpr extends SemLiteralExpr { + SemNumericLiteralExpr() { + Specific::integerLiteral(this, _, _) + or + Specific::largeIntegerLiteral(this, _, _) + or + Specific::floatingPointLiteral(this, _, _) + } + + /** + * Gets an approximation of the value of the literal, as a `float`. + * + * If the value can be precisely represented as a `float`, the result will be exact. If the actual + * value cannot be precisely represented (for example, it is an integer with more than 53 + * significant bits), then the result is an approximation. + */ + float getApproximateFloatValue() { none() } +} + +/** An expression that returns an integer literal value. */ +class SemIntegerLiteralExpr extends SemNumericLiteralExpr { + SemIntegerLiteralExpr() { + Specific::integerLiteral(this, _, _) + or + Specific::largeIntegerLiteral(this, _, _) + } + + /** + * Gets the value of the literal, if it can be represented as an `int`. + * + * If the value is outside the range of an `int`, use `getApproximateFloatValue()` to get a value + * that is equal to the actual integer value, within rounding error. + */ + final int getIntValue() { Specific::integerLiteral(this, _, result) } + + final override float getApproximateFloatValue() { + result = getIntValue() + or + Specific::largeIntegerLiteral(this, _, result) + } +} + +/** + * An expression that returns a floating-point literal value. + */ +class SemFloatingPointLiteralExpr extends SemNumericLiteralExpr { + float value; + + SemFloatingPointLiteralExpr() { Specific::floatingPointLiteral(this, _, value) } + + final override float getApproximateFloatValue() { result = value } + + /** Gets the value of the literal. */ + final float getFloatValue() { result = value } +} + +/** + * An expression that consumes two operands. + */ +class SemBinaryExpr extends SemKnownExpr { + SemExpr leftOperand; + SemExpr rightOperand; + + SemBinaryExpr() { Specific::binaryExpr(this, opcode, type, leftOperand, rightOperand) } + + /** Gets the left operand. */ + final SemExpr getLeftOperand() { result = leftOperand } + + /** Gets the right operand. */ + final SemExpr getRightOperand() { result = rightOperand } + + /** Holds if `a` and `b` are the two operands, in either order. */ + final predicate hasOperands(SemExpr a, SemExpr b) { + a = getLeftOperand() and b = getRightOperand() + or + a = getRightOperand() and b = getLeftOperand() + } + + /** Gets the two operands. */ + final SemExpr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } +} + +/** An expression that performs and ordered comparison of two operands. */ +class SemRelationalExpr extends SemBinaryExpr { + SemRelationalExpr() { + opcode instanceof Opcode::CompareLT + or + opcode instanceof Opcode::CompareLE + or + opcode instanceof Opcode::CompareGT + or + opcode instanceof Opcode::CompareGE + } + + /** + * Get the operand that will be less than the other operand if the result of the comparison is + * `true`. + * + * For `x < y` or `x <= y`, this will return `x`. + * For `x > y` or `x >= y`, this will return `y`.` + */ + final SemExpr getLesserOperand() { + if opcode instanceof Opcode::CompareLT or opcode instanceof Opcode::CompareLE + then result = getLeftOperand() + else result = getRightOperand() + } + + /** + * Get the operand that will be greater than the other operand if the result of the comparison is + * `true`. + * + * For `x < y` or `x <= y`, this will return `y`. + * For `x > y` or `x >= y`, this will return `x`.` + */ + final SemExpr getGreaterOperand() { + if opcode instanceof Opcode::CompareGT or opcode instanceof Opcode::CompareGE + then result = getLeftOperand() + else result = getRightOperand() + } + + /** Holds if this comparison returns `false` if the two operands are equal. */ + final predicate isStrict() { + opcode instanceof Opcode::CompareLT or opcode instanceof Opcode::CompareGT + } +} + +class SemAddExpr extends SemBinaryExpr { + SemAddExpr() { opcode instanceof Opcode::Add or opcode instanceof Opcode::PointerAdd } +} + +class SemSubExpr extends SemBinaryExpr { + SemSubExpr() { opcode instanceof Opcode::Sub or opcode instanceof Opcode::PointerSub } +} + +class SemMulExpr extends SemBinaryExpr { + SemMulExpr() { opcode instanceof Opcode::Mul } +} + +class SemDivExpr extends SemBinaryExpr { + SemDivExpr() { opcode instanceof Opcode::Div } +} + +class SemRemExpr extends SemBinaryExpr { + SemRemExpr() { opcode instanceof Opcode::Rem } +} + +class SemShiftLeftExpr extends SemBinaryExpr { + SemShiftLeftExpr() { opcode instanceof Opcode::ShiftLeft } +} + +class SemShiftRightExpr extends SemBinaryExpr { + SemShiftRightExpr() { opcode instanceof Opcode::ShiftRight } +} + +class SemShiftRightUnsignedExpr extends SemBinaryExpr { + SemShiftRightUnsignedExpr() { opcode instanceof Opcode::ShiftRightUnsigned } +} + +class SemBitAndExpr extends SemBinaryExpr { + SemBitAndExpr() { opcode instanceof Opcode::BitAnd } +} + +class SemBitOrExpr extends SemBinaryExpr { + SemBitOrExpr() { opcode instanceof Opcode::BitOr } +} + +class SemBitXorExpr extends SemBinaryExpr { + SemBitXorExpr() { opcode instanceof Opcode::BitXor } +} + +class SemUnaryExpr extends SemKnownExpr { + SemExpr operand; + + SemUnaryExpr() { Specific::unaryExpr(this, opcode, type, operand) } + + final SemExpr getOperand() { result = operand } +} + +class SemBoxExpr extends SemUnaryExpr { + SemBoxExpr() { opcode instanceof Opcode::Box } +} + +class SemUnboxExpr extends SemUnaryExpr { + SemUnboxExpr() { opcode instanceof Opcode::Unbox } +} + +class SemConvertExpr extends SemUnaryExpr { + SemConvertExpr() { opcode instanceof Opcode::Convert } +} + +class SemCopyValueExpr extends SemUnaryExpr { + SemCopyValueExpr() { opcode instanceof Opcode::CopyValue } +} + +class SemNegateExpr extends SemUnaryExpr { + SemNegateExpr() { opcode instanceof Opcode::Negate } +} + +class SemBitComplementExpr extends SemUnaryExpr { + SemBitComplementExpr() { opcode instanceof Opcode::BitComplement } +} + +class SemLogicalNotExpr extends SemUnaryExpr { + SemLogicalNotExpr() { opcode instanceof Opcode::LogicalNot } +} + +class SemAddOneExpr extends SemUnaryExpr { + SemAddOneExpr() { opcode instanceof Opcode::AddOne } +} + +class SemSubOneExpr extends SemUnaryExpr { + SemSubOneExpr() { opcode instanceof Opcode::SubOne } +} + +private class SemNullaryExpr extends SemKnownExpr { + SemNullaryExpr() { Specific::nullaryExpr(this, opcode, type) } +} + +class SemInitializeParameterExpr extends SemNullaryExpr { + SemInitializeParameterExpr() { opcode instanceof Opcode::InitializeParameter } +} + +class SemLoadExpr extends SemNullaryExpr { + SemLoadExpr() { opcode instanceof Opcode::Load } + + final SemSsaVariable getDef() { result.getAUse() = this } +} + +class SemSsaLoadExpr extends SemLoadExpr { + SemSsaLoadExpr() { exists(getDef()) } +} + +class SemNonSsaLoadExpr extends SemLoadExpr { + SemNonSsaLoadExpr() { not exists(getDef()) } +} + +class SemStoreExpr extends SemUnaryExpr { + SemStoreExpr() { opcode instanceof Opcode::Store } +} + +class SemConditionalExpr extends SemKnownExpr { + SemExpr condition; + SemExpr trueResult; + SemExpr falseResult; + + SemConditionalExpr() { + opcode instanceof Opcode::Conditional and + Specific::conditionalExpr(this, type, condition, trueResult, falseResult) + } + + final SemExpr getBranchExpr(boolean branch) { + branch = true and result = trueResult + or + branch = false and result = falseResult + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll new file mode 100644 index 00000000000..6ac6081c558 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticExprSpecific.qll @@ -0,0 +1,450 @@ +/** + * C++-specific implementation of the semantic interface. + */ + +private import cpp as Cpp +private import semmle.code.cpp.ir.IR as IR +private import Semantic +private import analysis.Bound as IRBound +private import semmle.code.cpp.controlflow.IRGuards as IRGuards +private import semmle.code.cpp.ir.ValueNumbering + +module SemanticExprConfig { + class Location = Cpp::Location; + + /** A `ConvertInstruction` or a `CopyValueInstruction`. */ + private class Conversion extends IR::UnaryInstruction { + Conversion() { + this instanceof IR::CopyValueInstruction + or + this instanceof IR::ConvertInstruction + } + + /** Holds if this instruction converts a value of type `tFrom` to a value of type `tTo`. */ + predicate converts(SemType tFrom, SemType tTo) { + tFrom = getSemanticType(this.getUnary().getResultIRType()) and + tTo = getSemanticType(this.getResultIRType()) + } + } + + /** + * Gets a conversion-like instruction that consumes `op`, and + * which is guaranteed to not overflow. + */ + private IR::Instruction safeConversion(IR::Operand op) { + exists(Conversion conv, SemType tFrom, SemType tTo | + conv.converts(tFrom, tTo) and + conversionCannotOverflow(tFrom, tTo) and + conv.getUnaryOperand() = op and + result = conv + ) + } + + /** Holds if `i1 = i2` or if `i2` is a safe conversion that consumes `i1`. */ + private predicate idOrSafeConversion(IR::Instruction i1, IR::Instruction i2) { + not i1.getResultIRType() instanceof IR::IRVoidType and + ( + i1 = i2 + or + i2 = safeConversion(i1.getAUse()) and + i1.getBlock() = i2.getBlock() + ) + } + + module Equiv = QlBuiltins::EquivalenceRelation; + + /** + * The expressions on which we perform range analysis. + */ + class Expr extends Equiv::EquivalenceClass { + /** Gets the n'th instruction in this equivalence class. */ + private IR::Instruction getInstruction(int n) { + result = + rank[n + 1](IR::Instruction instr, int i, IR::IRBlock block | + this = Equiv::getEquivalenceClass(instr) and block.getInstruction(i) = instr + | + instr order by i + ) + } + + /** Gets a textual representation of this element. */ + string toString() { result = this.getUnconverted().toString() } + + /** Gets the basic block of this expression. */ + IR::IRBlock getBlock() { result = this.getUnconverted().getBlock() } + + /** Gets the unconverted instruction associated with this expression. */ + IR::Instruction getUnconverted() { result = this.getInstruction(0) } + + /** + * Gets the final instruction associated with this expression. This + * represents the result after applying all the safe conversions. + */ + IR::Instruction getConverted() { + exists(int n | + result = this.getInstruction(n) and + not exists(this.getInstruction(n + 1)) + ) + } + + /** Gets the type of the result produced by this instruction. */ + IR::IRType getResultIRType() { result = this.getConverted().getResultIRType() } + + /** Gets the location of the source code for this expression. */ + Location getLocation() { result = this.getUnconverted().getLocation() } + } + + SemBasicBlock getExprBasicBlock(Expr e) { result = getSemanticBasicBlock(e.getBlock()) } + + private predicate anyConstantExpr(Expr expr, SemType type, string value) { + exists(IR::ConstantInstruction instr | getSemanticExpr(instr) = expr | + type = getSemanticType(instr.getResultIRType()) and + value = instr.getValue() + ) + } + + predicate integerLiteral(Expr expr, SemIntegerType type, int value) { + exists(string valueString | + anyConstantExpr(expr, type, valueString) and + value = valueString.toInt() + ) + } + + predicate largeIntegerLiteral(Expr expr, SemIntegerType type, float approximateFloatValue) { + exists(string valueString | + anyConstantExpr(expr, type, valueString) and + not exists(valueString.toInt()) and + approximateFloatValue = valueString.toFloat() + ) + } + + predicate floatingPointLiteral(Expr expr, SemFloatingPointType type, float value) { + exists(string valueString | + anyConstantExpr(expr, type, valueString) and value = valueString.toFloat() + ) + } + + predicate booleanLiteral(Expr expr, SemBooleanType type, boolean value) { + exists(string valueString | + anyConstantExpr(expr, type, valueString) and + ( + valueString = "true" and value = true + or + valueString = "false" and value = false + ) + ) + } + + predicate nullLiteral(Expr expr, SemAddressType type) { anyConstantExpr(expr, type, _) } + + predicate stringLiteral(Expr expr, SemType type, string value) { + anyConstantExpr(expr, type, value) and + expr.getUnconverted() instanceof IR::StringConstantInstruction + } + + predicate binaryExpr(Expr expr, Opcode opcode, SemType type, Expr leftOperand, Expr rightOperand) { + exists(IR::BinaryInstruction instr | + instr = expr.getUnconverted() and + type = getSemanticType(instr.getResultIRType()) and + leftOperand = getSemanticExpr(instr.getLeft()) and + rightOperand = getSemanticExpr(instr.getRight()) and + // REVIEW: Merge the two `Opcode` types. + opcode.toString() = instr.getOpcode().toString() + ) + } + + predicate unaryExpr(Expr expr, Opcode opcode, SemType type, Expr operand) { + exists(IR::UnaryInstruction instr | instr = expr.getUnconverted() | + type = getSemanticType(instr.getResultIRType()) and + operand = getSemanticExpr(instr.getUnary()) and + // REVIEW: Merge the two operand types. + opcode.toString() = instr.getOpcode().toString() + ) + or + exists(IR::StoreInstruction instr | instr = expr.getUnconverted() | + type = getSemanticType(instr.getResultIRType()) and + operand = getSemanticExpr(instr.getSourceValue()) and + opcode instanceof Opcode::Store + ) + } + + predicate nullaryExpr(Expr expr, Opcode opcode, SemType type) { + exists(IR::LoadInstruction load | + load = expr.getUnconverted() and + type = getSemanticType(load.getResultIRType()) and + opcode instanceof Opcode::Load + ) + or + exists(IR::InitializeParameterInstruction init | + init = expr.getUnconverted() and + type = getSemanticType(init.getResultIRType()) and + opcode instanceof Opcode::InitializeParameter + ) + } + + predicate conditionalExpr( + Expr expr, SemType type, Expr condition, Expr trueResult, Expr falseResult + ) { + none() + } + + SemType getUnknownExprType(Expr expr) { result = getSemanticType(expr.getResultIRType()) } + + class BasicBlock = IR::IRBlock; + + predicate bbDominates(BasicBlock dominator, BasicBlock dominated) { + dominator.dominates(dominated) + } + + predicate hasDominanceInformation(BasicBlock block) { any() } + + private predicate id(Cpp::Locatable x, Cpp::Locatable y) { x = y } + + private predicate idOf(Cpp::Locatable x, int y) = equivalenceRelation(id/2)(x, y) + + int getBasicBlockUniqueId(BasicBlock block) { idOf(block.getFirstInstruction().getAst(), result) } + + newtype TSsaVariable = + TSsaInstruction(IR::Instruction instr) { instr.hasMemoryResult() } or + TSsaOperand(IR::Operand op) { op.isDefinitionInexact() } or + TSsaPointerArithmeticGuard(ValueNumber instr) { + exists(Guard g, IR::Operand use | + use = instr.getAUse() and use.getIRType() instanceof IR::IRAddressType + | + g.comparesLt(use, _, _, _, _) or + g.comparesLt(_, use, _, _, _) or + g.comparesEq(use, _, _, _, _) or + g.comparesEq(_, use, _, _, _) + ) + } + + class SsaVariable extends TSsaVariable { + string toString() { none() } + + Location getLocation() { none() } + + IR::Instruction asInstruction() { none() } + + ValueNumber asPointerArithGuard() { none() } + + IR::Operand asOperand() { none() } + } + + class SsaInstructionVariable extends SsaVariable, TSsaInstruction { + IR::Instruction instr; + + SsaInstructionVariable() { this = TSsaInstruction(instr) } + + final override string toString() { result = instr.toString() } + + final override Location getLocation() { result = instr.getLocation() } + + final override IR::Instruction asInstruction() { result = instr } + } + + class SsaPointerArithmeticGuard extends SsaVariable, TSsaPointerArithmeticGuard { + ValueNumber vn; + + SsaPointerArithmeticGuard() { this = TSsaPointerArithmeticGuard(vn) } + + final override string toString() { result = vn.toString() } + + final override Location getLocation() { result = vn.getLocation() } + + final override ValueNumber asPointerArithGuard() { result = vn } + } + + class SsaOperand extends SsaVariable, TSsaOperand { + IR::Operand op; + + SsaOperand() { this = TSsaOperand(op) } + + final override string toString() { result = op.toString() } + + final override Location getLocation() { result = op.getLocation() } + + final override IR::Operand asOperand() { result = op } + } + + predicate explicitUpdate(SsaVariable v, Expr sourceExpr) { + getSemanticExpr(v.asInstruction()) = sourceExpr + } + + predicate phi(SsaVariable v) { v.asInstruction() instanceof IR::PhiInstruction } + + SsaVariable getAPhiInput(SsaVariable v) { + exists(IR::PhiInstruction instr | v.asInstruction() = instr | + result.asInstruction() = instr.getAnInput() + or + result.asOperand() = instr.getAnInputOperand() + ) + } + + Expr getAUse(SsaVariable v) { + result.getUnconverted().(IR::LoadInstruction).getSourceValue() = v.asInstruction() + or + result.getUnconverted() = v.asPointerArithGuard().getAnInstruction() + } + + SemType getSsaVariableType(SsaVariable v) { + result = getSemanticType(v.asInstruction().getResultIRType()) + } + + BasicBlock getSsaVariableBasicBlock(SsaVariable v) { + result = v.asInstruction().getBlock() + or + result = v.asOperand().getUse().getBlock() + } + + private newtype TReadPosition = + TReadPositionBlock(IR::IRBlock block) or + TReadPositionPhiInputEdge(IR::IRBlock pred, IR::IRBlock succ) { + exists(IR::PhiInputOperand input | + pred = input.getPredecessorBlock() and + succ = input.getUse().getBlock() + ) + } + + class SsaReadPosition extends TReadPosition { + string toString() { none() } + + Location getLocation() { none() } + + predicate hasRead(SsaVariable v) { none() } + } + + private class SsaReadPositionBlock extends SsaReadPosition, TReadPositionBlock { + IR::IRBlock block; + + SsaReadPositionBlock() { this = TReadPositionBlock(block) } + + final override string toString() { result = block.toString() } + + final override Location getLocation() { result = block.getLocation() } + + final override predicate hasRead(SsaVariable v) { + exists(IR::Operand operand | + operand.getDef() = v.asInstruction() or + operand.getDef() = v.asPointerArithGuard().getAnInstruction() + | + not operand instanceof IR::PhiInputOperand and + operand.getUse().getBlock() = block + ) + } + } + + private class SsaReadPositionPhiInputEdge extends SsaReadPosition, TReadPositionPhiInputEdge { + IR::IRBlock pred; + IR::IRBlock succ; + + SsaReadPositionPhiInputEdge() { this = TReadPositionPhiInputEdge(pred, succ) } + + final override string toString() { result = pred.toString() + "->" + succ.toString() } + + final override Location getLocation() { result = succ.getLocation() } + + final override predicate hasRead(SsaVariable v) { + exists(IR::PhiInputOperand operand | + operand.getDef() = v.asInstruction() or + operand.getDef() = v.asPointerArithGuard().getAnInstruction() + | + operand.getPredecessorBlock() = pred and + operand.getUse().getBlock() = succ + ) + } + } + + predicate hasReadOfSsaVariable(SsaReadPosition pos, SsaVariable v) { pos.hasRead(v) } + + predicate readBlock(SsaReadPosition pos, BasicBlock block) { pos = TReadPositionBlock(block) } + + predicate phiInputEdge(SsaReadPosition pos, BasicBlock origBlock, BasicBlock phiBlock) { + pos = TReadPositionPhiInputEdge(origBlock, phiBlock) + } + + predicate phiInput(SsaReadPosition pos, SsaVariable phi, SsaVariable input) { + exists(IR::PhiInputOperand operand | + pos = TReadPositionPhiInputEdge(operand.getPredecessorBlock(), operand.getUse().getBlock()) + | + phi.asInstruction() = operand.getUse() and + ( + input.asInstruction() = operand.getDef() + or + input.asOperand() = operand + ) + ) + } + + class Bound instanceof IRBound::Bound { + string toString() { result = super.toString() } + + final Location getLocation() { result = super.getLocation() } + } + + private class ValueNumberBound extends Bound instanceof IRBound::ValueNumberBound { + override string toString() { result = IRBound::ValueNumberBound.super.toString() } + } + + predicate zeroBound(Bound bound) { bound instanceof IRBound::ZeroBound } + + predicate ssaBound(Bound bound, SsaVariable v) { + v.asInstruction() = bound.(IRBound::ValueNumberBound).getValueNumber().getAnInstruction() + } + + Expr getBoundExpr(Bound bound, int delta) { + result = getSemanticExpr(bound.(IRBound::Bound).getInstruction(delta)) + } + + class Guard = IRGuards::IRGuardCondition; + + predicate guard(Guard guard, BasicBlock block) { block = guard.getBlock() } + + Expr getGuardAsExpr(Guard guard) { result = getSemanticExpr(guard) } + + predicate equalityGuard(Guard guard, Expr e1, Expr e2, boolean polarity) { + exists(IR::Instruction left, IR::Instruction right | + getSemanticExpr(left) = e1 and + getSemanticExpr(right) = e2 and + guard.comparesEq(left.getAUse(), right.getAUse(), 0, true, polarity) + ) + } + + predicate guardDirectlyControlsBlock(Guard guard, BasicBlock controlled, boolean branch) { + guard.controls(controlled, branch) + } + + predicate guardHasBranchEdge(Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch) { + guard.controlsEdge(bb1, bb2, branch) + } + + Guard comparisonGuard(Expr e) { getSemanticExpr(result) = e } + + predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) { + none() // TODO + } + + /** Gets the expression associated with `instr`. */ + SemExpr getSemanticExpr(IR::Instruction instr) { result = Equiv::getEquivalenceClass(instr) } +} + +predicate getSemanticExpr = SemanticExprConfig::getSemanticExpr/1; + +SemBasicBlock getSemanticBasicBlock(IR::IRBlock block) { result = block } + +IR::IRBlock getCppBasicBlock(SemBasicBlock block) { block = result } + +SemSsaVariable getSemanticSsaVariable(IR::Instruction instr) { + result.(SemanticExprConfig::SsaVariable).asInstruction() = instr +} + +IR::Instruction getCppSsaVariableInstruction(SemSsaVariable var) { + var.(SemanticExprConfig::SsaVariable).asInstruction() = result +} + +SemBound getSemanticBound(IRBound::Bound bound) { result = bound } + +IRBound::Bound getCppBound(SemBound bound) { bound = result } + +SemGuard getSemanticGuard(IRGuards::IRGuardCondition guard) { result = guard } + +IRGuards::IRGuardCondition getCppGuard(SemGuard guard) { guard = result } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll new file mode 100644 index 00000000000..8faf6a3a1de --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticGuard.qll @@ -0,0 +1,65 @@ +/** + * Semantic interface to the guards library. + */ + +private import Semantic +private import SemanticExprSpecific::SemanticExprConfig as Specific + +class SemGuard instanceof Specific::Guard { + SemBasicBlock block; + + SemGuard() { Specific::guard(this, block) } + + final string toString() { result = super.toString() } + + final Specific::Location getLocation() { result = super.getLocation() } + + final predicate isEquality(SemExpr e1, SemExpr e2, boolean polarity) { + Specific::equalityGuard(this, e1, e2, polarity) + } + + final predicate directlyControls(SemBasicBlock controlled, boolean branch) { + Specific::guardDirectlyControlsBlock(this, controlled, branch) + } + + final predicate hasBranchEdge(SemBasicBlock bb1, SemBasicBlock bb2, boolean branch) { + Specific::guardHasBranchEdge(this, bb1, bb2, branch) + } + + final SemBasicBlock getBasicBlock() { result = block } + + final SemExpr asExpr() { result = Specific::getGuardAsExpr(this) } +} + +predicate semImplies_v2(SemGuard g1, boolean b1, SemGuard g2, boolean b2) { + Specific::implies_v2(g1, b1, g2, b2) +} + +/** + * Holds if `guard` directly controls the position `controlled` with the + * value `testIsTrue`. + */ +predicate semGuardDirectlyControlsSsaRead( + SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue +) { + guard.directlyControls(controlled.(SemSsaReadPositionBlock).getBlock(), testIsTrue) + or + exists(SemSsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled | + guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or + guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue) + ) +} + +/** + * Holds if `guard` controls the position `controlled` with the value `testIsTrue`. + */ +predicate semGuardControlsSsaRead(SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue) { + semGuardDirectlyControlsSsaRead(guard, controlled, testIsTrue) + or + exists(SemGuard guard0, boolean testIsTrue0 | + semImplies_v2(guard0, testIsTrue0, guard, testIsTrue) and + semGuardControlsSsaRead(guard0, controlled, testIsTrue0) + ) +} + +SemGuard semGetComparisonGuard(SemRelationalExpr e) { result = Specific::comparisonGuard(e) } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticLocation.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticLocation.qll new file mode 100644 index 00000000000..328f85151b5 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticLocation.qll @@ -0,0 +1,23 @@ +private import semmle.code.cpp.Location + +class SemLocation instanceof Location { + /** + * Gets a textual representation of this element. + * + * The format is "file://filePath:startLine:startColumn:endLine:endColumn". + */ + string toString() { result = super.toString() } + + /** + * Holds if this element is at the specified location. + * The location spans column `startcolumn` of line `startline` to + * column `endcolumn` of line `endline` in file `filepath`. + * For more information, see + * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + */ + predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticOpcode.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticOpcode.qll new file mode 100644 index 00000000000..bb56da71f73 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticOpcode.qll @@ -0,0 +1,187 @@ +/** + * Definitions of all possible opcodes for `SemExpr`. + */ +private newtype TOpcode = + TInitializeParameter() or + TCopyValue() or + TLoad() or + TStore() or + TAdd() or + TSub() or + TMul() or + TDiv() or + TRem() or + TNegate() or + TShiftLeft() or + TShiftRight() or + TShiftRightUnsigned() or // TODO: Based on type + TBitAnd() or + TBitOr() or + TBitXor() or + TBitComplement() or + TLogicalNot() or + TCompareEQ() or + TCompareNE() or + TCompareLT() or + TCompareGT() or + TCompareLE() or + TCompareGE() or + TPointerAdd() or + TPointerSub() or + TPointerDiff() or + TConvert() or + TConstant() or + TStringConstant() or + TAddOne() or // TODO: Combine with `TAdd` + TSubOne() or // TODO: Combine with `TSub` + TConditional() or // TODO: Represent as flow + TCall() or + TBox() or + TUnbox() or + TUnknown() + +class Opcode extends TOpcode { + string toString() { result = "???" } +} + +module Opcode { + class InitializeParameter extends Opcode, TInitializeParameter { + override string toString() { result = "InitializeParameter" } + } + + class CopyValue extends Opcode, TCopyValue { + override string toString() { result = "CopyValue" } + } + + class Load extends Opcode, TLoad { + override string toString() { result = "Load" } + } + + class Store extends Opcode, TStore { + override string toString() { result = "Store" } + } + + class Add extends Opcode, TAdd { + override string toString() { result = "Add" } + } + + class PointerAdd extends Opcode, TPointerAdd { + override string toString() { result = "PointerAdd" } + } + + class Sub extends Opcode, TSub { + override string toString() { result = "Sub" } + } + + class PointerSub extends Opcode, TPointerSub { + override string toString() { result = "PointerSub" } + } + + class Mul extends Opcode, TMul { + override string toString() { result = "Mul" } + } + + class Div extends Opcode, TDiv { + override string toString() { result = "Div" } + } + + class Rem extends Opcode, TRem { + override string toString() { result = "Rem" } + } + + class Negate extends Opcode, TNegate { + override string toString() { result = "Negate" } + } + + class ShiftLeft extends Opcode, TShiftLeft { + override string toString() { result = "ShiftLeft" } + } + + class ShiftRight extends Opcode, TShiftRight { + override string toString() { result = "ShiftRight" } + } + + class ShiftRightUnsigned extends Opcode, TShiftRightUnsigned { + override string toString() { result = "ShiftRightUnsigned" } + } + + class BitAnd extends Opcode, TBitAnd { + override string toString() { result = "BitAnd" } + } + + class BitOr extends Opcode, TBitOr { + override string toString() { result = "BitOr" } + } + + class BitXor extends Opcode, TBitXor { + override string toString() { result = "BitXor" } + } + + class BitComplement extends Opcode, TBitComplement { + override string toString() { result = "BitComplement" } + } + + class LogicalNot extends Opcode, TLogicalNot { + override string toString() { result = "LogicalNot" } + } + + class CompareEQ extends Opcode, TCompareEQ { + override string toString() { result = "CompareEQ" } + } + + class CompareNE extends Opcode, TCompareNE { + override string toString() { result = "CompareNE" } + } + + class CompareLT extends Opcode, TCompareLT { + override string toString() { result = "CompareLT" } + } + + class CompareLE extends Opcode, TCompareLE { + override string toString() { result = "CompareLE" } + } + + class CompareGT extends Opcode, TCompareGT { + override string toString() { result = "CompareGT" } + } + + class CompareGE extends Opcode, TCompareGE { + override string toString() { result = "CompareGE" } + } + + class Convert extends Opcode, TConvert { + override string toString() { result = "Convert" } + } + + class AddOne extends Opcode, TAddOne { + override string toString() { result = "AddOne" } + } + + class SubOne extends Opcode, TSubOne { + override string toString() { result = "SubOne" } + } + + class Conditional extends Opcode, TConditional { + override string toString() { result = "Conditional" } + } + + class Constant extends Opcode, TConstant { + override string toString() { result = "Constant" } + } + + class StringConstant extends Opcode, TStringConstant { + override string toString() { result = "StringConstant" } + } + + class Box extends Opcode, TBox { + override string toString() { result = "Box" } + } + + class Unbox extends Opcode, TUnbox { + override string toString() { result = "Unbox" } + } + + class Unknown extends Opcode, TUnknown { + override string toString() { result = "Unknown" } + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticSSA.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticSSA.qll new file mode 100644 index 00000000000..307f6e386b5 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticSSA.qll @@ -0,0 +1,75 @@ +/** + * Semantic interface to the SSA library. + */ + +private import Semantic +private import SemanticExprSpecific::SemanticExprConfig as Specific + +class SemSsaVariable instanceof Specific::SsaVariable { + final string toString() { result = super.toString() } + + final Specific::Location getLocation() { result = super.getLocation() } + + final SemExpr getAUse() { result = Specific::getAUse(this) } + + final SemType getType() { result = Specific::getSsaVariableType(this) } + + final SemBasicBlock getBasicBlock() { result = Specific::getSsaVariableBasicBlock(this) } +} + +class SemSsaExplicitUpdate extends SemSsaVariable { + SemExpr sourceExpr; + + SemSsaExplicitUpdate() { Specific::explicitUpdate(this, sourceExpr) } + + final SemExpr getSourceExpr() { result = sourceExpr } +} + +class SemSsaPhiNode extends SemSsaVariable { + SemSsaPhiNode() { Specific::phi(this) } + + final SemSsaVariable getAPhiInput() { result = Specific::getAPhiInput(this) } +} + +class SemSsaReadPosition instanceof Specific::SsaReadPosition { + final string toString() { result = super.toString() } + + final Specific::Location getLocation() { result = super.getLocation() } + + final predicate hasReadOfVar(SemSsaVariable var) { Specific::hasReadOfSsaVariable(this, var) } +} + +class SemSsaReadPositionPhiInputEdge extends SemSsaReadPosition { + SemBasicBlock origBlock; + SemBasicBlock phiBlock; + + SemSsaReadPositionPhiInputEdge() { Specific::phiInputEdge(this, origBlock, phiBlock) } + + predicate phiInput(SemSsaPhiNode phi, SemSsaVariable inp) { Specific::phiInput(this, phi, inp) } + + SemBasicBlock getOrigBlock() { result = origBlock } + + SemBasicBlock getPhiBlock() { result = phiBlock } +} + +class SemSsaReadPositionBlock extends SemSsaReadPosition { + SemBasicBlock block; + + SemSsaReadPositionBlock() { Specific::readBlock(this, block) } + + SemBasicBlock getBlock() { result = block } + + SemExpr getAnExpr() { result = getBlock().getAnExpr() } +} + +/** + * Holds if `inp` is an input to `phi` along a back edge. + */ +predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge) { + edge.phiInput(phi, inp) and + // Conservatively assume that every edge is a back edge if we don't have dominance information. + ( + phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or + not edge.getOrigBlock().hasDominanceInformation() + ) +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticType.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticType.qll new file mode 100644 index 00000000000..b86db02702c --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticType.qll @@ -0,0 +1,311 @@ +/** + * Minimal, language-neutral type system for semantic analysis. + */ + +private import SemanticTypeSpecific as Specific + +class LanguageType = Specific::Type; + +cached +private newtype TSemType = + TSemVoidType() { Specific::voidType(_) } or + TSemUnknownType() { Specific::unknownType(_) } or + TSemErrorType() { Specific::errorType(_) } or + TSemBooleanType(int byteSize) { Specific::booleanType(_, byteSize) } or + TSemIntegerType(int byteSize, boolean signed) { Specific::integerType(_, byteSize, signed) } or + TSemFloatingPointType(int byteSize) { Specific::floatingPointType(_, byteSize) } or + TSemAddressType(int byteSize) { Specific::addressType(_, byteSize) } or + TSemFunctionAddressType(int byteSize) { Specific::functionAddressType(_, byteSize) } or + TSemOpaqueType(int byteSize, Specific::OpaqueTypeTag tag) { + Specific::opaqueType(_, byteSize, tag) + } + +/** + * The language-neutral type of a semantic expression, + * The interface to `SemType` and its subclasses is the same across all languages for which the IR + * is supported, so analyses that expect to be used for multiple languages should generally use + * `SemType` rather than a language-specific type. + * + * Many types from the language-specific type system will map to a single canonical `SemType`. Two + * types that map to the same `SemType` are considered equivalent by semantic analysis. As an + * example, in C++, all pointer types map to the same instance of `SemAddressType`. + */ +class SemType extends TSemType { + /** Gets a textual representation of this type. */ + string toString() { none() } + + /** + * Gets a string that uniquely identifies this `SemType`. This string is often the same as the + * result of `SemType.toString()`, but for some types it may be more verbose to ensure uniqueness. + */ + string getIdentityString() { result = toString() } + + /** + * Gets the size of the type, in bytes, if known. + * + * This will hold for all `SemType` objects except `SemUnknownType` and `SemErrorType`. + */ + // 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() } +} + +/** + * An unknown type. Generally used to represent results and operands that access an unknown set of + * memory locations, such as the side effects of a function call. + */ +class SemUnknownType extends SemType, TSemUnknownType { + final override string toString() { result = "unknown" } + + final override int getByteSize() { none() } +} + +/** + * A void type, which has no values. Used to represent the result type of an expression that does + * not produce a result. + */ +class SemVoidType extends SemType, TSemVoidType { + final override string toString() { result = "void" } + + final override int getByteSize() { result = 0 } +} + +/** + * An error type. Used when an error in the source code prevents the extractor from determining the + * proper type. + */ +class SemErrorType extends SemType, TSemErrorType { + final override string toString() { result = "error" } + + final override int getByteSize() { result = 0 } +} + +private class SemSizedType extends SemType { + int byteSize; + + SemSizedType() { + this = TSemBooleanType(byteSize) or + this = TSemIntegerType(byteSize, _) or + this = TSemFloatingPointType(byteSize) or + this = TSemAddressType(byteSize) or + this = TSemFunctionAddressType(byteSize) or + this = TSemOpaqueType(byteSize, _) + } + // Don't override `getByteSize()` here. The optimizer seems to generate better code when this is + // overridden only in the leaf classes. +} + +/** + * A Boolean type, which can hold the values `true` (non-zero) or `false` (zero). + */ +class SemBooleanType extends SemSizedType, TSemBooleanType { + final override string toString() { result = "bool" + byteSize.toString() } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +/** + * A numeric type. This includes `SemSignedIntegerType`, `SemUnsignedIntegerType`, and + * `SemFloatingPointType`. + */ +class SemNumericType extends SemSizedType { + SemNumericType() { + this = TSemIntegerType(byteSize, _) or + this = TSemFloatingPointType(byteSize) + } + // Don't override `getByteSize()` here. The optimizer seems to generate better code when this is + // overridden only in the leaf classes. +} + +/** + * An integer type. This includes `SemSignedIntegerType` and `SemUnsignedIntegerType`. + */ +class SemIntegerType extends SemNumericType { + boolean signed; + + SemIntegerType() { this = TSemIntegerType(byteSize, signed) } + + /** Holds if this integer type is signed. */ + final predicate isSigned() { signed = true } + + /** Holds if this integer type is unsigned. */ + final predicate isUnsigned() { not isSigned() } + // Don't override `getByteSize()` here. The optimizer seems to generate better code when this is + // overridden only in the leaf classes. +} + +/** + * A signed two's-complement integer. Also used to represent enums whose underlying type is a signed + * integer, as well as character types whose representation is signed. + */ +class SemSignedIntegerType extends SemIntegerType { + SemSignedIntegerType() { signed = true } + + final override string toString() { result = "int" + byteSize.toString() } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +/** + * An unsigned two's-complement integer. Also used to represent enums whose underlying type is an + * unsigned integer, as well as character types whose representation is unsigned. + */ +class SemUnsignedIntegerType extends SemIntegerType { + SemUnsignedIntegerType() { signed = false } + + final override string toString() { result = "uint" + byteSize.toString() } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +/** + * A floating-point type. + */ +class SemFloatingPointType extends SemNumericType, TSemFloatingPointType { + final override string toString() { result = "float" + byteSize.toString() } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +/** + * An address type, representing the memory address of data. Used to represent pointers, references, + * and lvalues, include those that are garbage collected. + * + * The address of a function is represented by the separate `SemFunctionAddressType`. + */ +class SemAddressType extends SemSizedType, TSemAddressType { + final override string toString() { result = "addr" + byteSize.toString() } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +/** + * An address type, representing the memory address of code. Used to represent function pointers, + * function references, and the target of a direct function call. + */ +class SemFunctionAddressType extends SemSizedType, TSemFunctionAddressType { + final override string toString() { result = "func" + byteSize.toString() } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +/** + * A type with known size that does not fit any of the other kinds of type. Used to represent + * classes, structs, unions, fixed-size arrays, pointers-to-member, and more. + */ +class SemOpaqueType extends SemSizedType, TSemOpaqueType { + Specific::OpaqueTypeTag tag; + + SemOpaqueType() { this = TSemOpaqueType(byteSize, tag) } + + final override string toString() { + result = "opaque" + byteSize.toString() + "{" + tag.toString() + "}" + } + + final override string getIdentityString() { + result = "opaque" + byteSize.toString() + "{" + Specific::getOpaqueTagIdentityString(tag) + "}" + } + + /** + * Gets the "tag" that differentiates this type from other incompatible opaque types that have the + * same size. + */ + final Specific::OpaqueTypeTag getTag() { result = tag } + + pragma[noinline] + final override int getByteSize() { result = byteSize } +} + +cached +SemType getSemanticType(Specific::Type type) { + exists(int byteSize | + Specific::booleanType(type, byteSize) and result = TSemBooleanType(byteSize) + or + exists(boolean signed | + Specific::integerType(type, byteSize, signed) and + result = TSemIntegerType(byteSize, signed) + ) + or + Specific::floatingPointType(type, byteSize) and result = TSemFloatingPointType(byteSize) + or + Specific::addressType(type, byteSize) and result = TSemAddressType(byteSize) + or + Specific::functionAddressType(type, byteSize) and result = TSemFunctionAddressType(byteSize) + or + exists(Specific::OpaqueTypeTag tag | + Specific::opaqueType(type, byteSize, tag) and result = TSemOpaqueType(byteSize, tag) + ) + ) + or + Specific::errorType(type) and result = TSemErrorType() + or + Specific::unknownType(type) and result = TSemUnknownType() +} + +private class SemNumericOrBooleanType extends SemSizedType { + SemNumericOrBooleanType() { + this instanceof SemNumericType + or + this instanceof SemBooleanType + } +} + +/** + * Holds if the conversion from `fromType` to `toType` can never overflow or underflow. + */ +predicate conversionCannotOverflow(SemNumericOrBooleanType fromType, SemNumericOrBooleanType toType) { + // Identity cast + fromType = toType + or + // Treat any cast to an FP type as safe. It can lose precision, but not overflow. + toType instanceof SemFloatingPointType and fromType = any(SemNumericType n) + or + fromType instanceof SemBooleanType and toType instanceof SemIntegerType + or + exists(SemIntegerType fromInteger, SemIntegerType toInteger, int fromSize, int toSize | + fromInteger = fromType and + toInteger = toType and + fromSize = fromInteger.getByteSize() and + toSize = toInteger.getByteSize() + | + // Conversion to a larger type. Safe unless converting signed -> unsigned. + fromSize < toSize and + ( + toInteger.isSigned() + or + not fromInteger.isSigned() + ) + ) +} + +/** + * INTERNAL: Do not use. + * Query predicates used to check invariants that should hold for all `SemType` objects. + */ +module SemTypeConsistency { + /** + * Holds if the type has no result for `getSemanticType()`. + */ + query predicate missingSemType(Specific::Type type, string message) { + not exists(getSemanticType(type)) and + message = "`Type` does not have a corresponding `SemType`." + } + + /** + * Holds if the type has more than one result for `getSemanticType()`. + */ + query predicate multipleSemTypes(Specific::Type type, string message) { + strictcount(getSemanticType(type)) > 1 and + message = + "`Type` " + type + " has multiple `SemType`s: " + + concat(getSemanticType(type).toString(), ", ") + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticTypeSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticTypeSpecific.qll new file mode 100644 index 00000000000..e301587de2f --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/SemanticTypeSpecific.qll @@ -0,0 +1,43 @@ +/** + * C++-specific implementation of the semantic type system. + */ + +private import semmle.code.cpp.ir.IR as IR +private import cpp as Cpp +private import semmle.code.cpp.ir.internal.IRCppLanguage as Language + +class Type = IR::IRType; + +class OpaqueTypeTag = Language::OpaqueTypeTag; + +predicate voidType(Type type) { type instanceof IR::IRVoidType } + +predicate errorType(Type type) { type instanceof IR::IRErrorType } + +predicate unknownType(Type type) { type instanceof IR::IRUnknownType } + +predicate booleanType(Type type, int byteSize) { byteSize = type.(IR::IRBooleanType).getByteSize() } + +predicate integerType(Type type, int byteSize, boolean signed) { + byteSize = type.(IR::IRSignedIntegerType).getByteSize() and signed = true + or + byteSize = type.(IR::IRUnsignedIntegerType).getByteSize() and signed = false +} + +predicate floatingPointType(Type type, int byteSize) { + byteSize = type.(IR::IRFloatingPointType).getByteSize() +} + +predicate addressType(Type type, int byteSize) { byteSize = type.(IR::IRAddressType).getByteSize() } + +predicate functionAddressType(Type type, int byteSize) { + byteSize = type.(IR::IRFunctionAddressType).getByteSize() +} + +predicate opaqueType(Type type, int byteSize, OpaqueTypeTag tag) { + exists(IR::IROpaqueType opaque | opaque = type | + byteSize = opaque.getByteSize() and tag = opaque.getTag() + ) +} + +predicate getOpaqueTagIdentityString = Language::getOpaqueTagIdentityString/1; diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Bound.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Bound.qll new file mode 100644 index 00000000000..abff447ca87 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Bound.qll @@ -0,0 +1,86 @@ +import cpp +private import semmle.code.cpp.ir.IR +private import semmle.code.cpp.ir.ValueNumbering + +private newtype TBound = + TBoundZero() or + TBoundValueNumber(ValueNumber vn) { + exists(Instruction i | + vn.getAnInstruction() = i and + ( + i.getResultIRType() instanceof IRIntegerType or + i.getResultIRType() instanceof IRAddressType + ) and + not vn.getAnInstruction() instanceof ConstantInstruction + | + i instanceof PhiInstruction + or + i instanceof InitializeParameterInstruction + or + i instanceof CallInstruction + or + i instanceof VariableAddressInstruction + or + i instanceof FieldAddressInstruction + or + i.(LoadInstruction).getSourceAddress() instanceof VariableAddressInstruction + or + i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction + or + i.getAUse() instanceof ArgumentOperand + or + i instanceof PointerArithmeticInstruction + or + i.getAUse() instanceof AddressOperand + ) + } + +/** + * A bound that may be inferred for an expression plus/minus an integer delta. + */ +abstract class Bound extends TBound { + abstract string toString(); + + /** Gets an expression that equals this bound plus `delta`. */ + abstract Instruction getInstruction(int delta); + + /** Gets an expression that equals this bound. */ + Instruction getInstruction() { result = getInstruction(0) } + + abstract Location getLocation(); +} + +/** + * The bound that corresponds to the integer 0. This is used to represent all + * integer bounds as bounds are always accompanied by an added integer delta. + */ +class ZeroBound extends Bound, TBoundZero { + override string toString() { result = "0" } + + override Instruction getInstruction(int delta) { + result.(ConstantValueInstruction).getValue().toInt() = delta + } + + override Location getLocation() { result instanceof UnknownDefaultLocation } +} + +/** + * A bound corresponding to the value of an `Instruction`. + */ +class ValueNumberBound extends Bound, TBoundValueNumber { + ValueNumber vn; + + ValueNumberBound() { this = TBoundValueNumber(vn) } + + /** Gets an `Instruction` that equals this bound. */ + override Instruction getInstruction(int delta) { + this = TBoundValueNumber(valueNumber(result)) and delta = 0 + } + + override string toString() { result = "ValueNumberBound" } + + override Location getLocation() { result = vn.getLocation() } + + /** Gets the value number that equals this bound. */ + ValueNumber getValueNumber() { result = vn } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysis.qll new file mode 100644 index 00000000000..c01b64e73d6 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysis.qll @@ -0,0 +1,31 @@ +/** + * Simple constant analysis using the Semantic interface. + */ + +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +private import ConstantAnalysisSpecific as Specific + +/** An expression that always has the same integer value. */ +pragma[nomagic] +private predicate constantIntegerExpr(SemExpr e, int val) { + // An integer literal + e.(SemIntegerLiteralExpr).getIntValue() = val + or + // Copy of another constant + exists(SemSsaExplicitUpdate v, SemExpr src | + e = v.getAUse() and + src = v.getSourceExpr() and + constantIntegerExpr(src, val) + ) + or + // Language-specific enhancements + val = Specific::getIntConstantValue(e) +} + +/** An expression that always has the same integer value. */ +class SemConstantIntegerExpr extends SemExpr { + SemConstantIntegerExpr() { constantIntegerExpr(this, _) } + + /** Gets the integer value of this expression. */ + int getIntValue() { constantIntegerExpr(this, result) } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysisSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysisSpecific.qll new file mode 100644 index 00000000000..4713a10ebfc --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ConstantAnalysisSpecific.qll @@ -0,0 +1,10 @@ +/** + * C++-specific implementation of constant analysis. + */ + +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic + +/** + * Gets the constant integer value of the specified expression, if any. + */ +int getIntConstantValue(SemExpr expr) { none() } diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/FloatDelta.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/FloatDelta.qll new file mode 100644 index 00000000000..1dfcc445208 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/FloatDelta.qll @@ -0,0 +1,20 @@ +private import RangeAnalysisStage + +module FloatDelta implements DeltaSig { + class Delta = float; + + bindingset[d] + bindingset[result] + float toFloat(Delta d) { result = d } + + bindingset[d] + bindingset[result] + int toInt(Delta d) { result = d } + + bindingset[n] + bindingset[result] + Delta fromInt(int n) { result = n } + + bindingset[f] + Delta fromFloat(float f) { result = f } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/IntDelta.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/IntDelta.qll new file mode 100644 index 00000000000..83698b56229 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/IntDelta.qll @@ -0,0 +1,29 @@ +private import RangeAnalysisStage + +module IntDelta implements DeltaSig { + class Delta = int; + + bindingset[d] + bindingset[result] + float toFloat(Delta d) { result = d } + + bindingset[d] + bindingset[result] + int toInt(Delta d) { result = d } + + bindingset[n] + bindingset[result] + Delta fromInt(int n) { result = n } + + bindingset[f] + Delta fromFloat(float f) { + result = + min(float diff, float res | + diff = (res - f) and res = f.ceil() + or + diff = (f - res) and res = f.floor() + | + res order by diff + ) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll new file mode 100644 index 00000000000..a05e948a2b0 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysis.qll @@ -0,0 +1,341 @@ +/** + * Provides inferences of the form: `e` equals `b + v` modulo `m` where `e` is + * an expression, `b` is a `Bound` (typically zero or the value of an SSA + * variable), and `v` is an integer in the range `[0 .. m-1]`. + */ + +/* + * The main recursion has base cases in both `ssaModulus` (for guarded reads) and `semExprModulus` + * (for constant values). The most interesting recursive case is `phiModulusRankStep`, which + * handles phi inputs. + */ + +private import ModulusAnalysisSpecific::Private +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +private import ConstantAnalysis +private import RangeUtils +private import RangeAnalysisStage + +module ModulusAnalysis Bounds, UtilSig U> { + /** + * Holds if `e + delta` equals `v` at `pos`. + */ + private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) { + U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v) + or + exists(SemGuard guard, boolean testIsTrue | + pos.hasReadOfVar(v) and + guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and + semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) + ) + } + + /** + * Holds if `add` is the addition of `larg` and `rarg`, neither of which are + * `ConstantIntegerExpr`s. + */ + private predicate nonConstAddition(SemExpr add, SemExpr larg, SemExpr rarg) { + exists(SemAddExpr a | a = add | + larg = a.getLeftOperand() and + rarg = a.getRightOperand() + ) and + not larg instanceof SemConstantIntegerExpr and + not rarg instanceof SemConstantIntegerExpr + } + + /** + * Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not + * a `ConstantIntegerExpr`. + */ + private predicate nonConstSubtraction(SemExpr sub, SemExpr larg, SemExpr rarg) { + exists(SemSubExpr s | s = sub | + larg = s.getLeftOperand() and + rarg = s.getRightOperand() + ) and + not rarg instanceof SemConstantIntegerExpr + } + + /** Gets an expression that is the remainder modulo `mod` of `arg`. */ + private SemExpr modExpr(SemExpr arg, int mod) { + exists(SemRemExpr rem | + result = rem and + arg = rem.getLeftOperand() and + rem.getRightOperand().(SemConstantIntegerExpr).getIntValue() = mod and + mod >= 2 + ) + or + exists(SemConstantIntegerExpr c | + mod = 2.pow([1 .. 30]) and + c.getIntValue() = mod - 1 and + result.(SemBitAndExpr).hasOperands(arg, c) + ) + } + + /** + * Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on + * its `testIsTrue` branch. + */ + private SemGuard moduloCheck(SemSsaVariable v, int val, int mod, boolean testIsTrue) { + exists(SemExpr rem, SemConstantIntegerExpr c, int r, boolean polarity | + result.isEquality(rem, c, polarity) and + c.getIntValue() = r and + rem = modExpr(v.getAUse(), mod) and + ( + testIsTrue = polarity and val = r + or + testIsTrue = polarity.booleanNot() and + mod = 2 and + val = 1 - r and + (r = 0 or r = 1) + ) + ) + } + + /** + * Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`. + */ + private predicate moduloGuardedRead(SemSsaVariable v, SemSsaReadPosition pos, int val, int mod) { + exists(SemGuard guard, boolean testIsTrue | + pos.hasReadOfVar(v) and + guard = moduloCheck(v, val, mod, testIsTrue) and + semGuardControlsSsaRead(guard, pos, testIsTrue) + ) + } + + /** Holds if `factor` is a power of 2 that divides `mask`. */ + bindingset[mask] + private predicate andmaskFactor(int mask, int factor) { + mask % factor = 0 and + factor = 2.pow([1 .. 30]) + } + + /** Holds if `e` is evenly divisible by `factor`. */ + private predicate evenlyDivisibleExpr(SemExpr e, int factor) { + exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() | + e.(SemMulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2 + or + e.(SemShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0 + or + e.(SemBitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f)) + ) + } + + /** + * Holds if `rix` is the number of input edges to `phi`. + */ + private predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) { + rix = max(int r | rankedPhiInput(phi, _, _, r)) + } + + /** + * Gets the remainder of `val` modulo `mod`. + * + * For `mod = 0` the result equals `val` and for `mod > 1` the result is within + * the range `[0 .. mod-1]`. + */ + bindingset[val, mod] + private int remainder(int val, int mod) { + mod = 0 and result = val + or + mod > 1 and result = ((val % mod) + mod) % mod + } + + /** + * Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`. + */ + private predicate phiSelfModulus( + SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int mod + ) { + exists(Bounds::SemSsaBound phibound, int v, int m | + edge.phiInput(phi, inp) and + phibound.getAVariable() = phi and + ssaModulus(inp, edge, phibound, v, m) and + mod = m.gcd(v) and + mod != 1 + ) + } + + /** + * Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`. + */ + private predicate phiModulusInit(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) { + exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | + edge.phiInput(phi, inp) and + ssaModulus(inp, edge, b, val, mod) + ) + } + + /** + * Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`. + */ + pragma[nomagic] + private predicate phiModulusRankStep( + SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod, int rix + ) { + /* + * base case. If any phi input is equal to `b + val` modulo `mod`, that's a potential congruence + * class for the phi node. + */ + + rix = 0 and + phiModulusInit(phi, b, val, mod) + or + exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int v1, int m1 | + mod != 1 and + val = remainder(v1, mod) + | + /* + * Recursive case. If `inp` = `b + v2` mod `m2`, we combine that with the preceding potential + * congruence class `b + v1` mod `m1`. The result will be the congruence class of `v1` modulo + * the greatest common denominator of `m1`, `m2`, and `v1 - v2`. + */ + + exists(int v2, int m2 | + rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and + phiModulusRankStep(phi, b, v1, m1, rix - 1) and + ssaModulus(inp, edge, b, v2, m2) and + mod = m1.gcd(m2).gcd(v1 - v2) + ) + or + /* + * Recursive case. If `inp` = `phi` mod `m2`, we combine that with the preceding potential + * congruence class `b + v1` mod `m1`. The result will be a congruence class modulo the greatest + * common denominator of `m1` and `m2`. + */ + + exists(int m2 | + rankedPhiInput(phi, inp, edge, rix) and + phiModulusRankStep(phi, b, v1, m1, rix - 1) and + phiSelfModulus(phi, inp, edge, m2) and + mod = m1.gcd(m2) + ) + ) + } + + /** + * Holds if `phi` is equal to `b + val` modulo `mod`. + */ + private predicate phiModulus(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) { + exists(int r | + maxPhiInputRank(phi, r) and + phiModulusRankStep(phi, b, val, mod, r) + ) + } + + /** + * Holds if `v` at `pos` is equal to `b + val` modulo `mod`. + */ + private predicate ssaModulus( + SemSsaVariable v, SemSsaReadPosition pos, Bounds::SemBound b, int val, int mod + ) { + phiModulus(v, b, val, mod) and pos.hasReadOfVar(v) + or + b.(Bounds::SemSsaBound).getAVariable() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0 + or + exists(SemExpr e, int val0, int delta | + semExprModulus(e, b, val0, mod) and + valueFlowStepSsa(v, pos, e, delta) and + val = remainder(val0 + delta, mod) + ) + or + moduloGuardedRead(v, pos, val, mod) and b instanceof Bounds::SemZeroBound + } + + /** + * Holds if `e` is equal to `b + val` modulo `mod`. + * + * There are two cases for the modulus: + * - `mod = 0`: The equality `e = b + val` is an ordinary equality. + * - `mod > 1`: `val` lies within the range `[0 .. mod-1]`. + */ + cached + predicate semExprModulus(SemExpr e, Bounds::SemBound b, int val, int mod) { + not ignoreExprModulus(e) and + ( + e = b.getExpr(D::fromInt(val)) and mod = 0 + or + evenlyDivisibleExpr(e, mod) and + val = 0 and + b instanceof Bounds::SemZeroBound + or + exists(SemSsaVariable v, SemSsaReadPositionBlock bb | + ssaModulus(v, bb, b, val, mod) and + e = v.getAUse() and + bb.getAnExpr() = e + ) + or + exists(SemExpr mid, int val0, int delta | + semExprModulus(mid, b, val0, mod) and + U::semValueFlowStep(e, mid, D::fromInt(delta)) and + val = remainder(val0 + delta, mod) + ) + or + exists(SemConditionalExpr cond, int v1, int v2, int m1, int m2 | + cond = e and + condExprBranchModulus(cond, true, b, v1, m1) and + condExprBranchModulus(cond, false, b, v2, m2) and + mod = m1.gcd(m2).gcd(v1 - v2) and + mod != 1 and + val = remainder(v1, mod) + ) + or + exists(Bounds::SemBound b1, Bounds::SemBound b2, int v1, int v2, int m1, int m2 | + addModulus(e, true, b1, v1, m1) and + addModulus(e, false, b2, v2, m2) and + mod = m1.gcd(m2) and + mod != 1 and + val = remainder(v1 + v2, mod) + | + b = b1 and b2 instanceof Bounds::SemZeroBound + or + b = b2 and b1 instanceof Bounds::SemZeroBound + ) + or + exists(int v1, int v2, int m1, int m2 | + subModulus(e, true, b, v1, m1) and + subModulus(e, false, any(Bounds::SemZeroBound zb), v2, m2) and + mod = m1.gcd(m2) and + mod != 1 and + val = remainder(v1 - v2, mod) + ) + ) + } + + private predicate condExprBranchModulus( + SemConditionalExpr cond, boolean branch, Bounds::SemBound b, int val, int mod + ) { + semExprModulus(cond.getBranchExpr(branch), b, val, mod) + } + + private predicate addModulus(SemExpr add, boolean isLeft, Bounds::SemBound b, int val, int mod) { + exists(SemExpr larg, SemExpr rarg | nonConstAddition(add, larg, rarg) | + semExprModulus(larg, b, val, mod) and isLeft = true + or + semExprModulus(rarg, b, val, mod) and isLeft = false + ) + } + + private predicate subModulus(SemExpr sub, boolean isLeft, Bounds::SemBound b, int val, int mod) { + exists(SemExpr larg, SemExpr rarg | nonConstSubtraction(sub, larg, rarg) | + semExprModulus(larg, b, val, mod) and isLeft = true + or + semExprModulus(rarg, b, val, mod) and isLeft = false + ) + } + + /** + * Holds if `inp` is an input to `phi` along `edge` and this input has index `r` + * in an arbitrary 1-based numbering of the input edges to `phi`. + */ + private predicate rankedPhiInput( + SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r + ) { + edge.phiInput(phi, inp) and + edge = + rank[r](SemSsaReadPositionPhiInputEdge e | + e.phiInput(phi, _) + | + e order by e.getOrigBlock().getUniqueId() + ) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysisSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysisSpecific.qll new file mode 100644 index 00000000000..c0e7287e23b --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/ModulusAnalysisSpecific.qll @@ -0,0 +1,8 @@ +/** + * C++-specific implementation of modulus analysis. + */ +module Private { + private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic + + predicate ignoreExprModulus(SemExpr e) { none() } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysis.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysis.qll new file mode 100644 index 00000000000..5d15aa30fb4 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysis.qll @@ -0,0 +1,2 @@ +import RangeAnalysisImpl +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisImpl.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisImpl.qll new file mode 100644 index 00000000000..dd3a0f2e878 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisImpl.qll @@ -0,0 +1,107 @@ +private import RangeAnalysisStage +private import RangeAnalysisSpecific +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta +private import RangeUtils +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound as SemanticBound +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticSSA + +module ConstantBounds implements BoundSig { + class SemBound instanceof SemanticBound::SemBound { + SemBound() { + this instanceof SemanticBound::SemZeroBound + or + this.(SemanticBound::SemSsaBound).getAVariable() instanceof SemSsaPhiNode + } + + string toString() { result = super.toString() } + + SemLocation getLocation() { result = super.getLocation() } + + SemExpr getExpr(float delta) { result = super.getExpr(delta) } + } + + class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } + + class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { + SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } + } +} + +private module RelativeBounds implements BoundSig { + class SemBound instanceof SemanticBound::SemBound { + SemBound() { not this instanceof SemanticBound::SemZeroBound } + + string toString() { result = super.toString() } + + SemLocation getLocation() { result = super.getLocation() } + + SemExpr getExpr(float delta) { result = super.getExpr(delta) } + } + + class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } + + class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { + SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } + } +} + +private module ConstantStage = + RangeStage>; + +private module RelativeStage = + RangeStage>; + +private newtype TSemReason = + TSemNoReason() or + TSemCondReason(SemGuard guard) { + guard = any(ConstantStage::SemCondReason reason).getCond() + or + guard = any(RelativeStage::SemCondReason reason).getCond() + } + +/** + * A reason for an inferred bound. This can either be `CondReason` if the bound + * is due to a specific condition, or `NoReason` if the bound is inferred + * without going through a bounding condition. + */ +abstract class SemReason extends TSemReason { + /** Gets a textual representation of this reason. */ + abstract string toString(); +} + +/** + * A reason for an inferred bound that indicates that the bound is inferred + * without going through a bounding condition. + */ +class SemNoReason extends SemReason, TSemNoReason { + override string toString() { result = "NoReason" } +} + +/** A reason for an inferred bound pointing to a condition. */ +class SemCondReason extends SemReason, TSemCondReason { + /** Gets the condition that is the reason for the bound. */ + SemGuard getCond() { this = TSemCondReason(result) } + + override string toString() { result = getCond().toString() } +} + +private ConstantStage::SemReason constantReason(SemReason reason) { + result instanceof ConstantStage::SemNoReason and reason instanceof SemNoReason + or + result.(ConstantStage::SemCondReason).getCond() = reason.(SemCondReason).getCond() +} + +private RelativeStage::SemReason relativeReason(SemReason reason) { + result instanceof RelativeStage::SemNoReason and reason instanceof SemNoReason + or + result.(RelativeStage::SemCondReason).getCond() = reason.(SemCondReason).getCond() +} + +predicate semBounded( + SemExpr e, SemanticBound::SemBound b, float delta, boolean upper, SemReason reason +) { + ConstantStage::semBounded(e, b, delta, upper, constantReason(reason)) + or + RelativeStage::semBounded(e, b, delta, upper, relativeReason(reason)) +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisSpecific.qll new file mode 100644 index 00000000000..2ddc20c8a33 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisSpecific.qll @@ -0,0 +1,92 @@ +/** + * C++-specific implementation of range analysis. + */ + +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +private import RangeAnalysisStage +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta + +module CppLangImpl implements LangSig { + /** + * Holds if the specified expression should be excluded from the result of `ssaRead()`. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreSsaReadCopy(SemExpr e) { none() } + + /** + * Ignore the bound on this expression. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreExprBound(SemExpr e) { none() } + + /** + * Ignore any inferred zero lower bound on this expression. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreZeroLowerBound(SemExpr e) { none() } + + /** + * Holds if the specified expression should be excluded from the result of `ssaRead()`. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreSsaReadArithmeticExpr(SemExpr e) { none() } + + /** + * Holds if the specified variable should be excluded from the result of `ssaRead()`. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreSsaReadAssignment(SemSsaVariable v) { none() } + + /** + * Adds additional results to `ssaRead()` that are specific to Java. + * + * This predicate handles propagation of offsets for post-increment and post-decrement expressions + * in exactly the same way as the old Java implementation. Once the new implementation matches the + * old one, we should remove this predicate and propagate deltas for all similar patterns, whether + * or not they come from a post-increment/decrement expression. + */ + SemExpr specificSsaRead(SemSsaVariable v, float delta) { none() } + + /** + * Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`). + */ + predicate hasConstantBound(SemExpr e, float bound, boolean upper) { none() } + + /** + * Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`). + */ + predicate hasBound(SemExpr e, SemExpr bound, float delta, boolean upper) { none() } + + /** + * Holds if the value of `dest` is known to be `src + delta`. + */ + predicate additionalValueFlowStep(SemExpr dest, SemExpr src, float delta) { none() } + + /** + * Gets the type that range analysis should use to track the result of the specified expression, + * if a type other than the original type of the expression is to be used. + * + * This predicate is commonly used in languages that support immutable "boxed" types that are + * actually references but whose values can be tracked as the type contained in the box. + */ + SemType getAlternateType(SemExpr e) { none() } + + /** + * Gets the type that range analysis should use to track the result of the specified source + * variable, if a type other than the original type of the expression is to be used. + * + * This predicate is commonly used in languages that support immutable "boxed" types that are + * actually references but whose values can be tracked as the type contained in the box. + */ + SemType getAlternateTypeForSsaVariable(SemSsaVariable var) { none() } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll new file mode 100644 index 00000000000..2cdf7b1e233 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeAnalysisStage.qll @@ -0,0 +1,1217 @@ +/** + * Provides classes and predicates for range analysis. + * + * An inferred bound can either be a specific integer, the abstract value of an + * SSA variable, or the abstract value of an interesting expression. The latter + * category includes array lengths that are not SSA variables. + * + * If an inferred bound relies directly on a condition, then this condition is + * reported as the reason for the bound. + */ + +/* + * This library tackles range analysis as a flow problem. Consider e.g.: + * ``` + * len = arr.length; + * if (x < len) { ... y = x-1; ... y ... } + * ``` + * In this case we would like to infer `y <= arr.length - 2`, and this is + * accomplished by tracking the bound through a sequence of steps: + * ``` + * arr.length --> len = .. --> x < len --> x-1 --> y = .. --> y + * ``` + * + * In its simplest form the step relation `E1 --> E2` relates two expressions + * such that `E1 <= B` implies `E2 <= B` for any `B` (with a second separate + * step relation handling lower bounds). Examples of such steps include + * assignments `E2 = E1` and conditions `x <= E1` where `E2` is a use of `x` + * guarded by the condition. + * + * In order to handle subtractions and additions with constants, and strict + * comparisons, the step relation is augmented with an integer delta. With this + * generalization `E1 --(delta)--> E2` relates two expressions and an integer + * such that `E1 <= B` implies `E2 <= B + delta` for any `B`. This corresponds + * to the predicate `boundFlowStep`. + * + * The complete range analysis is then implemented as the transitive closure of + * the step relation summing the deltas along the way. If `E1` transitively + * steps to `E2`, `delta` is the sum of deltas along the path, and `B` is an + * interesting bound equal to the value of `E1` then `E2 <= B + delta`. This + * corresponds to the predicate `bounded`. + * + * Phi nodes need a little bit of extra handling. Consider `x0 = phi(x1, x2)`. + * There are essentially two cases: + * - If `x1 <= B + d1` and `x2 <= B + d2` then `x0 <= B + max(d1,d2)`. + * - If `x1 <= B + d1` and `x2 <= x0 + d2` with `d2 <= 0` then `x0 <= B + d1`. + * The first case is for whenever a bound can be proven without taking looping + * into account. The second case is relevant when `x2` comes from a back-edge + * where we can prove that the variable has been non-increasing through the + * loop-iteration as this means that any upper bound that holds prior to the + * loop also holds for the variable during the loop. + * This generalizes to a phi node with `n` inputs, so if + * `x0 = phi(x1, ..., xn)` and `xi <= B + delta` for one of the inputs, then we + * also have `x0 <= B + delta` if we can prove either: + * - `xj <= B + d` with `d <= delta` or + * - `xj <= x0 + d` with `d <= 0` + * for each input `xj`. + * + * As all inferred bounds can be related directly to a path in the source code + * the only source of non-termination is if successive redundant (and thereby + * increasingly worse) bounds are calculated along a loop in the source code. + * We prevent this by weakening the bound to a small finite set of bounds when + * a path follows a second back-edge (we postpone weakening till the second + * back-edge as a precise bound might require traversing a loop once). + */ + +private import RangeUtils as Utils +private import SignAnalysisCommon +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.ModulusAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExpr +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticSSA +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticGuard +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticCFG +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticType +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticOpcode +private import ConstantAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticLocation + +/** + * Holds if `typ` is a small integral type with the given lower and upper bounds. + */ +private predicate typeBound(SemIntegerType typ, float lowerbound, float upperbound) { + exists(int bitSize | bitSize = typ.getByteSize() * 8 | + if typ.isSigned() + then ( + upperbound = 2.pow(bitSize - 1) - 1 and + lowerbound = -upperbound - 1 + ) else ( + lowerbound = 0 and + upperbound = 2.pow(bitSize) - 1 + ) + ) +} + +signature module DeltaSig { + bindingset[this] + class Delta; + + bindingset[d] + bindingset[result] + float toFloat(Delta d); + + bindingset[d] + bindingset[result] + int toInt(Delta d); + + bindingset[n] + bindingset[result] + Delta fromInt(int n); + + bindingset[f] + Delta fromFloat(float f); +} + +signature module LangSig { + /** + * Holds if the specified expression should be excluded from the result of `ssaRead()`. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreSsaReadCopy(SemExpr e); + + /** + * Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`). + */ + predicate hasConstantBound(SemExpr e, D::Delta bound, boolean upper); + + /** + * Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`). + */ + predicate hasBound(SemExpr e, SemExpr bound, D::Delta delta, boolean upper); + + /** + * Ignore the bound on this expression. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreExprBound(SemExpr e); + + /** + * Ignore any inferred zero lower bound on this expression. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreZeroLowerBound(SemExpr e); + + /** + * Holds if the specified expression should be excluded from the result of `ssaRead()`. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreSsaReadArithmeticExpr(SemExpr e); + + /** + * Holds if the specified variable should be excluded from the result of `ssaRead()`. + * + * This predicate is to keep the results identical to the original Java implementation. It should be + * removed once we have the new implementation matching the old results exactly. + */ + predicate ignoreSsaReadAssignment(SemSsaVariable v); + + /** + * Adds additional results to `ssaRead()` that are specific to Java. + * + * This predicate handles propagation of offsets for post-increment and post-decrement expressions + * in exactly the same way as the old Java implementation. Once the new implementation matches the + * old one, we should remove this predicate and propagate deltas for all similar patterns, whether + * or not they come from a post-increment/decrement expression. + */ + SemExpr specificSsaRead(SemSsaVariable v, D::Delta delta); + + /** + * Holds if the value of `dest` is known to be `src + delta`. + */ + predicate additionalValueFlowStep(SemExpr dest, SemExpr src, D::Delta delta); + + /** + * Gets the type that range analysis should use to track the result of the specified expression, + * if a type other than the original type of the expression is to be used. + * + * This predicate is commonly used in languages that support immutable "boxed" types that are + * actually references but whose values can be tracked as the type contained in the box. + */ + SemType getAlternateType(SemExpr e); + + /** + * Gets the type that range analysis should use to track the result of the specified source + * variable, if a type other than the original type of the expression is to be used. + * + * This predicate is commonly used in languages that support immutable "boxed" types that are + * actually references but whose values can be tracked as the type contained in the box. + */ + SemType getAlternateTypeForSsaVariable(SemSsaVariable var); +} + +signature module UtilSig { + SemExpr semSsaRead(SemSsaVariable v, DeltaParam::Delta delta); + + SemGuard semEqFlowCond( + SemSsaVariable v, SemExpr e, DeltaParam::Delta delta, boolean isEq, boolean testIsTrue + ); + + predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, DeltaParam::Delta delta); + + predicate semValueFlowStep(SemExpr e2, SemExpr e1, DeltaParam::Delta delta); + + /** + * Gets the type used to track the specified source variable's range information. + * + * Usually, this just `e.getType()`, but the language can override this to track immutable boxed + * primitive types as the underlying primitive type. + */ + SemType getTrackedTypeForSsaVariable(SemSsaVariable var); + + /** + * Gets the type used to track the specified expression's range information. + * + * Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed + * primitive types as the underlying primitive type. + */ + SemType getTrackedType(SemExpr e); +} + +signature module BoundSig { + class SemBound { + string toString(); + + SemLocation getLocation(); + + SemExpr getExpr(D::Delta delta); + } + + class SemZeroBound extends SemBound; + + class SemSsaBound extends SemBound { + SemSsaVariable getAVariable(); + } +} + +module RangeStage Bounds, LangSig LangParam, UtilSig UtilParam> { + private import Bounds + private import LangParam + private import UtilParam + private import D + + /** + * An expression that does conversion, boxing, or unboxing + */ + private class ConvertOrBoxExpr instanceof SemUnaryExpr { + ConvertOrBoxExpr() { + this instanceof SemConvertExpr + or + this instanceof SemBoxExpr + or + this instanceof SemUnboxExpr + } + + string toString() { result = super.toString() } + + SemExpr getOperand() { result = super.getOperand() } + } + + /** + * A cast that can be ignored for the purpose of range analysis. + */ + private class SafeCastExpr extends ConvertOrBoxExpr { + SafeCastExpr() { + conversionCannotOverflow(getTrackedType(pragma[only_bind_into](getOperand())), + pragma[only_bind_out](getTrackedType(this))) + } + } + + /** + * A cast to a small integral type that may overflow or underflow. + */ + private class NarrowingCastExpr extends ConvertOrBoxExpr { + NarrowingCastExpr() { + not this instanceof SafeCastExpr and + typeBound(getTrackedType(this), _, _) + } + + /** Gets the lower bound of the resulting type. */ + float getLowerBound() { typeBound(getTrackedType(this), result, _) } + + /** Gets the upper bound of the resulting type. */ + float getUpperBound() { typeBound(getTrackedType(this), _, result) } + } + + private module SignAnalysisInstantiated = SignAnalysis; // TODO: will this cause reevaluation if it's instantiated with the same DeltaSig and UtilParam multiple times? + + private import SignAnalysisInstantiated + + private module ModulusAnalysisInstantiated = ModulusAnalysis; // TODO: will this cause reevaluation if it's instantiated with the same DeltaSig and UtilParam multiple times? + + private import ModulusAnalysisInstantiated + + cached + private module RangeAnalysisCache { + cached + module RangeAnalysisPublic { + /** + * Holds if `b + delta` is a valid bound for `e`. + * - `upper = true` : `e <= b + delta` + * - `upper = false` : `e >= b + delta` + * + * The reason for the bound is given by `reason` and may be either a condition + * or `NoReason` if the bound was proven directly without the use of a bounding + * condition. + */ + cached + predicate semBounded(SemExpr e, SemBound b, D::Delta delta, boolean upper, SemReason reason) { + bounded(e, b, delta, upper, _, _, reason) and + bestBound(e, b, delta, upper) + } + } + + /** + * Holds if `guard = boundFlowCond(_, _, _, _, _) or guard = eqFlowCond(_, _, _, _, _)`. + */ + cached + predicate possibleReason(SemGuard guard) { + guard = boundFlowCond(_, _, _, _, _) or guard = semEqFlowCond(_, _, _, _, _) + } + } + + private import RangeAnalysisCache + import RangeAnalysisPublic + + /** + * Holds if `b + delta` is a valid bound for `e` and this is the best such delta. + * - `upper = true` : `e <= b + delta` + * - `upper = false` : `e >= b + delta` + */ + private predicate bestBound(SemExpr e, SemBound b, D::Delta delta, boolean upper) { + delta = min(D::Delta d | bounded(e, b, d, upper, _, _, _) | d order by D::toFloat(d)) and + upper = true + or + delta = max(D::Delta d | bounded(e, b, d, upper, _, _, _) | d order by D::toFloat(d)) and + upper = false + } + + /** + * Holds if `comp` corresponds to: + * - `upper = true` : `v <= e + delta` or `v < e + delta` + * - `upper = false` : `v >= e + delta` or `v > e + delta` + */ + private predicate boundCondition( + SemRelationalExpr comp, SemSsaVariable v, SemExpr e, D::Delta delta, boolean upper + ) { + comp.getLesserOperand() = semSsaRead(v, delta) and + e = comp.getGreaterOperand() and + upper = true + or + comp.getGreaterOperand() = semSsaRead(v, delta) and + e = comp.getLesserOperand() and + upper = false + or + exists(SemSubExpr sub, SemConstantIntegerExpr c, D::Delta d | + // (v - d) - e < c + comp.getLesserOperand() = sub and + comp.getGreaterOperand() = c and + sub.getLeftOperand() = semSsaRead(v, d) and + sub.getRightOperand() = e and + upper = true and + delta = D::fromFloat(D::toFloat(d) + c.getIntValue()) + or + // (v - d) - e > c + comp.getGreaterOperand() = sub and + comp.getLesserOperand() = c and + sub.getLeftOperand() = semSsaRead(v, d) and + sub.getRightOperand() = e and + upper = false and + delta = D::fromFloat(D::toFloat(d) + c.getIntValue()) + or + // e - (v - d) < c + comp.getLesserOperand() = sub and + comp.getGreaterOperand() = c and + sub.getLeftOperand() = e and + sub.getRightOperand() = semSsaRead(v, d) and + upper = false and + delta = D::fromFloat(D::toFloat(d) - c.getIntValue()) + or + // e - (v - d) > c + comp.getGreaterOperand() = sub and + comp.getLesserOperand() = c and + sub.getLeftOperand() = e and + sub.getRightOperand() = semSsaRead(v, d) and + upper = true and + delta = D::fromFloat(D::toFloat(d) - c.getIntValue()) + ) + } + + /** + * Holds if `comp` is a comparison between `x` and `y` for which `y - x` has a + * fixed value modulo some `mod > 1`, such that the comparison can be + * strengthened by `strengthen` when evaluating to `testIsTrue`. + */ + private predicate modulusComparison(SemRelationalExpr comp, boolean testIsTrue, int strengthen) { + exists( + SemBound b, int v1, int v2, int mod1, int mod2, int mod, boolean resultIsStrict, int d, int k + | + // If `x <= y` and `x =(mod) b + v1` and `y =(mod) b + v2` then + // `0 <= y - x =(mod) v2 - v1`. By choosing `k =(mod) v2 - v1` with + // `0 <= k < mod` we get `k <= y - x`. If the resulting comparison is + // strict then the strengthening amount is instead `k - 1` modulo `mod`: + // `x < y` means `0 <= y - x - 1 =(mod) k - 1` so `k - 1 <= y - x - 1` and + // thus `k - 1 < y - x` with `0 <= k - 1 < mod`. + semExprModulus(comp.getLesserOperand(), b, v1, mod1) and + semExprModulus(comp.getGreaterOperand(), b, v2, mod2) and + mod = mod1.gcd(mod2) and + mod != 1 and + (testIsTrue = true or testIsTrue = false) and + ( + if comp.isStrict() + then resultIsStrict = testIsTrue + else resultIsStrict = testIsTrue.booleanNot() + ) and + ( + resultIsStrict = true and d = 1 + or + resultIsStrict = false and d = 0 + ) and + ( + testIsTrue = true and k = v2 - v1 + or + testIsTrue = false and k = v1 - v2 + ) and + strengthen = (((k - d) % mod) + mod) % mod + ) + } + + /** + * Gets a condition that tests whether `v` is bounded by `e + delta`. + * + * If the condition evaluates to `testIsTrue`: + * - `upper = true` : `v <= e + delta` + * - `upper = false` : `v >= e + delta` + */ + private SemGuard boundFlowCond( + SemSsaVariable v, SemExpr e, D::Delta delta, boolean upper, boolean testIsTrue + ) { + exists( + SemRelationalExpr comp, D::Delta d1, float d2, float d3, int strengthen, boolean compIsUpper, + boolean resultIsStrict + | + comp = result.asExpr() and + boundCondition(comp, v, e, d1, compIsUpper) and + (testIsTrue = true or testIsTrue = false) and + upper = compIsUpper.booleanXor(testIsTrue.booleanNot()) and + ( + if comp.isStrict() + then resultIsStrict = testIsTrue + else resultIsStrict = testIsTrue.booleanNot() + ) and + ( + if + getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or + getTrackedTypeForSsaVariable(v) instanceof SemAddressType + then + upper = true and strengthen = -1 + or + upper = false and strengthen = 1 + else strengthen = 0 + ) and + ( + exists(int k | modulusComparison(comp, testIsTrue, k) and d2 = strengthen * k) + or + not modulusComparison(comp, testIsTrue, _) and d2 = 0 + ) and + // A strict inequality `x < y` can be strengthened to `x <= y - 1`. + ( + resultIsStrict = true and d3 = strengthen + or + resultIsStrict = false and d3 = 0 + ) and + delta = D::fromFloat(D::toFloat(d1) + d2 + d3) + ) + or + exists(boolean testIsTrue0 | + semImplies_v2(result, testIsTrue, boundFlowCond(v, e, delta, upper, testIsTrue0), testIsTrue0) + ) + or + result = semEqFlowCond(v, e, delta, true, testIsTrue) and + (upper = true or upper = false) + or + // guard that tests whether `v2` is bounded by `e + delta + d1 - d2` and + // exists a guard `guardEq` such that `v = v2 - d1 + d2`. + exists( + SemSsaVariable v2, SemGuard guardEq, boolean eqIsTrue, D::Delta d1, D::Delta d2, + D::Delta oldDelta + | + guardEq = semEqFlowCond(v, semSsaRead(pragma[only_bind_into](v2), d1), d2, true, eqIsTrue) and + result = boundFlowCond(v2, e, oldDelta, upper, testIsTrue) and + // guardEq needs to control guard + guardEq.directlyControls(result.getBasicBlock(), eqIsTrue) and + delta = D::fromFloat(D::toFloat(oldDelta) - D::toFloat(d1) + D::toFloat(d2)) + ) + } + + private newtype TSemReason = + TSemNoReason() or + TSemCondReason(SemGuard guard) { possibleReason(guard) } + + /** + * A reason for an inferred bound. This can either be `CondReason` if the bound + * is due to a specific condition, or `NoReason` if the bound is inferred + * without going through a bounding condition. + */ + abstract class SemReason extends TSemReason { + /** Gets a textual representation of this reason. */ + abstract string toString(); + } + + /** + * A reason for an inferred bound that indicates that the bound is inferred + * without going through a bounding condition. + */ + class SemNoReason extends SemReason, TSemNoReason { + override string toString() { result = "NoReason" } + } + + /** A reason for an inferred bound pointing to a condition. */ + class SemCondReason extends SemReason, TSemCondReason { + /** Gets the condition that is the reason for the bound. */ + SemGuard getCond() { this = TSemCondReason(result) } + + override string toString() { result = getCond().toString() } + } + + /** + * Holds if `e + delta` is a valid bound for `v` at `pos`. + * - `upper = true` : `v <= e + delta` + * - `upper = false` : `v >= e + delta` + */ + private predicate boundFlowStepSsa( + SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, D::Delta delta, boolean upper, + SemReason reason + ) { + semSsaUpdateStep(v, e, delta) and + pos.hasReadOfVar(v) and + (upper = true or upper = false) and + reason = TSemNoReason() + or + exists(SemGuard guard, boolean testIsTrue | + pos.hasReadOfVar(v) and + guard = boundFlowCond(v, e, delta, upper, testIsTrue) and + semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and + reason = TSemCondReason(guard) + ) + } + + /** Holds if `v != e + delta` at `pos` and `v` is of integral type. */ + private predicate unequalFlowStepIntegralSsa( + SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, D::Delta delta, SemReason reason + ) { + getTrackedTypeForSsaVariable(v) instanceof SemIntegerType and + exists(SemGuard guard, boolean testIsTrue | + pos.hasReadOfVar(v) and + guard = semEqFlowCond(v, e, delta, false, testIsTrue) and + semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and + reason = TSemCondReason(guard) + ) + } + + /** Holds if `e >= 1` as determined by sign analysis. */ + private predicate strictlyPositiveIntegralExpr(SemExpr e) { + semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType + } + + /** Holds if `e <= -1` as determined by sign analysis. */ + private predicate strictlyNegativeIntegralExpr(SemExpr e) { + semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType + } + + /** + * Holds if `e1 + delta` is a valid bound for `e2`. + * - `upper = true` : `e2 <= e1 + delta` + * - `upper = false` : `e2 >= e1 + delta` + */ + private predicate boundFlowStep(SemExpr e2, SemExpr e1, D::Delta delta, boolean upper) { + semValueFlowStep(e2, e1, delta) and + (upper = true or upper = false) + or + e2.(SafeCastExpr).getOperand() = e1 and + delta = D::fromInt(0) and + (upper = true or upper = false) + or + exists(SemExpr x, SemSubExpr sub | + e2 = sub and + sub.getLeftOperand() = e1 and + sub.getRightOperand() = x + | + // `x instanceof ConstantIntegerExpr` is covered by valueFlowStep + not x instanceof SemConstantIntegerExpr and + if strictlyPositiveIntegralExpr(x) + then upper = true and delta = D::fromInt(-1) + else + if semPositive(x) + then upper = true and delta = D::fromInt(0) + else + if strictlyNegativeIntegralExpr(x) + then upper = false and delta = D::fromInt(1) + else + if semNegative(x) + then upper = false and delta = D::fromInt(0) + else none() + ) + or + e2.(SemRemExpr).getRightOperand() = e1 and + semPositive(e1) and + delta = D::fromInt(-1) and + upper = true + or + e2.(SemRemExpr).getLeftOperand() = e1 and + semPositive(e1) and + delta = D::fromInt(0) and + upper = true + or + e2.(SemBitAndExpr).getAnOperand() = e1 and + semPositive(e1) and + delta = D::fromInt(0) and + upper = true + or + e2.(SemBitOrExpr).getAnOperand() = e1 and + semPositive(e2) and + delta = D::fromInt(0) and + upper = false + or + hasBound(e2, e1, delta, upper) + } + + /** Holds if `e2 = e1 * factor` and `factor > 0`. */ + private predicate boundFlowStepMul(SemExpr e2, SemExpr e1, D::Delta factor) { + exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 | + e2.(SemMulExpr).hasOperands(e1, c) and factor = D::fromInt(k) + or + exists(SemShiftLeftExpr e | + e = e2 and + e.getLeftOperand() = e1 and + e.getRightOperand() = c and + factor = D::fromInt(2.pow(k)) + ) + ) + } + + /** + * Holds if `e2 = e1 / factor` and `factor > 0`. + * + * This conflates division, right shift, and unsigned right shift and is + * therefore only valid for non-negative numbers. + */ + private predicate boundFlowStepDiv(SemExpr e2, SemExpr e1, D::Delta factor) { + exists(SemConstantIntegerExpr c, D::Delta k | + k = D::fromInt(c.getIntValue()) and D::toFloat(k) > 0 + | + exists(SemDivExpr e | + e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = k + ) + or + exists(SemShiftRightExpr e | + e = e2 and + e.getLeftOperand() = e1 and + e.getRightOperand() = c and + factor = D::fromInt(2.pow(D::toInt(k))) + ) + or + exists(SemShiftRightUnsignedExpr e | + e = e2 and + e.getLeftOperand() = e1 and + e.getRightOperand() = c and + factor = D::fromInt(2.pow(D::toInt(k))) + ) + ) + } + + /** + * Holds if `b + delta` is a valid bound for `v` at `pos`. + * - `upper = true` : `v <= b + delta` + * - `upper = false` : `v >= b + delta` + */ + private predicate boundedSsa( + SemSsaVariable v, SemSsaReadPosition pos, SemBound b, D::Delta delta, boolean upper, + boolean fromBackEdge, D::Delta origdelta, SemReason reason + ) { + exists(SemExpr mid, D::Delta d1, D::Delta d2, SemReason r1, SemReason r2 | + boundFlowStepSsa(v, pos, mid, d1, upper, r1) and + bounded(mid, b, d2, upper, fromBackEdge, origdelta, r2) and + // upper = true: v <= mid + d1 <= b + d1 + d2 = b + delta + // upper = false: v >= mid + d1 >= b + d1 + d2 = b + delta + delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) and + (if r1 instanceof SemNoReason then reason = r2 else reason = r1) + ) + or + exists(D::Delta d, SemReason r1, SemReason r2 | + boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or + boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2) + | + unequalIntegralSsa(v, pos, b, d, r1) and + ( + upper = true and delta = D::fromFloat(D::toFloat(d) - 1) + or + upper = false and delta = D::fromFloat(D::toFloat(d) + 1) + ) and + ( + reason = r1 + or + reason = r2 and not r2 instanceof SemNoReason + ) + ) + } + + /** + * Holds if `v != b + delta` at `pos` and `v` is of integral type. + */ + private predicate unequalIntegralSsa( + SemSsaVariable v, SemSsaReadPosition pos, SemBound b, D::Delta delta, SemReason reason + ) { + exists(SemExpr e, D::Delta d1, D::Delta d2 | + unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and + boundedUpper(e, b, d1) and + boundedLower(e, b, d2) and + delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) + ) + } + + /** + * Holds if `b + delta` is an upper bound for `e`. + * + * This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`. + */ + pragma[nomagic] + private predicate boundedUpper(SemExpr e, SemBound b, D::Delta delta) { + bounded(e, b, delta, true, _, _, _) + } + + /** + * Holds if `b + delta` is a lower bound for `e`. + * + * This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`. + */ + pragma[nomagic] + private predicate boundedLower(SemExpr e, SemBound b, D::Delta delta) { + bounded(e, b, delta, false, _, _, _) + } + + /** Weakens a delta to lie in the range `[-1..1]`. */ + bindingset[delta, upper] + private D::Delta weakenDelta(boolean upper, D::Delta delta) { + delta = D::fromFloat([-1 .. 1]) and result = delta + or + upper = true and result = D::fromFloat(-1) and D::toFloat(delta) < -1 + or + upper = false and result = D::fromFloat(1) and D::toFloat(delta) > 1 + } + + /** + * Holds if `b + delta` is a valid bound for `inp` when used as an input to + * `phi` along `edge`. + * - `upper = true` : `inp <= b + delta` + * - `upper = false` : `inp >= b + delta` + */ + private predicate boundedPhiInp( + SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, SemBound b, + D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta, SemReason reason + ) { + edge.phiInput(phi, inp) and + exists(D::Delta d, boolean fromBackEdge0 | + boundedSsa(inp, edge, b, d, upper, fromBackEdge0, origdelta, reason) + or + boundedPhi(inp, b, d, upper, fromBackEdge0, origdelta, reason) + or + b.(SemSsaBound).getAVariable() = inp and + d = D::fromFloat(0) and + (upper = true or upper = false) and + fromBackEdge0 = false and + origdelta = D::fromFloat(0) and + reason = TSemNoReason() + | + if semBackEdge(phi, inp, edge) + then + fromBackEdge = true and + ( + fromBackEdge0 = true and + delta = + D::fromFloat(D::toFloat(weakenDelta(upper, + D::fromFloat(D::toFloat(d) - D::toFloat(origdelta)))) + D::toFloat(origdelta)) + or + fromBackEdge0 = false and delta = d + ) + else ( + delta = d and fromBackEdge = fromBackEdge0 + ) + ) + } + + /** + * Holds if `b + delta` is a valid bound for `inp` when used as an input to + * `phi` along `edge`. + * - `upper = true` : `inp <= b + delta` + * - `upper = false` : `inp >= b + delta` + * + * Equivalent to `boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _)`. + */ + pragma[noinline] + private predicate boundedPhiInp1( + SemSsaPhiNode phi, SemBound b, boolean upper, SemSsaVariable inp, + SemSsaReadPositionPhiInputEdge edge, D::Delta delta + ) { + boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _) + } + + /** + * Holds if `phi` is a valid bound for `inp` when used as an input to `phi` + * along `edge`. + * - `upper = true` : `inp <= phi` + * - `upper = false` : `inp >= phi` + */ + private predicate selfBoundedPhiInp( + SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, boolean upper + ) { + exists(D::Delta d, SemSsaBound phibound | + phibound.getAVariable() = phi and + boundedPhiInp(phi, inp, edge, phibound, d, upper, _, _, _) and + ( + upper = true and D::toFloat(d) <= 0 + or + upper = false and D::toFloat(d) >= 0 + ) + ) + } + + /** + * Holds if `b + delta` is a valid bound for some input, `inp`, to `phi`, and + * thus a candidate bound for `phi`. + * - `upper = true` : `inp <= b + delta` + * - `upper = false` : `inp >= b + delta` + */ + pragma[noinline] + private predicate boundedPhiCand( + SemSsaPhiNode phi, boolean upper, SemBound b, D::Delta delta, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + boundedPhiInp(phi, _, _, b, delta, upper, fromBackEdge, origdelta, reason) + } + + /** + * Holds if the candidate bound `b + delta` for `phi` is valid for the phi input + * `inp` along `edge`. + */ + private predicate boundedPhiCandValidForEdge( + SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, + D::Delta origdelta, SemReason reason, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge + ) { + boundedPhiCand(phi, upper, b, delta, fromBackEdge, origdelta, reason) and + ( + exists(D::Delta d | boundedPhiInp1(phi, b, upper, inp, edge, d) | + upper = true and D::toFloat(d) <= D::toFloat(delta) + ) + or + exists(D::Delta d | boundedPhiInp1(phi, b, upper, inp, edge, d) | + upper = false and D::toFloat(d) >= D::toFloat(delta) + ) + or + selfBoundedPhiInp(phi, inp, edge, upper) + ) + } + + /** + * Holds if `b + delta` is a valid bound for `phi`. + * - `upper = true` : `phi <= b + delta` + * - `upper = false` : `phi >= b + delta` + */ + private predicate boundedPhi( + SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + forex(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | edge.phiInput(phi, inp) | + boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge) + ) + } + + /** + * Holds if `e` has an upper (for `upper = true`) or lower + * (for `upper = false`) bound of `b`. + */ + private predicate baseBound(SemExpr e, D::Delta b, boolean upper) { + hasConstantBound(e, b, upper) + or + upper = false and + b = D::fromInt(0) and + semPositive(e.(SemBitAndExpr).getAnOperand()) and + // REVIEW: We let the language opt out here to preserve original results. + not ignoreZeroLowerBound(e) + } + + /** + * Holds if the value being cast has an upper (for `upper = true`) or lower + * (for `upper = false`) bound within the bounds of the resulting type. + * For `upper = true` this means that the cast will not overflow and for + * `upper = false` this means that the cast will not underflow. + */ + private predicate safeNarrowingCast(NarrowingCastExpr cast, boolean upper) { + exists(D::Delta bound | + bounded(cast.getOperand(), any(SemZeroBound zb), bound, upper, _, _, _) + | + upper = true and D::toFloat(bound) <= cast.getUpperBound() + or + upper = false and D::toFloat(bound) >= cast.getLowerBound() + ) + } + + pragma[noinline] + private predicate boundedCastExpr( + NarrowingCastExpr cast, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason) + } + + /** + * Computes a normal form of `x` where -0.0 has changed to +0.0. This can be + * needed on the lesser side of a floating-point comparison or on both sides of + * a floating point equality because QL does not follow IEEE in floating-point + * comparisons but instead defines -0.0 to be less than and distinct from 0.0. + */ + bindingset[x] + private float normalizeFloatUp(float x) { result = x + 0.0 } + + /** + * Holds if `b + delta` is a valid bound for `e`. + * - `upper = true` : `e <= b + delta` + * - `upper = false` : `e >= b + delta` + */ + private predicate bounded( + SemExpr e, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta, + SemReason reason + ) { + not ignoreExprBound(e) and + ( + e = b.getExpr(delta) and + (upper = true or upper = false) and + fromBackEdge = false and + origdelta = delta and + reason = TSemNoReason() + or + baseBound(e, delta, upper) and + b instanceof SemZeroBound and + fromBackEdge = false and + origdelta = delta and + reason = TSemNoReason() + or + exists(SemSsaVariable v, SemSsaReadPositionBlock bb | + boundedSsa(v, bb, b, delta, upper, fromBackEdge, origdelta, reason) and + e = v.getAUse() and + bb.getBlock() = e.getBasicBlock() + ) + or + exists(SemExpr mid, D::Delta d1, D::Delta d2 | + boundFlowStep(e, mid, d1, upper) and + // Constants have easy, base-case bounds, so let's not infer any recursive bounds. + not e instanceof SemConstantIntegerExpr and + bounded(mid, b, d2, upper, fromBackEdge, origdelta, reason) and + // upper = true: e <= mid + d1 <= b + d1 + d2 = b + delta + // upper = false: e >= mid + d1 >= b + d1 + d2 = b + delta + delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) + ) + or + exists(SemSsaPhiNode phi | + boundedPhi(phi, b, delta, upper, fromBackEdge, origdelta, reason) and + e = phi.getAUse() + ) + or + exists(SemExpr mid, D::Delta factor, D::Delta d | + boundFlowStepMul(e, mid, factor) and + not e instanceof SemConstantIntegerExpr and + bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and + b instanceof SemZeroBound and + delta = D::fromFloat(D::toFloat(d) * D::toFloat(factor)) + ) + or + exists(SemExpr mid, D::Delta factor, D::Delta d | + boundFlowStepDiv(e, mid, factor) and + not e instanceof SemConstantIntegerExpr and + bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and + b instanceof SemZeroBound and + D::toFloat(d) >= 0 and + delta = D::fromFloat(D::toFloat(d) / D::toFloat(factor)) + ) + or + exists(NarrowingCastExpr cast | + cast = e and + safeNarrowingCast(cast, upper.booleanNot()) and + boundedCastExpr(cast, b, delta, upper, fromBackEdge, origdelta, reason) + ) + or + exists( + SemConditionalExpr cond, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2, D::Delta od1, + D::Delta od2, SemReason r1, SemReason r2 + | + cond = e and + boundedConditionalExpr(cond, b, upper, true, d1, fbe1, od1, r1) and + boundedConditionalExpr(cond, b, upper, false, d2, fbe2, od2, r2) and + ( + delta = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1 + or + delta = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2 + ) + | + upper = true and delta = D::fromFloat(D::toFloat(d1).maximum(D::toFloat(d2))) + or + upper = false and delta = D::fromFloat(D::toFloat(d1).minimum(D::toFloat(d2))) + ) + or + exists(SemExpr mid, D::Delta d, float f | + e.(SemNegateExpr).getOperand() = mid and + b instanceof SemZeroBound and + bounded(mid, b, d, upper.booleanNot(), fromBackEdge, origdelta, reason) and + f = normalizeFloatUp(-D::toFloat(d)) and + delta = D::fromFloat(f) and + if semPositive(e) then f >= 0 else any() + ) + or + exists( + SemBound bLeft, SemBound bRight, D::Delta dLeft, D::Delta dRight, boolean fbeLeft, + boolean fbeRight, D::Delta odLeft, D::Delta odRight, SemReason rLeft, SemReason rRight + | + boundedAddOperand(e, upper, bLeft, false, dLeft, fbeLeft, odLeft, rLeft) and + boundedAddOperand(e, upper, bRight, true, dRight, fbeRight, odRight, rRight) and + delta = D::fromFloat(D::toFloat(dLeft) + D::toFloat(dRight)) and + fromBackEdge = fbeLeft.booleanOr(fbeRight) + | + b = bLeft and origdelta = odLeft and reason = rLeft and bRight instanceof SemZeroBound + or + b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound + ) + or + exists( + SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2, + D::Delta od1, D::Delta od2, SemReason r1, SemReason r2 + | + rem = e and + b instanceof SemZeroBound and + not (upper = true and semPositive(rem.getRightOperand())) and + not (upper = true and semPositive(rem.getLeftOperand())) and + boundedRemExpr(rem, true, d1, fbe1, od1, r1) and + boundedRemExpr(rem, false, d2, fbe2, od2, r2) and + ( + if D::toFloat(d1).abs() > D::toFloat(d2).abs() + then ( + d_max = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1 + ) else ( + d_max = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2 + ) + ) + | + upper = true and delta = D::fromFloat(D::toFloat(d_max).abs() - 1) + or + upper = false and delta = D::fromFloat(-D::toFloat(d_max).abs() + 1) + ) + or + exists( + D::Delta dLeft, D::Delta dRight, boolean fbeLeft, boolean fbeRight, D::Delta odLeft, + D::Delta odRight, SemReason rLeft, SemReason rRight + | + boundedMulOperand(e, upper, true, dLeft, fbeLeft, odLeft, rLeft) and + boundedMulOperand(e, upper, false, dRight, fbeRight, odRight, rRight) and + delta = D::fromFloat(D::toFloat(dLeft) * D::toFloat(dRight)) and + fromBackEdge = fbeLeft.booleanOr(fbeRight) + | + b instanceof SemZeroBound and origdelta = odLeft and reason = rLeft + or + b instanceof SemZeroBound and origdelta = odRight and reason = rRight + ) + ) + } + + pragma[nomagic] + private predicate boundedConditionalExpr( + SemConditionalExpr cond, SemBound b, boolean upper, boolean branch, D::Delta delta, + boolean fromBackEdge, D::Delta origdelta, SemReason reason + ) { + bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason) + } + + pragma[nomagic] + private predicate boundedAddOperand( + SemAddExpr add, boolean upper, SemBound b, boolean isLeft, D::Delta delta, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + // `semValueFlowStep` already handles the case where one of the operands is a constant. + not semValueFlowStep(add, _, _) and + ( + isLeft = true and + bounded(add.getLeftOperand(), b, delta, upper, fromBackEdge, origdelta, reason) + or + isLeft = false and + bounded(add.getRightOperand(), b, delta, upper, fromBackEdge, origdelta, reason) + ) + } + + pragma[nomagic] + private predicate boundedRemExpr( + SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta, + SemReason reason + ) { + bounded(rem.getRightOperand(), any(SemZeroBound zb), delta, upper, fromBackEdge, origdelta, + reason) + } + + /** + * Define `cmp(true) = <=` and `cmp(false) = >=`. + * + * Holds if `mul = left * right`, and in order to know if `mul cmp(upper) 0 + k` (for + * some `k`) we need to know that `left cmp(upperLeft) 0 + k1` and + * `right cmp(upperRight) 0 + k2` (for some `k1` and `k2`). + */ + pragma[nomagic] + private predicate boundedMulOperandCand( + SemMulExpr mul, SemExpr left, SemExpr right, boolean upper, boolean upperLeft, + boolean upperRight + ) { + not boundFlowStepMul(mul, _, _) and + mul.getLeftOperand() = left and + mul.getRightOperand() = right and + ( + semPositive(left) and + ( + // left, right >= 0 + semPositive(right) and + ( + // max(left * right) = max(left) * max(right) + upper = true and + upperLeft = true and + upperRight = true + or + // min(left * right) = min(left) * min(right) + upper = false and + upperLeft = false and + upperRight = false + ) + or + // left >= 0, right <= 0 + semNegative(right) and + ( + // max(left * right) = min(left) * max(right) + upper = true and + upperLeft = false and + upperRight = true + or + // min(left * right) = max(left) * min(right) + upper = false and + upperLeft = true and + upperRight = false + ) + ) + or + semNegative(left) and + ( + // left <= 0, right >= 0 + semPositive(right) and + ( + // max(left * right) = max(left) * min(right) + upper = true and + upperLeft = true and + upperRight = false + or + // min(left * right) = min(left) * max(right) + upper = false and + upperLeft = false and + upperRight = true + ) + or + // left, right <= 0 + semNegative(right) and + ( + // max(left * right) = min(left) * min(right) + upper = true and + upperLeft = false and + upperRight = false + or + // min(left * right) = max(left) * max(right) + upper = false and + upperLeft = true and + upperRight = true + ) + ) + ) + } + + /** + * Holds if `isLeft = true` and `mul`'s left operand is bounded by `delta`, + * or if `isLeft = false` and `mul`'s right operand is bounded by `delta`. + * + * If `upper = true` the computed bound contributes to an upper bound of `mul`, + * and if `upper = false` it contributes to a lower bound. + * The `fromBackEdge`, `origdelta`, `reason` triple are defined by the recursive + * call to `bounded`. + */ + pragma[nomagic] + private predicate boundedMulOperand( + SemMulExpr mul, boolean upper, boolean isLeft, D::Delta delta, boolean fromBackEdge, + D::Delta origdelta, SemReason reason + ) { + exists(boolean upperLeft, boolean upperRight, SemExpr left, SemExpr right | + boundedMulOperandCand(mul, left, right, upper, upperLeft, upperRight) + | + isLeft = true and + bounded(left, any(SemZeroBound zb), delta, upperLeft, fromBackEdge, origdelta, reason) + or + isLeft = false and + bounded(right, any(SemZeroBound zb), delta, upperRight, fromBackEdge, origdelta, reason) + ) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll new file mode 100644 index 00000000000..7eeed5d7975 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/RangeUtils.qll @@ -0,0 +1,140 @@ +/** + * Provides utility predicates for range analysis. + */ + +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +private import RangeAnalysisSpecific +private import RangeAnalysisStage as Range +private import ConstantAnalysis + +module RangeUtil Lang> implements Range::UtilSig { + /** + * Gets an expression that equals `v - d`. + */ + SemExpr semSsaRead(SemSsaVariable v, D::Delta delta) { + // There are various language-specific extension points that can be removed once we no longer + // expect to match the original Java implementation's results exactly. + result = v.getAUse() and delta = D::fromInt(0) + or + exists(D::Delta d1, SemConstantIntegerExpr c | + result.(SemAddExpr).hasOperands(semSsaRead(v, d1), c) and + delta = D::fromFloat(D::toFloat(d1) - c.getIntValue()) and + not Lang::ignoreSsaReadArithmeticExpr(result) + ) + or + exists(SemSubExpr sub, D::Delta d1, SemConstantIntegerExpr c | + result = sub and + sub.getLeftOperand() = semSsaRead(v, d1) and + sub.getRightOperand() = c and + delta = D::fromFloat(D::toFloat(d1) + c.getIntValue()) and + not Lang::ignoreSsaReadArithmeticExpr(result) + ) + or + result = v.(SemSsaExplicitUpdate).getSourceExpr() and + delta = D::fromFloat(0) and + not Lang::ignoreSsaReadAssignment(v) + or + result = Lang::specificSsaRead(v, delta) + or + result.(SemCopyValueExpr).getOperand() = semSsaRead(v, delta) and + not Lang::ignoreSsaReadCopy(result) + or + result.(SemStoreExpr).getOperand() = semSsaRead(v, delta) + } + + /** + * Gets a condition that tests whether `v` equals `e + delta`. + * + * If the condition evaluates to `testIsTrue`: + * - `isEq = true` : `v == e + delta` + * - `isEq = false` : `v != e + delta` + */ + SemGuard semEqFlowCond( + SemSsaVariable v, SemExpr e, D::Delta delta, boolean isEq, boolean testIsTrue + ) { + exists(boolean eqpolarity | + result.isEquality(semSsaRead(v, delta), e, eqpolarity) and + (testIsTrue = true or testIsTrue = false) and + eqpolarity.booleanXor(testIsTrue).booleanNot() = isEq + ) + or + exists(boolean testIsTrue0 | + semImplies_v2(result, testIsTrue, semEqFlowCond(v, e, delta, isEq, testIsTrue0), testIsTrue0) + ) + } + + /** + * Holds if `v` is an `SsaExplicitUpdate` that equals `e + delta`. + */ + predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, D::Delta delta) { + exists(SemExpr defExpr | defExpr = v.getSourceExpr() | + defExpr.(SemCopyValueExpr).getOperand() = e and delta = D::fromFloat(0) + or + defExpr.(SemStoreExpr).getOperand() = e and delta = D::fromFloat(0) + or + defExpr.(SemAddOneExpr).getOperand() = e and delta = D::fromFloat(1) + or + defExpr.(SemSubOneExpr).getOperand() = e and delta = D::fromFloat(-1) + or + e = defExpr and + not ( + defExpr instanceof SemCopyValueExpr or + defExpr instanceof SemStoreExpr or + defExpr instanceof SemAddOneExpr or + defExpr instanceof SemSubOneExpr + ) and + delta = D::fromFloat(0) + ) + } + + /** + * Holds if `e1 + delta` equals `e2`. + */ + predicate semValueFlowStep(SemExpr e2, SemExpr e1, D::Delta delta) { + e2.(SemCopyValueExpr).getOperand() = e1 and delta = D::fromFloat(0) + or + e2.(SemStoreExpr).getOperand() = e1 and delta = D::fromFloat(0) + or + e2.(SemAddOneExpr).getOperand() = e1 and delta = D::fromFloat(1) + or + e2.(SemSubOneExpr).getOperand() = e1 and delta = D::fromFloat(-1) + or + Lang::additionalValueFlowStep(e2, e1, delta) + or + exists(SemExpr x | e2.(SemAddExpr).hasOperands(e1, x) | + D::fromInt(x.(SemConstantIntegerExpr).getIntValue()) = delta + ) + or + exists(SemExpr x, SemSubExpr sub | + e2 = sub and + sub.getLeftOperand() = e1 and + sub.getRightOperand() = x + | + D::fromInt(-x.(SemConstantIntegerExpr).getIntValue()) = delta + ) + } + + /** + * Gets the type used to track the specified expression's range information. + * + * Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed + * primitive types as the underlying primitive type. + */ + SemType getTrackedType(SemExpr e) { + result = Lang::getAlternateType(e) + or + not exists(Lang::getAlternateType(e)) and result = e.getSemType() + } + + /** + * Gets the type used to track the specified source variable's range information. + * + * Usually, this just `e.getType()`, but the language can override this to track immutable boxed + * primitive types as the underlying primitive type. + */ + SemType getTrackedTypeForSsaVariable(SemSsaVariable var) { + result = Lang::getAlternateTypeForSsaVariable(var) + or + not exists(Lang::getAlternateTypeForSsaVariable(var)) and result = var.getType() + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Sign.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Sign.qll new file mode 100644 index 00000000000..814691d9bcd --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/Sign.qll @@ -0,0 +1,267 @@ +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic + +newtype TSign = + TNeg() or + TZero() or + TPos() + +/** Class representing expression signs (+, -, 0). */ +class Sign extends TSign { + /** Gets the string representation of this sign. */ + string toString() { + result = "-" and this = TNeg() + or + result = "0" and this = TZero() + or + result = "+" and this = TPos() + } + + /** Gets a possible sign after incrementing an expression that has this sign. */ + Sign inc() { + this = TNeg() and result = TNeg() + or + this = TNeg() and result = TZero() + or + this = TZero() and result = TPos() + or + this = TPos() and result = TPos() + } + + /** Gets a possible sign after decrementing an expression that has this sign. */ + Sign dec() { result.inc() = this } + + /** Gets a possible sign after negating an expression that has this sign. */ + Sign neg() { + this = TNeg() and result = TPos() + or + this = TZero() and result = TZero() + or + this = TPos() and result = TNeg() + } + + /** + * Gets a possible sign after bitwise complementing an expression that has this + * sign. + */ + Sign bitnot() { + this = TNeg() and result = TPos() + or + this = TNeg() and result = TZero() + or + this = TZero() and result = TNeg() + or + this = TPos() and result = TNeg() + } + + /** + * Gets a possible sign after adding an expression with sign `s` to an expression + * that has this sign. + */ + Sign add(Sign s) { + this = TZero() and result = s + or + s = TZero() and result = this + or + this = s and this = result + or + this = TPos() and s = TNeg() + or + this = TNeg() and s = TPos() + } + + /** + * Gets a possible sign after subtracting an expression with sign `s` from an expression + * that has this sign. + */ + Sign sub(Sign s) { result = add(s.neg()) } + + /** + * Gets a possible sign after multiplying an expression with sign `s` to an expression + * that has this sign. + */ + Sign mul(Sign s) { + result = TZero() and this = TZero() + or + result = TZero() and s = TZero() + or + result = TNeg() and this = TPos() and s = TNeg() + or + result = TNeg() and this = TNeg() and s = TPos() + or + result = TPos() and this = TPos() and s = TPos() + or + result = TPos() and this = TNeg() and s = TNeg() + } + + /** + * Gets a possible sign after integer dividing an expression that has this sign + * by an expression with sign `s`. + */ + Sign div(Sign s) { + result = TZero() and s = TNeg() // ex: 3 / -5 = 0 + or + result = TZero() and s = TPos() // ex: 3 / 5 = 0 + or + result = TNeg() and this = TPos() and s = TNeg() + or + result = TNeg() and this = TNeg() and s = TPos() + or + result = TPos() and this = TPos() and s = TPos() + or + result = TPos() and this = TNeg() and s = TNeg() + } + + /** + * Gets a possible sign after modulo dividing an expression that has this sign + * by an expression with sign `s`. + */ + Sign rem(Sign s) { + result = TZero() and s = TNeg() + or + result = TZero() and s = TPos() + or + result = this and s = TNeg() + or + result = this and s = TPos() + } + + /** + * Gets a possible sign after bitwise `and` of an expression that has this sign + * and an expression with sign `s`. + */ + Sign bitand(Sign s) { + result = TZero() and this = TZero() + or + result = TZero() and s = TZero() + or + result = TZero() and this = TPos() + or + result = TZero() and s = TPos() + or + result = TNeg() and this = TNeg() and s = TNeg() + or + result = TPos() and this = TNeg() and s = TPos() + or + result = TPos() and this = TPos() and s = TNeg() + or + result = TPos() and this = TPos() and s = TPos() + } + + /** + * Gets a possible sign after bitwise `or` of an expression that has this sign + * and an expression with sign `s`. + */ + Sign bitor(Sign s) { + result = TZero() and this = TZero() and s = TZero() + or + result = TNeg() and this = TNeg() + or + result = TNeg() and s = TNeg() + or + result = TPos() and this = TPos() and s = TZero() + or + result = TPos() and this = TZero() and s = TPos() + or + result = TPos() and this = TPos() and s = TPos() + } + + /** + * Gets a possible sign after bitwise `xor` of an expression that has this sign + * and an expression with sign `s`. + */ + Sign bitxor(Sign s) { + result = TZero() and this = s + or + result = this and s = TZero() + or + result = s and this = TZero() + or + result = TPos() and this = TPos() and s = TPos() + or + result = TNeg() and this = TNeg() and s = TPos() + or + result = TNeg() and this = TPos() and s = TNeg() + or + result = TPos() and this = TNeg() and s = TNeg() + } + + /** + * Gets a possible sign after left shift of an expression that has this sign + * by an expression with sign `s`. + */ + Sign lshift(Sign s) { + result = TZero() and this = TZero() + or + result = this and s = TZero() + or + this != TZero() and s != TZero() + } + + /** + * Gets a possible sign after right shift of an expression that has this sign + * by an expression with sign `s`. + */ + Sign rshift(Sign s) { + result = TZero() and this = TZero() + or + result = this and s = TZero() + or + result = TNeg() and this = TNeg() + or + result != TNeg() and this = TPos() and s != TZero() + } + + /** + * Gets a possible sign after unsigned right shift of an expression that has + * this sign by an expression with sign `s`. + */ + Sign urshift(Sign s) { + result = TZero() and this = TZero() + or + result = this and s = TZero() + or + result != TZero() and this = TNeg() and s != TZero() + or + result != TNeg() and this = TPos() and s != TZero() + } + + /** Perform `op` on this sign. */ + Sign applyUnaryOp(Opcode op) { + op instanceof Opcode::CopyValue and result = this + or + op instanceof Opcode::Store and result = this + or + op instanceof Opcode::AddOne and result = inc() + or + op instanceof Opcode::SubOne and result = dec() + or + op instanceof Opcode::Negate and result = neg() + or + op instanceof Opcode::BitComplement and result = bitnot() + } + + /** Perform `op` on this sign and sign `s`. */ + Sign applyBinaryOp(Sign s, Opcode op) { + op instanceof Opcode::Add and result = add(s) + or + op instanceof Opcode::Sub and result = sub(s) + or + op instanceof Opcode::Mul and result = mul(s) + or + op instanceof Opcode::Div and result = div(s) + or + op instanceof Opcode::Rem and result = rem(s) + or + op instanceof Opcode::BitAnd and result = bitand(s) + or + op instanceof Opcode::BitOr and result = bitor(s) + or + op instanceof Opcode::BitXor and result = bitxor(s) + or + op instanceof Opcode::ShiftLeft and result = lshift(s) + or + op instanceof Opcode::ShiftRight and result = rshift(s) + or + op instanceof Opcode::ShiftRightUnsigned and result = urshift(s) + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisCommon.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisCommon.qll new file mode 100644 index 00000000000..9abcdc842ab --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisCommon.qll @@ -0,0 +1,510 @@ +/** + * Provides sign analysis to determine whether expression are always positive + * or negative. + * + * The analysis is implemented as an abstract interpretation over the + * three-valued domain `{negative, zero, positive}`. + */ + +private import RangeAnalysisStage +private import SignAnalysisSpecific as Specific +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +private import ConstantAnalysis +private import RangeUtils +private import Sign + +module SignAnalysis Utils> { + /** + * An SSA definition for which the analysis can compute the sign. + * + * The actual computation of the sign is done in an override of the `getSign()` predicate. The + * charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures + * that the charpred does not introduce negative recursion. The `getSign()` predicate may be + * recursive. + */ + abstract private class SignDef instanceof SemSsaVariable { + final string toString() { result = super.toString() } + + /** Gets the possible signs of this SSA definition. */ + abstract Sign getSign(); + } + + /** An SSA definition whose sign is computed based on standard flow. */ + abstract private class FlowSignDef extends SignDef { + abstract override Sign getSign(); + } + + /** An SSA definition whose sign is determined by the sign of that definitions source expression. */ + private class ExplicitSignDef extends FlowSignDef instanceof SemSsaExplicitUpdate { + final override Sign getSign() { result = semExprSign(super.getSourceExpr()) } + } + + /** An SSA Phi definition, whose sign is the union of the signs of its inputs. */ + private class PhiSignDef extends FlowSignDef instanceof SemSsaPhiNode { + final override Sign getSign() { + exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | + edge.phiInput(this, inp) and + result = semSsaSign(inp, edge) + ) + } + } + + /** An SSA definition whose sign is computed by a language-specific implementation. */ + abstract class CustomSignDef extends SignDef { + abstract override Sign getSign(); + } + + /** + * An expression for which the analysis can compute the sign. + * + * The actual computation of the sign is done in an override of the `getSign()` predicate. The + * charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures + * that the charpred does not introduce negative recursion. The `getSign()` predicate may be + * recursive. + * + * Concrete implementations extend one of the following subclasses: + * - `ConstantSignExpr`, for expressions with a compile-time constant value. + * - `FlowSignExpr`, for expressions whose sign can be computed from the signs of their operands. + * - `CustomsignExpr`, for expressions whose sign can be computed by a language-specific + * implementation. + * + * If the same expression matches more than one of the above subclasses, the sign is computed as + * follows: + * - The sign of a `ConstantSignExpr` is computed solely from `ConstantSignExpr.getSign()`, + * regardless of any other subclasses. + * - If a non-`ConstantSignExpr` expression matches exactly one of `FlowSignExpr` or + * `CustomSignExpr`, the sign is computed by that class' `getSign()` predicate. + * - If a non-`ConstantSignExpr` expression matches both `FlowSignExpr` and `CustomSignExpr`, the + * sign is the _intersection_ of the signs of those two classes' `getSign()` predicates. Thus, + * both classes have the opportunity to _restrict_ the set of possible signs, not to generate new + * possible signs. + * - If an expression does not match any of the three subclasses, then it can have any sign. + * + * Note that the `getSign()` predicate is introduced only in subclasses of `SignExpr`. + */ + abstract class SignExpr instanceof SemExpr { + SignExpr() { not Specific::ignoreExprSign(this) } + + final string toString() { result = super.toString() } + + abstract Sign getSign(); + } + + /** An expression whose sign is determined by its constant numeric value. */ + private class ConstantSignExpr extends SignExpr { + ConstantSignExpr() { + this instanceof SemConstantIntegerExpr or + exists(this.(SemNumericLiteralExpr).getApproximateFloatValue()) + } + + final override Sign getSign() { + exists(int i | this.(SemConstantIntegerExpr).getIntValue() = i | + i < 0 and result = TNeg() + or + i = 0 and result = TZero() + or + i > 0 and result = TPos() + ) + or + not exists(this.(SemConstantIntegerExpr).getIntValue()) and + exists(float f | f = this.(SemNumericLiteralExpr).getApproximateFloatValue() | + f < 0 and result = TNeg() + or + f = 0 and result = TZero() + or + f > 0 and result = TPos() + ) + } + } + + abstract private class NonConstantSignExpr extends SignExpr { + NonConstantSignExpr() { not this instanceof ConstantSignExpr } + + final override Sign getSign() { + // The result is the _intersection_ of the signs computed from flow and by the language. + (result = this.(FlowSignExpr).getSignRestriction() or not this instanceof FlowSignExpr) and + (result = this.(CustomSignExpr).getSignRestriction() or not this instanceof CustomSignExpr) + } + } + + /** An expression whose sign is computed from the signs of its operands. */ + abstract private class FlowSignExpr extends NonConstantSignExpr { + abstract Sign getSignRestriction(); + } + + /** An expression whose sign is computed by a language-specific implementation. */ + abstract class CustomSignExpr extends NonConstantSignExpr { + abstract Sign getSignRestriction(); + } + + /** An expression whose sign is unknown. */ + private class UnknownSignExpr extends SignExpr { + UnknownSignExpr() { + not this instanceof FlowSignExpr and + not this instanceof CustomSignExpr and + not this instanceof ConstantSignExpr and + ( + // Only track numeric types. + Utils::getTrackedType(this) instanceof SemNumericType + or + // Unless the language says to track this expression anyway. + Specific::trackUnknownNonNumericExpr(this) + ) + } + + final override Sign getSign() { semAnySign(result) } + } + + /** + * A `Load` expression whose sign is computed from the sign of its SSA definition, restricted by + * inference from any intervening guards. + */ + class UseSignExpr extends FlowSignExpr { + SemSsaVariable v; + + UseSignExpr() { v.getAUse() = this } + + override Sign getSignRestriction() { + // Propagate via SSA + // Propagate the sign from the def of `v`, incorporating any inference from guards. + result = semSsaSign(v, any(SemSsaReadPositionBlock bb | bb.getAnExpr() = this)) + or + // No block for this read. Just use the sign of the def. + // REVIEW: How can this happen? + not exists(SemSsaReadPositionBlock bb | bb.getAnExpr() = this) and + result = semSsaDefSign(v) + } + } + + /** A binary expression whose sign is computed from the signs of its operands. */ + private class BinarySignExpr extends FlowSignExpr { + SemBinaryExpr binary; + + BinarySignExpr() { binary = this } + + override Sign getSignRestriction() { + exists(SemExpr left, SemExpr right | + binaryExprOperands(binary, left, right) and + result = + semExprSign(pragma[only_bind_out](left)) + .applyBinaryOp(semExprSign(pragma[only_bind_out](right)), binary.getOpcode()) + ) + or + exists(SemDivExpr div | div = binary | + result = semExprSign(div.getLeftOperand()) and + result != TZero() and + div.getRightOperand().(SemFloatingPointLiteralExpr).getFloatValue() = 0 + ) + } + } + + /** An expression of an unsigned type. */ + private class UnsignedExpr extends FlowSignExpr { + UnsignedExpr() { Utils::getTrackedType(this) instanceof SemUnsignedIntegerType } + + override Sign getSignRestriction() { + result = TPos() or + result = TZero() + } + } + + pragma[nomagic] + private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) { + binary.getLeftOperand() = left and binary.getRightOperand() = right + } + + /** + * A `Convert`, `Box`, or `Unbox` expression. + */ + private class SemCastExpr instanceof SemUnaryExpr { + string toString() { result = super.toString() } + + SemCastExpr() { + this instanceof SemConvertExpr + or + this instanceof SemBoxExpr + or + this instanceof SemUnboxExpr + } + } + + /** A unary expression whose sign is computed from the sign of its operand. */ + private class UnarySignExpr extends FlowSignExpr { + SemUnaryExpr unary; + + UnarySignExpr() { unary = this and not this instanceof SemCastExpr } + + override Sign getSignRestriction() { + result = + semExprSign(pragma[only_bind_out](unary.getOperand())).applyUnaryOp(unary.getOpcode()) + } + } + + /** + * A `Convert`, `Box`, or `Unbox` expression, whose sign is computed based on + * the sign of its operand and the source and destination types. + */ + abstract private class CastSignExpr extends FlowSignExpr { + SemUnaryExpr cast; + + CastSignExpr() { cast = this and cast instanceof SemCastExpr } + + override Sign getSignRestriction() { result = semExprSign(cast.getOperand()) } + } + + /** + * A `Convert` expression. + */ + private class ConvertSignExpr extends CastSignExpr { + override SemConvertExpr cast; + } + + /** + * A `Box` expression. + */ + private class BoxSignExpr extends CastSignExpr { + override SemBoxExpr cast; + } + + /** + * An `Unbox` expression. + */ + private class UnboxSignExpr extends CastSignExpr { + override SemUnboxExpr cast; + + UnboxSignExpr() { + exists(SemType fromType | fromType = Utils::getTrackedType(cast.getOperand()) | + // Only numeric source types are handled here. + fromType instanceof SemNumericType + ) + } + } + + private predicate unknownSign(SemExpr e) { e instanceof UnknownSignExpr } + + /** + * Holds if `lowerbound` is a lower bound for `v` at `pos`. This is restricted + * to only include bounds for which we might determine a sign. + */ + private predicate lowerBound( + SemExpr lowerbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict + ) { + exists(boolean testIsTrue, SemRelationalExpr comp | + pos.hasReadOfVar(v) and + semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and + not unknownSign(lowerbound) + | + testIsTrue = true and + comp.getLesserOperand() = lowerbound and + comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and + (if comp.isStrict() then isStrict = true else isStrict = false) + or + testIsTrue = false and + comp.getGreaterOperand() = lowerbound and + comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and + (if comp.isStrict() then isStrict = false else isStrict = true) + ) + } + + /** + * Holds if `upperbound` is an upper bound for `v` at `pos`. This is restricted + * to only include bounds for which we might determine a sign. + */ + private predicate upperBound( + SemExpr upperbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict + ) { + exists(boolean testIsTrue, SemRelationalExpr comp | + pos.hasReadOfVar(v) and + semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and + not unknownSign(upperbound) + | + testIsTrue = true and + comp.getGreaterOperand() = upperbound and + comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and + (if comp.isStrict() then isStrict = true else isStrict = false) + or + testIsTrue = false and + comp.getLesserOperand() = upperbound and + comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and + (if comp.isStrict() then isStrict = false else isStrict = true) + ) + } + + /** + * Holds if `eqbound` is an equality/inequality for `v` at `pos`. This is + * restricted to only include bounds for which we might determine a sign. The + * boolean `isEq` gives the polarity: + * - `isEq = true` : `v = eqbound` + * - `isEq = false` : `v != eqbound` + */ + private predicate eqBound(SemExpr eqbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isEq) { + exists(SemGuard guard, boolean testIsTrue, boolean polarity, SemExpr e | + pos.hasReadOfVar(pragma[only_bind_into](v)) and + semGuardControlsSsaRead(guard, pragma[only_bind_into](pos), testIsTrue) and + e = Utils::semSsaRead(pragma[only_bind_into](v), D::fromInt(0)) and + guard.isEquality(eqbound, e, polarity) and + isEq = polarity.booleanXor(testIsTrue).booleanNot() and + not unknownSign(eqbound) + ) + } + + /** + * Holds if `bound` is a bound for `v` at `pos` that needs to be positive in + * order for `v` to be positive. + */ + private predicate posBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { + upperBound(bound, v, pos, _) or + eqBound(bound, v, pos, true) + } + + /** + * Holds if `bound` is a bound for `v` at `pos` that needs to be negative in + * order for `v` to be negative. + */ + private predicate negBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { + lowerBound(bound, v, pos, _) or + eqBound(bound, v, pos, true) + } + + /** + * Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v` + * can be zero. + */ + private predicate zeroBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { + lowerBound(bound, v, pos, _) or + upperBound(bound, v, pos, _) or + eqBound(bound, v, pos, _) + } + + /** Holds if `bound` allows `v` to be positive at `pos`. */ + private predicate posBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { + posBound(bound, v, pos) and TPos() = semExprSign(bound) + } + + /** Holds if `bound` allows `v` to be negative at `pos`. */ + private predicate negBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { + negBound(bound, v, pos) and TNeg() = semExprSign(bound) + } + + /** Holds if `bound` allows `v` to be zero at `pos`. */ + private predicate zeroBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { + lowerBound(bound, v, pos, _) and TNeg() = semExprSign(bound) + or + lowerBound(bound, v, pos, false) and TZero() = semExprSign(bound) + or + upperBound(bound, v, pos, _) and TPos() = semExprSign(bound) + or + upperBound(bound, v, pos, false) and TZero() = semExprSign(bound) + or + eqBound(bound, v, pos, true) and TZero() = semExprSign(bound) + or + eqBound(bound, v, pos, false) and TZero() != semExprSign(bound) + } + + /** + * Holds if there is a bound that might restrict whether `v` has the sign `s` + * at `pos`. + */ + private predicate hasGuard(SemSsaVariable v, SemSsaReadPosition pos, Sign s) { + s = TPos() and posBound(_, v, pos) + or + s = TNeg() and negBound(_, v, pos) + or + s = TZero() and zeroBound(_, v, pos) + } + + /** + * Gets a possible sign of `v` at `pos` based on its definition, where the sign + * might be ruled out by a guard. + */ + pragma[noinline] + private Sign guardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) { + result = semSsaDefSign(v) and + pos.hasReadOfVar(v) and + hasGuard(v, pos, result) + } + + /** + * Gets a possible sign of `v` at `pos` based on its definition, where no guard + * can rule it out. + */ + pragma[noinline] + private Sign unguardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) { + result = semSsaDefSign(v) and + pos.hasReadOfVar(v) and + not hasGuard(v, pos, result) + } + + /** + * Gets a possible sign of `v` at read position `pos`, where a guard could have + * ruled out the sign but does not. + * This does not check that the definition of `v` also allows the sign. + */ + private Sign guardedSsaSignOk(SemSsaVariable v, SemSsaReadPosition pos) { + result = TPos() and + forex(SemExpr bound | posBound(bound, v, pos) | posBoundOk(bound, v, pos)) + or + result = TNeg() and + forex(SemExpr bound | negBound(bound, v, pos) | negBoundOk(bound, v, pos)) + or + result = TZero() and + forex(SemExpr bound | zeroBound(bound, v, pos) | zeroBoundOk(bound, v, pos)) + } + + /** Gets a possible sign for `v` at `pos`. */ + private Sign semSsaSign(SemSsaVariable v, SemSsaReadPosition pos) { + result = unguardedSsaSign(v, pos) + or + result = guardedSsaSign(v, pos) and + result = guardedSsaSignOk(v, pos) + } + + /** Gets a possible sign for `v`. */ + pragma[nomagic] + Sign semSsaDefSign(SemSsaVariable v) { result = v.(SignDef).getSign() } + + /** Gets a possible sign for `e`. */ + cached + Sign semExprSign(SemExpr e) { + exists(Sign s | s = e.(SignExpr).getSign() | + if + Utils::getTrackedType(e) instanceof SemUnsignedIntegerType and + s = TNeg() and + not Specific::ignoreTypeRestrictions(e) + then result = TPos() + else result = s + ) + } + + /** + * Dummy predicate that holds for any sign. This is added to improve readability + * of cases where the sign is unrestricted. + */ + predicate semAnySign(Sign s) { any() } + + /** Holds if `e` can be positive and cannot be negative. */ + predicate semPositive(SemExpr e) { + semExprSign(e) = TPos() and + not semExprSign(e) = TNeg() + } + + /** Holds if `e` can be negative and cannot be positive. */ + predicate semNegative(SemExpr e) { + semExprSign(e) = TNeg() and + not semExprSign(e) = TPos() + } + + /** Holds if `e` is strictly positive. */ + predicate semStrictlyPositive(SemExpr e) { + semExprSign(e) = TPos() and + not semExprSign(e) = TNeg() and + not semExprSign(e) = TZero() + } + + /** Holds if `e` is strictly negative. */ + predicate semStrictlyNegative(SemExpr e) { + semExprSign(e) = TNeg() and + not semExprSign(e) = TPos() and + not semExprSign(e) = TZero() + } +} diff --git a/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisSpecific.qll b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisSpecific.qll new file mode 100644 index 00000000000..8bdb9dbc6b9 --- /dev/null +++ b/cpp/ql/lib/semmle/code/cpp/rangeanalysis/new/internal/semantic/analysis/SignAnalysisSpecific.qll @@ -0,0 +1,23 @@ +/** + * Provides C++-specific definitions for use in sign analysis. + */ + +private import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic + +/** + * Workaround to allow certain expressions to have a negative sign, even if the type of the + * expression is unsigned. + */ +predicate ignoreTypeRestrictions(SemExpr e) { none() } + +/** + * Workaround to track the sign of certain expressions even if the type of the expression is not + * numeric. + */ +predicate trackUnknownNonNumericExpr(SemExpr e) { none() } + +/** + * Workaround to ignore tracking of certain expressions even if the type of the expression is + * numeric. + */ +predicate ignoreExprSign(SemExpr e) { none() } From 4c5ca082ce3c19b0b48afea549ebf42fe03cad04 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 3 Apr 2023 13:52:13 +0100 Subject: [PATCH 137/141] C++: Delete the experimental range-analysis library. --- .../semmle/code/cpp/semantic/Semantic.qll | 7 - .../code/cpp/semantic/SemanticBound.qll | 45 - .../semmle/code/cpp/semantic/SemanticCFG.qll | 22 - .../semmle/code/cpp/semantic/SemanticExpr.qll | 309 ----- .../cpp/semantic/SemanticExprSpecific.qll | 450 ------ .../code/cpp/semantic/SemanticGuard.qll | 65 - .../code/cpp/semantic/SemanticLocation.qll | 23 - .../code/cpp/semantic/SemanticOpcode.qll | 187 --- .../semmle/code/cpp/semantic/SemanticSSA.qll | 75 - .../semmle/code/cpp/semantic/SemanticType.qll | 311 ----- .../cpp/semantic/SemanticTypeSpecific.qll | 43 - .../semantic/analysis/ConstantAnalysis.qll | 31 - .../analysis/ConstantAnalysisSpecific.qll | 10 - .../code/cpp/semantic/analysis/FloatDelta.qll | 20 - .../code/cpp/semantic/analysis/IntDelta.qll | 29 - .../cpp/semantic/analysis/ModulusAnalysis.qll | 341 ----- .../analysis/ModulusAnalysisSpecific.qll | 8 - .../cpp/semantic/analysis/RangeAnalysis.qll | 2 - .../semantic/analysis/RangeAnalysisImpl.qll | 107 -- .../analysis/RangeAnalysisSpecific.qll | 92 -- .../semantic/analysis/RangeAnalysisStage.qll | 1217 ----------------- .../code/cpp/semantic/analysis/RangeUtils.qll | 140 -- .../code/cpp/semantic/analysis/Sign.qll | 267 ---- .../semantic/analysis/SignAnalysisCommon.qll | 510 ------- .../analysis/SignAnalysisSpecific.qll | 23 - .../semantic/analysis/SimpleRangeAnalysis.qll | 132 -- 26 files changed, 4466 deletions(-) delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/Semantic.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticCFG.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticGuard.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticSSA.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticTypeSpecific.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysis.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysisSpecific.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysis.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysisSpecific.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisSpecific.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeUtils.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/Sign.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisSpecific.qll delete mode 100644 cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/Semantic.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/Semantic.qll deleted file mode 100644 index 2238a8b6c94..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/Semantic.qll +++ /dev/null @@ -1,7 +0,0 @@ -import SemanticExpr -import SemanticBound -import SemanticSSA -import SemanticGuard -import SemanticCFG -import SemanticType -import SemanticOpcode diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll deleted file mode 100644 index a1814f659fc..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticBound.qll +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Semantic wrapper around the language-specific bounds library. - */ - -private import SemanticExpr -private import SemanticExprSpecific::SemanticExprConfig as Specific -private import SemanticSSA -private import SemanticLocation - -/** - * A valid base for an expression bound. - * - * Can be either a variable (`SemSsaBound`) or zero (`SemZeroBound`). - */ -class SemBound instanceof Specific::Bound { - final string toString() { result = super.toString() } - - final SemLocation getLocation() { result = super.getLocation() } - - final SemExpr getExpr(int delta) { result = Specific::getBoundExpr(this, delta) } -} - -/** - * A bound that is a constant zero. - */ -class SemZeroBound extends SemBound { - SemZeroBound() { Specific::zeroBound(this) } -} - -/** - * A bound that is an SSA definition. - */ -class SemSsaBound extends SemBound { - /** - * The variables whose value is used as the bound. - * - * Can be multi-valued in some implementations. If so, all variables will be equivalent. - */ - SemSsaVariable var; - - SemSsaBound() { Specific::ssaBound(this, var) } - - /** Gets a variable whose value is used as the bound. */ - final SemSsaVariable getAVariable() { result = var } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticCFG.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticCFG.qll deleted file mode 100644 index 333edc46b6e..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticCFG.qll +++ /dev/null @@ -1,22 +0,0 @@ -/** - * Semantic interface to the control flow graph. - */ - -private import Semantic -private import SemanticExprSpecific::SemanticExprConfig as Specific - -/** - * A basic block in the control-flow graph. - */ -class SemBasicBlock extends Specific::BasicBlock { - /** Holds if this block (transitively) dominates `otherblock`. */ - final predicate bbDominates(SemBasicBlock otherBlock) { Specific::bbDominates(this, otherBlock) } - - /** Holds if this block has dominance information. */ - final predicate hasDominanceInformation() { Specific::hasDominanceInformation(this) } - - /** Gets an expression that is evaluated in this basic block. */ - final SemExpr getAnExpr() { result.getBasicBlock() = this } - - final int getUniqueId() { result = Specific::getBasicBlockUniqueId(this) } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll deleted file mode 100644 index 2ea958931da..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExpr.qll +++ /dev/null @@ -1,309 +0,0 @@ -/** - * Semantic interface for expressions. - */ - -private import Semantic -private import SemanticExprSpecific::SemanticExprConfig as Specific - -/** - * An language-neutral expression. - * - * The expression computes a value of type `getSemType()`. The actual computation is determined by - * the expression's opcode (`getOpcode()`). - */ -class SemExpr instanceof Specific::Expr { - final string toString() { result = super.toString() } - - final Specific::Location getLocation() { result = super.getLocation() } - - Opcode getOpcode() { result instanceof Opcode::Unknown } - - SemType getSemType() { result = Specific::getUnknownExprType(this) } - - final SemBasicBlock getBasicBlock() { result = Specific::getExprBasicBlock(this) } -} - -/** An expression with an opcode other than `Unknown`. */ -abstract private class SemKnownExpr extends SemExpr { - Opcode opcode; - SemType type; - - final override Opcode getOpcode() { result = opcode } - - final override SemType getSemType() { result = type } -} - -/** An expression that returns a literal value. */ -class SemLiteralExpr extends SemKnownExpr { - SemLiteralExpr() { - Specific::integerLiteral(this, type, _) and opcode instanceof Opcode::Constant - or - Specific::largeIntegerLiteral(this, type, _) and opcode instanceof Opcode::Constant - or - Specific::booleanLiteral(this, type, _) and opcode instanceof Opcode::Constant - or - Specific::floatingPointLiteral(this, type, _) and opcode instanceof Opcode::Constant - or - Specific::nullLiteral(this, type) and opcode instanceof Opcode::Constant - or - Specific::stringLiteral(this, type, _) and opcode instanceof Opcode::StringConstant - } -} - -/** An expression that returns a numeric literal value. */ -class SemNumericLiteralExpr extends SemLiteralExpr { - SemNumericLiteralExpr() { - Specific::integerLiteral(this, _, _) - or - Specific::largeIntegerLiteral(this, _, _) - or - Specific::floatingPointLiteral(this, _, _) - } - - /** - * Gets an approximation of the value of the literal, as a `float`. - * - * If the value can be precisely represented as a `float`, the result will be exact. If the actual - * value cannot be precisely represented (for example, it is an integer with more than 53 - * significant bits), then the result is an approximation. - */ - float getApproximateFloatValue() { none() } -} - -/** An expression that returns an integer literal value. */ -class SemIntegerLiteralExpr extends SemNumericLiteralExpr { - SemIntegerLiteralExpr() { - Specific::integerLiteral(this, _, _) - or - Specific::largeIntegerLiteral(this, _, _) - } - - /** - * Gets the value of the literal, if it can be represented as an `int`. - * - * If the value is outside the range of an `int`, use `getApproximateFloatValue()` to get a value - * that is equal to the actual integer value, within rounding error. - */ - final int getIntValue() { Specific::integerLiteral(this, _, result) } - - final override float getApproximateFloatValue() { - result = getIntValue() - or - Specific::largeIntegerLiteral(this, _, result) - } -} - -/** - * An expression that returns a floating-point literal value. - */ -class SemFloatingPointLiteralExpr extends SemNumericLiteralExpr { - float value; - - SemFloatingPointLiteralExpr() { Specific::floatingPointLiteral(this, _, value) } - - final override float getApproximateFloatValue() { result = value } - - /** Gets the value of the literal. */ - final float getFloatValue() { result = value } -} - -/** - * An expression that consumes two operands. - */ -class SemBinaryExpr extends SemKnownExpr { - SemExpr leftOperand; - SemExpr rightOperand; - - SemBinaryExpr() { Specific::binaryExpr(this, opcode, type, leftOperand, rightOperand) } - - /** Gets the left operand. */ - final SemExpr getLeftOperand() { result = leftOperand } - - /** Gets the right operand. */ - final SemExpr getRightOperand() { result = rightOperand } - - /** Holds if `a` and `b` are the two operands, in either order. */ - final predicate hasOperands(SemExpr a, SemExpr b) { - a = getLeftOperand() and b = getRightOperand() - or - a = getRightOperand() and b = getLeftOperand() - } - - /** Gets the two operands. */ - final SemExpr getAnOperand() { result = getLeftOperand() or result = getRightOperand() } -} - -/** An expression that performs and ordered comparison of two operands. */ -class SemRelationalExpr extends SemBinaryExpr { - SemRelationalExpr() { - opcode instanceof Opcode::CompareLT - or - opcode instanceof Opcode::CompareLE - or - opcode instanceof Opcode::CompareGT - or - opcode instanceof Opcode::CompareGE - } - - /** - * Get the operand that will be less than the other operand if the result of the comparison is - * `true`. - * - * For `x < y` or `x <= y`, this will return `x`. - * For `x > y` or `x >= y`, this will return `y`.` - */ - final SemExpr getLesserOperand() { - if opcode instanceof Opcode::CompareLT or opcode instanceof Opcode::CompareLE - then result = getLeftOperand() - else result = getRightOperand() - } - - /** - * Get the operand that will be greater than the other operand if the result of the comparison is - * `true`. - * - * For `x < y` or `x <= y`, this will return `y`. - * For `x > y` or `x >= y`, this will return `x`.` - */ - final SemExpr getGreaterOperand() { - if opcode instanceof Opcode::CompareGT or opcode instanceof Opcode::CompareGE - then result = getLeftOperand() - else result = getRightOperand() - } - - /** Holds if this comparison returns `false` if the two operands are equal. */ - final predicate isStrict() { - opcode instanceof Opcode::CompareLT or opcode instanceof Opcode::CompareGT - } -} - -class SemAddExpr extends SemBinaryExpr { - SemAddExpr() { opcode instanceof Opcode::Add or opcode instanceof Opcode::PointerAdd } -} - -class SemSubExpr extends SemBinaryExpr { - SemSubExpr() { opcode instanceof Opcode::Sub or opcode instanceof Opcode::PointerSub } -} - -class SemMulExpr extends SemBinaryExpr { - SemMulExpr() { opcode instanceof Opcode::Mul } -} - -class SemDivExpr extends SemBinaryExpr { - SemDivExpr() { opcode instanceof Opcode::Div } -} - -class SemRemExpr extends SemBinaryExpr { - SemRemExpr() { opcode instanceof Opcode::Rem } -} - -class SemShiftLeftExpr extends SemBinaryExpr { - SemShiftLeftExpr() { opcode instanceof Opcode::ShiftLeft } -} - -class SemShiftRightExpr extends SemBinaryExpr { - SemShiftRightExpr() { opcode instanceof Opcode::ShiftRight } -} - -class SemShiftRightUnsignedExpr extends SemBinaryExpr { - SemShiftRightUnsignedExpr() { opcode instanceof Opcode::ShiftRightUnsigned } -} - -class SemBitAndExpr extends SemBinaryExpr { - SemBitAndExpr() { opcode instanceof Opcode::BitAnd } -} - -class SemBitOrExpr extends SemBinaryExpr { - SemBitOrExpr() { opcode instanceof Opcode::BitOr } -} - -class SemBitXorExpr extends SemBinaryExpr { - SemBitXorExpr() { opcode instanceof Opcode::BitXor } -} - -class SemUnaryExpr extends SemKnownExpr { - SemExpr operand; - - SemUnaryExpr() { Specific::unaryExpr(this, opcode, type, operand) } - - final SemExpr getOperand() { result = operand } -} - -class SemBoxExpr extends SemUnaryExpr { - SemBoxExpr() { opcode instanceof Opcode::Box } -} - -class SemUnboxExpr extends SemUnaryExpr { - SemUnboxExpr() { opcode instanceof Opcode::Unbox } -} - -class SemConvertExpr extends SemUnaryExpr { - SemConvertExpr() { opcode instanceof Opcode::Convert } -} - -class SemCopyValueExpr extends SemUnaryExpr { - SemCopyValueExpr() { opcode instanceof Opcode::CopyValue } -} - -class SemNegateExpr extends SemUnaryExpr { - SemNegateExpr() { opcode instanceof Opcode::Negate } -} - -class SemBitComplementExpr extends SemUnaryExpr { - SemBitComplementExpr() { opcode instanceof Opcode::BitComplement } -} - -class SemLogicalNotExpr extends SemUnaryExpr { - SemLogicalNotExpr() { opcode instanceof Opcode::LogicalNot } -} - -class SemAddOneExpr extends SemUnaryExpr { - SemAddOneExpr() { opcode instanceof Opcode::AddOne } -} - -class SemSubOneExpr extends SemUnaryExpr { - SemSubOneExpr() { opcode instanceof Opcode::SubOne } -} - -private class SemNullaryExpr extends SemKnownExpr { - SemNullaryExpr() { Specific::nullaryExpr(this, opcode, type) } -} - -class SemInitializeParameterExpr extends SemNullaryExpr { - SemInitializeParameterExpr() { opcode instanceof Opcode::InitializeParameter } -} - -class SemLoadExpr extends SemNullaryExpr { - SemLoadExpr() { opcode instanceof Opcode::Load } - - final SemSsaVariable getDef() { result.getAUse() = this } -} - -class SemSsaLoadExpr extends SemLoadExpr { - SemSsaLoadExpr() { exists(getDef()) } -} - -class SemNonSsaLoadExpr extends SemLoadExpr { - SemNonSsaLoadExpr() { not exists(getDef()) } -} - -class SemStoreExpr extends SemUnaryExpr { - SemStoreExpr() { opcode instanceof Opcode::Store } -} - -class SemConditionalExpr extends SemKnownExpr { - SemExpr condition; - SemExpr trueResult; - SemExpr falseResult; - - SemConditionalExpr() { - opcode instanceof Opcode::Conditional and - Specific::conditionalExpr(this, type, condition, trueResult, falseResult) - } - - final SemExpr getBranchExpr(boolean branch) { - branch = true and result = trueResult - or - branch = false and result = falseResult - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll deleted file mode 100644 index 0b3249a3013..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticExprSpecific.qll +++ /dev/null @@ -1,450 +0,0 @@ -/** - * C++-specific implementation of the semantic interface. - */ - -private import cpp as Cpp -private import semmle.code.cpp.ir.IR as IR -private import Semantic -private import experimental.semmle.code.cpp.rangeanalysis.Bound as IRBound -private import semmle.code.cpp.controlflow.IRGuards as IRGuards -private import semmle.code.cpp.ir.ValueNumbering - -module SemanticExprConfig { - class Location = Cpp::Location; - - /** A `ConvertInstruction` or a `CopyValueInstruction`. */ - private class Conversion extends IR::UnaryInstruction { - Conversion() { - this instanceof IR::CopyValueInstruction - or - this instanceof IR::ConvertInstruction - } - - /** Holds if this instruction converts a value of type `tFrom` to a value of type `tTo`. */ - predicate converts(SemType tFrom, SemType tTo) { - tFrom = getSemanticType(this.getUnary().getResultIRType()) and - tTo = getSemanticType(this.getResultIRType()) - } - } - - /** - * Gets a conversion-like instruction that consumes `op`, and - * which is guaranteed to not overflow. - */ - private IR::Instruction safeConversion(IR::Operand op) { - exists(Conversion conv, SemType tFrom, SemType tTo | - conv.converts(tFrom, tTo) and - conversionCannotOverflow(tFrom, tTo) and - conv.getUnaryOperand() = op and - result = conv - ) - } - - /** Holds if `i1 = i2` or if `i2` is a safe conversion that consumes `i1`. */ - private predicate idOrSafeConversion(IR::Instruction i1, IR::Instruction i2) { - not i1.getResultIRType() instanceof IR::IRVoidType and - ( - i1 = i2 - or - i2 = safeConversion(i1.getAUse()) and - i1.getBlock() = i2.getBlock() - ) - } - - module Equiv = QlBuiltins::EquivalenceRelation; - - /** - * The expressions on which we perform range analysis. - */ - class Expr extends Equiv::EquivalenceClass { - /** Gets the n'th instruction in this equivalence class. */ - private IR::Instruction getInstruction(int n) { - result = - rank[n + 1](IR::Instruction instr, int i, IR::IRBlock block | - this = Equiv::getEquivalenceClass(instr) and block.getInstruction(i) = instr - | - instr order by i - ) - } - - /** Gets a textual representation of this element. */ - string toString() { result = this.getUnconverted().toString() } - - /** Gets the basic block of this expression. */ - IR::IRBlock getBlock() { result = this.getUnconverted().getBlock() } - - /** Gets the unconverted instruction associated with this expression. */ - IR::Instruction getUnconverted() { result = this.getInstruction(0) } - - /** - * Gets the final instruction associated with this expression. This - * represents the result after applying all the safe conversions. - */ - IR::Instruction getConverted() { - exists(int n | - result = this.getInstruction(n) and - not exists(this.getInstruction(n + 1)) - ) - } - - /** Gets the type of the result produced by this instruction. */ - IR::IRType getResultIRType() { result = this.getConverted().getResultIRType() } - - /** Gets the location of the source code for this expression. */ - Location getLocation() { result = this.getUnconverted().getLocation() } - } - - SemBasicBlock getExprBasicBlock(Expr e) { result = getSemanticBasicBlock(e.getBlock()) } - - private predicate anyConstantExpr(Expr expr, SemType type, string value) { - exists(IR::ConstantInstruction instr | getSemanticExpr(instr) = expr | - type = getSemanticType(instr.getResultIRType()) and - value = instr.getValue() - ) - } - - predicate integerLiteral(Expr expr, SemIntegerType type, int value) { - exists(string valueString | - anyConstantExpr(expr, type, valueString) and - value = valueString.toInt() - ) - } - - predicate largeIntegerLiteral(Expr expr, SemIntegerType type, float approximateFloatValue) { - exists(string valueString | - anyConstantExpr(expr, type, valueString) and - not exists(valueString.toInt()) and - approximateFloatValue = valueString.toFloat() - ) - } - - predicate floatingPointLiteral(Expr expr, SemFloatingPointType type, float value) { - exists(string valueString | - anyConstantExpr(expr, type, valueString) and value = valueString.toFloat() - ) - } - - predicate booleanLiteral(Expr expr, SemBooleanType type, boolean value) { - exists(string valueString | - anyConstantExpr(expr, type, valueString) and - ( - valueString = "true" and value = true - or - valueString = "false" and value = false - ) - ) - } - - predicate nullLiteral(Expr expr, SemAddressType type) { anyConstantExpr(expr, type, _) } - - predicate stringLiteral(Expr expr, SemType type, string value) { - anyConstantExpr(expr, type, value) and - expr.getUnconverted() instanceof IR::StringConstantInstruction - } - - predicate binaryExpr(Expr expr, Opcode opcode, SemType type, Expr leftOperand, Expr rightOperand) { - exists(IR::BinaryInstruction instr | - instr = expr.getUnconverted() and - type = getSemanticType(instr.getResultIRType()) and - leftOperand = getSemanticExpr(instr.getLeft()) and - rightOperand = getSemanticExpr(instr.getRight()) and - // REVIEW: Merge the two `Opcode` types. - opcode.toString() = instr.getOpcode().toString() - ) - } - - predicate unaryExpr(Expr expr, Opcode opcode, SemType type, Expr operand) { - exists(IR::UnaryInstruction instr | instr = expr.getUnconverted() | - type = getSemanticType(instr.getResultIRType()) and - operand = getSemanticExpr(instr.getUnary()) and - // REVIEW: Merge the two operand types. - opcode.toString() = instr.getOpcode().toString() - ) - or - exists(IR::StoreInstruction instr | instr = expr.getUnconverted() | - type = getSemanticType(instr.getResultIRType()) and - operand = getSemanticExpr(instr.getSourceValue()) and - opcode instanceof Opcode::Store - ) - } - - predicate nullaryExpr(Expr expr, Opcode opcode, SemType type) { - exists(IR::LoadInstruction load | - load = expr.getUnconverted() and - type = getSemanticType(load.getResultIRType()) and - opcode instanceof Opcode::Load - ) - or - exists(IR::InitializeParameterInstruction init | - init = expr.getUnconverted() and - type = getSemanticType(init.getResultIRType()) and - opcode instanceof Opcode::InitializeParameter - ) - } - - predicate conditionalExpr( - Expr expr, SemType type, Expr condition, Expr trueResult, Expr falseResult - ) { - none() - } - - SemType getUnknownExprType(Expr expr) { result = getSemanticType(expr.getResultIRType()) } - - class BasicBlock = IR::IRBlock; - - predicate bbDominates(BasicBlock dominator, BasicBlock dominated) { - dominator.dominates(dominated) - } - - predicate hasDominanceInformation(BasicBlock block) { any() } - - private predicate id(Cpp::Locatable x, Cpp::Locatable y) { x = y } - - private predicate idOf(Cpp::Locatable x, int y) = equivalenceRelation(id/2)(x, y) - - int getBasicBlockUniqueId(BasicBlock block) { idOf(block.getFirstInstruction().getAst(), result) } - - newtype TSsaVariable = - TSsaInstruction(IR::Instruction instr) { instr.hasMemoryResult() } or - TSsaOperand(IR::Operand op) { op.isDefinitionInexact() } or - TSsaPointerArithmeticGuard(ValueNumber instr) { - exists(Guard g, IR::Operand use | - use = instr.getAUse() and use.getIRType() instanceof IR::IRAddressType - | - g.comparesLt(use, _, _, _, _) or - g.comparesLt(_, use, _, _, _) or - g.comparesEq(use, _, _, _, _) or - g.comparesEq(_, use, _, _, _) - ) - } - - class SsaVariable extends TSsaVariable { - string toString() { none() } - - Location getLocation() { none() } - - IR::Instruction asInstruction() { none() } - - ValueNumber asPointerArithGuard() { none() } - - IR::Operand asOperand() { none() } - } - - class SsaInstructionVariable extends SsaVariable, TSsaInstruction { - IR::Instruction instr; - - SsaInstructionVariable() { this = TSsaInstruction(instr) } - - final override string toString() { result = instr.toString() } - - final override Location getLocation() { result = instr.getLocation() } - - final override IR::Instruction asInstruction() { result = instr } - } - - class SsaPointerArithmeticGuard extends SsaVariable, TSsaPointerArithmeticGuard { - ValueNumber vn; - - SsaPointerArithmeticGuard() { this = TSsaPointerArithmeticGuard(vn) } - - final override string toString() { result = vn.toString() } - - final override Location getLocation() { result = vn.getLocation() } - - final override ValueNumber asPointerArithGuard() { result = vn } - } - - class SsaOperand extends SsaVariable, TSsaOperand { - IR::Operand op; - - SsaOperand() { this = TSsaOperand(op) } - - final override string toString() { result = op.toString() } - - final override Location getLocation() { result = op.getLocation() } - - final override IR::Operand asOperand() { result = op } - } - - predicate explicitUpdate(SsaVariable v, Expr sourceExpr) { - getSemanticExpr(v.asInstruction()) = sourceExpr - } - - predicate phi(SsaVariable v) { v.asInstruction() instanceof IR::PhiInstruction } - - SsaVariable getAPhiInput(SsaVariable v) { - exists(IR::PhiInstruction instr | v.asInstruction() = instr | - result.asInstruction() = instr.getAnInput() - or - result.asOperand() = instr.getAnInputOperand() - ) - } - - Expr getAUse(SsaVariable v) { - result.getUnconverted().(IR::LoadInstruction).getSourceValue() = v.asInstruction() - or - result.getUnconverted() = v.asPointerArithGuard().getAnInstruction() - } - - SemType getSsaVariableType(SsaVariable v) { - result = getSemanticType(v.asInstruction().getResultIRType()) - } - - BasicBlock getSsaVariableBasicBlock(SsaVariable v) { - result = v.asInstruction().getBlock() - or - result = v.asOperand().getUse().getBlock() - } - - private newtype TReadPosition = - TReadPositionBlock(IR::IRBlock block) or - TReadPositionPhiInputEdge(IR::IRBlock pred, IR::IRBlock succ) { - exists(IR::PhiInputOperand input | - pred = input.getPredecessorBlock() and - succ = input.getUse().getBlock() - ) - } - - class SsaReadPosition extends TReadPosition { - string toString() { none() } - - Location getLocation() { none() } - - predicate hasRead(SsaVariable v) { none() } - } - - private class SsaReadPositionBlock extends SsaReadPosition, TReadPositionBlock { - IR::IRBlock block; - - SsaReadPositionBlock() { this = TReadPositionBlock(block) } - - final override string toString() { result = block.toString() } - - final override Location getLocation() { result = block.getLocation() } - - final override predicate hasRead(SsaVariable v) { - exists(IR::Operand operand | - operand.getDef() = v.asInstruction() or - operand.getDef() = v.asPointerArithGuard().getAnInstruction() - | - not operand instanceof IR::PhiInputOperand and - operand.getUse().getBlock() = block - ) - } - } - - private class SsaReadPositionPhiInputEdge extends SsaReadPosition, TReadPositionPhiInputEdge { - IR::IRBlock pred; - IR::IRBlock succ; - - SsaReadPositionPhiInputEdge() { this = TReadPositionPhiInputEdge(pred, succ) } - - final override string toString() { result = pred.toString() + "->" + succ.toString() } - - final override Location getLocation() { result = succ.getLocation() } - - final override predicate hasRead(SsaVariable v) { - exists(IR::PhiInputOperand operand | - operand.getDef() = v.asInstruction() or - operand.getDef() = v.asPointerArithGuard().getAnInstruction() - | - operand.getPredecessorBlock() = pred and - operand.getUse().getBlock() = succ - ) - } - } - - predicate hasReadOfSsaVariable(SsaReadPosition pos, SsaVariable v) { pos.hasRead(v) } - - predicate readBlock(SsaReadPosition pos, BasicBlock block) { pos = TReadPositionBlock(block) } - - predicate phiInputEdge(SsaReadPosition pos, BasicBlock origBlock, BasicBlock phiBlock) { - pos = TReadPositionPhiInputEdge(origBlock, phiBlock) - } - - predicate phiInput(SsaReadPosition pos, SsaVariable phi, SsaVariable input) { - exists(IR::PhiInputOperand operand | - pos = TReadPositionPhiInputEdge(operand.getPredecessorBlock(), operand.getUse().getBlock()) - | - phi.asInstruction() = operand.getUse() and - ( - input.asInstruction() = operand.getDef() - or - input.asOperand() = operand - ) - ) - } - - class Bound instanceof IRBound::Bound { - string toString() { result = super.toString() } - - final Location getLocation() { result = super.getLocation() } - } - - private class ValueNumberBound extends Bound instanceof IRBound::ValueNumberBound { - override string toString() { result = IRBound::ValueNumberBound.super.toString() } - } - - predicate zeroBound(Bound bound) { bound instanceof IRBound::ZeroBound } - - predicate ssaBound(Bound bound, SsaVariable v) { - v.asInstruction() = bound.(IRBound::ValueNumberBound).getValueNumber().getAnInstruction() - } - - Expr getBoundExpr(Bound bound, int delta) { - result = getSemanticExpr(bound.(IRBound::Bound).getInstruction(delta)) - } - - class Guard = IRGuards::IRGuardCondition; - - predicate guard(Guard guard, BasicBlock block) { block = guard.getBlock() } - - Expr getGuardAsExpr(Guard guard) { result = getSemanticExpr(guard) } - - predicate equalityGuard(Guard guard, Expr e1, Expr e2, boolean polarity) { - exists(IR::Instruction left, IR::Instruction right | - getSemanticExpr(left) = e1 and - getSemanticExpr(right) = e2 and - guard.comparesEq(left.getAUse(), right.getAUse(), 0, true, polarity) - ) - } - - predicate guardDirectlyControlsBlock(Guard guard, BasicBlock controlled, boolean branch) { - guard.controls(controlled, branch) - } - - predicate guardHasBranchEdge(Guard guard, BasicBlock bb1, BasicBlock bb2, boolean branch) { - guard.controlsEdge(bb1, bb2, branch) - } - - Guard comparisonGuard(Expr e) { getSemanticExpr(result) = e } - - predicate implies_v2(Guard g1, boolean b1, Guard g2, boolean b2) { - none() // TODO - } - - /** Gets the expression associated with `instr`. */ - SemExpr getSemanticExpr(IR::Instruction instr) { result = Equiv::getEquivalenceClass(instr) } -} - -predicate getSemanticExpr = SemanticExprConfig::getSemanticExpr/1; - -SemBasicBlock getSemanticBasicBlock(IR::IRBlock block) { result = block } - -IR::IRBlock getCppBasicBlock(SemBasicBlock block) { block = result } - -SemSsaVariable getSemanticSsaVariable(IR::Instruction instr) { - result.(SemanticExprConfig::SsaVariable).asInstruction() = instr -} - -IR::Instruction getCppSsaVariableInstruction(SemSsaVariable var) { - var.(SemanticExprConfig::SsaVariable).asInstruction() = result -} - -SemBound getSemanticBound(IRBound::Bound bound) { result = bound } - -IRBound::Bound getCppBound(SemBound bound) { bound = result } - -SemGuard getSemanticGuard(IRGuards::IRGuardCondition guard) { result = guard } - -IRGuards::IRGuardCondition getCppGuard(SemGuard guard) { guard = result } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticGuard.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticGuard.qll deleted file mode 100644 index 8faf6a3a1de..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticGuard.qll +++ /dev/null @@ -1,65 +0,0 @@ -/** - * Semantic interface to the guards library. - */ - -private import Semantic -private import SemanticExprSpecific::SemanticExprConfig as Specific - -class SemGuard instanceof Specific::Guard { - SemBasicBlock block; - - SemGuard() { Specific::guard(this, block) } - - final string toString() { result = super.toString() } - - final Specific::Location getLocation() { result = super.getLocation() } - - final predicate isEquality(SemExpr e1, SemExpr e2, boolean polarity) { - Specific::equalityGuard(this, e1, e2, polarity) - } - - final predicate directlyControls(SemBasicBlock controlled, boolean branch) { - Specific::guardDirectlyControlsBlock(this, controlled, branch) - } - - final predicate hasBranchEdge(SemBasicBlock bb1, SemBasicBlock bb2, boolean branch) { - Specific::guardHasBranchEdge(this, bb1, bb2, branch) - } - - final SemBasicBlock getBasicBlock() { result = block } - - final SemExpr asExpr() { result = Specific::getGuardAsExpr(this) } -} - -predicate semImplies_v2(SemGuard g1, boolean b1, SemGuard g2, boolean b2) { - Specific::implies_v2(g1, b1, g2, b2) -} - -/** - * Holds if `guard` directly controls the position `controlled` with the - * value `testIsTrue`. - */ -predicate semGuardDirectlyControlsSsaRead( - SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue -) { - guard.directlyControls(controlled.(SemSsaReadPositionBlock).getBlock(), testIsTrue) - or - exists(SemSsaReadPositionPhiInputEdge controlledEdge | controlledEdge = controlled | - guard.directlyControls(controlledEdge.getOrigBlock(), testIsTrue) or - guard.hasBranchEdge(controlledEdge.getOrigBlock(), controlledEdge.getPhiBlock(), testIsTrue) - ) -} - -/** - * Holds if `guard` controls the position `controlled` with the value `testIsTrue`. - */ -predicate semGuardControlsSsaRead(SemGuard guard, SemSsaReadPosition controlled, boolean testIsTrue) { - semGuardDirectlyControlsSsaRead(guard, controlled, testIsTrue) - or - exists(SemGuard guard0, boolean testIsTrue0 | - semImplies_v2(guard0, testIsTrue0, guard, testIsTrue) and - semGuardControlsSsaRead(guard0, controlled, testIsTrue0) - ) -} - -SemGuard semGetComparisonGuard(SemRelationalExpr e) { result = Specific::comparisonGuard(e) } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll deleted file mode 100644 index 328f85151b5..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticLocation.qll +++ /dev/null @@ -1,23 +0,0 @@ -private import semmle.code.cpp.Location - -class SemLocation instanceof Location { - /** - * Gets a textual representation of this element. - * - * The format is "file://filePath:startLine:startColumn:endLine:endColumn". - */ - string toString() { result = super.toString() } - - /** - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll deleted file mode 100644 index bb56da71f73..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticOpcode.qll +++ /dev/null @@ -1,187 +0,0 @@ -/** - * Definitions of all possible opcodes for `SemExpr`. - */ -private newtype TOpcode = - TInitializeParameter() or - TCopyValue() or - TLoad() or - TStore() or - TAdd() or - TSub() or - TMul() or - TDiv() or - TRem() or - TNegate() or - TShiftLeft() or - TShiftRight() or - TShiftRightUnsigned() or // TODO: Based on type - TBitAnd() or - TBitOr() or - TBitXor() or - TBitComplement() or - TLogicalNot() or - TCompareEQ() or - TCompareNE() or - TCompareLT() or - TCompareGT() or - TCompareLE() or - TCompareGE() or - TPointerAdd() or - TPointerSub() or - TPointerDiff() or - TConvert() or - TConstant() or - TStringConstant() or - TAddOne() or // TODO: Combine with `TAdd` - TSubOne() or // TODO: Combine with `TSub` - TConditional() or // TODO: Represent as flow - TCall() or - TBox() or - TUnbox() or - TUnknown() - -class Opcode extends TOpcode { - string toString() { result = "???" } -} - -module Opcode { - class InitializeParameter extends Opcode, TInitializeParameter { - override string toString() { result = "InitializeParameter" } - } - - class CopyValue extends Opcode, TCopyValue { - override string toString() { result = "CopyValue" } - } - - class Load extends Opcode, TLoad { - override string toString() { result = "Load" } - } - - class Store extends Opcode, TStore { - override string toString() { result = "Store" } - } - - class Add extends Opcode, TAdd { - override string toString() { result = "Add" } - } - - class PointerAdd extends Opcode, TPointerAdd { - override string toString() { result = "PointerAdd" } - } - - class Sub extends Opcode, TSub { - override string toString() { result = "Sub" } - } - - class PointerSub extends Opcode, TPointerSub { - override string toString() { result = "PointerSub" } - } - - class Mul extends Opcode, TMul { - override string toString() { result = "Mul" } - } - - class Div extends Opcode, TDiv { - override string toString() { result = "Div" } - } - - class Rem extends Opcode, TRem { - override string toString() { result = "Rem" } - } - - class Negate extends Opcode, TNegate { - override string toString() { result = "Negate" } - } - - class ShiftLeft extends Opcode, TShiftLeft { - override string toString() { result = "ShiftLeft" } - } - - class ShiftRight extends Opcode, TShiftRight { - override string toString() { result = "ShiftRight" } - } - - class ShiftRightUnsigned extends Opcode, TShiftRightUnsigned { - override string toString() { result = "ShiftRightUnsigned" } - } - - class BitAnd extends Opcode, TBitAnd { - override string toString() { result = "BitAnd" } - } - - class BitOr extends Opcode, TBitOr { - override string toString() { result = "BitOr" } - } - - class BitXor extends Opcode, TBitXor { - override string toString() { result = "BitXor" } - } - - class BitComplement extends Opcode, TBitComplement { - override string toString() { result = "BitComplement" } - } - - class LogicalNot extends Opcode, TLogicalNot { - override string toString() { result = "LogicalNot" } - } - - class CompareEQ extends Opcode, TCompareEQ { - override string toString() { result = "CompareEQ" } - } - - class CompareNE extends Opcode, TCompareNE { - override string toString() { result = "CompareNE" } - } - - class CompareLT extends Opcode, TCompareLT { - override string toString() { result = "CompareLT" } - } - - class CompareLE extends Opcode, TCompareLE { - override string toString() { result = "CompareLE" } - } - - class CompareGT extends Opcode, TCompareGT { - override string toString() { result = "CompareGT" } - } - - class CompareGE extends Opcode, TCompareGE { - override string toString() { result = "CompareGE" } - } - - class Convert extends Opcode, TConvert { - override string toString() { result = "Convert" } - } - - class AddOne extends Opcode, TAddOne { - override string toString() { result = "AddOne" } - } - - class SubOne extends Opcode, TSubOne { - override string toString() { result = "SubOne" } - } - - class Conditional extends Opcode, TConditional { - override string toString() { result = "Conditional" } - } - - class Constant extends Opcode, TConstant { - override string toString() { result = "Constant" } - } - - class StringConstant extends Opcode, TStringConstant { - override string toString() { result = "StringConstant" } - } - - class Box extends Opcode, TBox { - override string toString() { result = "Box" } - } - - class Unbox extends Opcode, TUnbox { - override string toString() { result = "Unbox" } - } - - class Unknown extends Opcode, TUnknown { - override string toString() { result = "Unknown" } - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticSSA.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticSSA.qll deleted file mode 100644 index 307f6e386b5..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticSSA.qll +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Semantic interface to the SSA library. - */ - -private import Semantic -private import SemanticExprSpecific::SemanticExprConfig as Specific - -class SemSsaVariable instanceof Specific::SsaVariable { - final string toString() { result = super.toString() } - - final Specific::Location getLocation() { result = super.getLocation() } - - final SemExpr getAUse() { result = Specific::getAUse(this) } - - final SemType getType() { result = Specific::getSsaVariableType(this) } - - final SemBasicBlock getBasicBlock() { result = Specific::getSsaVariableBasicBlock(this) } -} - -class SemSsaExplicitUpdate extends SemSsaVariable { - SemExpr sourceExpr; - - SemSsaExplicitUpdate() { Specific::explicitUpdate(this, sourceExpr) } - - final SemExpr getSourceExpr() { result = sourceExpr } -} - -class SemSsaPhiNode extends SemSsaVariable { - SemSsaPhiNode() { Specific::phi(this) } - - final SemSsaVariable getAPhiInput() { result = Specific::getAPhiInput(this) } -} - -class SemSsaReadPosition instanceof Specific::SsaReadPosition { - final string toString() { result = super.toString() } - - final Specific::Location getLocation() { result = super.getLocation() } - - final predicate hasReadOfVar(SemSsaVariable var) { Specific::hasReadOfSsaVariable(this, var) } -} - -class SemSsaReadPositionPhiInputEdge extends SemSsaReadPosition { - SemBasicBlock origBlock; - SemBasicBlock phiBlock; - - SemSsaReadPositionPhiInputEdge() { Specific::phiInputEdge(this, origBlock, phiBlock) } - - predicate phiInput(SemSsaPhiNode phi, SemSsaVariable inp) { Specific::phiInput(this, phi, inp) } - - SemBasicBlock getOrigBlock() { result = origBlock } - - SemBasicBlock getPhiBlock() { result = phiBlock } -} - -class SemSsaReadPositionBlock extends SemSsaReadPosition { - SemBasicBlock block; - - SemSsaReadPositionBlock() { Specific::readBlock(this, block) } - - SemBasicBlock getBlock() { result = block } - - SemExpr getAnExpr() { result = getBlock().getAnExpr() } -} - -/** - * Holds if `inp` is an input to `phi` along a back edge. - */ -predicate semBackEdge(SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge) { - edge.phiInput(phi, inp) and - // Conservatively assume that every edge is a back edge if we don't have dominance information. - ( - phi.getBasicBlock().bbDominates(edge.getOrigBlock()) or - not edge.getOrigBlock().hasDominanceInformation() - ) -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll deleted file mode 100644 index b86db02702c..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticType.qll +++ /dev/null @@ -1,311 +0,0 @@ -/** - * Minimal, language-neutral type system for semantic analysis. - */ - -private import SemanticTypeSpecific as Specific - -class LanguageType = Specific::Type; - -cached -private newtype TSemType = - TSemVoidType() { Specific::voidType(_) } or - TSemUnknownType() { Specific::unknownType(_) } or - TSemErrorType() { Specific::errorType(_) } or - TSemBooleanType(int byteSize) { Specific::booleanType(_, byteSize) } or - TSemIntegerType(int byteSize, boolean signed) { Specific::integerType(_, byteSize, signed) } or - TSemFloatingPointType(int byteSize) { Specific::floatingPointType(_, byteSize) } or - TSemAddressType(int byteSize) { Specific::addressType(_, byteSize) } or - TSemFunctionAddressType(int byteSize) { Specific::functionAddressType(_, byteSize) } or - TSemOpaqueType(int byteSize, Specific::OpaqueTypeTag tag) { - Specific::opaqueType(_, byteSize, tag) - } - -/** - * The language-neutral type of a semantic expression, - * The interface to `SemType` and its subclasses is the same across all languages for which the IR - * is supported, so analyses that expect to be used for multiple languages should generally use - * `SemType` rather than a language-specific type. - * - * Many types from the language-specific type system will map to a single canonical `SemType`. Two - * types that map to the same `SemType` are considered equivalent by semantic analysis. As an - * example, in C++, all pointer types map to the same instance of `SemAddressType`. - */ -class SemType extends TSemType { - /** Gets a textual representation of this type. */ - string toString() { none() } - - /** - * Gets a string that uniquely identifies this `SemType`. This string is often the same as the - * result of `SemType.toString()`, but for some types it may be more verbose to ensure uniqueness. - */ - string getIdentityString() { result = toString() } - - /** - * Gets the size of the type, in bytes, if known. - * - * This will hold for all `SemType` objects except `SemUnknownType` and `SemErrorType`. - */ - // 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() } -} - -/** - * An unknown type. Generally used to represent results and operands that access an unknown set of - * memory locations, such as the side effects of a function call. - */ -class SemUnknownType extends SemType, TSemUnknownType { - final override string toString() { result = "unknown" } - - final override int getByteSize() { none() } -} - -/** - * A void type, which has no values. Used to represent the result type of an expression that does - * not produce a result. - */ -class SemVoidType extends SemType, TSemVoidType { - final override string toString() { result = "void" } - - final override int getByteSize() { result = 0 } -} - -/** - * An error type. Used when an error in the source code prevents the extractor from determining the - * proper type. - */ -class SemErrorType extends SemType, TSemErrorType { - final override string toString() { result = "error" } - - final override int getByteSize() { result = 0 } -} - -private class SemSizedType extends SemType { - int byteSize; - - SemSizedType() { - this = TSemBooleanType(byteSize) or - this = TSemIntegerType(byteSize, _) or - this = TSemFloatingPointType(byteSize) or - this = TSemAddressType(byteSize) or - this = TSemFunctionAddressType(byteSize) or - this = TSemOpaqueType(byteSize, _) - } - // Don't override `getByteSize()` here. The optimizer seems to generate better code when this is - // overridden only in the leaf classes. -} - -/** - * A Boolean type, which can hold the values `true` (non-zero) or `false` (zero). - */ -class SemBooleanType extends SemSizedType, TSemBooleanType { - final override string toString() { result = "bool" + byteSize.toString() } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -/** - * A numeric type. This includes `SemSignedIntegerType`, `SemUnsignedIntegerType`, and - * `SemFloatingPointType`. - */ -class SemNumericType extends SemSizedType { - SemNumericType() { - this = TSemIntegerType(byteSize, _) or - this = TSemFloatingPointType(byteSize) - } - // Don't override `getByteSize()` here. The optimizer seems to generate better code when this is - // overridden only in the leaf classes. -} - -/** - * An integer type. This includes `SemSignedIntegerType` and `SemUnsignedIntegerType`. - */ -class SemIntegerType extends SemNumericType { - boolean signed; - - SemIntegerType() { this = TSemIntegerType(byteSize, signed) } - - /** Holds if this integer type is signed. */ - final predicate isSigned() { signed = true } - - /** Holds if this integer type is unsigned. */ - final predicate isUnsigned() { not isSigned() } - // Don't override `getByteSize()` here. The optimizer seems to generate better code when this is - // overridden only in the leaf classes. -} - -/** - * A signed two's-complement integer. Also used to represent enums whose underlying type is a signed - * integer, as well as character types whose representation is signed. - */ -class SemSignedIntegerType extends SemIntegerType { - SemSignedIntegerType() { signed = true } - - final override string toString() { result = "int" + byteSize.toString() } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -/** - * An unsigned two's-complement integer. Also used to represent enums whose underlying type is an - * unsigned integer, as well as character types whose representation is unsigned. - */ -class SemUnsignedIntegerType extends SemIntegerType { - SemUnsignedIntegerType() { signed = false } - - final override string toString() { result = "uint" + byteSize.toString() } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -/** - * A floating-point type. - */ -class SemFloatingPointType extends SemNumericType, TSemFloatingPointType { - final override string toString() { result = "float" + byteSize.toString() } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -/** - * An address type, representing the memory address of data. Used to represent pointers, references, - * and lvalues, include those that are garbage collected. - * - * The address of a function is represented by the separate `SemFunctionAddressType`. - */ -class SemAddressType extends SemSizedType, TSemAddressType { - final override string toString() { result = "addr" + byteSize.toString() } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -/** - * An address type, representing the memory address of code. Used to represent function pointers, - * function references, and the target of a direct function call. - */ -class SemFunctionAddressType extends SemSizedType, TSemFunctionAddressType { - final override string toString() { result = "func" + byteSize.toString() } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -/** - * A type with known size that does not fit any of the other kinds of type. Used to represent - * classes, structs, unions, fixed-size arrays, pointers-to-member, and more. - */ -class SemOpaqueType extends SemSizedType, TSemOpaqueType { - Specific::OpaqueTypeTag tag; - - SemOpaqueType() { this = TSemOpaqueType(byteSize, tag) } - - final override string toString() { - result = "opaque" + byteSize.toString() + "{" + tag.toString() + "}" - } - - final override string getIdentityString() { - result = "opaque" + byteSize.toString() + "{" + Specific::getOpaqueTagIdentityString(tag) + "}" - } - - /** - * Gets the "tag" that differentiates this type from other incompatible opaque types that have the - * same size. - */ - final Specific::OpaqueTypeTag getTag() { result = tag } - - pragma[noinline] - final override int getByteSize() { result = byteSize } -} - -cached -SemType getSemanticType(Specific::Type type) { - exists(int byteSize | - Specific::booleanType(type, byteSize) and result = TSemBooleanType(byteSize) - or - exists(boolean signed | - Specific::integerType(type, byteSize, signed) and - result = TSemIntegerType(byteSize, signed) - ) - or - Specific::floatingPointType(type, byteSize) and result = TSemFloatingPointType(byteSize) - or - Specific::addressType(type, byteSize) and result = TSemAddressType(byteSize) - or - Specific::functionAddressType(type, byteSize) and result = TSemFunctionAddressType(byteSize) - or - exists(Specific::OpaqueTypeTag tag | - Specific::opaqueType(type, byteSize, tag) and result = TSemOpaqueType(byteSize, tag) - ) - ) - or - Specific::errorType(type) and result = TSemErrorType() - or - Specific::unknownType(type) and result = TSemUnknownType() -} - -private class SemNumericOrBooleanType extends SemSizedType { - SemNumericOrBooleanType() { - this instanceof SemNumericType - or - this instanceof SemBooleanType - } -} - -/** - * Holds if the conversion from `fromType` to `toType` can never overflow or underflow. - */ -predicate conversionCannotOverflow(SemNumericOrBooleanType fromType, SemNumericOrBooleanType toType) { - // Identity cast - fromType = toType - or - // Treat any cast to an FP type as safe. It can lose precision, but not overflow. - toType instanceof SemFloatingPointType and fromType = any(SemNumericType n) - or - fromType instanceof SemBooleanType and toType instanceof SemIntegerType - or - exists(SemIntegerType fromInteger, SemIntegerType toInteger, int fromSize, int toSize | - fromInteger = fromType and - toInteger = toType and - fromSize = fromInteger.getByteSize() and - toSize = toInteger.getByteSize() - | - // Conversion to a larger type. Safe unless converting signed -> unsigned. - fromSize < toSize and - ( - toInteger.isSigned() - or - not fromInteger.isSigned() - ) - ) -} - -/** - * INTERNAL: Do not use. - * Query predicates used to check invariants that should hold for all `SemType` objects. - */ -module SemTypeConsistency { - /** - * Holds if the type has no result for `getSemanticType()`. - */ - query predicate missingSemType(Specific::Type type, string message) { - not exists(getSemanticType(type)) and - message = "`Type` does not have a corresponding `SemType`." - } - - /** - * Holds if the type has more than one result for `getSemanticType()`. - */ - query predicate multipleSemTypes(Specific::Type type, string message) { - strictcount(getSemanticType(type)) > 1 and - message = - "`Type` " + type + " has multiple `SemType`s: " + - concat(getSemanticType(type).toString(), ", ") - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticTypeSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticTypeSpecific.qll deleted file mode 100644 index e301587de2f..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/SemanticTypeSpecific.qll +++ /dev/null @@ -1,43 +0,0 @@ -/** - * C++-specific implementation of the semantic type system. - */ - -private import semmle.code.cpp.ir.IR as IR -private import cpp as Cpp -private import semmle.code.cpp.ir.internal.IRCppLanguage as Language - -class Type = IR::IRType; - -class OpaqueTypeTag = Language::OpaqueTypeTag; - -predicate voidType(Type type) { type instanceof IR::IRVoidType } - -predicate errorType(Type type) { type instanceof IR::IRErrorType } - -predicate unknownType(Type type) { type instanceof IR::IRUnknownType } - -predicate booleanType(Type type, int byteSize) { byteSize = type.(IR::IRBooleanType).getByteSize() } - -predicate integerType(Type type, int byteSize, boolean signed) { - byteSize = type.(IR::IRSignedIntegerType).getByteSize() and signed = true - or - byteSize = type.(IR::IRUnsignedIntegerType).getByteSize() and signed = false -} - -predicate floatingPointType(Type type, int byteSize) { - byteSize = type.(IR::IRFloatingPointType).getByteSize() -} - -predicate addressType(Type type, int byteSize) { byteSize = type.(IR::IRAddressType).getByteSize() } - -predicate functionAddressType(Type type, int byteSize) { - byteSize = type.(IR::IRFunctionAddressType).getByteSize() -} - -predicate opaqueType(Type type, int byteSize, OpaqueTypeTag tag) { - exists(IR::IROpaqueType opaque | opaque = type | - byteSize = opaque.getByteSize() and tag = opaque.getTag() - ) -} - -predicate getOpaqueTagIdentityString = Language::getOpaqueTagIdentityString/1; diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysis.qll deleted file mode 100644 index 2cfa99ae30a..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysis.qll +++ /dev/null @@ -1,31 +0,0 @@ -/** - * Simple constant analysis using the Semantic interface. - */ - -private import experimental.semmle.code.cpp.semantic.Semantic -private import ConstantAnalysisSpecific as Specific - -/** An expression that always has the same integer value. */ -pragma[nomagic] -private predicate constantIntegerExpr(SemExpr e, int val) { - // An integer literal - e.(SemIntegerLiteralExpr).getIntValue() = val - or - // Copy of another constant - exists(SemSsaExplicitUpdate v, SemExpr src | - e = v.getAUse() and - src = v.getSourceExpr() and - constantIntegerExpr(src, val) - ) - or - // Language-specific enhancements - val = Specific::getIntConstantValue(e) -} - -/** An expression that always has the same integer value. */ -class SemConstantIntegerExpr extends SemExpr { - SemConstantIntegerExpr() { constantIntegerExpr(this, _) } - - /** Gets the integer value of this expression. */ - int getIntValue() { constantIntegerExpr(this, result) } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysisSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysisSpecific.qll deleted file mode 100644 index cd7f96d6557..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ConstantAnalysisSpecific.qll +++ /dev/null @@ -1,10 +0,0 @@ -/** - * C++-specific implementation of constant analysis. - */ - -private import experimental.semmle.code.cpp.semantic.Semantic - -/** - * Gets the constant integer value of the specified expression, if any. - */ -int getIntConstantValue(SemExpr expr) { none() } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll deleted file mode 100644 index 1dfcc445208..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/FloatDelta.qll +++ /dev/null @@ -1,20 +0,0 @@ -private import RangeAnalysisStage - -module FloatDelta implements DeltaSig { - class Delta = float; - - bindingset[d] - bindingset[result] - float toFloat(Delta d) { result = d } - - bindingset[d] - bindingset[result] - int toInt(Delta d) { result = d } - - bindingset[n] - bindingset[result] - Delta fromInt(int n) { result = n } - - bindingset[f] - Delta fromFloat(float f) { result = f } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll deleted file mode 100644 index 83698b56229..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/IntDelta.qll +++ /dev/null @@ -1,29 +0,0 @@ -private import RangeAnalysisStage - -module IntDelta implements DeltaSig { - class Delta = int; - - bindingset[d] - bindingset[result] - float toFloat(Delta d) { result = d } - - bindingset[d] - bindingset[result] - int toInt(Delta d) { result = d } - - bindingset[n] - bindingset[result] - Delta fromInt(int n) { result = n } - - bindingset[f] - Delta fromFloat(float f) { - result = - min(float diff, float res | - diff = (res - f) and res = f.ceil() - or - diff = (f - res) and res = f.floor() - | - res order by diff - ) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysis.qll deleted file mode 100644 index acb5436e9c9..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysis.qll +++ /dev/null @@ -1,341 +0,0 @@ -/** - * Provides inferences of the form: `e` equals `b + v` modulo `m` where `e` is - * an expression, `b` is a `Bound` (typically zero or the value of an SSA - * variable), and `v` is an integer in the range `[0 .. m-1]`. - */ - -/* - * The main recursion has base cases in both `ssaModulus` (for guarded reads) and `semExprModulus` - * (for constant values). The most interesting recursive case is `phiModulusRankStep`, which - * handles phi inputs. - */ - -private import ModulusAnalysisSpecific::Private -private import experimental.semmle.code.cpp.semantic.Semantic -private import ConstantAnalysis -private import RangeUtils -private import RangeAnalysisStage - -module ModulusAnalysis Bounds, UtilSig U> { - /** - * Holds if `e + delta` equals `v` at `pos`. - */ - private predicate valueFlowStepSsa(SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, int delta) { - U::semSsaUpdateStep(v, e, D::fromInt(delta)) and pos.hasReadOfVar(v) - or - exists(SemGuard guard, boolean testIsTrue | - pos.hasReadOfVar(v) and - guard = U::semEqFlowCond(v, e, D::fromInt(delta), true, testIsTrue) and - semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) - ) - } - - /** - * Holds if `add` is the addition of `larg` and `rarg`, neither of which are - * `ConstantIntegerExpr`s. - */ - private predicate nonConstAddition(SemExpr add, SemExpr larg, SemExpr rarg) { - exists(SemAddExpr a | a = add | - larg = a.getLeftOperand() and - rarg = a.getRightOperand() - ) and - not larg instanceof SemConstantIntegerExpr and - not rarg instanceof SemConstantIntegerExpr - } - - /** - * Holds if `sub` is the subtraction of `larg` and `rarg`, where `rarg` is not - * a `ConstantIntegerExpr`. - */ - private predicate nonConstSubtraction(SemExpr sub, SemExpr larg, SemExpr rarg) { - exists(SemSubExpr s | s = sub | - larg = s.getLeftOperand() and - rarg = s.getRightOperand() - ) and - not rarg instanceof SemConstantIntegerExpr - } - - /** Gets an expression that is the remainder modulo `mod` of `arg`. */ - private SemExpr modExpr(SemExpr arg, int mod) { - exists(SemRemExpr rem | - result = rem and - arg = rem.getLeftOperand() and - rem.getRightOperand().(SemConstantIntegerExpr).getIntValue() = mod and - mod >= 2 - ) - or - exists(SemConstantIntegerExpr c | - mod = 2.pow([1 .. 30]) and - c.getIntValue() = mod - 1 and - result.(SemBitAndExpr).hasOperands(arg, c) - ) - } - - /** - * Gets a guard that tests whether `v` is congruent with `val` modulo `mod` on - * its `testIsTrue` branch. - */ - private SemGuard moduloCheck(SemSsaVariable v, int val, int mod, boolean testIsTrue) { - exists(SemExpr rem, SemConstantIntegerExpr c, int r, boolean polarity | - result.isEquality(rem, c, polarity) and - c.getIntValue() = r and - rem = modExpr(v.getAUse(), mod) and - ( - testIsTrue = polarity and val = r - or - testIsTrue = polarity.booleanNot() and - mod = 2 and - val = 1 - r and - (r = 0 or r = 1) - ) - ) - } - - /** - * Holds if a guard ensures that `v` at `pos` is congruent with `val` modulo `mod`. - */ - private predicate moduloGuardedRead(SemSsaVariable v, SemSsaReadPosition pos, int val, int mod) { - exists(SemGuard guard, boolean testIsTrue | - pos.hasReadOfVar(v) and - guard = moduloCheck(v, val, mod, testIsTrue) and - semGuardControlsSsaRead(guard, pos, testIsTrue) - ) - } - - /** Holds if `factor` is a power of 2 that divides `mask`. */ - bindingset[mask] - private predicate andmaskFactor(int mask, int factor) { - mask % factor = 0 and - factor = 2.pow([1 .. 30]) - } - - /** Holds if `e` is evenly divisible by `factor`. */ - private predicate evenlyDivisibleExpr(SemExpr e, int factor) { - exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() | - e.(SemMulExpr).getAnOperand() = c and factor = k.abs() and factor >= 2 - or - e.(SemShiftLeftExpr).getRightOperand() = c and factor = 2.pow(k) and k > 0 - or - e.(SemBitAndExpr).getAnOperand() = c and factor = max(int f | andmaskFactor(k, f)) - ) - } - - /** - * Holds if `rix` is the number of input edges to `phi`. - */ - private predicate maxPhiInputRank(SemSsaPhiNode phi, int rix) { - rix = max(int r | rankedPhiInput(phi, _, _, r)) - } - - /** - * Gets the remainder of `val` modulo `mod`. - * - * For `mod = 0` the result equals `val` and for `mod > 1` the result is within - * the range `[0 .. mod-1]`. - */ - bindingset[val, mod] - private int remainder(int val, int mod) { - mod = 0 and result = val - or - mod > 1 and result = ((val % mod) + mod) % mod - } - - /** - * Holds if `inp` is an input to `phi` and equals `phi` modulo `mod` along `edge`. - */ - private predicate phiSelfModulus( - SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int mod - ) { - exists(Bounds::SemSsaBound phibound, int v, int m | - edge.phiInput(phi, inp) and - phibound.getAVariable() = phi and - ssaModulus(inp, edge, phibound, v, m) and - mod = m.gcd(v) and - mod != 1 - ) - } - - /** - * Holds if `b + val` modulo `mod` is a candidate congruence class for `phi`. - */ - private predicate phiModulusInit(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) { - exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | - edge.phiInput(phi, inp) and - ssaModulus(inp, edge, b, val, mod) - ) - } - - /** - * Holds if all inputs to `phi` numbered `1` to `rix` are equal to `b + val` modulo `mod`. - */ - pragma[nomagic] - private predicate phiModulusRankStep( - SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod, int rix - ) { - /* - * base case. If any phi input is equal to `b + val` modulo `mod`, that's a potential congruence - * class for the phi node. - */ - - rix = 0 and - phiModulusInit(phi, b, val, mod) - or - exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int v1, int m1 | - mod != 1 and - val = remainder(v1, mod) - | - /* - * Recursive case. If `inp` = `b + v2` mod `m2`, we combine that with the preceding potential - * congruence class `b + v1` mod `m1`. The result will be the congruence class of `v1` modulo - * the greatest common denominator of `m1`, `m2`, and `v1 - v2`. - */ - - exists(int v2, int m2 | - rankedPhiInput(pragma[only_bind_out](phi), inp, edge, rix) and - phiModulusRankStep(phi, b, v1, m1, rix - 1) and - ssaModulus(inp, edge, b, v2, m2) and - mod = m1.gcd(m2).gcd(v1 - v2) - ) - or - /* - * Recursive case. If `inp` = `phi` mod `m2`, we combine that with the preceding potential - * congruence class `b + v1` mod `m1`. The result will be a congruence class modulo the greatest - * common denominator of `m1` and `m2`. - */ - - exists(int m2 | - rankedPhiInput(phi, inp, edge, rix) and - phiModulusRankStep(phi, b, v1, m1, rix - 1) and - phiSelfModulus(phi, inp, edge, m2) and - mod = m1.gcd(m2) - ) - ) - } - - /** - * Holds if `phi` is equal to `b + val` modulo `mod`. - */ - private predicate phiModulus(SemSsaPhiNode phi, Bounds::SemBound b, int val, int mod) { - exists(int r | - maxPhiInputRank(phi, r) and - phiModulusRankStep(phi, b, val, mod, r) - ) - } - - /** - * Holds if `v` at `pos` is equal to `b + val` modulo `mod`. - */ - private predicate ssaModulus( - SemSsaVariable v, SemSsaReadPosition pos, Bounds::SemBound b, int val, int mod - ) { - phiModulus(v, b, val, mod) and pos.hasReadOfVar(v) - or - b.(Bounds::SemSsaBound).getAVariable() = v and pos.hasReadOfVar(v) and val = 0 and mod = 0 - or - exists(SemExpr e, int val0, int delta | - semExprModulus(e, b, val0, mod) and - valueFlowStepSsa(v, pos, e, delta) and - val = remainder(val0 + delta, mod) - ) - or - moduloGuardedRead(v, pos, val, mod) and b instanceof Bounds::SemZeroBound - } - - /** - * Holds if `e` is equal to `b + val` modulo `mod`. - * - * There are two cases for the modulus: - * - `mod = 0`: The equality `e = b + val` is an ordinary equality. - * - `mod > 1`: `val` lies within the range `[0 .. mod-1]`. - */ - cached - predicate semExprModulus(SemExpr e, Bounds::SemBound b, int val, int mod) { - not ignoreExprModulus(e) and - ( - e = b.getExpr(D::fromInt(val)) and mod = 0 - or - evenlyDivisibleExpr(e, mod) and - val = 0 and - b instanceof Bounds::SemZeroBound - or - exists(SemSsaVariable v, SemSsaReadPositionBlock bb | - ssaModulus(v, bb, b, val, mod) and - e = v.getAUse() and - bb.getAnExpr() = e - ) - or - exists(SemExpr mid, int val0, int delta | - semExprModulus(mid, b, val0, mod) and - U::semValueFlowStep(e, mid, D::fromInt(delta)) and - val = remainder(val0 + delta, mod) - ) - or - exists(SemConditionalExpr cond, int v1, int v2, int m1, int m2 | - cond = e and - condExprBranchModulus(cond, true, b, v1, m1) and - condExprBranchModulus(cond, false, b, v2, m2) and - mod = m1.gcd(m2).gcd(v1 - v2) and - mod != 1 and - val = remainder(v1, mod) - ) - or - exists(Bounds::SemBound b1, Bounds::SemBound b2, int v1, int v2, int m1, int m2 | - addModulus(e, true, b1, v1, m1) and - addModulus(e, false, b2, v2, m2) and - mod = m1.gcd(m2) and - mod != 1 and - val = remainder(v1 + v2, mod) - | - b = b1 and b2 instanceof Bounds::SemZeroBound - or - b = b2 and b1 instanceof Bounds::SemZeroBound - ) - or - exists(int v1, int v2, int m1, int m2 | - subModulus(e, true, b, v1, m1) and - subModulus(e, false, any(Bounds::SemZeroBound zb), v2, m2) and - mod = m1.gcd(m2) and - mod != 1 and - val = remainder(v1 - v2, mod) - ) - ) - } - - private predicate condExprBranchModulus( - SemConditionalExpr cond, boolean branch, Bounds::SemBound b, int val, int mod - ) { - semExprModulus(cond.getBranchExpr(branch), b, val, mod) - } - - private predicate addModulus(SemExpr add, boolean isLeft, Bounds::SemBound b, int val, int mod) { - exists(SemExpr larg, SemExpr rarg | nonConstAddition(add, larg, rarg) | - semExprModulus(larg, b, val, mod) and isLeft = true - or - semExprModulus(rarg, b, val, mod) and isLeft = false - ) - } - - private predicate subModulus(SemExpr sub, boolean isLeft, Bounds::SemBound b, int val, int mod) { - exists(SemExpr larg, SemExpr rarg | nonConstSubtraction(sub, larg, rarg) | - semExprModulus(larg, b, val, mod) and isLeft = true - or - semExprModulus(rarg, b, val, mod) and isLeft = false - ) - } - - /** - * Holds if `inp` is an input to `phi` along `edge` and this input has index `r` - * in an arbitrary 1-based numbering of the input edges to `phi`. - */ - private predicate rankedPhiInput( - SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, int r - ) { - edge.phiInput(phi, inp) and - edge = - rank[r](SemSsaReadPositionPhiInputEdge e | - e.phiInput(phi, _) - | - e order by e.getOrigBlock().getUniqueId() - ) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysisSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysisSpecific.qll deleted file mode 100644 index a2fb5598e0e..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/ModulusAnalysisSpecific.qll +++ /dev/null @@ -1,8 +0,0 @@ -/** - * C++-specific implementation of modulus analysis. - */ -module Private { - private import experimental.semmle.code.cpp.semantic.Semantic - - predicate ignoreExprModulus(SemExpr e) { none() } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll deleted file mode 100644 index e9b7d9dc2ac..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysis.qll +++ /dev/null @@ -1,2 +0,0 @@ -import RangeAnalysisImpl -import experimental.semmle.code.cpp.semantic.SemanticBound diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll deleted file mode 100644 index 49b8541b17f..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisImpl.qll +++ /dev/null @@ -1,107 +0,0 @@ -private import RangeAnalysisStage -private import RangeAnalysisSpecific -private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta -private import RangeUtils -private import experimental.semmle.code.cpp.semantic.SemanticBound as SemanticBound -private import experimental.semmle.code.cpp.semantic.SemanticLocation -private import experimental.semmle.code.cpp.semantic.SemanticSSA - -module ConstantBounds implements BoundSig { - class SemBound instanceof SemanticBound::SemBound { - SemBound() { - this instanceof SemanticBound::SemZeroBound - or - this.(SemanticBound::SemSsaBound).getAVariable() instanceof SemSsaPhiNode - } - - string toString() { result = super.toString() } - - SemLocation getLocation() { result = super.getLocation() } - - SemExpr getExpr(float delta) { result = super.getExpr(delta) } - } - - class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } - - class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { - SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } - } -} - -private module RelativeBounds implements BoundSig { - class SemBound instanceof SemanticBound::SemBound { - SemBound() { not this instanceof SemanticBound::SemZeroBound } - - string toString() { result = super.toString() } - - SemLocation getLocation() { result = super.getLocation() } - - SemExpr getExpr(float delta) { result = super.getExpr(delta) } - } - - class SemZeroBound extends SemBound instanceof SemanticBound::SemZeroBound { } - - class SemSsaBound extends SemBound instanceof SemanticBound::SemSsaBound { - SemSsaVariable getAVariable() { result = this.(SemanticBound::SemSsaBound).getAVariable() } - } -} - -private module ConstantStage = - RangeStage>; - -private module RelativeStage = - RangeStage>; - -private newtype TSemReason = - TSemNoReason() or - TSemCondReason(SemGuard guard) { - guard = any(ConstantStage::SemCondReason reason).getCond() - or - guard = any(RelativeStage::SemCondReason reason).getCond() - } - -/** - * A reason for an inferred bound. This can either be `CondReason` if the bound - * is due to a specific condition, or `NoReason` if the bound is inferred - * without going through a bounding condition. - */ -abstract class SemReason extends TSemReason { - /** Gets a textual representation of this reason. */ - abstract string toString(); -} - -/** - * A reason for an inferred bound that indicates that the bound is inferred - * without going through a bounding condition. - */ -class SemNoReason extends SemReason, TSemNoReason { - override string toString() { result = "NoReason" } -} - -/** A reason for an inferred bound pointing to a condition. */ -class SemCondReason extends SemReason, TSemCondReason { - /** Gets the condition that is the reason for the bound. */ - SemGuard getCond() { this = TSemCondReason(result) } - - override string toString() { result = getCond().toString() } -} - -private ConstantStage::SemReason constantReason(SemReason reason) { - result instanceof ConstantStage::SemNoReason and reason instanceof SemNoReason - or - result.(ConstantStage::SemCondReason).getCond() = reason.(SemCondReason).getCond() -} - -private RelativeStage::SemReason relativeReason(SemReason reason) { - result instanceof RelativeStage::SemNoReason and reason instanceof SemNoReason - or - result.(RelativeStage::SemCondReason).getCond() = reason.(SemCondReason).getCond() -} - -predicate semBounded( - SemExpr e, SemanticBound::SemBound b, float delta, boolean upper, SemReason reason -) { - ConstantStage::semBounded(e, b, delta, upper, constantReason(reason)) - or - RelativeStage::semBounded(e, b, delta, upper, relativeReason(reason)) -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisSpecific.qll deleted file mode 100644 index 34d5bca116b..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisSpecific.qll +++ /dev/null @@ -1,92 +0,0 @@ -/** - * C++-specific implementation of range analysis. - */ - -private import experimental.semmle.code.cpp.semantic.Semantic -private import RangeAnalysisStage -private import experimental.semmle.code.cpp.semantic.analysis.FloatDelta - -module CppLangImpl implements LangSig { - /** - * Holds if the specified expression should be excluded from the result of `ssaRead()`. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreSsaReadCopy(SemExpr e) { none() } - - /** - * Ignore the bound on this expression. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreExprBound(SemExpr e) { none() } - - /** - * Ignore any inferred zero lower bound on this expression. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreZeroLowerBound(SemExpr e) { none() } - - /** - * Holds if the specified expression should be excluded from the result of `ssaRead()`. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreSsaReadArithmeticExpr(SemExpr e) { none() } - - /** - * Holds if the specified variable should be excluded from the result of `ssaRead()`. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreSsaReadAssignment(SemSsaVariable v) { none() } - - /** - * Adds additional results to `ssaRead()` that are specific to Java. - * - * This predicate handles propagation of offsets for post-increment and post-decrement expressions - * in exactly the same way as the old Java implementation. Once the new implementation matches the - * old one, we should remove this predicate and propagate deltas for all similar patterns, whether - * or not they come from a post-increment/decrement expression. - */ - SemExpr specificSsaRead(SemSsaVariable v, float delta) { none() } - - /** - * Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`). - */ - predicate hasConstantBound(SemExpr e, float bound, boolean upper) { none() } - - /** - * Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`). - */ - predicate hasBound(SemExpr e, SemExpr bound, float delta, boolean upper) { none() } - - /** - * Holds if the value of `dest` is known to be `src + delta`. - */ - predicate additionalValueFlowStep(SemExpr dest, SemExpr src, float delta) { none() } - - /** - * Gets the type that range analysis should use to track the result of the specified expression, - * if a type other than the original type of the expression is to be used. - * - * This predicate is commonly used in languages that support immutable "boxed" types that are - * actually references but whose values can be tracked as the type contained in the box. - */ - SemType getAlternateType(SemExpr e) { none() } - - /** - * Gets the type that range analysis should use to track the result of the specified source - * variable, if a type other than the original type of the expression is to be used. - * - * This predicate is commonly used in languages that support immutable "boxed" types that are - * actually references but whose values can be tracked as the type contained in the box. - */ - SemType getAlternateTypeForSsaVariable(SemSsaVariable var) { none() } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll deleted file mode 100644 index c544dec893f..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeAnalysisStage.qll +++ /dev/null @@ -1,1217 +0,0 @@ -/** - * Provides classes and predicates for range analysis. - * - * An inferred bound can either be a specific integer, the abstract value of an - * SSA variable, or the abstract value of an interesting expression. The latter - * category includes array lengths that are not SSA variables. - * - * If an inferred bound relies directly on a condition, then this condition is - * reported as the reason for the bound. - */ - -/* - * This library tackles range analysis as a flow problem. Consider e.g.: - * ``` - * len = arr.length; - * if (x < len) { ... y = x-1; ... y ... } - * ``` - * In this case we would like to infer `y <= arr.length - 2`, and this is - * accomplished by tracking the bound through a sequence of steps: - * ``` - * arr.length --> len = .. --> x < len --> x-1 --> y = .. --> y - * ``` - * - * In its simplest form the step relation `E1 --> E2` relates two expressions - * such that `E1 <= B` implies `E2 <= B` for any `B` (with a second separate - * step relation handling lower bounds). Examples of such steps include - * assignments `E2 = E1` and conditions `x <= E1` where `E2` is a use of `x` - * guarded by the condition. - * - * In order to handle subtractions and additions with constants, and strict - * comparisons, the step relation is augmented with an integer delta. With this - * generalization `E1 --(delta)--> E2` relates two expressions and an integer - * such that `E1 <= B` implies `E2 <= B + delta` for any `B`. This corresponds - * to the predicate `boundFlowStep`. - * - * The complete range analysis is then implemented as the transitive closure of - * the step relation summing the deltas along the way. If `E1` transitively - * steps to `E2`, `delta` is the sum of deltas along the path, and `B` is an - * interesting bound equal to the value of `E1` then `E2 <= B + delta`. This - * corresponds to the predicate `bounded`. - * - * Phi nodes need a little bit of extra handling. Consider `x0 = phi(x1, x2)`. - * There are essentially two cases: - * - If `x1 <= B + d1` and `x2 <= B + d2` then `x0 <= B + max(d1,d2)`. - * - If `x1 <= B + d1` and `x2 <= x0 + d2` with `d2 <= 0` then `x0 <= B + d1`. - * The first case is for whenever a bound can be proven without taking looping - * into account. The second case is relevant when `x2` comes from a back-edge - * where we can prove that the variable has been non-increasing through the - * loop-iteration as this means that any upper bound that holds prior to the - * loop also holds for the variable during the loop. - * This generalizes to a phi node with `n` inputs, so if - * `x0 = phi(x1, ..., xn)` and `xi <= B + delta` for one of the inputs, then we - * also have `x0 <= B + delta` if we can prove either: - * - `xj <= B + d` with `d <= delta` or - * - `xj <= x0 + d` with `d <= 0` - * for each input `xj`. - * - * As all inferred bounds can be related directly to a path in the source code - * the only source of non-termination is if successive redundant (and thereby - * increasingly worse) bounds are calculated along a loop in the source code. - * We prevent this by weakening the bound to a small finite set of bounds when - * a path follows a second back-edge (we postpone weakening till the second - * back-edge as a precise bound might require traversing a loop once). - */ - -private import RangeUtils as Utils -private import SignAnalysisCommon -private import experimental.semmle.code.cpp.semantic.analysis.ModulusAnalysis -import experimental.semmle.code.cpp.semantic.SemanticExpr -import experimental.semmle.code.cpp.semantic.SemanticSSA -import experimental.semmle.code.cpp.semantic.SemanticGuard -import experimental.semmle.code.cpp.semantic.SemanticCFG -import experimental.semmle.code.cpp.semantic.SemanticType -import experimental.semmle.code.cpp.semantic.SemanticOpcode -private import ConstantAnalysis -import experimental.semmle.code.cpp.semantic.SemanticLocation - -/** - * Holds if `typ` is a small integral type with the given lower and upper bounds. - */ -private predicate typeBound(SemIntegerType typ, float lowerbound, float upperbound) { - exists(int bitSize | bitSize = typ.getByteSize() * 8 | - if typ.isSigned() - then ( - upperbound = 2.pow(bitSize - 1) - 1 and - lowerbound = -upperbound - 1 - ) else ( - lowerbound = 0 and - upperbound = 2.pow(bitSize) - 1 - ) - ) -} - -signature module DeltaSig { - bindingset[this] - class Delta; - - bindingset[d] - bindingset[result] - float toFloat(Delta d); - - bindingset[d] - bindingset[result] - int toInt(Delta d); - - bindingset[n] - bindingset[result] - Delta fromInt(int n); - - bindingset[f] - Delta fromFloat(float f); -} - -signature module LangSig { - /** - * Holds if the specified expression should be excluded from the result of `ssaRead()`. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreSsaReadCopy(SemExpr e); - - /** - * Holds if `e >= bound` (if `upper = false`) or `e <= bound` (if `upper = true`). - */ - predicate hasConstantBound(SemExpr e, D::Delta bound, boolean upper); - - /** - * Holds if `e >= bound + delta` (if `upper = false`) or `e <= bound + delta` (if `upper = true`). - */ - predicate hasBound(SemExpr e, SemExpr bound, D::Delta delta, boolean upper); - - /** - * Ignore the bound on this expression. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreExprBound(SemExpr e); - - /** - * Ignore any inferred zero lower bound on this expression. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreZeroLowerBound(SemExpr e); - - /** - * Holds if the specified expression should be excluded from the result of `ssaRead()`. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreSsaReadArithmeticExpr(SemExpr e); - - /** - * Holds if the specified variable should be excluded from the result of `ssaRead()`. - * - * This predicate is to keep the results identical to the original Java implementation. It should be - * removed once we have the new implementation matching the old results exactly. - */ - predicate ignoreSsaReadAssignment(SemSsaVariable v); - - /** - * Adds additional results to `ssaRead()` that are specific to Java. - * - * This predicate handles propagation of offsets for post-increment and post-decrement expressions - * in exactly the same way as the old Java implementation. Once the new implementation matches the - * old one, we should remove this predicate and propagate deltas for all similar patterns, whether - * or not they come from a post-increment/decrement expression. - */ - SemExpr specificSsaRead(SemSsaVariable v, D::Delta delta); - - /** - * Holds if the value of `dest` is known to be `src + delta`. - */ - predicate additionalValueFlowStep(SemExpr dest, SemExpr src, D::Delta delta); - - /** - * Gets the type that range analysis should use to track the result of the specified expression, - * if a type other than the original type of the expression is to be used. - * - * This predicate is commonly used in languages that support immutable "boxed" types that are - * actually references but whose values can be tracked as the type contained in the box. - */ - SemType getAlternateType(SemExpr e); - - /** - * Gets the type that range analysis should use to track the result of the specified source - * variable, if a type other than the original type of the expression is to be used. - * - * This predicate is commonly used in languages that support immutable "boxed" types that are - * actually references but whose values can be tracked as the type contained in the box. - */ - SemType getAlternateTypeForSsaVariable(SemSsaVariable var); -} - -signature module UtilSig { - SemExpr semSsaRead(SemSsaVariable v, DeltaParam::Delta delta); - - SemGuard semEqFlowCond( - SemSsaVariable v, SemExpr e, DeltaParam::Delta delta, boolean isEq, boolean testIsTrue - ); - - predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, DeltaParam::Delta delta); - - predicate semValueFlowStep(SemExpr e2, SemExpr e1, DeltaParam::Delta delta); - - /** - * Gets the type used to track the specified source variable's range information. - * - * Usually, this just `e.getType()`, but the language can override this to track immutable boxed - * primitive types as the underlying primitive type. - */ - SemType getTrackedTypeForSsaVariable(SemSsaVariable var); - - /** - * Gets the type used to track the specified expression's range information. - * - * Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed - * primitive types as the underlying primitive type. - */ - SemType getTrackedType(SemExpr e); -} - -signature module BoundSig { - class SemBound { - string toString(); - - SemLocation getLocation(); - - SemExpr getExpr(D::Delta delta); - } - - class SemZeroBound extends SemBound; - - class SemSsaBound extends SemBound { - SemSsaVariable getAVariable(); - } -} - -module RangeStage Bounds, LangSig LangParam, UtilSig UtilParam> { - private import Bounds - private import LangParam - private import UtilParam - private import D - - /** - * An expression that does conversion, boxing, or unboxing - */ - private class ConvertOrBoxExpr instanceof SemUnaryExpr { - ConvertOrBoxExpr() { - this instanceof SemConvertExpr - or - this instanceof SemBoxExpr - or - this instanceof SemUnboxExpr - } - - string toString() { result = super.toString() } - - SemExpr getOperand() { result = super.getOperand() } - } - - /** - * A cast that can be ignored for the purpose of range analysis. - */ - private class SafeCastExpr extends ConvertOrBoxExpr { - SafeCastExpr() { - conversionCannotOverflow(getTrackedType(pragma[only_bind_into](getOperand())), - pragma[only_bind_out](getTrackedType(this))) - } - } - - /** - * A cast to a small integral type that may overflow or underflow. - */ - private class NarrowingCastExpr extends ConvertOrBoxExpr { - NarrowingCastExpr() { - not this instanceof SafeCastExpr and - typeBound(getTrackedType(this), _, _) - } - - /** Gets the lower bound of the resulting type. */ - float getLowerBound() { typeBound(getTrackedType(this), result, _) } - - /** Gets the upper bound of the resulting type. */ - float getUpperBound() { typeBound(getTrackedType(this), _, result) } - } - - private module SignAnalysisInstantiated = SignAnalysis; // TODO: will this cause reevaluation if it's instantiated with the same DeltaSig and UtilParam multiple times? - - private import SignAnalysisInstantiated - - private module ModulusAnalysisInstantiated = ModulusAnalysis; // TODO: will this cause reevaluation if it's instantiated with the same DeltaSig and UtilParam multiple times? - - private import ModulusAnalysisInstantiated - - cached - private module RangeAnalysisCache { - cached - module RangeAnalysisPublic { - /** - * Holds if `b + delta` is a valid bound for `e`. - * - `upper = true` : `e <= b + delta` - * - `upper = false` : `e >= b + delta` - * - * The reason for the bound is given by `reason` and may be either a condition - * or `NoReason` if the bound was proven directly without the use of a bounding - * condition. - */ - cached - predicate semBounded(SemExpr e, SemBound b, D::Delta delta, boolean upper, SemReason reason) { - bounded(e, b, delta, upper, _, _, reason) and - bestBound(e, b, delta, upper) - } - } - - /** - * Holds if `guard = boundFlowCond(_, _, _, _, _) or guard = eqFlowCond(_, _, _, _, _)`. - */ - cached - predicate possibleReason(SemGuard guard) { - guard = boundFlowCond(_, _, _, _, _) or guard = semEqFlowCond(_, _, _, _, _) - } - } - - private import RangeAnalysisCache - import RangeAnalysisPublic - - /** - * Holds if `b + delta` is a valid bound for `e` and this is the best such delta. - * - `upper = true` : `e <= b + delta` - * - `upper = false` : `e >= b + delta` - */ - private predicate bestBound(SemExpr e, SemBound b, D::Delta delta, boolean upper) { - delta = min(D::Delta d | bounded(e, b, d, upper, _, _, _) | d order by D::toFloat(d)) and - upper = true - or - delta = max(D::Delta d | bounded(e, b, d, upper, _, _, _) | d order by D::toFloat(d)) and - upper = false - } - - /** - * Holds if `comp` corresponds to: - * - `upper = true` : `v <= e + delta` or `v < e + delta` - * - `upper = false` : `v >= e + delta` or `v > e + delta` - */ - private predicate boundCondition( - SemRelationalExpr comp, SemSsaVariable v, SemExpr e, D::Delta delta, boolean upper - ) { - comp.getLesserOperand() = semSsaRead(v, delta) and - e = comp.getGreaterOperand() and - upper = true - or - comp.getGreaterOperand() = semSsaRead(v, delta) and - e = comp.getLesserOperand() and - upper = false - or - exists(SemSubExpr sub, SemConstantIntegerExpr c, D::Delta d | - // (v - d) - e < c - comp.getLesserOperand() = sub and - comp.getGreaterOperand() = c and - sub.getLeftOperand() = semSsaRead(v, d) and - sub.getRightOperand() = e and - upper = true and - delta = D::fromFloat(D::toFloat(d) + c.getIntValue()) - or - // (v - d) - e > c - comp.getGreaterOperand() = sub and - comp.getLesserOperand() = c and - sub.getLeftOperand() = semSsaRead(v, d) and - sub.getRightOperand() = e and - upper = false and - delta = D::fromFloat(D::toFloat(d) + c.getIntValue()) - or - // e - (v - d) < c - comp.getLesserOperand() = sub and - comp.getGreaterOperand() = c and - sub.getLeftOperand() = e and - sub.getRightOperand() = semSsaRead(v, d) and - upper = false and - delta = D::fromFloat(D::toFloat(d) - c.getIntValue()) - or - // e - (v - d) > c - comp.getGreaterOperand() = sub and - comp.getLesserOperand() = c and - sub.getLeftOperand() = e and - sub.getRightOperand() = semSsaRead(v, d) and - upper = true and - delta = D::fromFloat(D::toFloat(d) - c.getIntValue()) - ) - } - - /** - * Holds if `comp` is a comparison between `x` and `y` for which `y - x` has a - * fixed value modulo some `mod > 1`, such that the comparison can be - * strengthened by `strengthen` when evaluating to `testIsTrue`. - */ - private predicate modulusComparison(SemRelationalExpr comp, boolean testIsTrue, int strengthen) { - exists( - SemBound b, int v1, int v2, int mod1, int mod2, int mod, boolean resultIsStrict, int d, int k - | - // If `x <= y` and `x =(mod) b + v1` and `y =(mod) b + v2` then - // `0 <= y - x =(mod) v2 - v1`. By choosing `k =(mod) v2 - v1` with - // `0 <= k < mod` we get `k <= y - x`. If the resulting comparison is - // strict then the strengthening amount is instead `k - 1` modulo `mod`: - // `x < y` means `0 <= y - x - 1 =(mod) k - 1` so `k - 1 <= y - x - 1` and - // thus `k - 1 < y - x` with `0 <= k - 1 < mod`. - semExprModulus(comp.getLesserOperand(), b, v1, mod1) and - semExprModulus(comp.getGreaterOperand(), b, v2, mod2) and - mod = mod1.gcd(mod2) and - mod != 1 and - (testIsTrue = true or testIsTrue = false) and - ( - if comp.isStrict() - then resultIsStrict = testIsTrue - else resultIsStrict = testIsTrue.booleanNot() - ) and - ( - resultIsStrict = true and d = 1 - or - resultIsStrict = false and d = 0 - ) and - ( - testIsTrue = true and k = v2 - v1 - or - testIsTrue = false and k = v1 - v2 - ) and - strengthen = (((k - d) % mod) + mod) % mod - ) - } - - /** - * Gets a condition that tests whether `v` is bounded by `e + delta`. - * - * If the condition evaluates to `testIsTrue`: - * - `upper = true` : `v <= e + delta` - * - `upper = false` : `v >= e + delta` - */ - private SemGuard boundFlowCond( - SemSsaVariable v, SemExpr e, D::Delta delta, boolean upper, boolean testIsTrue - ) { - exists( - SemRelationalExpr comp, D::Delta d1, float d2, float d3, int strengthen, boolean compIsUpper, - boolean resultIsStrict - | - comp = result.asExpr() and - boundCondition(comp, v, e, d1, compIsUpper) and - (testIsTrue = true or testIsTrue = false) and - upper = compIsUpper.booleanXor(testIsTrue.booleanNot()) and - ( - if comp.isStrict() - then resultIsStrict = testIsTrue - else resultIsStrict = testIsTrue.booleanNot() - ) and - ( - if - getTrackedTypeForSsaVariable(v) instanceof SemIntegerType or - getTrackedTypeForSsaVariable(v) instanceof SemAddressType - then - upper = true and strengthen = -1 - or - upper = false and strengthen = 1 - else strengthen = 0 - ) and - ( - exists(int k | modulusComparison(comp, testIsTrue, k) and d2 = strengthen * k) - or - not modulusComparison(comp, testIsTrue, _) and d2 = 0 - ) and - // A strict inequality `x < y` can be strengthened to `x <= y - 1`. - ( - resultIsStrict = true and d3 = strengthen - or - resultIsStrict = false and d3 = 0 - ) and - delta = D::fromFloat(D::toFloat(d1) + d2 + d3) - ) - or - exists(boolean testIsTrue0 | - semImplies_v2(result, testIsTrue, boundFlowCond(v, e, delta, upper, testIsTrue0), testIsTrue0) - ) - or - result = semEqFlowCond(v, e, delta, true, testIsTrue) and - (upper = true or upper = false) - or - // guard that tests whether `v2` is bounded by `e + delta + d1 - d2` and - // exists a guard `guardEq` such that `v = v2 - d1 + d2`. - exists( - SemSsaVariable v2, SemGuard guardEq, boolean eqIsTrue, D::Delta d1, D::Delta d2, - D::Delta oldDelta - | - guardEq = semEqFlowCond(v, semSsaRead(pragma[only_bind_into](v2), d1), d2, true, eqIsTrue) and - result = boundFlowCond(v2, e, oldDelta, upper, testIsTrue) and - // guardEq needs to control guard - guardEq.directlyControls(result.getBasicBlock(), eqIsTrue) and - delta = D::fromFloat(D::toFloat(oldDelta) - D::toFloat(d1) + D::toFloat(d2)) - ) - } - - private newtype TSemReason = - TSemNoReason() or - TSemCondReason(SemGuard guard) { possibleReason(guard) } - - /** - * A reason for an inferred bound. This can either be `CondReason` if the bound - * is due to a specific condition, or `NoReason` if the bound is inferred - * without going through a bounding condition. - */ - abstract class SemReason extends TSemReason { - /** Gets a textual representation of this reason. */ - abstract string toString(); - } - - /** - * A reason for an inferred bound that indicates that the bound is inferred - * without going through a bounding condition. - */ - class SemNoReason extends SemReason, TSemNoReason { - override string toString() { result = "NoReason" } - } - - /** A reason for an inferred bound pointing to a condition. */ - class SemCondReason extends SemReason, TSemCondReason { - /** Gets the condition that is the reason for the bound. */ - SemGuard getCond() { this = TSemCondReason(result) } - - override string toString() { result = getCond().toString() } - } - - /** - * Holds if `e + delta` is a valid bound for `v` at `pos`. - * - `upper = true` : `v <= e + delta` - * - `upper = false` : `v >= e + delta` - */ - private predicate boundFlowStepSsa( - SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, D::Delta delta, boolean upper, - SemReason reason - ) { - semSsaUpdateStep(v, e, delta) and - pos.hasReadOfVar(v) and - (upper = true or upper = false) and - reason = TSemNoReason() - or - exists(SemGuard guard, boolean testIsTrue | - pos.hasReadOfVar(v) and - guard = boundFlowCond(v, e, delta, upper, testIsTrue) and - semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and - reason = TSemCondReason(guard) - ) - } - - /** Holds if `v != e + delta` at `pos` and `v` is of integral type. */ - private predicate unequalFlowStepIntegralSsa( - SemSsaVariable v, SemSsaReadPosition pos, SemExpr e, D::Delta delta, SemReason reason - ) { - getTrackedTypeForSsaVariable(v) instanceof SemIntegerType and - exists(SemGuard guard, boolean testIsTrue | - pos.hasReadOfVar(v) and - guard = semEqFlowCond(v, e, delta, false, testIsTrue) and - semGuardDirectlyControlsSsaRead(guard, pos, testIsTrue) and - reason = TSemCondReason(guard) - ) - } - - /** Holds if `e >= 1` as determined by sign analysis. */ - private predicate strictlyPositiveIntegralExpr(SemExpr e) { - semStrictlyPositive(e) and getTrackedType(e) instanceof SemIntegerType - } - - /** Holds if `e <= -1` as determined by sign analysis. */ - private predicate strictlyNegativeIntegralExpr(SemExpr e) { - semStrictlyNegative(e) and getTrackedType(e) instanceof SemIntegerType - } - - /** - * Holds if `e1 + delta` is a valid bound for `e2`. - * - `upper = true` : `e2 <= e1 + delta` - * - `upper = false` : `e2 >= e1 + delta` - */ - private predicate boundFlowStep(SemExpr e2, SemExpr e1, D::Delta delta, boolean upper) { - semValueFlowStep(e2, e1, delta) and - (upper = true or upper = false) - or - e2.(SafeCastExpr).getOperand() = e1 and - delta = D::fromInt(0) and - (upper = true or upper = false) - or - exists(SemExpr x, SemSubExpr sub | - e2 = sub and - sub.getLeftOperand() = e1 and - sub.getRightOperand() = x - | - // `x instanceof ConstantIntegerExpr` is covered by valueFlowStep - not x instanceof SemConstantIntegerExpr and - if strictlyPositiveIntegralExpr(x) - then upper = true and delta = D::fromInt(-1) - else - if semPositive(x) - then upper = true and delta = D::fromInt(0) - else - if strictlyNegativeIntegralExpr(x) - then upper = false and delta = D::fromInt(1) - else - if semNegative(x) - then upper = false and delta = D::fromInt(0) - else none() - ) - or - e2.(SemRemExpr).getRightOperand() = e1 and - semPositive(e1) and - delta = D::fromInt(-1) and - upper = true - or - e2.(SemRemExpr).getLeftOperand() = e1 and - semPositive(e1) and - delta = D::fromInt(0) and - upper = true - or - e2.(SemBitAndExpr).getAnOperand() = e1 and - semPositive(e1) and - delta = D::fromInt(0) and - upper = true - or - e2.(SemBitOrExpr).getAnOperand() = e1 and - semPositive(e2) and - delta = D::fromInt(0) and - upper = false - or - hasBound(e2, e1, delta, upper) - } - - /** Holds if `e2 = e1 * factor` and `factor > 0`. */ - private predicate boundFlowStepMul(SemExpr e2, SemExpr e1, D::Delta factor) { - exists(SemConstantIntegerExpr c, int k | k = c.getIntValue() and k > 0 | - e2.(SemMulExpr).hasOperands(e1, c) and factor = D::fromInt(k) - or - exists(SemShiftLeftExpr e | - e = e2 and - e.getLeftOperand() = e1 and - e.getRightOperand() = c and - factor = D::fromInt(2.pow(k)) - ) - ) - } - - /** - * Holds if `e2 = e1 / factor` and `factor > 0`. - * - * This conflates division, right shift, and unsigned right shift and is - * therefore only valid for non-negative numbers. - */ - private predicate boundFlowStepDiv(SemExpr e2, SemExpr e1, D::Delta factor) { - exists(SemConstantIntegerExpr c, D::Delta k | - k = D::fromInt(c.getIntValue()) and D::toFloat(k) > 0 - | - exists(SemDivExpr e | - e = e2 and e.getLeftOperand() = e1 and e.getRightOperand() = c and factor = k - ) - or - exists(SemShiftRightExpr e | - e = e2 and - e.getLeftOperand() = e1 and - e.getRightOperand() = c and - factor = D::fromInt(2.pow(D::toInt(k))) - ) - or - exists(SemShiftRightUnsignedExpr e | - e = e2 and - e.getLeftOperand() = e1 and - e.getRightOperand() = c and - factor = D::fromInt(2.pow(D::toInt(k))) - ) - ) - } - - /** - * Holds if `b + delta` is a valid bound for `v` at `pos`. - * - `upper = true` : `v <= b + delta` - * - `upper = false` : `v >= b + delta` - */ - private predicate boundedSsa( - SemSsaVariable v, SemSsaReadPosition pos, SemBound b, D::Delta delta, boolean upper, - boolean fromBackEdge, D::Delta origdelta, SemReason reason - ) { - exists(SemExpr mid, D::Delta d1, D::Delta d2, SemReason r1, SemReason r2 | - boundFlowStepSsa(v, pos, mid, d1, upper, r1) and - bounded(mid, b, d2, upper, fromBackEdge, origdelta, r2) and - // upper = true: v <= mid + d1 <= b + d1 + d2 = b + delta - // upper = false: v >= mid + d1 >= b + d1 + d2 = b + delta - delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) and - (if r1 instanceof SemNoReason then reason = r2 else reason = r1) - ) - or - exists(D::Delta d, SemReason r1, SemReason r2 | - boundedSsa(v, pos, b, d, upper, fromBackEdge, origdelta, r2) or - boundedPhi(v, b, d, upper, fromBackEdge, origdelta, r2) - | - unequalIntegralSsa(v, pos, b, d, r1) and - ( - upper = true and delta = D::fromFloat(D::toFloat(d) - 1) - or - upper = false and delta = D::fromFloat(D::toFloat(d) + 1) - ) and - ( - reason = r1 - or - reason = r2 and not r2 instanceof SemNoReason - ) - ) - } - - /** - * Holds if `v != b + delta` at `pos` and `v` is of integral type. - */ - private predicate unequalIntegralSsa( - SemSsaVariable v, SemSsaReadPosition pos, SemBound b, D::Delta delta, SemReason reason - ) { - exists(SemExpr e, D::Delta d1, D::Delta d2 | - unequalFlowStepIntegralSsa(v, pos, e, d1, reason) and - boundedUpper(e, b, d1) and - boundedLower(e, b, d2) and - delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) - ) - } - - /** - * Holds if `b + delta` is an upper bound for `e`. - * - * This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`. - */ - pragma[nomagic] - private predicate boundedUpper(SemExpr e, SemBound b, D::Delta delta) { - bounded(e, b, delta, true, _, _, _) - } - - /** - * Holds if `b + delta` is a lower bound for `e`. - * - * This predicate only exists to prevent a bad standard order in `unequalIntegralSsa`. - */ - pragma[nomagic] - private predicate boundedLower(SemExpr e, SemBound b, D::Delta delta) { - bounded(e, b, delta, false, _, _, _) - } - - /** Weakens a delta to lie in the range `[-1..1]`. */ - bindingset[delta, upper] - private D::Delta weakenDelta(boolean upper, D::Delta delta) { - delta = D::fromFloat([-1 .. 1]) and result = delta - or - upper = true and result = D::fromFloat(-1) and D::toFloat(delta) < -1 - or - upper = false and result = D::fromFloat(1) and D::toFloat(delta) > 1 - } - - /** - * Holds if `b + delta` is a valid bound for `inp` when used as an input to - * `phi` along `edge`. - * - `upper = true` : `inp <= b + delta` - * - `upper = false` : `inp >= b + delta` - */ - private predicate boundedPhiInp( - SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, SemBound b, - D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta, SemReason reason - ) { - edge.phiInput(phi, inp) and - exists(D::Delta d, boolean fromBackEdge0 | - boundedSsa(inp, edge, b, d, upper, fromBackEdge0, origdelta, reason) - or - boundedPhi(inp, b, d, upper, fromBackEdge0, origdelta, reason) - or - b.(SemSsaBound).getAVariable() = inp and - d = D::fromFloat(0) and - (upper = true or upper = false) and - fromBackEdge0 = false and - origdelta = D::fromFloat(0) and - reason = TSemNoReason() - | - if semBackEdge(phi, inp, edge) - then - fromBackEdge = true and - ( - fromBackEdge0 = true and - delta = - D::fromFloat(D::toFloat(weakenDelta(upper, - D::fromFloat(D::toFloat(d) - D::toFloat(origdelta)))) + D::toFloat(origdelta)) - or - fromBackEdge0 = false and delta = d - ) - else ( - delta = d and fromBackEdge = fromBackEdge0 - ) - ) - } - - /** - * Holds if `b + delta` is a valid bound for `inp` when used as an input to - * `phi` along `edge`. - * - `upper = true` : `inp <= b + delta` - * - `upper = false` : `inp >= b + delta` - * - * Equivalent to `boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _)`. - */ - pragma[noinline] - private predicate boundedPhiInp1( - SemSsaPhiNode phi, SemBound b, boolean upper, SemSsaVariable inp, - SemSsaReadPositionPhiInputEdge edge, D::Delta delta - ) { - boundedPhiInp(phi, inp, edge, b, delta, upper, _, _, _) - } - - /** - * Holds if `phi` is a valid bound for `inp` when used as an input to `phi` - * along `edge`. - * - `upper = true` : `inp <= phi` - * - `upper = false` : `inp >= phi` - */ - private predicate selfBoundedPhiInp( - SemSsaPhiNode phi, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge, boolean upper - ) { - exists(D::Delta d, SemSsaBound phibound | - phibound.getAVariable() = phi and - boundedPhiInp(phi, inp, edge, phibound, d, upper, _, _, _) and - ( - upper = true and D::toFloat(d) <= 0 - or - upper = false and D::toFloat(d) >= 0 - ) - ) - } - - /** - * Holds if `b + delta` is a valid bound for some input, `inp`, to `phi`, and - * thus a candidate bound for `phi`. - * - `upper = true` : `inp <= b + delta` - * - `upper = false` : `inp >= b + delta` - */ - pragma[noinline] - private predicate boundedPhiCand( - SemSsaPhiNode phi, boolean upper, SemBound b, D::Delta delta, boolean fromBackEdge, - D::Delta origdelta, SemReason reason - ) { - boundedPhiInp(phi, _, _, b, delta, upper, fromBackEdge, origdelta, reason) - } - - /** - * Holds if the candidate bound `b + delta` for `phi` is valid for the phi input - * `inp` along `edge`. - */ - private predicate boundedPhiCandValidForEdge( - SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, - D::Delta origdelta, SemReason reason, SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge - ) { - boundedPhiCand(phi, upper, b, delta, fromBackEdge, origdelta, reason) and - ( - exists(D::Delta d | boundedPhiInp1(phi, b, upper, inp, edge, d) | - upper = true and D::toFloat(d) <= D::toFloat(delta) - ) - or - exists(D::Delta d | boundedPhiInp1(phi, b, upper, inp, edge, d) | - upper = false and D::toFloat(d) >= D::toFloat(delta) - ) - or - selfBoundedPhiInp(phi, inp, edge, upper) - ) - } - - /** - * Holds if `b + delta` is a valid bound for `phi`. - * - `upper = true` : `phi <= b + delta` - * - `upper = false` : `phi >= b + delta` - */ - private predicate boundedPhi( - SemSsaPhiNode phi, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, - D::Delta origdelta, SemReason reason - ) { - forex(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | edge.phiInput(phi, inp) | - boundedPhiCandValidForEdge(phi, b, delta, upper, fromBackEdge, origdelta, reason, inp, edge) - ) - } - - /** - * Holds if `e` has an upper (for `upper = true`) or lower - * (for `upper = false`) bound of `b`. - */ - private predicate baseBound(SemExpr e, D::Delta b, boolean upper) { - hasConstantBound(e, b, upper) - or - upper = false and - b = D::fromInt(0) and - semPositive(e.(SemBitAndExpr).getAnOperand()) and - // REVIEW: We let the language opt out here to preserve original results. - not ignoreZeroLowerBound(e) - } - - /** - * Holds if the value being cast has an upper (for `upper = true`) or lower - * (for `upper = false`) bound within the bounds of the resulting type. - * For `upper = true` this means that the cast will not overflow and for - * `upper = false` this means that the cast will not underflow. - */ - private predicate safeNarrowingCast(NarrowingCastExpr cast, boolean upper) { - exists(D::Delta bound | - bounded(cast.getOperand(), any(SemZeroBound zb), bound, upper, _, _, _) - | - upper = true and D::toFloat(bound) <= cast.getUpperBound() - or - upper = false and D::toFloat(bound) >= cast.getLowerBound() - ) - } - - pragma[noinline] - private predicate boundedCastExpr( - NarrowingCastExpr cast, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, - D::Delta origdelta, SemReason reason - ) { - bounded(cast.getOperand(), b, delta, upper, fromBackEdge, origdelta, reason) - } - - /** - * Computes a normal form of `x` where -0.0 has changed to +0.0. This can be - * needed on the lesser side of a floating-point comparison or on both sides of - * a floating point equality because QL does not follow IEEE in floating-point - * comparisons but instead defines -0.0 to be less than and distinct from 0.0. - */ - bindingset[x] - private float normalizeFloatUp(float x) { result = x + 0.0 } - - /** - * Holds if `b + delta` is a valid bound for `e`. - * - `upper = true` : `e <= b + delta` - * - `upper = false` : `e >= b + delta` - */ - private predicate bounded( - SemExpr e, SemBound b, D::Delta delta, boolean upper, boolean fromBackEdge, D::Delta origdelta, - SemReason reason - ) { - not ignoreExprBound(e) and - ( - e = b.getExpr(delta) and - (upper = true or upper = false) and - fromBackEdge = false and - origdelta = delta and - reason = TSemNoReason() - or - baseBound(e, delta, upper) and - b instanceof SemZeroBound and - fromBackEdge = false and - origdelta = delta and - reason = TSemNoReason() - or - exists(SemSsaVariable v, SemSsaReadPositionBlock bb | - boundedSsa(v, bb, b, delta, upper, fromBackEdge, origdelta, reason) and - e = v.getAUse() and - bb.getBlock() = e.getBasicBlock() - ) - or - exists(SemExpr mid, D::Delta d1, D::Delta d2 | - boundFlowStep(e, mid, d1, upper) and - // Constants have easy, base-case bounds, so let's not infer any recursive bounds. - not e instanceof SemConstantIntegerExpr and - bounded(mid, b, d2, upper, fromBackEdge, origdelta, reason) and - // upper = true: e <= mid + d1 <= b + d1 + d2 = b + delta - // upper = false: e >= mid + d1 >= b + d1 + d2 = b + delta - delta = D::fromFloat(D::toFloat(d1) + D::toFloat(d2)) - ) - or - exists(SemSsaPhiNode phi | - boundedPhi(phi, b, delta, upper, fromBackEdge, origdelta, reason) and - e = phi.getAUse() - ) - or - exists(SemExpr mid, D::Delta factor, D::Delta d | - boundFlowStepMul(e, mid, factor) and - not e instanceof SemConstantIntegerExpr and - bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and - b instanceof SemZeroBound and - delta = D::fromFloat(D::toFloat(d) * D::toFloat(factor)) - ) - or - exists(SemExpr mid, D::Delta factor, D::Delta d | - boundFlowStepDiv(e, mid, factor) and - not e instanceof SemConstantIntegerExpr and - bounded(mid, b, d, upper, fromBackEdge, origdelta, reason) and - b instanceof SemZeroBound and - D::toFloat(d) >= 0 and - delta = D::fromFloat(D::toFloat(d) / D::toFloat(factor)) - ) - or - exists(NarrowingCastExpr cast | - cast = e and - safeNarrowingCast(cast, upper.booleanNot()) and - boundedCastExpr(cast, b, delta, upper, fromBackEdge, origdelta, reason) - ) - or - exists( - SemConditionalExpr cond, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2, D::Delta od1, - D::Delta od2, SemReason r1, SemReason r2 - | - cond = e and - boundedConditionalExpr(cond, b, upper, true, d1, fbe1, od1, r1) and - boundedConditionalExpr(cond, b, upper, false, d2, fbe2, od2, r2) and - ( - delta = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1 - or - delta = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2 - ) - | - upper = true and delta = D::fromFloat(D::toFloat(d1).maximum(D::toFloat(d2))) - or - upper = false and delta = D::fromFloat(D::toFloat(d1).minimum(D::toFloat(d2))) - ) - or - exists(SemExpr mid, D::Delta d, float f | - e.(SemNegateExpr).getOperand() = mid and - b instanceof SemZeroBound and - bounded(mid, b, d, upper.booleanNot(), fromBackEdge, origdelta, reason) and - f = normalizeFloatUp(-D::toFloat(d)) and - delta = D::fromFloat(f) and - if semPositive(e) then f >= 0 else any() - ) - or - exists( - SemBound bLeft, SemBound bRight, D::Delta dLeft, D::Delta dRight, boolean fbeLeft, - boolean fbeRight, D::Delta odLeft, D::Delta odRight, SemReason rLeft, SemReason rRight - | - boundedAddOperand(e, upper, bLeft, false, dLeft, fbeLeft, odLeft, rLeft) and - boundedAddOperand(e, upper, bRight, true, dRight, fbeRight, odRight, rRight) and - delta = D::fromFloat(D::toFloat(dLeft) + D::toFloat(dRight)) and - fromBackEdge = fbeLeft.booleanOr(fbeRight) - | - b = bLeft and origdelta = odLeft and reason = rLeft and bRight instanceof SemZeroBound - or - b = bRight and origdelta = odRight and reason = rRight and bLeft instanceof SemZeroBound - ) - or - exists( - SemRemExpr rem, D::Delta d_max, D::Delta d1, D::Delta d2, boolean fbe1, boolean fbe2, - D::Delta od1, D::Delta od2, SemReason r1, SemReason r2 - | - rem = e and - b instanceof SemZeroBound and - not (upper = true and semPositive(rem.getRightOperand())) and - not (upper = true and semPositive(rem.getLeftOperand())) and - boundedRemExpr(rem, true, d1, fbe1, od1, r1) and - boundedRemExpr(rem, false, d2, fbe2, od2, r2) and - ( - if D::toFloat(d1).abs() > D::toFloat(d2).abs() - then ( - d_max = d1 and fromBackEdge = fbe1 and origdelta = od1 and reason = r1 - ) else ( - d_max = d2 and fromBackEdge = fbe2 and origdelta = od2 and reason = r2 - ) - ) - | - upper = true and delta = D::fromFloat(D::toFloat(d_max).abs() - 1) - or - upper = false and delta = D::fromFloat(-D::toFloat(d_max).abs() + 1) - ) - or - exists( - D::Delta dLeft, D::Delta dRight, boolean fbeLeft, boolean fbeRight, D::Delta odLeft, - D::Delta odRight, SemReason rLeft, SemReason rRight - | - boundedMulOperand(e, upper, true, dLeft, fbeLeft, odLeft, rLeft) and - boundedMulOperand(e, upper, false, dRight, fbeRight, odRight, rRight) and - delta = D::fromFloat(D::toFloat(dLeft) * D::toFloat(dRight)) and - fromBackEdge = fbeLeft.booleanOr(fbeRight) - | - b instanceof SemZeroBound and origdelta = odLeft and reason = rLeft - or - b instanceof SemZeroBound and origdelta = odRight and reason = rRight - ) - ) - } - - pragma[nomagic] - private predicate boundedConditionalExpr( - SemConditionalExpr cond, SemBound b, boolean upper, boolean branch, D::Delta delta, - boolean fromBackEdge, D::Delta origdelta, SemReason reason - ) { - bounded(cond.getBranchExpr(branch), b, delta, upper, fromBackEdge, origdelta, reason) - } - - pragma[nomagic] - private predicate boundedAddOperand( - SemAddExpr add, boolean upper, SemBound b, boolean isLeft, D::Delta delta, boolean fromBackEdge, - D::Delta origdelta, SemReason reason - ) { - // `semValueFlowStep` already handles the case where one of the operands is a constant. - not semValueFlowStep(add, _, _) and - ( - isLeft = true and - bounded(add.getLeftOperand(), b, delta, upper, fromBackEdge, origdelta, reason) - or - isLeft = false and - bounded(add.getRightOperand(), b, delta, upper, fromBackEdge, origdelta, reason) - ) - } - - pragma[nomagic] - private predicate boundedRemExpr( - SemRemExpr rem, boolean upper, D::Delta delta, boolean fromBackEdge, D::Delta origdelta, - SemReason reason - ) { - bounded(rem.getRightOperand(), any(SemZeroBound zb), delta, upper, fromBackEdge, origdelta, - reason) - } - - /** - * Define `cmp(true) = <=` and `cmp(false) = >=`. - * - * Holds if `mul = left * right`, and in order to know if `mul cmp(upper) 0 + k` (for - * some `k`) we need to know that `left cmp(upperLeft) 0 + k1` and - * `right cmp(upperRight) 0 + k2` (for some `k1` and `k2`). - */ - pragma[nomagic] - private predicate boundedMulOperandCand( - SemMulExpr mul, SemExpr left, SemExpr right, boolean upper, boolean upperLeft, - boolean upperRight - ) { - not boundFlowStepMul(mul, _, _) and - mul.getLeftOperand() = left and - mul.getRightOperand() = right and - ( - semPositive(left) and - ( - // left, right >= 0 - semPositive(right) and - ( - // max(left * right) = max(left) * max(right) - upper = true and - upperLeft = true and - upperRight = true - or - // min(left * right) = min(left) * min(right) - upper = false and - upperLeft = false and - upperRight = false - ) - or - // left >= 0, right <= 0 - semNegative(right) and - ( - // max(left * right) = min(left) * max(right) - upper = true and - upperLeft = false and - upperRight = true - or - // min(left * right) = max(left) * min(right) - upper = false and - upperLeft = true and - upperRight = false - ) - ) - or - semNegative(left) and - ( - // left <= 0, right >= 0 - semPositive(right) and - ( - // max(left * right) = max(left) * min(right) - upper = true and - upperLeft = true and - upperRight = false - or - // min(left * right) = min(left) * max(right) - upper = false and - upperLeft = false and - upperRight = true - ) - or - // left, right <= 0 - semNegative(right) and - ( - // max(left * right) = min(left) * min(right) - upper = true and - upperLeft = false and - upperRight = false - or - // min(left * right) = max(left) * max(right) - upper = false and - upperLeft = true and - upperRight = true - ) - ) - ) - } - - /** - * Holds if `isLeft = true` and `mul`'s left operand is bounded by `delta`, - * or if `isLeft = false` and `mul`'s right operand is bounded by `delta`. - * - * If `upper = true` the computed bound contributes to an upper bound of `mul`, - * and if `upper = false` it contributes to a lower bound. - * The `fromBackEdge`, `origdelta`, `reason` triple are defined by the recursive - * call to `bounded`. - */ - pragma[nomagic] - private predicate boundedMulOperand( - SemMulExpr mul, boolean upper, boolean isLeft, D::Delta delta, boolean fromBackEdge, - D::Delta origdelta, SemReason reason - ) { - exists(boolean upperLeft, boolean upperRight, SemExpr left, SemExpr right | - boundedMulOperandCand(mul, left, right, upper, upperLeft, upperRight) - | - isLeft = true and - bounded(left, any(SemZeroBound zb), delta, upperLeft, fromBackEdge, origdelta, reason) - or - isLeft = false and - bounded(right, any(SemZeroBound zb), delta, upperRight, fromBackEdge, origdelta, reason) - ) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeUtils.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeUtils.qll deleted file mode 100644 index d9cc2cc9a71..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/RangeUtils.qll +++ /dev/null @@ -1,140 +0,0 @@ -/** - * Provides utility predicates for range analysis. - */ - -private import experimental.semmle.code.cpp.semantic.Semantic -private import RangeAnalysisSpecific -private import RangeAnalysisStage as Range -private import ConstantAnalysis - -module RangeUtil Lang> implements Range::UtilSig { - /** - * Gets an expression that equals `v - d`. - */ - SemExpr semSsaRead(SemSsaVariable v, D::Delta delta) { - // There are various language-specific extension points that can be removed once we no longer - // expect to match the original Java implementation's results exactly. - result = v.getAUse() and delta = D::fromInt(0) - or - exists(D::Delta d1, SemConstantIntegerExpr c | - result.(SemAddExpr).hasOperands(semSsaRead(v, d1), c) and - delta = D::fromFloat(D::toFloat(d1) - c.getIntValue()) and - not Lang::ignoreSsaReadArithmeticExpr(result) - ) - or - exists(SemSubExpr sub, D::Delta d1, SemConstantIntegerExpr c | - result = sub and - sub.getLeftOperand() = semSsaRead(v, d1) and - sub.getRightOperand() = c and - delta = D::fromFloat(D::toFloat(d1) + c.getIntValue()) and - not Lang::ignoreSsaReadArithmeticExpr(result) - ) - or - result = v.(SemSsaExplicitUpdate).getSourceExpr() and - delta = D::fromFloat(0) and - not Lang::ignoreSsaReadAssignment(v) - or - result = Lang::specificSsaRead(v, delta) - or - result.(SemCopyValueExpr).getOperand() = semSsaRead(v, delta) and - not Lang::ignoreSsaReadCopy(result) - or - result.(SemStoreExpr).getOperand() = semSsaRead(v, delta) - } - - /** - * Gets a condition that tests whether `v` equals `e + delta`. - * - * If the condition evaluates to `testIsTrue`: - * - `isEq = true` : `v == e + delta` - * - `isEq = false` : `v != e + delta` - */ - SemGuard semEqFlowCond( - SemSsaVariable v, SemExpr e, D::Delta delta, boolean isEq, boolean testIsTrue - ) { - exists(boolean eqpolarity | - result.isEquality(semSsaRead(v, delta), e, eqpolarity) and - (testIsTrue = true or testIsTrue = false) and - eqpolarity.booleanXor(testIsTrue).booleanNot() = isEq - ) - or - exists(boolean testIsTrue0 | - semImplies_v2(result, testIsTrue, semEqFlowCond(v, e, delta, isEq, testIsTrue0), testIsTrue0) - ) - } - - /** - * Holds if `v` is an `SsaExplicitUpdate` that equals `e + delta`. - */ - predicate semSsaUpdateStep(SemSsaExplicitUpdate v, SemExpr e, D::Delta delta) { - exists(SemExpr defExpr | defExpr = v.getSourceExpr() | - defExpr.(SemCopyValueExpr).getOperand() = e and delta = D::fromFloat(0) - or - defExpr.(SemStoreExpr).getOperand() = e and delta = D::fromFloat(0) - or - defExpr.(SemAddOneExpr).getOperand() = e and delta = D::fromFloat(1) - or - defExpr.(SemSubOneExpr).getOperand() = e and delta = D::fromFloat(-1) - or - e = defExpr and - not ( - defExpr instanceof SemCopyValueExpr or - defExpr instanceof SemStoreExpr or - defExpr instanceof SemAddOneExpr or - defExpr instanceof SemSubOneExpr - ) and - delta = D::fromFloat(0) - ) - } - - /** - * Holds if `e1 + delta` equals `e2`. - */ - predicate semValueFlowStep(SemExpr e2, SemExpr e1, D::Delta delta) { - e2.(SemCopyValueExpr).getOperand() = e1 and delta = D::fromFloat(0) - or - e2.(SemStoreExpr).getOperand() = e1 and delta = D::fromFloat(0) - or - e2.(SemAddOneExpr).getOperand() = e1 and delta = D::fromFloat(1) - or - e2.(SemSubOneExpr).getOperand() = e1 and delta = D::fromFloat(-1) - or - Lang::additionalValueFlowStep(e2, e1, delta) - or - exists(SemExpr x | e2.(SemAddExpr).hasOperands(e1, x) | - D::fromInt(x.(SemConstantIntegerExpr).getIntValue()) = delta - ) - or - exists(SemExpr x, SemSubExpr sub | - e2 = sub and - sub.getLeftOperand() = e1 and - sub.getRightOperand() = x - | - D::fromInt(-x.(SemConstantIntegerExpr).getIntValue()) = delta - ) - } - - /** - * Gets the type used to track the specified expression's range information. - * - * Usually, this just `e.getSemType()`, but the language can override this to track immutable boxed - * primitive types as the underlying primitive type. - */ - SemType getTrackedType(SemExpr e) { - result = Lang::getAlternateType(e) - or - not exists(Lang::getAlternateType(e)) and result = e.getSemType() - } - - /** - * Gets the type used to track the specified source variable's range information. - * - * Usually, this just `e.getType()`, but the language can override this to track immutable boxed - * primitive types as the underlying primitive type. - */ - SemType getTrackedTypeForSsaVariable(SemSsaVariable var) { - result = Lang::getAlternateTypeForSsaVariable(var) - or - not exists(Lang::getAlternateTypeForSsaVariable(var)) and result = var.getType() - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/Sign.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/Sign.qll deleted file mode 100644 index 692a812911c..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/Sign.qll +++ /dev/null @@ -1,267 +0,0 @@ -private import experimental.semmle.code.cpp.semantic.Semantic - -newtype TSign = - TNeg() or - TZero() or - TPos() - -/** Class representing expression signs (+, -, 0). */ -class Sign extends TSign { - /** Gets the string representation of this sign. */ - string toString() { - result = "-" and this = TNeg() - or - result = "0" and this = TZero() - or - result = "+" and this = TPos() - } - - /** Gets a possible sign after incrementing an expression that has this sign. */ - Sign inc() { - this = TNeg() and result = TNeg() - or - this = TNeg() and result = TZero() - or - this = TZero() and result = TPos() - or - this = TPos() and result = TPos() - } - - /** Gets a possible sign after decrementing an expression that has this sign. */ - Sign dec() { result.inc() = this } - - /** Gets a possible sign after negating an expression that has this sign. */ - Sign neg() { - this = TNeg() and result = TPos() - or - this = TZero() and result = TZero() - or - this = TPos() and result = TNeg() - } - - /** - * Gets a possible sign after bitwise complementing an expression that has this - * sign. - */ - Sign bitnot() { - this = TNeg() and result = TPos() - or - this = TNeg() and result = TZero() - or - this = TZero() and result = TNeg() - or - this = TPos() and result = TNeg() - } - - /** - * Gets a possible sign after adding an expression with sign `s` to an expression - * that has this sign. - */ - Sign add(Sign s) { - this = TZero() and result = s - or - s = TZero() and result = this - or - this = s and this = result - or - this = TPos() and s = TNeg() - or - this = TNeg() and s = TPos() - } - - /** - * Gets a possible sign after subtracting an expression with sign `s` from an expression - * that has this sign. - */ - Sign sub(Sign s) { result = add(s.neg()) } - - /** - * Gets a possible sign after multiplying an expression with sign `s` to an expression - * that has this sign. - */ - Sign mul(Sign s) { - result = TZero() and this = TZero() - or - result = TZero() and s = TZero() - or - result = TNeg() and this = TPos() and s = TNeg() - or - result = TNeg() and this = TNeg() and s = TPos() - or - result = TPos() and this = TPos() and s = TPos() - or - result = TPos() and this = TNeg() and s = TNeg() - } - - /** - * Gets a possible sign after integer dividing an expression that has this sign - * by an expression with sign `s`. - */ - Sign div(Sign s) { - result = TZero() and s = TNeg() // ex: 3 / -5 = 0 - or - result = TZero() and s = TPos() // ex: 3 / 5 = 0 - or - result = TNeg() and this = TPos() and s = TNeg() - or - result = TNeg() and this = TNeg() and s = TPos() - or - result = TPos() and this = TPos() and s = TPos() - or - result = TPos() and this = TNeg() and s = TNeg() - } - - /** - * Gets a possible sign after modulo dividing an expression that has this sign - * by an expression with sign `s`. - */ - Sign rem(Sign s) { - result = TZero() and s = TNeg() - or - result = TZero() and s = TPos() - or - result = this and s = TNeg() - or - result = this and s = TPos() - } - - /** - * Gets a possible sign after bitwise `and` of an expression that has this sign - * and an expression with sign `s`. - */ - Sign bitand(Sign s) { - result = TZero() and this = TZero() - or - result = TZero() and s = TZero() - or - result = TZero() and this = TPos() - or - result = TZero() and s = TPos() - or - result = TNeg() and this = TNeg() and s = TNeg() - or - result = TPos() and this = TNeg() and s = TPos() - or - result = TPos() and this = TPos() and s = TNeg() - or - result = TPos() and this = TPos() and s = TPos() - } - - /** - * Gets a possible sign after bitwise `or` of an expression that has this sign - * and an expression with sign `s`. - */ - Sign bitor(Sign s) { - result = TZero() and this = TZero() and s = TZero() - or - result = TNeg() and this = TNeg() - or - result = TNeg() and s = TNeg() - or - result = TPos() and this = TPos() and s = TZero() - or - result = TPos() and this = TZero() and s = TPos() - or - result = TPos() and this = TPos() and s = TPos() - } - - /** - * Gets a possible sign after bitwise `xor` of an expression that has this sign - * and an expression with sign `s`. - */ - Sign bitxor(Sign s) { - result = TZero() and this = s - or - result = this and s = TZero() - or - result = s and this = TZero() - or - result = TPos() and this = TPos() and s = TPos() - or - result = TNeg() and this = TNeg() and s = TPos() - or - result = TNeg() and this = TPos() and s = TNeg() - or - result = TPos() and this = TNeg() and s = TNeg() - } - - /** - * Gets a possible sign after left shift of an expression that has this sign - * by an expression with sign `s`. - */ - Sign lshift(Sign s) { - result = TZero() and this = TZero() - or - result = this and s = TZero() - or - this != TZero() and s != TZero() - } - - /** - * Gets a possible sign after right shift of an expression that has this sign - * by an expression with sign `s`. - */ - Sign rshift(Sign s) { - result = TZero() and this = TZero() - or - result = this and s = TZero() - or - result = TNeg() and this = TNeg() - or - result != TNeg() and this = TPos() and s != TZero() - } - - /** - * Gets a possible sign after unsigned right shift of an expression that has - * this sign by an expression with sign `s`. - */ - Sign urshift(Sign s) { - result = TZero() and this = TZero() - or - result = this and s = TZero() - or - result != TZero() and this = TNeg() and s != TZero() - or - result != TNeg() and this = TPos() and s != TZero() - } - - /** Perform `op` on this sign. */ - Sign applyUnaryOp(Opcode op) { - op instanceof Opcode::CopyValue and result = this - or - op instanceof Opcode::Store and result = this - or - op instanceof Opcode::AddOne and result = inc() - or - op instanceof Opcode::SubOne and result = dec() - or - op instanceof Opcode::Negate and result = neg() - or - op instanceof Opcode::BitComplement and result = bitnot() - } - - /** Perform `op` on this sign and sign `s`. */ - Sign applyBinaryOp(Sign s, Opcode op) { - op instanceof Opcode::Add and result = add(s) - or - op instanceof Opcode::Sub and result = sub(s) - or - op instanceof Opcode::Mul and result = mul(s) - or - op instanceof Opcode::Div and result = div(s) - or - op instanceof Opcode::Rem and result = rem(s) - or - op instanceof Opcode::BitAnd and result = bitand(s) - or - op instanceof Opcode::BitOr and result = bitor(s) - or - op instanceof Opcode::BitXor and result = bitxor(s) - or - op instanceof Opcode::ShiftLeft and result = lshift(s) - or - op instanceof Opcode::ShiftRight and result = rshift(s) - or - op instanceof Opcode::ShiftRightUnsigned and result = urshift(s) - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll deleted file mode 100644 index ec3427558d4..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisCommon.qll +++ /dev/null @@ -1,510 +0,0 @@ -/** - * Provides sign analysis to determine whether expression are always positive - * or negative. - * - * The analysis is implemented as an abstract interpretation over the - * three-valued domain `{negative, zero, positive}`. - */ - -private import RangeAnalysisStage -private import SignAnalysisSpecific as Specific -private import experimental.semmle.code.cpp.semantic.Semantic -private import ConstantAnalysis -private import RangeUtils -private import Sign - -module SignAnalysis Utils> { - /** - * An SSA definition for which the analysis can compute the sign. - * - * The actual computation of the sign is done in an override of the `getSign()` predicate. The - * charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures - * that the charpred does not introduce negative recursion. The `getSign()` predicate may be - * recursive. - */ - abstract private class SignDef instanceof SemSsaVariable { - final string toString() { result = super.toString() } - - /** Gets the possible signs of this SSA definition. */ - abstract Sign getSign(); - } - - /** An SSA definition whose sign is computed based on standard flow. */ - abstract private class FlowSignDef extends SignDef { - abstract override Sign getSign(); - } - - /** An SSA definition whose sign is determined by the sign of that definitions source expression. */ - private class ExplicitSignDef extends FlowSignDef instanceof SemSsaExplicitUpdate { - final override Sign getSign() { result = semExprSign(super.getSourceExpr()) } - } - - /** An SSA Phi definition, whose sign is the union of the signs of its inputs. */ - private class PhiSignDef extends FlowSignDef instanceof SemSsaPhiNode { - final override Sign getSign() { - exists(SemSsaVariable inp, SemSsaReadPositionPhiInputEdge edge | - edge.phiInput(this, inp) and - result = semSsaSign(inp, edge) - ) - } - } - - /** An SSA definition whose sign is computed by a language-specific implementation. */ - abstract class CustomSignDef extends SignDef { - abstract override Sign getSign(); - } - - /** - * An expression for which the analysis can compute the sign. - * - * The actual computation of the sign is done in an override of the `getSign()` predicate. The - * charpred of any subclass must _not_ invoke `getSign()`, directly or indirectly. This ensures - * that the charpred does not introduce negative recursion. The `getSign()` predicate may be - * recursive. - * - * Concrete implementations extend one of the following subclasses: - * - `ConstantSignExpr`, for expressions with a compile-time constant value. - * - `FlowSignExpr`, for expressions whose sign can be computed from the signs of their operands. - * - `CustomsignExpr`, for expressions whose sign can be computed by a language-specific - * implementation. - * - * If the same expression matches more than one of the above subclasses, the sign is computed as - * follows: - * - The sign of a `ConstantSignExpr` is computed solely from `ConstantSignExpr.getSign()`, - * regardless of any other subclasses. - * - If a non-`ConstantSignExpr` expression matches exactly one of `FlowSignExpr` or - * `CustomSignExpr`, the sign is computed by that class' `getSign()` predicate. - * - If a non-`ConstantSignExpr` expression matches both `FlowSignExpr` and `CustomSignExpr`, the - * sign is the _intersection_ of the signs of those two classes' `getSign()` predicates. Thus, - * both classes have the opportunity to _restrict_ the set of possible signs, not to generate new - * possible signs. - * - If an expression does not match any of the three subclasses, then it can have any sign. - * - * Note that the `getSign()` predicate is introduced only in subclasses of `SignExpr`. - */ - abstract class SignExpr instanceof SemExpr { - SignExpr() { not Specific::ignoreExprSign(this) } - - final string toString() { result = super.toString() } - - abstract Sign getSign(); - } - - /** An expression whose sign is determined by its constant numeric value. */ - private class ConstantSignExpr extends SignExpr { - ConstantSignExpr() { - this instanceof SemConstantIntegerExpr or - exists(this.(SemNumericLiteralExpr).getApproximateFloatValue()) - } - - final override Sign getSign() { - exists(int i | this.(SemConstantIntegerExpr).getIntValue() = i | - i < 0 and result = TNeg() - or - i = 0 and result = TZero() - or - i > 0 and result = TPos() - ) - or - not exists(this.(SemConstantIntegerExpr).getIntValue()) and - exists(float f | f = this.(SemNumericLiteralExpr).getApproximateFloatValue() | - f < 0 and result = TNeg() - or - f = 0 and result = TZero() - or - f > 0 and result = TPos() - ) - } - } - - abstract private class NonConstantSignExpr extends SignExpr { - NonConstantSignExpr() { not this instanceof ConstantSignExpr } - - final override Sign getSign() { - // The result is the _intersection_ of the signs computed from flow and by the language. - (result = this.(FlowSignExpr).getSignRestriction() or not this instanceof FlowSignExpr) and - (result = this.(CustomSignExpr).getSignRestriction() or not this instanceof CustomSignExpr) - } - } - - /** An expression whose sign is computed from the signs of its operands. */ - abstract private class FlowSignExpr extends NonConstantSignExpr { - abstract Sign getSignRestriction(); - } - - /** An expression whose sign is computed by a language-specific implementation. */ - abstract class CustomSignExpr extends NonConstantSignExpr { - abstract Sign getSignRestriction(); - } - - /** An expression whose sign is unknown. */ - private class UnknownSignExpr extends SignExpr { - UnknownSignExpr() { - not this instanceof FlowSignExpr and - not this instanceof CustomSignExpr and - not this instanceof ConstantSignExpr and - ( - // Only track numeric types. - Utils::getTrackedType(this) instanceof SemNumericType - or - // Unless the language says to track this expression anyway. - Specific::trackUnknownNonNumericExpr(this) - ) - } - - final override Sign getSign() { semAnySign(result) } - } - - /** - * A `Load` expression whose sign is computed from the sign of its SSA definition, restricted by - * inference from any intervening guards. - */ - class UseSignExpr extends FlowSignExpr { - SemSsaVariable v; - - UseSignExpr() { v.getAUse() = this } - - override Sign getSignRestriction() { - // Propagate via SSA - // Propagate the sign from the def of `v`, incorporating any inference from guards. - result = semSsaSign(v, any(SemSsaReadPositionBlock bb | bb.getAnExpr() = this)) - or - // No block for this read. Just use the sign of the def. - // REVIEW: How can this happen? - not exists(SemSsaReadPositionBlock bb | bb.getAnExpr() = this) and - result = semSsaDefSign(v) - } - } - - /** A binary expression whose sign is computed from the signs of its operands. */ - private class BinarySignExpr extends FlowSignExpr { - SemBinaryExpr binary; - - BinarySignExpr() { binary = this } - - override Sign getSignRestriction() { - exists(SemExpr left, SemExpr right | - binaryExprOperands(binary, left, right) and - result = - semExprSign(pragma[only_bind_out](left)) - .applyBinaryOp(semExprSign(pragma[only_bind_out](right)), binary.getOpcode()) - ) - or - exists(SemDivExpr div | div = binary | - result = semExprSign(div.getLeftOperand()) and - result != TZero() and - div.getRightOperand().(SemFloatingPointLiteralExpr).getFloatValue() = 0 - ) - } - } - - /** An expression of an unsigned type. */ - private class UnsignedExpr extends FlowSignExpr { - UnsignedExpr() { Utils::getTrackedType(this) instanceof SemUnsignedIntegerType } - - override Sign getSignRestriction() { - result = TPos() or - result = TZero() - } - } - - pragma[nomagic] - private predicate binaryExprOperands(SemBinaryExpr binary, SemExpr left, SemExpr right) { - binary.getLeftOperand() = left and binary.getRightOperand() = right - } - - /** - * A `Convert`, `Box`, or `Unbox` expression. - */ - private class SemCastExpr instanceof SemUnaryExpr { - string toString() { result = super.toString() } - - SemCastExpr() { - this instanceof SemConvertExpr - or - this instanceof SemBoxExpr - or - this instanceof SemUnboxExpr - } - } - - /** A unary expression whose sign is computed from the sign of its operand. */ - private class UnarySignExpr extends FlowSignExpr { - SemUnaryExpr unary; - - UnarySignExpr() { unary = this and not this instanceof SemCastExpr } - - override Sign getSignRestriction() { - result = - semExprSign(pragma[only_bind_out](unary.getOperand())).applyUnaryOp(unary.getOpcode()) - } - } - - /** - * A `Convert`, `Box`, or `Unbox` expression, whose sign is computed based on - * the sign of its operand and the source and destination types. - */ - abstract private class CastSignExpr extends FlowSignExpr { - SemUnaryExpr cast; - - CastSignExpr() { cast = this and cast instanceof SemCastExpr } - - override Sign getSignRestriction() { result = semExprSign(cast.getOperand()) } - } - - /** - * A `Convert` expression. - */ - private class ConvertSignExpr extends CastSignExpr { - override SemConvertExpr cast; - } - - /** - * A `Box` expression. - */ - private class BoxSignExpr extends CastSignExpr { - override SemBoxExpr cast; - } - - /** - * An `Unbox` expression. - */ - private class UnboxSignExpr extends CastSignExpr { - override SemUnboxExpr cast; - - UnboxSignExpr() { - exists(SemType fromType | fromType = Utils::getTrackedType(cast.getOperand()) | - // Only numeric source types are handled here. - fromType instanceof SemNumericType - ) - } - } - - private predicate unknownSign(SemExpr e) { e instanceof UnknownSignExpr } - - /** - * Holds if `lowerbound` is a lower bound for `v` at `pos`. This is restricted - * to only include bounds for which we might determine a sign. - */ - private predicate lowerBound( - SemExpr lowerbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict - ) { - exists(boolean testIsTrue, SemRelationalExpr comp | - pos.hasReadOfVar(v) and - semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and - not unknownSign(lowerbound) - | - testIsTrue = true and - comp.getLesserOperand() = lowerbound and - comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and - (if comp.isStrict() then isStrict = true else isStrict = false) - or - testIsTrue = false and - comp.getGreaterOperand() = lowerbound and - comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and - (if comp.isStrict() then isStrict = false else isStrict = true) - ) - } - - /** - * Holds if `upperbound` is an upper bound for `v` at `pos`. This is restricted - * to only include bounds for which we might determine a sign. - */ - private predicate upperBound( - SemExpr upperbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isStrict - ) { - exists(boolean testIsTrue, SemRelationalExpr comp | - pos.hasReadOfVar(v) and - semGuardControlsSsaRead(semGetComparisonGuard(comp), pos, testIsTrue) and - not unknownSign(upperbound) - | - testIsTrue = true and - comp.getGreaterOperand() = upperbound and - comp.getLesserOperand() = Utils::semSsaRead(v, D::fromInt(0)) and - (if comp.isStrict() then isStrict = true else isStrict = false) - or - testIsTrue = false and - comp.getLesserOperand() = upperbound and - comp.getGreaterOperand() = Utils::semSsaRead(v, D::fromInt(0)) and - (if comp.isStrict() then isStrict = false else isStrict = true) - ) - } - - /** - * Holds if `eqbound` is an equality/inequality for `v` at `pos`. This is - * restricted to only include bounds for which we might determine a sign. The - * boolean `isEq` gives the polarity: - * - `isEq = true` : `v = eqbound` - * - `isEq = false` : `v != eqbound` - */ - private predicate eqBound(SemExpr eqbound, SemSsaVariable v, SemSsaReadPosition pos, boolean isEq) { - exists(SemGuard guard, boolean testIsTrue, boolean polarity, SemExpr e | - pos.hasReadOfVar(pragma[only_bind_into](v)) and - semGuardControlsSsaRead(guard, pragma[only_bind_into](pos), testIsTrue) and - e = Utils::semSsaRead(pragma[only_bind_into](v), D::fromInt(0)) and - guard.isEquality(eqbound, e, polarity) and - isEq = polarity.booleanXor(testIsTrue).booleanNot() and - not unknownSign(eqbound) - ) - } - - /** - * Holds if `bound` is a bound for `v` at `pos` that needs to be positive in - * order for `v` to be positive. - */ - private predicate posBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { - upperBound(bound, v, pos, _) or - eqBound(bound, v, pos, true) - } - - /** - * Holds if `bound` is a bound for `v` at `pos` that needs to be negative in - * order for `v` to be negative. - */ - private predicate negBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { - lowerBound(bound, v, pos, _) or - eqBound(bound, v, pos, true) - } - - /** - * Holds if `bound` is a bound for `v` at `pos` that can restrict whether `v` - * can be zero. - */ - private predicate zeroBound(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { - lowerBound(bound, v, pos, _) or - upperBound(bound, v, pos, _) or - eqBound(bound, v, pos, _) - } - - /** Holds if `bound` allows `v` to be positive at `pos`. */ - private predicate posBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { - posBound(bound, v, pos) and TPos() = semExprSign(bound) - } - - /** Holds if `bound` allows `v` to be negative at `pos`. */ - private predicate negBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { - negBound(bound, v, pos) and TNeg() = semExprSign(bound) - } - - /** Holds if `bound` allows `v` to be zero at `pos`. */ - private predicate zeroBoundOk(SemExpr bound, SemSsaVariable v, SemSsaReadPosition pos) { - lowerBound(bound, v, pos, _) and TNeg() = semExprSign(bound) - or - lowerBound(bound, v, pos, false) and TZero() = semExprSign(bound) - or - upperBound(bound, v, pos, _) and TPos() = semExprSign(bound) - or - upperBound(bound, v, pos, false) and TZero() = semExprSign(bound) - or - eqBound(bound, v, pos, true) and TZero() = semExprSign(bound) - or - eqBound(bound, v, pos, false) and TZero() != semExprSign(bound) - } - - /** - * Holds if there is a bound that might restrict whether `v` has the sign `s` - * at `pos`. - */ - private predicate hasGuard(SemSsaVariable v, SemSsaReadPosition pos, Sign s) { - s = TPos() and posBound(_, v, pos) - or - s = TNeg() and negBound(_, v, pos) - or - s = TZero() and zeroBound(_, v, pos) - } - - /** - * Gets a possible sign of `v` at `pos` based on its definition, where the sign - * might be ruled out by a guard. - */ - pragma[noinline] - private Sign guardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) { - result = semSsaDefSign(v) and - pos.hasReadOfVar(v) and - hasGuard(v, pos, result) - } - - /** - * Gets a possible sign of `v` at `pos` based on its definition, where no guard - * can rule it out. - */ - pragma[noinline] - private Sign unguardedSsaSign(SemSsaVariable v, SemSsaReadPosition pos) { - result = semSsaDefSign(v) and - pos.hasReadOfVar(v) and - not hasGuard(v, pos, result) - } - - /** - * Gets a possible sign of `v` at read position `pos`, where a guard could have - * ruled out the sign but does not. - * This does not check that the definition of `v` also allows the sign. - */ - private Sign guardedSsaSignOk(SemSsaVariable v, SemSsaReadPosition pos) { - result = TPos() and - forex(SemExpr bound | posBound(bound, v, pos) | posBoundOk(bound, v, pos)) - or - result = TNeg() and - forex(SemExpr bound | negBound(bound, v, pos) | negBoundOk(bound, v, pos)) - or - result = TZero() and - forex(SemExpr bound | zeroBound(bound, v, pos) | zeroBoundOk(bound, v, pos)) - } - - /** Gets a possible sign for `v` at `pos`. */ - private Sign semSsaSign(SemSsaVariable v, SemSsaReadPosition pos) { - result = unguardedSsaSign(v, pos) - or - result = guardedSsaSign(v, pos) and - result = guardedSsaSignOk(v, pos) - } - - /** Gets a possible sign for `v`. */ - pragma[nomagic] - Sign semSsaDefSign(SemSsaVariable v) { result = v.(SignDef).getSign() } - - /** Gets a possible sign for `e`. */ - cached - Sign semExprSign(SemExpr e) { - exists(Sign s | s = e.(SignExpr).getSign() | - if - Utils::getTrackedType(e) instanceof SemUnsignedIntegerType and - s = TNeg() and - not Specific::ignoreTypeRestrictions(e) - then result = TPos() - else result = s - ) - } - - /** - * Dummy predicate that holds for any sign. This is added to improve readability - * of cases where the sign is unrestricted. - */ - predicate semAnySign(Sign s) { any() } - - /** Holds if `e` can be positive and cannot be negative. */ - predicate semPositive(SemExpr e) { - semExprSign(e) = TPos() and - not semExprSign(e) = TNeg() - } - - /** Holds if `e` can be negative and cannot be positive. */ - predicate semNegative(SemExpr e) { - semExprSign(e) = TNeg() and - not semExprSign(e) = TPos() - } - - /** Holds if `e` is strictly positive. */ - predicate semStrictlyPositive(SemExpr e) { - semExprSign(e) = TPos() and - not semExprSign(e) = TNeg() and - not semExprSign(e) = TZero() - } - - /** Holds if `e` is strictly negative. */ - predicate semStrictlyNegative(SemExpr e) { - semExprSign(e) = TNeg() and - not semExprSign(e) = TPos() and - not semExprSign(e) = TZero() - } -} diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisSpecific.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisSpecific.qll deleted file mode 100644 index 0f482790d4d..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SignAnalysisSpecific.qll +++ /dev/null @@ -1,23 +0,0 @@ -/** - * Provides C++-specific definitions for use in sign analysis. - */ - -private import experimental.semmle.code.cpp.semantic.Semantic - -/** - * Workaround to allow certain expressions to have a negative sign, even if the type of the - * expression is unsigned. - */ -predicate ignoreTypeRestrictions(SemExpr e) { none() } - -/** - * Workaround to track the sign of certain expressions even if the type of the expression is not - * numeric. - */ -predicate trackUnknownNonNumericExpr(SemExpr e) { none() } - -/** - * Workaround to ignore tracking of certain expressions even if the type of the expression is - * numeric. - */ -predicate ignoreExprSign(SemExpr e) { none() } diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll b/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll deleted file mode 100644 index bd234390e3d..00000000000 --- a/cpp/ql/lib/experimental/semmle/code/cpp/semantic/analysis/SimpleRangeAnalysis.qll +++ /dev/null @@ -1,132 +0,0 @@ -/** - * Wrapper for the semantic range analysis library that mimics the - * interface of the simple range analysis library. - */ - -private import cpp -private import semmle.code.cpp.ir.IR -private import experimental.semmle.code.cpp.semantic.SemanticBound -private import experimental.semmle.code.cpp.semantic.SemanticExprSpecific -private import RangeAnalysis - -/** - * Gets the lower bound of the expression. - * - * Note: expressions in C/C++ are often implicitly or explicitly cast to a - * different result type. Such casts can cause the value of the expression - * to overflow or to be truncated. This predicate computes the lower bound - * of the expression without including the effect of the casts. To compute - * the lower bound of the expression after all the casts have been applied, - * call `lowerBound` like this: - * - * `lowerBound(expr.getFullyConverted())` - */ -float lowerBound(Expr expr) { - exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound | - semBounded(getSemanticExpr(i), b, result, false, _) - ) -} - -/** - * Gets the upper bound of the expression. - * - * Note: expressions in C/C++ are often implicitly or explicitly cast to a - * different result type. Such casts can cause the value of the expression - * to overflow or to be truncated. This predicate computes the upper bound - * of the expression without including the effect of the casts. To compute - * the upper bound of the expression after all the casts have been applied, - * call `upperBound` like this: - * - * `upperBound(expr.getFullyConverted())` - */ -float upperBound(Expr expr) { - exists(Instruction i, SemBound b | i.getAst() = expr and b instanceof SemZeroBound | - semBounded(getSemanticExpr(i), b, result, true, _) - ) -} - -/** - * Holds if the upper bound of `expr` may have been widened. This means the - * upper bound is in practice likely to be overly wide. - */ -predicate upperBoundMayBeWidened(Expr e) { none() } - -/** - * Holds if `expr` has a provably empty range. For example: - * - * 10 < expr and expr < 5 - * - * The range of an expression can only be empty if it can never be - * executed. For example: - * - * ```cpp - * if (10 < x) { - * if (x < 5) { - * // Unreachable code - * return x; // x has an empty range: 10 < x && x < 5 - * } - * } - * ``` - */ -predicate exprWithEmptyRange(Expr expr) { lowerBound(expr) > upperBound(expr) } - -/** Holds if the definition might overflow negatively. */ -predicate defMightOverflowNegatively(RangeSsaDefinition def, StackVariable v) { none() } - -/** Holds if the definition might overflow positively. */ -predicate defMightOverflowPositively(RangeSsaDefinition def, StackVariable v) { none() } - -/** - * Holds if the definition might overflow (either positively or - * negatively). - */ -predicate defMightOverflow(RangeSsaDefinition def, StackVariable v) { - defMightOverflowNegatively(def, v) or - defMightOverflowPositively(def, v) -} - -/** - * Holds if the expression might overflow negatively. This predicate - * does not consider the possibility that the expression might overflow - * due to a conversion. - */ -predicate exprMightOverflowNegatively(Expr expr) { none() } - -/** - * Holds if the expression might overflow negatively. Conversions - * are also taken into account. For example the expression - * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than - * due to the addition. - */ -predicate convertedExprMightOverflowNegatively(Expr expr) { - exprMightOverflowNegatively(expr) or - convertedExprMightOverflowNegatively(expr.getConversion()) -} - -/** - * Holds if the expression might overflow positively. This predicate - * does not consider the possibility that the expression might overflow - * due to a conversion. - */ -predicate exprMightOverflowPositively(Expr expr) { none() } - -/** - * Holds if the expression might overflow positively. Conversions - * are also taken into account. For example the expression - * `(int16)(x+y)` might overflow due to the `(int16)` cast, rather than - * due to the addition. - */ -predicate convertedExprMightOverflowPositively(Expr expr) { - exprMightOverflowPositively(expr) or - convertedExprMightOverflowPositively(expr.getConversion()) -} - -/** - * Holds if the expression might overflow (either positively or - * negatively). The possibility that the expression might overflow - * due to an implicit or explicit cast is also considered. - */ -predicate convertedExprMightOverflow(Expr expr) { - convertedExprMightOverflowNegatively(expr) or - convertedExprMightOverflowPositively(expr) -} From aa337c72c25ea660f1feeb0e153911f83039ecab Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 3 Apr 2023 13:53:28 +0100 Subject: [PATCH 138/141] C++: Update import paths in tests and experimental queries. --- .../Likely Bugs/ArrayAccessProductFlow.ql | 9 +++++---- .../Likely Bugs/OverrunWriteProductFlow.ql | 6 +++--- .../CWE/CWE-193/ConstantSizeArrayOffByOne.ql | 6 +++--- .../Security/CWE/CWE-193/InvalidPointerDeref.ql | 6 +++--- .../ir/modulus-analysis/ModulusAnalysis.ql | 14 +++++++------- .../ir/range-analysis/RangeAnalysis.ql | 6 +++--- .../library-tests/ir/sign-analysis/SignAnalysis.ql | 12 ++++++------ 7 files changed, 30 insertions(+), 29 deletions(-) diff --git a/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql index 61c0af6be26..8a3fe2c0e02 100644 --- a/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql @@ -11,9 +11,10 @@ import cpp import experimental.semmle.code.cpp.dataflow.ProductFlow -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis -import experimental.semmle.code.cpp.rangeanalysis.Bound -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.Bound import semmle.code.cpp.ir.IR import semmle.code.cpp.valuenumbering.GlobalValueNumbering import semmle.code.cpp.models.interfaces.Allocation @@ -34,7 +35,7 @@ class PhpEmalloc extends AllocationFunction { override int getSizeArg() { result = 0 } } -predicate bounded(Instruction i, Bound b, int delta, boolean upper) { +predicate bounded(Instruction i, SemBound b, int delta, boolean upper) { // TODO: reason semBounded(getSemanticExpr(i), b, delta, upper, _) } diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql index 5f6bf7d7166..c33cc792474 100644 --- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql @@ -17,9 +17,9 @@ import experimental.semmle.code.cpp.dataflow.ProductFlow import semmle.code.cpp.ir.IR import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.models.interfaces.ArrayFunction -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis -import experimental.semmle.code.cpp.semantic.SemanticBound -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import DataFlow::PathGraph pragma[nomagic] diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql index 66346b7aea7..6cbc2ac6fef 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql @@ -10,9 +10,9 @@ * experimental */ -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis -import experimental.semmle.code.cpp.semantic.SemanticBound -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.DataFlow import PointerArithmeticToDerefFlow::PathGraph diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql index 4f1fdb5d08a..01651e7d5aa 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -17,9 +17,9 @@ import cpp import experimental.semmle.code.cpp.dataflow.ProductFlow -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis -import experimental.semmle.code.cpp.semantic.SemanticBound -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR pragma[nomagic] diff --git a/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql b/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql index e7c56c240df..30ca575b767 100644 --- a/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/modulus-analysis/ModulusAnalysis.ql @@ -1,11 +1,11 @@ import cpp -import experimental.semmle.code.cpp.semantic.analysis.ModulusAnalysis -import experimental.semmle.code.cpp.semantic.Semantic -import experimental.semmle.code.cpp.semantic.analysis.RangeUtils -import experimental.semmle.code.cpp.semantic.analysis.FloatDelta -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisImpl -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.ModulusAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeUtils +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisImpl +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR as IR import TestUtilities.InlineExpectationsTest diff --git a/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql b/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql index 9cae7bf9e72..6c79e56cc5b 100644 --- a/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/range-analysis/RangeAnalysis.ql @@ -1,7 +1,7 @@ import cpp -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysis -import experimental.semmle.code.cpp.semantic.Semantic -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis +import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR as IR import TestUtilities.InlineExpectationsTest diff --git a/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql b/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql index 7b78b077a9b..8f95759ec7d 100644 --- a/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql +++ b/cpp/ql/test/library-tests/ir/sign-analysis/SignAnalysis.ql @@ -1,10 +1,10 @@ import cpp -import experimental.semmle.code.cpp.semantic.analysis.SignAnalysisCommon -import experimental.semmle.code.cpp.semantic.Semantic -import experimental.semmle.code.cpp.semantic.analysis.RangeUtils -import experimental.semmle.code.cpp.semantic.analysis.FloatDelta -import experimental.semmle.code.cpp.semantic.analysis.RangeAnalysisSpecific -import experimental.semmle.code.cpp.semantic.SemanticExprSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.SignAnalysisCommon +import semmle.code.cpp.rangeanalysis.new.internal.semantic.Semantic +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeUtils +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.FloatDelta +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysisSpecific +import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR as IR import TestUtilities.InlineExpectationsTest From c19edc5f0bd54be93e8dc7812d3ee4781fd84495 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 3 Apr 2023 14:18:31 +0100 Subject: [PATCH 139/141] C++: Fix Code Scanning errors. --- cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql | 1 - cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql | 1 - .../Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql | 1 - .../src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql | 1 - 4 files changed, 4 deletions(-) diff --git a/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql index 8a3fe2c0e02..1be0172abf7 100644 --- a/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql @@ -12,7 +12,6 @@ import cpp import experimental.semmle.code.cpp.dataflow.ProductFlow import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis -import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.Bound import semmle.code.cpp.ir.IR diff --git a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql index c33cc792474..7fde728e5bf 100644 --- a/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/OverrunWriteProductFlow.ql @@ -18,7 +18,6 @@ import semmle.code.cpp.ir.IR import semmle.code.cpp.models.interfaces.Allocation import semmle.code.cpp.models.interfaces.ArrayFunction import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis -import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import DataFlow::PathGraph diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql index 6cbc2ac6fef..20cd6f639ef 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/ConstantSizeArrayOffByOne.ql @@ -11,7 +11,6 @@ */ import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis -import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR import semmle.code.cpp.ir.dataflow.DataFlow diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql index 01651e7d5aa..1fefbbfcf36 100644 --- a/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql +++ b/cpp/ql/src/experimental/Security/CWE/CWE-193/InvalidPointerDeref.ql @@ -18,7 +18,6 @@ import cpp import experimental.semmle.code.cpp.dataflow.ProductFlow import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.RangeAnalysis -import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticBound import semmle.code.cpp.rangeanalysis.new.internal.semantic.SemanticExprSpecific import semmle.code.cpp.ir.IR From f6e774ed2e6cb6ec3366aefe2e2ef85d9b273242 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Mon, 3 Apr 2023 18:18:33 +0100 Subject: [PATCH 140/141] C++: Alias the experimental 'Bound.qll' with the non-experimental one. --- .../semmle/code/cpp/rangeanalysis/Bound.qll | 87 +------------------ 1 file changed, 1 insertion(+), 86 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll index abff447ca87..cca5f635ad6 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/rangeanalysis/Bound.qll @@ -1,86 +1 @@ -import cpp -private import semmle.code.cpp.ir.IR -private import semmle.code.cpp.ir.ValueNumbering - -private newtype TBound = - TBoundZero() or - TBoundValueNumber(ValueNumber vn) { - exists(Instruction i | - vn.getAnInstruction() = i and - ( - i.getResultIRType() instanceof IRIntegerType or - i.getResultIRType() instanceof IRAddressType - ) and - not vn.getAnInstruction() instanceof ConstantInstruction - | - i instanceof PhiInstruction - or - i instanceof InitializeParameterInstruction - or - i instanceof CallInstruction - or - i instanceof VariableAddressInstruction - or - i instanceof FieldAddressInstruction - or - i.(LoadInstruction).getSourceAddress() instanceof VariableAddressInstruction - or - i.(LoadInstruction).getSourceAddress() instanceof FieldAddressInstruction - or - i.getAUse() instanceof ArgumentOperand - or - i instanceof PointerArithmeticInstruction - or - i.getAUse() instanceof AddressOperand - ) - } - -/** - * A bound that may be inferred for an expression plus/minus an integer delta. - */ -abstract class Bound extends TBound { - abstract string toString(); - - /** Gets an expression that equals this bound plus `delta`. */ - abstract Instruction getInstruction(int delta); - - /** Gets an expression that equals this bound. */ - Instruction getInstruction() { result = getInstruction(0) } - - abstract Location getLocation(); -} - -/** - * The bound that corresponds to the integer 0. This is used to represent all - * integer bounds as bounds are always accompanied by an added integer delta. - */ -class ZeroBound extends Bound, TBoundZero { - override string toString() { result = "0" } - - override Instruction getInstruction(int delta) { - result.(ConstantValueInstruction).getValue().toInt() = delta - } - - override Location getLocation() { result instanceof UnknownDefaultLocation } -} - -/** - * A bound corresponding to the value of an `Instruction`. - */ -class ValueNumberBound extends Bound, TBoundValueNumber { - ValueNumber vn; - - ValueNumberBound() { this = TBoundValueNumber(vn) } - - /** Gets an `Instruction` that equals this bound. */ - override Instruction getInstruction(int delta) { - this = TBoundValueNumber(valueNumber(result)) and delta = 0 - } - - override string toString() { result = "ValueNumberBound" } - - override Location getLocation() { result = vn.getLocation() } - - /** Gets the value number that equals this bound. */ - ValueNumber getValueNumber() { result = vn } -} +import semmle.code.cpp.rangeanalysis.new.internal.semantic.analysis.Bound From f007083ef00fbb863d39242c8670ab85278c8591 Mon Sep 17 00:00:00 2001 From: Mathias Vorreiter Pedersen Date: Tue, 4 Apr 2023 09:43:23 +0100 Subject: [PATCH 141/141] C++: Switch back to a 'Bound' instead of a 'SemBound'. --- cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql b/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql index 1be0172abf7..39c54573b06 100644 --- a/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql +++ b/cpp/ql/src/experimental/Likely Bugs/ArrayAccessProductFlow.ql @@ -34,7 +34,7 @@ class PhpEmalloc extends AllocationFunction { override int getSizeArg() { result = 0 } } -predicate bounded(Instruction i, SemBound b, int delta, boolean upper) { +predicate bounded(Instruction i, Bound b, int delta, boolean upper) { // TODO: reason semBounded(getSemanticExpr(i), b, delta, upper, _) }