diff --git a/.github/workflows/codeqltest.yml b/.github/workflows/codeqltest.yml
index ab25e15dcab..0d9275a0f2e 100644
--- a/.github/workflows/codeqltest.yml
+++ b/.github/workflows/codeqltest.yml
@@ -7,10 +7,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- - name: Set up Go 1.16
+ - name: Set up Go 1.17
uses: actions/setup-go@v1
with:
- go-version: 1.16
+ go-version: 1.17
id: go
- name: Set up CodeQL CLI
@@ -20,7 +20,7 @@ jobs:
echo "Done"
cd $HOME
echo "Downloading CodeQL CLI..."
- LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | tail -1)
+ LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-linux64.zip "$LATEST"
echo "Done"
echo "Unpacking CodeQL CLI..."
@@ -59,10 +59,10 @@ jobs:
name: Test MacOS
runs-on: macOS-latest
steps:
- - name: Set up Go 1.16
+ - name: Set up Go 1.17
uses: actions/setup-go@v1
with:
- go-version: 1.16
+ go-version: 1.17
id: go
- name: Set up CodeQL CLI
@@ -72,7 +72,7 @@ jobs:
echo "Done"
cd $HOME
echo "Downloading CodeQL CLI..."
- LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | tail -1)
+ LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-osx64.zip "$LATEST"
echo "Done"
echo "Unpacking CodeQL CLI..."
@@ -99,10 +99,10 @@ jobs:
name: Test Windows
runs-on: windows-latest
steps:
- - name: Set up Go 1.16
+ - name: Set up Go 1.17
uses: actions/setup-go@v1
with:
- go-version: 1.16
+ go-version: 1.17
id: go
- name: Set up CodeQL CLI
@@ -112,7 +112,7 @@ jobs:
echo "Done"
cd "$HOME"
echo "Downloading CodeQL CLI..."
- LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | tail -1)
+ LATEST=$(gh release list --repo https://github.com/github/codeql-cli-binaries | cut -f 1 | sort --version-sort | grep -v beta | tail -1)
gh release download --repo https://github.com/github/codeql-cli-binaries --pattern codeql-win64.zip "$LATEST"
echo "Done"
echo "Unpacking CodeQL CLI..."
diff --git a/CODEOWNERS b/CODEOWNERS
index 72a3954cfb5..d076d9576d4 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,6 +1 @@
* @github/codeql-go
-
-# Documentation
-**/*.qhelp @shati-patel
-# Exclude experimental
-**/experimental/**/*.qhelp @github/codeql-go
diff --git a/change-notes/2021-05-06-xorm.md b/change-notes/2021-05-06-xorm.md
new file mode 100644
index 00000000000..0398530b950
--- /dev/null
+++ b/change-notes/2021-05-06-xorm.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* Added support for the `xorm.io/xorm` package
diff --git a/change-notes/2021-07-28-insufficient-key-size.md b/change-notes/2021-07-28-insufficient-key-size.md
new file mode 100644
index 00000000000..d3880bee73f
--- /dev/null
+++ b/change-notes/2021-07-28-insufficient-key-size.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* Query "Use of a weak cryptographic key" (`go/insufficient-key-size`) is promoted from experimental status. This checks that any RSA keys which are generated have a size of at least 2048 bits.
diff --git a/change-notes/2021-08-17-go-117.md b/change-notes/2021-08-17-go-117.md
new file mode 100644
index 00000000000..640f771b5f0
--- /dev/null
+++ b/change-notes/2021-08-17-go-117.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* The extractor now supports Go 1.17 features and models the changed libraries.
diff --git a/change-notes/2021-08-23-getPrimaryQlClasses.md b/change-notes/2021-08-23-getPrimaryQlClasses.md
new file mode 100644
index 00000000000..30b00908a23
--- /dev/null
+++ b/change-notes/2021-08-23-getPrimaryQlClasses.md
@@ -0,0 +1,2 @@
+lgtm,codescanning
+* Added `AstNode.getPrimaryQlClasses()` predicate, which gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
diff --git a/codeql-extractor.yml b/codeql-extractor.yml
index b258b193f56..e4da61ac7af 100644
--- a/codeql-extractor.yml
+++ b/codeql-extractor.yml
@@ -6,6 +6,8 @@ pull_request_triggers:
- "**/glide.yaml"
- "**/Gopkg.toml"
column_kind: "utf8"
+extra_env_vars:
+ CODEQL_REDUCE_FILES_FOLDERS_RELATIONS: "true"
file_types:
- name: go
display_name: Go
diff --git a/codeql-tools/pre-finalize.cmd b/codeql-tools/pre-finalize.cmd
index 4abac249933..f8909ea54ef 100644
--- a/codeql-tools/pre-finalize.cmd
+++ b/codeql-tools/pre-finalize.cmd
@@ -1,6 +1,8 @@
@echo off
SETLOCAL EnableDelayedExpansion
+SET CODEQL_REDUCE_FILES_FOLDERS_RELATIONS=true
+
if NOT "%CODEQL_EXTRACTOR_GO_EXTRACT_HTML%"=="no" (
type NUL && "%CODEQL_DIST%/codeql.exe" database index-files ^
--working-dir=. ^
diff --git a/codeql-tools/pre-finalize.sh b/codeql-tools/pre-finalize.sh
index 3a8b31c70a0..6151f552698 100755
--- a/codeql-tools/pre-finalize.sh
+++ b/codeql-tools/pre-finalize.sh
@@ -3,7 +3,7 @@
set -eu
if [ "${CODEQL_EXTRACTOR_GO_EXTRACT_HTML:-yes}" != "no" ]; then
- "$CODEQL_DIST/codeql" database index-files \
+ CODEQL_REDUCE_FILES_FOLDERS_RELATIONS=true "$CODEQL_DIST/codeql" database index-files \
--working-dir=. \
--include-extension=.htm \
--include-extension=.html \
diff --git a/extractor/dbscheme/tables.go b/extractor/dbscheme/tables.go
index 0a968fd8ecd..8da7312dfb8 100644
--- a/extractor/dbscheme/tables.go
+++ b/extractor/dbscheme/tables.go
@@ -896,16 +896,12 @@ var NumlinesTable = NewTable("numlines",
var FilesTable = NewTable("files",
EntityColumn(FileType, "id").Key(),
StringColumn("name"),
- StringColumn("simple"),
- StringColumn("ext"),
- IntColumn("fromSource"),
)
// FoldersTable is the table defining folder entities
var FoldersTable = NewTable("folders",
EntityColumn(FolderType, "id").Key(),
StringColumn("name"),
- StringColumn("simple"),
)
// ContainerParentTable is the table defining the parent-child relation among container entities
diff --git a/extractor/extractor.go b/extractor/extractor.go
index 704f80ebbed..4208a788d02 100644
--- a/extractor/extractor.go
+++ b/extractor/extractor.go
@@ -458,7 +458,7 @@ func (extraction *Extraction) extractError(tw *trap.Writer, err packages.Error,
e error
)
- if pos == "" {
+ if pos == "" || pos == "-" {
// extract a dummy file
wd, e := os.Getwd()
if e != nil {
@@ -590,15 +590,6 @@ func (extraction *Extraction) extractFile(ast *ast.File, pkg *packages.Package)
return nil
}
-// stemAndExt splits a given file name into its stem (the part before the last '.')
-// and extension (the part after the last '.')
-func stemAndExt(base string) (string, string) {
- if i := strings.LastIndexByte(base, '.'); i >= 0 {
- return base[:i], base[i+1:]
- }
- return base, ""
-}
-
// extractFileInfo extracts file-system level information for the given file, populating
// the `files` and `containerparent` tables
func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string) {
@@ -627,9 +618,8 @@ func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string) {
path = parentPath + "/" + component
}
if i == len(components)-1 {
- stem, ext := stemAndExt(component)
lbl := tw.Labeler.FileLabelFor(file)
- dbscheme.FilesTable.Emit(tw, lbl, path, stem, ext, 0)
+ dbscheme.FilesTable.Emit(tw, lbl, path)
dbscheme.ContainerParentTable.Emit(tw, parentLbl, lbl)
dbscheme.HasLocationTable.Emit(tw, lbl, emitLocation(tw, lbl, 0, 0, 0, 0))
extraction.Lock.Lock()
@@ -639,7 +629,7 @@ func (extraction *Extraction) extractFileInfo(tw *trap.Writer, file string) {
break
}
lbl := tw.Labeler.GlobalID(util.EscapeTrapSpecialChars(path) + ";folder")
- dbscheme.FoldersTable.Emit(tw, lbl, path, component)
+ dbscheme.FoldersTable.Emit(tw, lbl, path)
if i > 0 {
dbscheme.ContainerParentTable.Emit(tw, parentLbl, lbl)
}
diff --git a/go.mod b/go.mod
index 50a9c825682..5d77091a50c 100644
--- a/go.mod
+++ b/go.mod
@@ -1,8 +1,13 @@
module github.com/github/codeql-go
-go 1.16
+go 1.17
require (
- golang.org/x/mod v0.3.0
- golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9
+ golang.org/x/mod v0.5.0
+ golang.org/x/tools v0.1.5
+)
+
+require (
+ golang.org/x/sys v0.0.0-20210510120138-977fb7262007 // indirect
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
diff --git a/go.sum b/go.sum
index b336fd3e273..57b82477ee7 100644
--- a/go.sum
+++ b/go.sum
@@ -1,23 +1,27 @@
-github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
-golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
-golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
-golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
+golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
+golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
-golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
-golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
-golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9 h1:sEvmEcJVKBNUvgCUClbUQeHOAa9U0I2Ce1BooMvVCY4=
-golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
+golang.org/x/tools v0.1.5 h1:ouewzE6p+/VEB31YYnTbEJdi8pFqKp4P4n85vwo3DHA=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
diff --git a/ql/src/experimental/CWE-326/InsufficientKeySize.qhelp b/ql/src/Security/CWE-326/InsufficientKeySize.qhelp
similarity index 96%
rename from ql/src/experimental/CWE-326/InsufficientKeySize.qhelp
rename to ql/src/Security/CWE-326/InsufficientKeySize.qhelp
index c18341ca922..6547993458b 100644
--- a/ql/src/experimental/CWE-326/InsufficientKeySize.qhelp
+++ b/ql/src/Security/CWE-326/InsufficientKeySize.qhelp
@@ -26,7 +26,7 @@
- In the example below the key size is set to 2048 bits.
+ In the example below, the key size is set to 2048 bits.
diff --git a/ql/src/experimental/CWE-326/InsufficientKeySize.ql b/ql/src/Security/CWE-326/InsufficientKeySize.ql
similarity index 83%
rename from ql/src/experimental/CWE-326/InsufficientKeySize.ql
rename to ql/src/Security/CWE-326/InsufficientKeySize.ql
index ab5637f2914..6e1096f7708 100644
--- a/ql/src/experimental/CWE-326/InsufficientKeySize.ql
+++ b/ql/src/Security/CWE-326/InsufficientKeySize.ql
@@ -1,11 +1,13 @@
/**
* @name Use of a weak cryptographic key
- * @description Using weak cryptographic key can allow an attacker to compromise security.
+ * @description Using a weak cryptographic key can allow an attacker to compromise security.
* @kind path-problem
* @problem.severity error
+ * @security-severity 7.5
+ * @precision high
* @id go/weak-crypto-key
* @tags security
- * external/cwe/cwe-326
+ * external/cwe/cwe-326
*/
import go
diff --git a/ql/src/experimental/CWE-326/InsufficientKeySizeBad.go b/ql/src/Security/CWE-326/InsufficientKeySizeBad.go
similarity index 100%
rename from ql/src/experimental/CWE-326/InsufficientKeySizeBad.go
rename to ql/src/Security/CWE-326/InsufficientKeySizeBad.go
diff --git a/ql/src/experimental/CWE-326/InsufficientKeySizeGood.go b/ql/src/Security/CWE-326/InsufficientKeySizeGood.go
similarity index 100%
rename from ql/src/experimental/CWE-326/InsufficientKeySizeGood.go
rename to ql/src/Security/CWE-326/InsufficientKeySizeGood.go
diff --git a/ql/src/codeql-suites/go-developer-happiness.qls b/ql/src/codeql-suites/go-developer-happiness.qls
new file mode 100644
index 00000000000..0b2a2b1ae9e
--- /dev/null
+++ b/ql/src/codeql-suites/go-developer-happiness.qls
@@ -0,0 +1,8 @@
+- description: Experimental queries showing how we use CodeQL internally for developer happiness
+- qlpack: codeql-go
+- include:
+ id: go/examples/database-call-in-loop
+- include:
+ id: go/examples/deferinloop
+- include:
+ id: go/examples/gorm-error-not-checked
diff --git a/ql/src/experimental/CWE-400/DatabaseCallInLoop.go b/ql/src/experimental/CWE-400/DatabaseCallInLoop.go
new file mode 100644
index 00000000000..138bbbcd9d4
--- /dev/null
+++ b/ql/src/experimental/CWE-400/DatabaseCallInLoop.go
@@ -0,0 +1,13 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUsers(db *gorm.DB, names []string) []User {
+ res := make([]User, 0, len(names))
+ for _, name := range names {
+ var user User
+ db.Where("name = ?", name).First(&user)
+ res = append(res, user)
+ }
+ return res
+}
diff --git a/ql/src/experimental/CWE-400/DatabaseCallInLoop.qhelp b/ql/src/experimental/CWE-400/DatabaseCallInLoop.qhelp
new file mode 100644
index 00000000000..d9c8a50fae7
--- /dev/null
+++ b/ql/src/experimental/CWE-400/DatabaseCallInLoop.qhelp
@@ -0,0 +1,29 @@
+
+
+
+
+Database calls in loops are slower than running a single query and consume more resources. This
+can lead to denial of service attacks if the loop bounds can be controlled by an attacker.
+
+
+
+Ensure that where possible, database queries are not run in a loop, instead running a single query to get all relevant data.
+
+
+
+
+In the example below, users in a database are queried one by one in a loop:
+
+
+
+This is corrected by running a single query that selects all of the users at once:
+
+
+
+
+
+
+
+
diff --git a/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql b/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql
new file mode 100644
index 00000000000..2e4f25fe495
--- /dev/null
+++ b/ql/src/experimental/CWE-400/DatabaseCallInLoop.ql
@@ -0,0 +1,69 @@
+/**
+ * @name Database call in loop
+ * @description Detects database operations within loops.
+ * Doing operations in series can be slow and lead to N+1 situations.
+ * @kind path-problem
+ * @problem.severity warning
+ * @precision high
+ * @id go/examples/database-call-in-loop
+ */
+
+import go
+
+class DatabaseAccess extends DataFlow::MethodCallNode {
+ DatabaseAccess() {
+ exists(string name |
+ this.getTarget().hasQualifiedName(Gorm::packagePath(), "DB", name) and
+ // all terminating Gorm methods
+ name =
+ [
+ "Find", "Take", "Last", "Scan", "Row", "Rows", "ScanRows", "Pluck", "Count", "First",
+ "FirstOrInit", "FindOrCreate", "Update", "Updates", "UpdateColumn", "UpdateColumns",
+ "Save", "Create", "Delete", "Exec"
+ ]
+ )
+ }
+}
+
+class CallGraphNode extends Locatable {
+ CallGraphNode() {
+ this instanceof LoopStmt
+ or
+ this instanceof CallExpr
+ or
+ this instanceof FuncDef
+ }
+}
+
+/**
+ * Holds if `pred` calls `succ`, i.e. is an edge in the call graph,
+ * This includes explicit edges from call -> callee, to produce better paths.
+ */
+predicate callGraphEdge(CallGraphNode pred, CallGraphNode succ) {
+ // Go from a loop to an enclosed expression.
+ pred.(LoopStmt).getBody().getAChild*() = succ.(CallExpr)
+ or
+ // Go from a call to the called function.
+ pred.(CallExpr) = succ.(FuncDef).getACall().asExpr()
+ or
+ // Go from a function to an enclosed loop.
+ pred.(FuncDef) = succ.(LoopStmt).getEnclosingFunction()
+ or
+ // Go from a function to an enclosed call.
+ pred.(FuncDef) = succ.(CallExpr).getEnclosingFunction()
+}
+
+query predicate edges(CallGraphNode pred, CallGraphNode succ) {
+ callGraphEdge(pred, succ) and
+ // Limit the range of edges to only those that are relevant.
+ // This helps to speed up the query by reducing the size of the outputted path information.
+ exists(LoopStmt loop, DatabaseAccess dbAccess |
+ // is between a loop and a db access
+ callGraphEdge*(loop, pred) and
+ callGraphEdge*(succ, dbAccess.asExpr())
+ )
+}
+
+from LoopStmt loop, DatabaseAccess dbAccess
+where edges*(loop, dbAccess.asExpr())
+select dbAccess, loop, dbAccess, "$@ is called in $@", dbAccess, dbAccess.toString(), loop, "a loop"
diff --git a/ql/src/experimental/CWE-400/DatabaseCallInLoopGood.go b/ql/src/experimental/CWE-400/DatabaseCallInLoopGood.go
new file mode 100644
index 00000000000..22928a6abc2
--- /dev/null
+++ b/ql/src/experimental/CWE-400/DatabaseCallInLoopGood.go
@@ -0,0 +1,9 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUsersGood(db *gorm.DB, names []string) []User {
+ res := make([]User, 0, len(names))
+ db.Where("name IN ?", names).Find(&res)
+ return res
+}
diff --git a/ql/src/experimental/InconsistentCode/DeferInLoop.go b/ql/src/experimental/InconsistentCode/DeferInLoop.go
new file mode 100644
index 00000000000..1b57d1855b4
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/DeferInLoop.go
@@ -0,0 +1,14 @@
+package main
+
+import "os"
+
+func openFiles(filenames []string) {
+ for _, filename := range filenames {
+ file, err := os.Open(filename)
+ defer file.Close()
+ if err != nil {
+ // handle error
+ }
+ // work on file
+ }
+}
diff --git a/ql/src/experimental/InconsistentCode/DeferInLoop.qhelp b/ql/src/experimental/InconsistentCode/DeferInLoop.qhelp
new file mode 100644
index 00000000000..ea31e6829ed
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/DeferInLoop.qhelp
@@ -0,0 +1,32 @@
+
+
+
+
+A deferred statement in a loop will not execute until the end of the function. This can lead to unintentionally holding resources open, like file handles or database transactions.
+
+
+
+Either run the deferred function manually, or create a subroutine that contains the defer.
+
+
+
+
+In the example below, the files opened in the loop are not closed until the end of the function:
+
+
+
+The corrected version puts the loop body into a function.
+
+
+
+
+
+
+
+ Defer statements.
+
+
+
+
diff --git a/ql/examples/snippets/deferinloop.ql b/ql/src/experimental/InconsistentCode/DeferInLoop.ql
similarity index 100%
rename from ql/examples/snippets/deferinloop.ql
rename to ql/src/experimental/InconsistentCode/DeferInLoop.ql
diff --git a/ql/src/experimental/InconsistentCode/DeferInLoopGood.go b/ql/src/experimental/InconsistentCode/DeferInLoopGood.go
new file mode 100644
index 00000000000..d28bc8e4cb9
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/DeferInLoopGood.go
@@ -0,0 +1,18 @@
+package main
+
+import "os"
+
+func openFile(filename string) {
+ file, err := os.Open(filename)
+ defer file.Close()
+ if err != nil {
+ // handle error
+ }
+ // work on file
+}
+
+func openFilesGood(filenames []string) {
+ for _, filename := range filenames {
+ openFile(filename)
+ }
+}
diff --git a/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.go b/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.go
new file mode 100644
index 00000000000..422e49b5f10
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.go
@@ -0,0 +1,9 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUserId(db *gorm.DB, name string) int64 {
+ var user User
+ db.Where("name = ?", name).First(&user)
+ return user.Id
+}
diff --git a/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.qhelp b/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.qhelp
new file mode 100644
index 00000000000..499e38eeff2
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.qhelp
@@ -0,0 +1,34 @@
+
+
+
+
+GORM errors are returned as a field of the return value instead of a separate return value.
+
+It is therefore very easy to miss that an error may occur and omit error handling routines.
+
+
+
+Ensure that GORM errors are checked.
+
+
+
+
+In the example below, the error from the database query is never checked:
+
+
+
+The corrected version checks and handles the error before returning.
+
+
+
+
+
+
+
+ GORM Error Handling.
+
+
+
+
diff --git a/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.ql b/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.ql
new file mode 100644
index 00000000000..15ab4450f6d
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/GORMErrorNotChecked.ql
@@ -0,0 +1,35 @@
+/**
+ * @name GORM error not checked
+ * @description A call that interacts with the database using the GORM library
+ * without checking whether there was an error.
+ * @kind problem
+ * @problem.severity warning
+ * @id go/examples/gorm-error-not-checked
+ * @precision high
+ */
+
+import go
+import semmle.go.frameworks.SQL
+
+from DataFlow::MethodCallNode call
+where
+ exists(string name | call.getTarget().hasQualifiedName(Gorm::packagePath(), "DB", name) |
+ name != "InstantSet" and
+ name != "LogMode"
+ ) and
+ // the value from the call does not:
+ not exists(DataFlow::Node succ | TaintTracking::localTaintStep*(call, succ) |
+ // get assigned to any variables
+ succ = any(Write w).getRhs()
+ or
+ // get returned
+ succ instanceof DataFlow::ResultNode
+ or
+ // have any methods chained on it
+ exists(DataFlow::MethodCallNode m | succ = m.getReceiver())
+ or
+ // have its `Error` field read
+ exists(DataFlow::FieldReadNode fr | fr.readsField(succ, _, _, "Error"))
+ )
+select call,
+ "This call appears to interact with the database without checking whether an error was encountered."
diff --git a/ql/src/experimental/InconsistentCode/GORMErrorNotCheckedGood.go b/ql/src/experimental/InconsistentCode/GORMErrorNotCheckedGood.go
new file mode 100644
index 00000000000..551e06fb66a
--- /dev/null
+++ b/ql/src/experimental/InconsistentCode/GORMErrorNotCheckedGood.go
@@ -0,0 +1,11 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUserIdGood(db *gorm.DB, name string) int64 {
+ var user User
+ if err := db.Where("name = ?", name).First(&user).Error; err != nil {
+ // handle errors
+ }
+ return user.Id
+}
diff --git a/ql/src/experimental/frameworks/CleverGo.qll b/ql/src/experimental/frameworks/CleverGo.qll
index 9ff5ea7da21..c061c416b88 100644
--- a/ql/src/experimental/frameworks/CleverGo.qll
+++ b/ql/src/experimental/frameworks/CleverGo.qll
@@ -25,46 +25,46 @@ private module CleverGo {
|
receiverName = "Context" and
(
- // signature: func (*Context).BasicAuth() (username string, password string, ok bool)
+ // signature: func (*Context) BasicAuth() (username string, password string, ok bool)
methodName = "BasicAuth" and
out.isResult([0, 1])
or
- // signature: func (*Context).Decode(v interface{}) (err error)
+ // signature: func (*Context) Decode(v interface{}) (err error)
methodName = "Decode" and
out.isParameter(0)
or
- // signature: func (*Context).DefaultQuery(key string, defaultVlue string) string
+ // signature: func (*Context) DefaultQuery(key string, defaultVlue string) string
methodName = "DefaultQuery" and
out.isResult()
or
- // signature: func (*Context).FormValue(key string) string
+ // signature: func (*Context) FormValue(key string) string
methodName = "FormValue" and
out.isResult()
or
- // signature: func (*Context).GetHeader(name string) string
+ // signature: func (*Context) GetHeader(name string) string
methodName = "GetHeader" and
out.isResult()
or
- // signature: func (*Context).PostFormValue(key string) string
+ // signature: func (*Context) PostFormValue(key string) string
methodName = "PostFormValue" and
out.isResult()
or
- // signature: func (*Context).QueryParam(key string) string
+ // signature: func (*Context) QueryParam(key string) string
methodName = "QueryParam" and
out.isResult()
or
- // signature: func (*Context).QueryParams() net/url.Values
+ // signature: func (*Context) QueryParams() net/url.Values
methodName = "QueryParams" and
out.isResult()
or
- // signature: func (*Context).QueryString() string
+ // signature: func (*Context) QueryString() string
methodName = "QueryString" and
out.isResult()
)
or
receiverName = "Params" and
(
- // signature: func (Params).String(name string) string
+ // signature: func (Params) String(name string) string
methodName = "String" and
out.isResult()
)
@@ -77,7 +77,7 @@ private module CleverGo {
|
interfaceName = "Decoder" and
(
- // signature: func (Decoder).Decode(req *net/http.Request, v interface{}) error
+ // signature: func (Decoder) Decode(req *net/http.Request, v interface{}) error
methodName = "Decode" and
out.isParameter(1)
)
@@ -135,31 +135,31 @@ private module CleverGo {
// Taint-tracking models for package: clevergo.tech/clevergo@v0.5.2
(
// Receiver type: Application
- // signature: func (*Application).RouteURL(name string, args ...string) (*net/url.URL, error)
+ // signature: func (*Application) RouteURL(name string, args ...string) (*net/url.URL, error)
this.hasQualifiedName(packagePath(), "Application", "RouteURL") and
inp.isParameter(_) and
out.isResult(0)
or
// Receiver type: Context
- // signature: func (*Context).Context() context.Context
+ // signature: func (*Context) Context() context.Context
this.hasQualifiedName(packagePath(), "Context", "Context") and
inp.isReceiver() and
out.isResult()
or
// Receiver type: Params
- // signature: func (Params).String(name string) string
+ // signature: func (Params) String(name string) string
this.hasQualifiedName(packagePath(), "Params", "String") and
inp.isReceiver() and
out.isResult()
or
// Receiver interface: Decoder
- // signature: func (Decoder).Decode(req *net/http.Request, v interface{}) error
+ // signature: func (Decoder) Decode(req *net/http.Request, v interface{}) error
this.implements(packagePath(), "Decoder", "Decode") and
inp.isParameter(0) and
out.isParameter(1)
or
// Receiver interface: Renderer
- // signature: func (Renderer).Render(w io.Writer, name string, data interface{}, c *Context) error
+ // signature: func (Renderer) Render(w io.Writer, name string, data interface{}, c *Context) error
this.implements(packagePath(), "Renderer", "Render") and
inp.isParameter(2) and
out.isParameter(0)
@@ -183,7 +183,7 @@ private module CleverGo {
package = packagePath() and
// Receiver type: Context
(
- // signature: func (*Context).Redirect(code int, url string) error
+ // signature: func (*Context) Redirect(code int, url string) error
this = any(Method m | m.hasQualifiedName(package, "Context", "Redirect")).getACall() and
urlNode = this.getArgument(1)
)
@@ -227,72 +227,72 @@ private module CleverGo {
// Receiver type: Context
receiverName = "Context" and
(
- // signature: func (*Context).Error(code int, msg string) error
+ // signature: func (*Context) Error(code int, msg string) error
methodName = "Error" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/plain"
or
- // signature: func (*Context).HTML(code int, html string) error
+ // signature: func (*Context) HTML(code int, html string) error
methodName = "HTML" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/html"
or
- // signature: func (*Context).HTMLBlob(code int, bs []byte) error
+ // signature: func (*Context) HTMLBlob(code int, bs []byte) error
methodName = "HTMLBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/html"
or
- // signature: func (*Context).JSON(code int, data interface{}) error
+ // signature: func (*Context) JSON(code int, data interface{}) error
methodName = "JSON" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/json"
or
- // signature: func (*Context).JSONBlob(code int, bs []byte) error
+ // signature: func (*Context) JSONBlob(code int, bs []byte) error
methodName = "JSONBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/json"
or
- // signature: func (*Context).JSONP(code int, data interface{}) error
+ // signature: func (*Context) JSONP(code int, data interface{}) error
methodName = "JSONP" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/javascript"
or
- // signature: func (*Context).JSONPBlob(code int, bs []byte) error
+ // signature: func (*Context) JSONPBlob(code int, bs []byte) error
methodName = "JSONPBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "application/javascript"
or
- // signature: func (*Context).JSONPCallback(code int, callback string, data interface{}) error
+ // signature: func (*Context) JSONPCallback(code int, callback string, data interface{}) error
methodName = "JSONPCallback" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeString = "application/javascript"
or
- // signature: func (*Context).JSONPCallbackBlob(code int, callback string, bs []byte) (err error)
+ // signature: func (*Context) JSONPCallbackBlob(code int, callback string, bs []byte) (err error)
methodName = "JSONPCallbackBlob" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeString = "application/javascript"
or
- // signature: func (*Context).String(code int, s string) error
+ // signature: func (*Context) String(code int, s string) error
methodName = "String" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/plain"
or
- // signature: func (*Context).StringBlob(code int, bs []byte) error
+ // signature: func (*Context) StringBlob(code int, bs []byte) error
methodName = "StringBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/plain"
or
- // signature: func (*Context).Stringf(code int, format string, a ...interface{}) error
+ // signature: func (*Context) Stringf(code int, format string, a ...interface{}) error
methodName = "Stringf" and
bodyNode = bodySetterCall.getArgument([1, any(int i | i >= 2)]) and
contentTypeString = "text/plain"
or
- // signature: func (*Context).XML(code int, data interface{}) error
+ // signature: func (*Context) XML(code int, data interface{}) error
methodName = "XML" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/xml"
or
- // signature: func (*Context).XMLBlob(code int, bs []byte) error
+ // signature: func (*Context) XMLBlob(code int, bs []byte) error
methodName = "XMLBlob" and
bodyNode = bodySetterCall.getArgument(1) and
contentTypeString = "text/xml"
@@ -335,12 +335,12 @@ private module CleverGo {
// Receiver type: Context
receiverName = "Context" and
(
- // signature: func (*Context).Blob(code int, contentType string, bs []byte) (err error)
+ // signature: func (*Context) Blob(code int, contentType string, bs []byte) (err error)
methodName = "Blob" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeNode = bodySetterCall.getArgument(1)
or
- // signature: func (*Context).Emit(code int, contentType string, body string) (err error)
+ // signature: func (*Context) Emit(code int, contentType string, body string) (err error)
methodName = "Emit" and
bodyNode = bodySetterCall.getArgument(2) and
contentTypeNode = bodySetterCall.getArgument(1)
@@ -378,11 +378,11 @@ private module CleverGo {
// Receiver type: Context
receiverName = "Context" and
(
- // signature: func (*Context).Write(data []byte) (int, error)
+ // signature: func (*Context) Write(data []byte) (int, error)
methodName = "Write" and
bodyNode = bodySetterCall.getArgument(0)
or
- // signature: func (*Context).WriteString(data string) (int, error)
+ // signature: func (*Context) WriteString(data string) (int, error)
methodName = "WriteString" and
bodyNode = bodySetterCall.getArgument(0)
)
@@ -425,7 +425,7 @@ private module CleverGo {
// Receiver type: Context
receiverName = "Context" and
(
- // signature: func (*Context).SetHeader(key string, value string)
+ // signature: func (*Context) SetHeader(key string, value string)
methodName = "SetHeader" and
headerNameNode = headerSetterCall.getArgument(0) and
headerValueNode = headerSetterCall.getArgument(1)
@@ -471,19 +471,19 @@ private module CleverGo {
// Receiver type: Context
receiverName = "Context" and
(
- // signature: func (*Context).SetContentTypeHTML()
+ // signature: func (*Context) SetContentTypeHTML()
methodName = "SetContentTypeHTML" and
valueString = "text/html"
or
- // signature: func (*Context).SetContentTypeJSON()
+ // signature: func (*Context) SetContentTypeJSON()
methodName = "SetContentTypeJSON" and
valueString = "application/json"
or
- // signature: func (*Context).SetContentTypeText()
+ // signature: func (*Context) SetContentTypeText()
methodName = "SetContentTypeText" and
valueString = "text/plain"
or
- // signature: func (*Context).SetContentTypeXML()
+ // signature: func (*Context) SetContentTypeXML()
methodName = "SetContentTypeXML" and
valueString = "text/xml"
)
@@ -526,7 +526,7 @@ private module CleverGo {
// Receiver type: Context
receiverName = "Context" and
(
- // signature: func (*Context).SetContentType(v string)
+ // signature: func (*Context) SetContentType(v string)
methodName = "SetContentType" and
valueNode = setterCall.getArgument(0)
)
diff --git a/ql/src/experimental/frameworks/Fiber.qll b/ql/src/experimental/frameworks/Fiber.qll
index 08a0d961d41..a3240a0b85a 100644
--- a/ql/src/experimental/frameworks/Fiber.qll
+++ b/ql/src/experimental/frameworks/Fiber.qll
@@ -138,7 +138,7 @@ private module Fiber {
package = fiberPackagePath() and
// Receiver type: Ctx
(
- // signature: func (*Ctx).Redirect(location string, status ...int)
+ // signature: func (*Ctx) Redirect(location string, status ...int)
this = any(Method m | m.hasQualifiedName(package, "Ctx", "Redirect")).getACall() and
urlNode = this.getArgument(0)
)
@@ -184,12 +184,12 @@ private module Fiber {
// Receiver type: Ctx
receiverName = "Ctx" and
(
- // signature: func (*Ctx).Append(field string, values ...string)
+ // signature: func (*Ctx) Append(field string, values ...string)
methodName = "Append" and
headerNameNode = headerSetterCall.getArgument(0) and
headerValueNode = headerSetterCall.getArgument(any(int i | i >= 1))
or
- // signature: func (*Ctx).Set(key string, val string)
+ // signature: func (*Ctx) Set(key string, val string)
methodName = "Set" and
headerNameNode = headerSetterCall.getArgument(0) and
headerValueNode = headerSetterCall.getArgument(1)
@@ -231,12 +231,12 @@ private module Fiber {
// Receiver type: Ctx
receiverName = "Ctx" and
(
- // signature: func (*Ctx).JSON(data interface{}) error
+ // signature: func (*Ctx) JSON(data interface{}) error
methodName = "JSON" and
bodyNode = bodySetterCall.getArgument(0) and
contentTypeString = "application/json"
or
- // signature: func (*Ctx).JSONP(data interface{}, callback ...string) error
+ // signature: func (*Ctx) JSONP(data interface{}, callback ...string) error
methodName = "JSONP" and
bodyNode = bodySetterCall.getArgument(0) and
contentTypeString = "application/javascript"
@@ -274,27 +274,27 @@ private module Fiber {
// Receiver type: Ctx
receiverName = "Ctx" and
(
- // signature: func (*Ctx).Format(body interface{})
+ // signature: func (*Ctx) Format(body interface{})
methodName = "Format" and
bodyNode = bodySetterCall.getArgument(0)
or
- // signature: func (*Ctx).Send(bodies ...interface{})
+ // signature: func (*Ctx) Send(bodies ...interface{})
methodName = "Send" and
bodyNode = bodySetterCall.getArgument(_)
or
- // signature: func (*Ctx).SendBytes(body []byte)
+ // signature: func (*Ctx) SendBytes(body []byte)
methodName = "SendBytes" and
bodyNode = bodySetterCall.getArgument(0)
or
- // signature: func (*Ctx).SendStream(stream io.Reader, size ...int)
+ // signature: func (*Ctx) SendStream(stream io.Reader, size ...int)
methodName = "SendStream" and
bodyNode = bodySetterCall.getArgument(0)
or
- // signature: func (*Ctx).SendString(body string)
+ // signature: func (*Ctx) SendString(body string)
methodName = "SendString" and
bodyNode = bodySetterCall.getArgument(0)
or
- // signature: func (*Ctx).Write(bodies ...interface{})
+ // signature: func (*Ctx) Write(bodies ...interface{})
methodName = "Write" and
bodyNode = bodySetterCall.getArgument(_)
)
@@ -314,71 +314,71 @@ private module Fiber {
|
receiverName = "Ctx" and
(
- // signature: func (*Ctx).BaseURL() string
+ // signature: func (*Ctx) BaseURL() string
methodName = "BaseURL" and
out.isResult()
or
- // signature: func (*Ctx).Body() string
+ // signature: func (*Ctx) Body() string
methodName = "Body" and
out.isResult()
or
- // signature: func (*Ctx).BodyParser(out interface{}) error
+ // signature: func (*Ctx) BodyParser(out interface{}) error
methodName = "BodyParser" and
out.isParameter(0)
or
- // signature: func (*Ctx).Cookies(key string, defaultValue ...string) string
+ // signature: func (*Ctx) Cookies(key string, defaultValue ...string) string
methodName = "Cookies" and
out.isResult()
or
- // signature: func (*Ctx).FormFile(key string) (*mime/multipart.FileHeader, error)
+ // signature: func (*Ctx) FormFile(key string) (*mime/multipart.FileHeader, error)
methodName = "FormFile" and
out.isResult(0)
or
- // signature: func (*Ctx).FormValue(key string) (value string)
+ // signature: func (*Ctx) FormValue(key string) (value string)
methodName = "FormValue" and
out.isResult()
or
- // signature: func (*Ctx).Get(key string, defaultValue ...string) string
+ // signature: func (*Ctx) Get(key string, defaultValue ...string) string
methodName = "Get" and
out.isResult()
or
- // signature: func (*Ctx).Hostname() string
+ // signature: func (*Ctx) Hostname() string
methodName = "Hostname" and
out.isResult()
or
- // signature: func (*Ctx).Method(override ...string) string
+ // signature: func (*Ctx) Method(override ...string) string
methodName = "Method" and
out.isResult()
or
- // signature: func (*Ctx).MultipartForm() (*mime/multipart.Form, error)
+ // signature: func (*Ctx) MultipartForm() (*mime/multipart.Form, error)
methodName = "MultipartForm" and
out.isResult(0)
or
- // signature: func (*Ctx).OriginalURL() string
+ // signature: func (*Ctx) OriginalURL() string
methodName = "OriginalURL" and
out.isResult()
or
- // signature: func (*Ctx).Params(key string, defaultValue ...string) string
+ // signature: func (*Ctx) Params(key string, defaultValue ...string) string
methodName = "Params" and
out.isResult()
or
- // signature: func (*Ctx).Path(override ...string) string
+ // signature: func (*Ctx) Path(override ...string) string
methodName = "Path" and
out.isResult()
or
- // signature: func (*Ctx).Query(key string, defaultValue ...string) string
+ // signature: func (*Ctx) Query(key string, defaultValue ...string) string
methodName = "Query" and
out.isResult()
or
- // signature: func (*Ctx).QueryParser(out interface{}) error
+ // signature: func (*Ctx) QueryParser(out interface{}) error
methodName = "QueryParser" and
out.isParameter(0)
or
- // signature: func (*Ctx).Range(size int) (rangeData Range, err error)
+ // signature: func (*Ctx) Range(size int) (rangeData Range, err error)
methodName = "Range" and
out.isResult(0)
or
- // signature: func (*Ctx).Subdomains(offset ...int) []string
+ // signature: func (*Ctx) Subdomains(offset ...int) []string
methodName = "Subdomains" and
out.isResult()
)
diff --git a/ql/src/go.dbscheme b/ql/src/go.dbscheme
index b37faf5d62c..2842941c6f9 100644
--- a/ql/src/go.dbscheme
+++ b/ql/src/go.dbscheme
@@ -133,9 +133,9 @@ locations_default(unique int id: @location_default, int file: @file ref, int beg
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, string simple: string ref, string ext: string ref, int fromSource: int ref);
+files(unique int id: @file, string name: string ref);
-folders(unique int id: @folder, string name: string ref, string simple: string ref);
+folders(unique int id: @folder, string name: string ref);
containerparent(int parent: @container ref, unique int child: @container ref);
diff --git a/ql/src/go.dbscheme.stats b/ql/src/go.dbscheme.stats
index 4a1886f84c2..b18e8556fb2 100644
--- a/ql/src/go.dbscheme.stats
+++ b/ql/src/go.dbscheme.stats
@@ -8175,18 +8175,6 @@
name
529
-
- simple
- 373
-
-
- ext
- 3
-
-
- fromSource
- 1
-
@@ -8205,54 +8193,6 @@
-
- id
- simple
-
-
- 12
-
-
- 1
- 2
- 529
-
-
-
-
-
-
- id
- ext
-
-
- 12
-
-
- 1
- 2
- 529
-
-
-
-
-
-
- id
- fromSource
-
-
- 12
-
-
- 1
- 2
- 529
-
-
-
-
-
name
id
@@ -8269,301 +8209,6 @@
-
- name
- simple
-
-
- 12
-
-
- 1
- 2
- 529
-
-
-
-
-
-
- name
- ext
-
-
- 12
-
-
- 1
- 2
- 529
-
-
-
-
-
-
- name
- fromSource
-
-
- 12
-
-
- 1
- 2
- 529
-
-
-
-
-
-
- simple
- id
-
-
- 12
-
-
- 1
- 2
- 301
-
-
- 2
- 3
- 47
-
-
- 3
- 22
- 25
-
-
-
-
-
-
- simple
- name
-
-
- 12
-
-
- 1
- 2
- 301
-
-
- 2
- 3
- 47
-
-
- 3
- 22
- 25
-
-
-
-
-
-
- simple
- ext
-
-
- 12
-
-
- 1
- 2
- 368
-
-
- 2
- 3
- 5
-
-
-
-
-
-
- simple
- fromSource
-
-
- 12
-
-
- 1
- 2
- 373
-
-
-
-
-
-
- ext
- id
-
-
- 12
-
-
- 1
- 2
- 1
-
-
- 14
- 15
- 1
-
-
- 514
- 515
- 1
-
-
-
-
-
-
- ext
- name
-
-
- 12
-
-
- 1
- 2
- 1
-
-
- 14
- 15
- 1
-
-
- 514
- 515
- 1
-
-
-
-
-
-
- ext
- simple
-
-
- 12
-
-
- 1
- 2
- 1
-
-
- 14
- 15
- 1
-
-
- 363
- 364
- 1
-
-
-
-
-
-
- ext
- fromSource
-
-
- 12
-
-
- 1
- 2
- 3
-
-
-
-
-
-
- fromSource
- id
-
-
- 12
-
-
- 529
- 530
- 1
-
-
-
-
-
-
- fromSource
- name
-
-
- 12
-
-
- 529
- 530
- 1
-
-
-
-
-
-
- fromSource
- simple
-
-
- 12
-
-
- 373
- 374
- 1
-
-
-
-
-
-
- fromSource
- ext
-
-
- 12
-
-
- 3
- 4
- 1
-
-
-
-
-
@@ -8578,10 +8223,6 @@
name
210
-
- simple
- 178
-
@@ -8600,22 +8241,6 @@
-
- id
- simple
-
-
- 12
-
-
- 1
- 2
- 210
-
-
-
-
-
name
id
@@ -8632,74 +8257,6 @@
-
- name
- simple
-
-
- 12
-
-
- 1
- 2
- 210
-
-
-
-
-
-
- simple
- id
-
-
- 12
-
-
- 1
- 2
- 157
-
-
- 2
- 3
- 18
-
-
- 3
- 10
- 3
-
-
-
-
-
-
- simple
- name
-
-
- 12
-
-
- 1
- 2
- 157
-
-
- 2
- 3
- 18
-
-
- 3
- 10
- 3
-
-
-
-
-
diff --git a/ql/src/semmle/go/AST.qll b/ql/src/semmle/go/AST.qll
index 8468fba1276..6ce205aefae 100644
--- a/ql/src/semmle/go/AST.qll
+++ b/ql/src/semmle/go/AST.qll
@@ -81,6 +81,11 @@ class AstNode extends @node, Locatable {
/** Gets the innermost function definition to which this AST node belongs, if any. */
FuncDef getEnclosingFunction() { result = getParent().parentInSameFunction*() }
+ /**
+ * Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
+ */
+ final string getPrimaryQlClasses() { result = concat(getAPrimaryQlClass(), ",") }
+
/**
* Gets the name of a primary CodeQL class to which this node belongs.
*
diff --git a/ql/src/semmle/go/Comments.qll b/ql/src/semmle/go/Comments.qll
index 2a765c5e972..e072c0cb7ca 100644
--- a/ql/src/semmle/go/Comments.qll
+++ b/ql/src/semmle/go/Comments.qll
@@ -189,7 +189,7 @@ private Comment getInitialComment(File f, int i) {
}
/**
- * A build constraint comment of the form `// +build ...`.
+ * A build constraint comment of the form `// +build ...` or `//go:build ...`.
*
* Examples:
*
@@ -203,17 +203,23 @@ class BuildConstraintComment extends LineComment {
// a line comment preceding the package declaration, itself only preceded by
// line comments
exists(File f, int i |
+ // correctness of the placement of the build constraint is not checked here;
+ // this is more lax than the actual rules for build constraints
this = getInitialComment(f, i) and
not getInitialComment(f, [0 .. i - 1]) instanceof BlockComment
) and
- // comment text starts with `+build`
- getText().regexpMatch("\\s*\\+build.*")
+ (
+ // comment text starts with `+build` or `go:build`
+ this.getText().regexpMatch("\\s*\\+build.*")
+ or
+ this.getText().regexpMatch("\\s*go:build.*")
+ )
}
override string getAPrimaryQlClass() { result = "BuildConstraintComment" }
/** Gets the body of this build constraint. */
- string getConstraintBody() { result = getText().splitAt("+build ", 1) }
+ string getConstraintBody() { result = getText().splitAt("build ", 1) }
/** Gets a disjunct of this build constraint. */
string getADisjunct() { result = getConstraintBody().splitAt(" ") }
diff --git a/ql/src/semmle/go/Files.qll b/ql/src/semmle/go/Files.qll
index ed27c6b557b..28cb395beb3 100644
--- a/ql/src/semmle/go/Files.qll
+++ b/ql/src/semmle/go/Files.qll
@@ -155,7 +155,7 @@ abstract class Container extends @container {
/** A folder. */
class Folder extends Container, @folder {
- override string getAbsolutePath() { folders(this, result, _) }
+ override string getAbsolutePath() { folders(this, result) }
/** Gets the file or subfolder in this folder that has the given `name`, if any. */
Container getChildContainer(string name) {
@@ -182,7 +182,7 @@ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent
DeclParent, ScopeNode {
override Location getLocation() { has_location(this, result) }
- override string getAbsolutePath() { files(this, result, _, _, _) }
+ override string getAbsolutePath() { files(this, result) }
/** Gets the number of lines in this file. */
int getNumberOfLines() { numlines(this, result, _, _) }
@@ -222,6 +222,8 @@ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent
exists(BuildConstraintComment bcc | this = bcc.getFile() |
forex(string disjunct | disjunct = bcc.getADisjunct() |
disjunct.splitAt(",").(Architecture).getBitSize() = bitSize
+ or
+ disjunct.splitAt("/").(Architecture).getBitSize() = bitSize
)
)
}
diff --git a/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll b/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll
index 341f92925db..5642a853513 100644
--- a/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll
+++ b/ql/src/semmle/go/controlflow/ControlFlowGraphImpl.qll
@@ -1184,6 +1184,14 @@ module CFG {
}
private class ConversionExprTree extends PostOrderTree, ConversionExpr {
+ override Completion getCompletion() {
+ // conversions of a slice to an array pointer are the only kind that may panic
+ this.getType().(PointerType).getBaseType() instanceof ArrayType and
+ result = Panic()
+ or
+ result = Done()
+ }
+
override ControlFlow::Node getNode() { result = MkExprNode(this) }
override ControlFlowTree getChildTree(int i) { i = 0 and result = getOperand() }
diff --git a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll
index eab96dac19e..c4aed4ddd1e 100644
--- a/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll
+++ b/ql/src/semmle/go/dataflow/internal/DataFlowUtil.qll
@@ -1219,7 +1219,7 @@ abstract class BarrierGuard extends Node {
// Case: a function like "return someBarrierGuard(arg)"
// or "return !someBarrierGuard(arg) && otherCond(...)"
exists(boolean outcome |
- not exists(DataFlow::Node otherRet | otherRet = outp.getEntryNode(fd) | otherRet != ret) and
+ ret = getUniqueOutputNode(fd, outp) and
this.checks(arg.asExpr(), outcome) and
// This predicate's contract is (p holds of ret ==> arg is checked),
// (and we have (this has outcome ==> arg is checked))
@@ -1234,7 +1234,7 @@ abstract class BarrierGuard extends Node {
Function f2, FunctionInput inp2, FunctionOutput outp2, CallNode c,
DataFlow::Property outpProp
|
- not exists(DataFlow::Node otherRet | otherRet = outp.getEntryNode(fd) | otherRet != ret) and
+ ret = getUniqueOutputNode(fd, outp) and
this.guardingFunction(f2, inp2, outp2, outpProp) and
c = f2.getACall() and
arg = inp2.getNode(c) and
@@ -1252,6 +1252,10 @@ abstract class BarrierGuard extends Node {
}
}
+DataFlow::Node getUniqueOutputNode(FuncDecl fd, FunctionOutput outp) {
+ result = unique(DataFlow::Node n | n = outp.getEntryNode(fd) | n)
+}
+
/**
* Holds if `ret` is a data-flow node whose value contributes to the output `res` of `fd`,
* and that node may have Boolean value `b`.
diff --git a/ql/src/semmle/go/frameworks/SQL.qll b/ql/src/semmle/go/frameworks/SQL.qll
index f626fe097ca..b8c51750b8f 100644
--- a/ql/src/semmle/go/frameworks/SQL.qll
+++ b/ql/src/semmle/go/frameworks/SQL.qll
@@ -224,3 +224,33 @@ module Gorm {
result = package(["github.com/jinzhu/gorm", "github.com/go-gorm/gorm", "gorm.io/gorm"], "")
}
}
+
+/**
+ * Provides classes for working with the [XORM](https://xorm.io/) package.
+ */
+module Xorm {
+ /** Gets the package name for Xorm. */
+ string packagePath() { result = package(["xorm.io/xorm", "github.com/go-xorm/xorm"], "") }
+
+ /** A model for sinks of XORM. */
+ private class XormSink extends SQL::QueryString::Range {
+ XormSink() {
+ exists(Method meth, string type, string name, int n |
+ meth.hasQualifiedName(Xorm::packagePath(), type, name) and
+ this = meth.getACall().getArgument(n) and
+ type = ["Engine", "Session"]
+ |
+ name =
+ [
+ "Query", "Exec", "QueryString", "QueryInterface", "SQL", "Where", "And", "Or", "Alias",
+ "NotIn", "In", "Select", "SetExpr", "OrderBy", "Having", "GroupBy"
+ ] and
+ n = 0
+ or
+ name = ["SumInt", "Sum", "Sums", "SumsInt"] and n = 1
+ or
+ name = "Join" and n = [0, 1, 2]
+ )
+ }
+ }
+}
diff --git a/ql/src/semmle/go/frameworks/stdlib/ArchiveTar.qll b/ql/src/semmle/go/frameworks/stdlib/ArchiveTar.qll
index 4b57dd6919c..baaf8ca603f 100644
--- a/ql/src/semmle/go/frameworks/stdlib/ArchiveTar.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/ArchiveTar.qll
@@ -35,15 +35,15 @@ module ArchiveTar {
MethodModels() {
// Methods:
- // signature: func (*Header).FileInfo() os.FileInfo
+ // signature: func (*Header) FileInfo() os.FileInfo
hasQualifiedName("archive/tar", "Header", "FileInfo") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Reader).Next() (*Header, error)
+ // signature: func (*Reader) Next() (*Header, error)
hasQualifiedName("archive/tar", "Reader", "Next") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Writer).WriteHeader(hdr *Header) error
+ // signature: func (*Writer) WriteHeader(hdr *Header) error
hasQualifiedName("archive/tar", "Writer", "WriteHeader") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/ArchiveZip.qll b/ql/src/semmle/go/frameworks/stdlib/ArchiveZip.qll
index e1e480b285f..8b25fd334fc 100644
--- a/ql/src/semmle/go/frameworks/stdlib/ArchiveZip.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/ArchiveZip.qll
@@ -38,15 +38,27 @@ module ArchiveZip {
FunctionOutput outp;
MethodModels() {
- // signature: func (*File).Open() (io.ReadCloser, error)
+ // signature: func (*File) Open() (io.ReadCloser, error)
hasQualifiedName("archive/zip", "File", "Open") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Writer).Create(name string) (io.Writer, error)
+ // signature: func (*File) OpenRaw() (io.Reader, error)
+ hasQualifiedName("archive/zip", "File", "OpenRaw") and
+ (inp.isReceiver() and outp.isResult(0))
+ or
+ // signature: func (*Writer) Copy(f *File) error
+ hasQualifiedName("archive/zip", "Writer", "Copy") and
+ (inp.isParameter(0) and outp.isReceiver())
+ or
+ // signature: func (*Writer) Create(name string) (io.Writer, error)
hasQualifiedName("archive/zip", "Writer", "Create") and
(inp.isResult(0) and outp.isReceiver())
or
- // signature: func (*Writer).CreateHeader(fh *FileHeader) (io.Writer, error)
+ // signature: func (*Writer) CreateRaw(fh *FileHeader) (io.Writer, error)
+ hasQualifiedName("archive/zip", "Writer", "CreateRaw") and
+ (inp.isResult(0) and outp.isReceiver())
+ or
+ // signature: func (*Writer) CreateHeader(fh *FileHeader) (io.Writer, error)
hasQualifiedName("archive/zip", "Writer", "CreateHeader") and
(inp.isResult(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Bufio.qll b/ql/src/semmle/go/frameworks/stdlib/Bufio.qll
index 4c81861a12c..dc0fa3a5cc6 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Bufio.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Bufio.qll
@@ -79,39 +79,39 @@ module Bufio {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Reader).Peek(n int) ([]byte, error)
+ // signature: func (*Reader) Peek(n int) ([]byte, error)
hasQualifiedName("bufio", "Reader", "Peek") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadBytes(delim byte) ([]byte, error)
+ // signature: func (*Reader) ReadBytes(delim byte) ([]byte, error)
hasQualifiedName("bufio", "Reader", "ReadBytes") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadLine() (line []byte, isPrefix bool, err error)
+ // signature: func (*Reader) ReadLine() (line []byte, isPrefix bool, err error)
hasQualifiedName("bufio", "Reader", "ReadLine") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadSlice(delim byte) (line []byte, err error)
+ // signature: func (*Reader) ReadSlice(delim byte) (line []byte, err error)
hasQualifiedName("bufio", "Reader", "ReadSlice") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadString(delim byte) (string, error)
+ // signature: func (*Reader) ReadString(delim byte) (string, error)
hasQualifiedName("bufio", "Reader", "ReadString") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).Reset(r io.Reader)
+ // signature: func (*Reader) Reset(r io.Reader)
hasQualifiedName("bufio", "Reader", "Reset") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Scanner).Bytes() []byte
+ // signature: func (*Scanner) Bytes() []byte
hasQualifiedName("bufio", "Scanner", "Bytes") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Scanner).Text() string
+ // signature: func (*Scanner) Text() string
hasQualifiedName("bufio", "Scanner", "Text") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Writer).Reset(w io.Writer)
+ // signature: func (*Writer) Reset(w io.Writer)
hasQualifiedName("bufio", "Writer", "Reset") and
(inp.isReceiver() and outp.isParameter(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Bytes.qll b/ql/src/semmle/go/frameworks/stdlib/Bytes.qll
index c87d69b4541..c2791b1eaa3 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Bytes.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Bytes.qll
@@ -150,23 +150,23 @@ module Bytes {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Buffer).Bytes() []byte
+ // signature: func (*Buffer) Bytes() []byte
hasQualifiedName("bytes", "Buffer", "Bytes") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Buffer).Next(n int) []byte
+ // signature: func (*Buffer) Next(n int) []byte
hasQualifiedName("bytes", "Buffer", "Next") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Buffer).ReadBytes(delim byte) (line []byte, err error)
+ // signature: func (*Buffer) ReadBytes(delim byte) (line []byte, err error)
hasQualifiedName("bytes", "Buffer", "ReadBytes") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Buffer).ReadString(delim byte) (line string, err error)
+ // signature: func (*Buffer) ReadString(delim byte) (line string, err error)
hasQualifiedName("bytes", "Buffer", "ReadString") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).Reset(b []byte)
+ // signature: func (*Reader) Reset(b []byte)
hasQualifiedName("bytes", "Reader", "Reset") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/CompressFlate.qll b/ql/src/semmle/go/frameworks/stdlib/CompressFlate.qll
index dee4bf9aca3..a26ad967699 100644
--- a/ql/src/semmle/go/frameworks/stdlib/CompressFlate.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/CompressFlate.qll
@@ -38,11 +38,11 @@ module CompressFlate {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Writer).Reset(dst io.Writer)
+ // signature: func (*Writer) Reset(dst io.Writer)
hasQualifiedName("compress/flate", "Writer", "Reset") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (Resetter).Reset(r io.Reader, dict []byte) error
+ // signature: func (Resetter) Reset(r io.Reader, dict []byte) error
implements("compress/flate", "Resetter", "Reset") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/CompressGzip.qll b/ql/src/semmle/go/frameworks/stdlib/CompressGzip.qll
index 772ee24cded..366f8c7a634 100644
--- a/ql/src/semmle/go/frameworks/stdlib/CompressGzip.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/CompressGzip.qll
@@ -34,11 +34,11 @@ module CompressGzip {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Reader).Reset(r io.Reader) error
+ // signature: func (*Reader) Reset(r io.Reader) error
hasQualifiedName("compress/gzip", "Reader", "Reset") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Writer).Reset(w io.Writer)
+ // signature: func (*Writer) Reset(w io.Writer)
hasQualifiedName("compress/gzip", "Writer", "Reset") and
(inp.isReceiver() and outp.isParameter(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/CompressZlib.qll b/ql/src/semmle/go/frameworks/stdlib/CompressZlib.qll
index 91f1b62318e..ab88b6319aa 100644
--- a/ql/src/semmle/go/frameworks/stdlib/CompressZlib.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/CompressZlib.qll
@@ -42,11 +42,11 @@ module CompressZlib {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Writer).Reset(w io.Writer)
+ // signature: func (*Writer) Reset(w io.Writer)
hasQualifiedName("compress/zlib", "Writer", "Reset") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (Resetter).Reset(r io.Reader, dict []byte) error
+ // signature: func (Resetter) Reset(r io.Reader, dict []byte) error
implements("compress/zlib", "Resetter", "Reset") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/ContainerHeap.qll b/ql/src/semmle/go/frameworks/stdlib/ContainerHeap.qll
index c62e5fe4725..ddd8c602c51 100644
--- a/ql/src/semmle/go/frameworks/stdlib/ContainerHeap.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/ContainerHeap.qll
@@ -34,11 +34,11 @@ module ContainerHeap {
FunctionOutput outp;
MethodModels() {
- // signature: func (Interface).Pop() interface{}
+ // signature: func (Interface) Pop() interface{}
implements("container/heap", "Interface", "Pop") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Interface).Push(x interface{})
+ // signature: func (Interface) Push(x interface{})
implements("container/heap", "Interface", "Push") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/ContainerList.qll b/ql/src/semmle/go/frameworks/stdlib/ContainerList.qll
index 3b44e3c8bed..6efa1e96b8e 100644
--- a/ql/src/semmle/go/frameworks/stdlib/ContainerList.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/ContainerList.qll
@@ -11,79 +11,79 @@ module ContainerList {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Element).Next() *Element
+ // signature: func (*Element) Next() *Element
hasQualifiedName("container/list", "Element", "Next") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Element).Prev() *Element
+ // signature: func (*Element) Prev() *Element
hasQualifiedName("container/list", "Element", "Prev") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*List).Back() *Element
+ // signature: func (*List) Back() *Element
hasQualifiedName("container/list", "List", "Back") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*List).Front() *Element
+ // signature: func (*List) Front() *Element
hasQualifiedName("container/list", "List", "Front") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*List).Init() *List
+ // signature: func (*List) Init() *List
hasQualifiedName("container/list", "List", "Init") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*List).InsertAfter(v interface{}, mark *Element) *Element
+ // signature: func (*List) InsertAfter(v interface{}, mark *Element) *Element
hasQualifiedName("container/list", "List", "InsertAfter") and
(
inp.isParameter(0) and
(outp.isReceiver() or outp.isResult())
)
or
- // signature: func (*List).InsertBefore(v interface{}, mark *Element) *Element
+ // signature: func (*List) InsertBefore(v interface{}, mark *Element) *Element
hasQualifiedName("container/list", "List", "InsertBefore") and
(
inp.isParameter(0) and
(outp.isReceiver() or outp.isResult())
)
or
- // signature: func (*List).MoveAfter(e *Element, mark *Element)
+ // signature: func (*List) MoveAfter(e *Element, mark *Element)
hasQualifiedName("container/list", "List", "MoveAfter") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*List).MoveBefore(e *Element, mark *Element)
+ // signature: func (*List) MoveBefore(e *Element, mark *Element)
hasQualifiedName("container/list", "List", "MoveBefore") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*List).MoveToBack(e *Element)
+ // signature: func (*List) MoveToBack(e *Element)
hasQualifiedName("container/list", "List", "MoveToBack") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*List).MoveToFront(e *Element)
+ // signature: func (*List) MoveToFront(e *Element)
hasQualifiedName("container/list", "List", "MoveToFront") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*List).PushBack(v interface{}) *Element
+ // signature: func (*List) PushBack(v interface{}) *Element
hasQualifiedName("container/list", "List", "PushBack") and
(
inp.isParameter(0) and
(outp.isReceiver() or outp.isResult())
)
or
- // signature: func (*List).PushBackList(other *List)
+ // signature: func (*List) PushBackList(other *List)
hasQualifiedName("container/list", "List", "PushBackList") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*List).PushFront(v interface{}) *Element
+ // signature: func (*List) PushFront(v interface{}) *Element
hasQualifiedName("container/list", "List", "PushFront") and
(
inp.isParameter(0) and
(outp.isReceiver() or outp.isResult())
)
or
- // signature: func (*List).PushFrontList(other *List)
+ // signature: func (*List) PushFrontList(other *List)
hasQualifiedName("container/list", "List", "PushFrontList") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*List).Remove(e *Element) interface{}
+ // signature: func (*List) Remove(e *Element) interface{}
hasQualifiedName("container/list", "List", "Remove") and
(inp.isParameter(0) and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/ContainerRing.qll b/ql/src/semmle/go/frameworks/stdlib/ContainerRing.qll
index 94b83b6faf2..7463c0455f6 100644
--- a/ql/src/semmle/go/frameworks/stdlib/ContainerRing.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/ContainerRing.qll
@@ -11,23 +11,23 @@ module ContainerRing {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Ring).Link(s *Ring) *Ring
+ // signature: func (*Ring) Link(s *Ring) *Ring
hasQualifiedName("container/ring", "Ring", "Link") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Ring).Move(n int) *Ring
+ // signature: func (*Ring) Move(n int) *Ring
hasQualifiedName("container/ring", "Ring", "Move") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Ring).Next() *Ring
+ // signature: func (*Ring) Next() *Ring
hasQualifiedName("container/ring", "Ring", "Next") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Ring).Prev() *Ring
+ // signature: func (*Ring) Prev() *Ring
hasQualifiedName("container/ring", "Ring", "Prev") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Ring).Unlink(n int) *Ring
+ // signature: func (*Ring) Unlink(n int) *Ring
hasQualifiedName("container/ring", "Ring", "Unlink") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Context.qll b/ql/src/semmle/go/frameworks/stdlib/Context.qll
index d8e7a133726..d65aa5c68dd 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Context.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Context.qll
@@ -46,7 +46,7 @@ module Context {
FunctionOutput outp;
MethodModels() {
- // signature: func (Context).Value(key interface{}) interface{}
+ // signature: func (Context) Value(key interface{}) interface{}
implements(packagePath(), "Context", "Value") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Crypto.qll b/ql/src/semmle/go/frameworks/stdlib/Crypto.qll
index bf9e32086b2..f1517304f7c 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Crypto.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Crypto.qll
@@ -11,7 +11,7 @@ module Crypto {
FunctionOutput outp;
MethodModels() {
- // signature: func (Decrypter).Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error)
+ // signature: func (Decrypter) Decrypt(rand io.Reader, msg []byte, opts DecrypterOpts) (plaintext []byte, err error)
implements("crypto", "Decrypter", "Decrypt") and
(inp.isParameter(1) and outp.isResult(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/CryptoCipher.qll b/ql/src/semmle/go/frameworks/stdlib/CryptoCipher.qll
index 8575afd3adb..a4817fe03b0 100644
--- a/ql/src/semmle/go/frameworks/stdlib/CryptoCipher.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/CryptoCipher.qll
@@ -11,11 +11,11 @@ module CryptoCipher {
FunctionOutput outp;
MethodModels() {
- // signature: func (Block).Decrypt(dst []byte, src []byte)
+ // signature: func (Block) Decrypt(dst []byte, src []byte)
implements("crypto/cipher", "Block", "Decrypt") and
(inp.isParameter(1) and outp.isParameter(0))
or
- // signature: func (AEAD).Open(dst []byte, nonce []byte, ciphertext []byte, additionalData []byte) ([]byte, error)
+ // signature: func (AEAD) Open(dst []byte, nonce []byte, ciphertext []byte, additionalData []byte) ([]byte, error)
implements("crypto/cipher", "AEAD", "Open") and
(
inp.isParameter(2) and
diff --git a/ql/src/semmle/go/frameworks/stdlib/CryptoRsa.qll b/ql/src/semmle/go/frameworks/stdlib/CryptoRsa.qll
index d43fd282baf..6b48847d6bf 100644
--- a/ql/src/semmle/go/frameworks/stdlib/CryptoRsa.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/CryptoRsa.qll
@@ -30,7 +30,7 @@ module CryptoRsa {
FunctionOutput outp;
MethodModels() {
- // signature: func (*PrivateKey).Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error)
+ // signature: func (*PrivateKey) Decrypt(rand io.Reader, ciphertext []byte, opts crypto.DecrypterOpts) (plaintext []byte, err error)
hasQualifiedName("crypto/rsa", "PrivateKey", "Decrypt") and
(inp.isParameter(1) and outp.isResult(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/DatabaseSql.qll b/ql/src/semmle/go/frameworks/stdlib/DatabaseSql.qll
index 85cf5adeeaf..fa6bf309fa7 100644
--- a/ql/src/semmle/go/frameworks/stdlib/DatabaseSql.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/DatabaseSql.qll
@@ -128,15 +128,15 @@ module DatabaseSql {
FunctionOutput outp;
SqlMethodModels() {
- // signature: func (*Row).Scan(dest ...interface{}) error
+ // signature: func (*Row) Scan(dest ...interface{}) error
this.hasQualifiedName("database/sql", "Row", "Scan") and
(inp.isReceiver() and outp.isParameter(_))
or
- // signature: func (*Rows).Scan(dest ...interface{}) error
+ // signature: func (*Rows) Scan(dest ...interface{}) error
this.hasQualifiedName("database/sql", "Rows", "Scan") and
(inp.isReceiver() and outp.isParameter(_))
or
- // signature: func (Scanner).Scan(src interface{}) error
+ // signature: func (Scanner) Scan(src interface{}) error
this.implements("database/sql", "Scanner", "Scan") and
(inp.isParameter(0) and outp.isReceiver())
or
@@ -159,27 +159,27 @@ module DatabaseSql {
FunctionOutput outp;
SqlDriverMethodModels() {
- // signature: func (NotNull).ConvertValue(v interface{}) (Value, error)
+ // signature: func (NotNull) ConvertValue(v interface{}) (Value, error)
this.hasQualifiedName("database/sql/driver", "NotNull", "ConvertValue") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (Null).ConvertValue(v interface{}) (Value, error)
+ // signature: func (Null) ConvertValue(v interface{}) (Value, error)
this.hasQualifiedName("database/sql/driver", "Null", "ConvertValue") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (ValueConverter).ConvertValue(v interface{}) (Value, error)
+ // signature: func (ValueConverter) ConvertValue(v interface{}) (Value, error)
this.implements("database/sql/driver", "ValueConverter", "ConvertValue") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (Conn).Prepare(query string) (Stmt, error)
+ // signature: func (Conn) Prepare(query string) (Stmt, error)
this.implements("database/sql/driver", "Conn", "Prepare") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (ConnPrepareContext).PrepareContext(ctx context.Context, query string) (Stmt, error)
+ // signature: func (ConnPrepareContext) PrepareContext(ctx context.Context, query string) (Stmt, error)
this.implements("database/sql/driver", "ConnPrepareContext", "PrepareContext") and
(inp.isParameter(1) and outp.isResult(0))
or
- // signature: func (Valuer).Value() (Value, error)
+ // signature: func (Valuer) Value() (Value, error)
this.implements("database/sql/driver", "Valuer", "Value") and
(inp.isReceiver() and outp.isResult(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Encoding.qll b/ql/src/semmle/go/frameworks/stdlib/Encoding.qll
index 732434489d1..767d2d64cd8 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Encoding.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Encoding.qll
@@ -11,19 +11,19 @@ module Encoding {
FunctionOutput outp;
MethodModels() {
- // signature: func (BinaryMarshaler).MarshalBinary() (data []byte, err error)
+ // signature: func (BinaryMarshaler) MarshalBinary() (data []byte, err error)
implements("encoding", "BinaryMarshaler", "MarshalBinary") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (TextMarshaler).MarshalText() (text []byte, err error)
+ // signature: func (TextMarshaler) MarshalText() (text []byte, err error)
implements("encoding", "TextMarshaler", "MarshalText") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (BinaryUnmarshaler).UnmarshalBinary(data []byte) error
+ // signature: func (BinaryUnmarshaler) UnmarshalBinary(data []byte) error
implements("encoding", "BinaryUnmarshaler", "UnmarshalBinary") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (TextUnmarshaler).UnmarshalText(text []byte) error
+ // signature: func (TextUnmarshaler) UnmarshalText(text []byte) error
implements("encoding", "TextUnmarshaler", "UnmarshalText") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/EncodingBase32.qll b/ql/src/semmle/go/frameworks/stdlib/EncodingBase32.qll
index 2d9dd67ec11..d1eae83abc2 100644
--- a/ql/src/semmle/go/frameworks/stdlib/EncodingBase32.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/EncodingBase32.qll
@@ -26,11 +26,11 @@ module EncodingBase32 {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Encoding).Decode(dst []byte, src []byte) (n int, err error)
+ // signature: func (*Encoding) Decode(dst []byte, src []byte) (n int, err error)
hasQualifiedName("encoding/base32", "Encoding", "Decode") and
(inp.isParameter(1) and outp.isParameter(0))
or
- // signature: func (*Encoding).DecodeString(s string) ([]byte, error)
+ // signature: func (*Encoding) DecodeString(s string) ([]byte, error)
hasQualifiedName("encoding/base32", "Encoding", "DecodeString") and
(inp.isParameter(0) and outp.isResult(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/EncodingBase64.qll b/ql/src/semmle/go/frameworks/stdlib/EncodingBase64.qll
index a70a4afe648..82a68b5d0c2 100644
--- a/ql/src/semmle/go/frameworks/stdlib/EncodingBase64.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/EncodingBase64.qll
@@ -26,11 +26,11 @@ module EncodingBase64 {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Encoding).Decode(dst []byte, src []byte) (n int, err error)
+ // signature: func (*Encoding) Decode(dst []byte, src []byte) (n int, err error)
hasQualifiedName("encoding/base64", "Encoding", "Decode") and
(inp.isParameter(1) and outp.isParameter(0))
or
- // signature: func (*Encoding).DecodeString(s string) ([]byte, error)
+ // signature: func (*Encoding) DecodeString(s string) ([]byte, error)
hasQualifiedName("encoding/base64", "Encoding", "DecodeString") and
(inp.isParameter(0) and outp.isResult(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/EncodingCsv.qll b/ql/src/semmle/go/frameworks/stdlib/EncodingCsv.qll
index f5c0d32e2bb..481dce5a5fd 100644
--- a/ql/src/semmle/go/frameworks/stdlib/EncodingCsv.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/EncodingCsv.qll
@@ -30,19 +30,19 @@ module EncodingCsv {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Reader).Read() (record []string, err error)
+ // signature: func (*Reader) Read() (record []string, err error)
hasQualifiedName("encoding/csv", "Reader", "Read") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadAll() (records [][]string, err error)
+ // signature: func (*Reader) ReadAll() (records [][]string, err error)
hasQualifiedName("encoding/csv", "Reader", "ReadAll") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Writer).Write(record []string) error
+ // signature: func (*Writer) Write(record []string) error
hasQualifiedName("encoding/csv", "Writer", "Write") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Writer).WriteAll(records [][]string) error
+ // signature: func (*Writer) WriteAll(records [][]string) error
hasQualifiedName("encoding/csv", "Writer", "WriteAll") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/EncodingGob.qll b/ql/src/semmle/go/frameworks/stdlib/EncodingGob.qll
index 98958be76db..19f7c1c6004 100644
--- a/ql/src/semmle/go/frameworks/stdlib/EncodingGob.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/EncodingGob.qll
@@ -30,27 +30,27 @@ module EncodingGob {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Decoder).Decode(e interface{}) error
+ // signature: func (*Decoder) Decode(e interface{}) error
hasQualifiedName("encoding/gob", "Decoder", "Decode") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Decoder).DecodeValue(v reflect.Value) error
+ // signature: func (*Decoder) DecodeValue(v reflect.Value) error
hasQualifiedName("encoding/gob", "Decoder", "DecodeValue") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Encoder).Encode(e interface{}) error
+ // signature: func (*Encoder) Encode(e interface{}) error
hasQualifiedName("encoding/gob", "Encoder", "Encode") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Encoder).EncodeValue(value reflect.Value) error
+ // signature: func (*Encoder) EncodeValue(value reflect.Value) error
hasQualifiedName("encoding/gob", "Encoder", "EncodeValue") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (GobDecoder).GobDecode([]byte) error
+ // signature: func (GobDecoder) GobDecode([]byte) error
implements("encoding/gob", "GobDecoder", "GobDecode") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (GobEncoder).GobEncode() ([]byte, error)
+ // signature: func (GobEncoder) GobEncode() ([]byte, error)
implements("encoding/gob", "GobEncoder", "GobEncode") and
(inp.isReceiver() and outp.isResult(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/EncodingJson.qll b/ql/src/semmle/go/frameworks/stdlib/EncodingJson.qll
index d05cc73c25f..6d58176d85a 100644
--- a/ql/src/semmle/go/frameworks/stdlib/EncodingJson.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/EncodingJson.qll
@@ -81,31 +81,31 @@ module EncodingJson {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Decoder).Buffered() io.Reader
+ // signature: func (*Decoder) Buffered() io.Reader
hasQualifiedName("encoding/json", "Decoder", "Buffered") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Decoder).Decode(v interface{}) error
+ // signature: func (*Decoder) Decode(v interface{}) error
hasQualifiedName("encoding/json", "Decoder", "Decode") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Decoder).Token() (Token, error)
+ // signature: func (*Decoder) Token() (Token, error)
hasQualifiedName("encoding/json", "Decoder", "Token") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Encoder).Encode(v interface{}) error
+ // signature: func (*Encoder) Encode(v interface{}) error
hasQualifiedName("encoding/json", "Encoder", "Encode") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Encoder).SetIndent(prefix string, indent string)
+ // signature: func (*Encoder) SetIndent(prefix string, indent string)
hasQualifiedName("encoding/json", "Encoder", "SetIndent") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (Marshaler).MarshalJSON() ([]byte, error)
+ // signature: func (Marshaler) MarshalJSON() ([]byte, error)
implements("encoding/json", "Marshaler", "MarshalJSON") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (Unmarshaler).UnmarshalJSON([]byte) error
+ // signature: func (Unmarshaler) UnmarshalJSON([]byte) error
implements("encoding/json", "Unmarshaler", "UnmarshalJSON") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/EncodingXml.qll b/ql/src/semmle/go/frameworks/stdlib/EncodingXml.qll
index 84ddecdd498..14d2e63e961 100644
--- a/ql/src/semmle/go/frameworks/stdlib/EncodingXml.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/EncodingXml.qll
@@ -82,67 +82,67 @@ module EncodingXml {
FunctionOutput outp;
MethodModels() {
- // signature: func (CharData).Copy() CharData
+ // signature: func (CharData) Copy() CharData
hasQualifiedName("encoding/xml", "CharData", "Copy") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Comment).Copy() Comment
+ // signature: func (Comment) Copy() Comment
hasQualifiedName("encoding/xml", "Comment", "Copy") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Decoder).Decode(v interface{}) error
+ // signature: func (*Decoder) Decode(v interface{}) error
hasQualifiedName("encoding/xml", "Decoder", "Decode") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Decoder).DecodeElement(v interface{}, start *StartElement) error
+ // signature: func (*Decoder) DecodeElement(v interface{}, start *StartElement) error
hasQualifiedName("encoding/xml", "Decoder", "DecodeElement") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Decoder).RawToken() (Token, error)
+ // signature: func (*Decoder) RawToken() (Token, error)
hasQualifiedName("encoding/xml", "Decoder", "RawToken") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Decoder).Token() (Token, error)
+ // signature: func (*Decoder) Token() (Token, error)
hasQualifiedName("encoding/xml", "Decoder", "Token") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (Directive).Copy() Directive
+ // signature: func (Directive) Copy() Directive
hasQualifiedName("encoding/xml", "Directive", "Copy") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Encoder).Encode(v interface{}) error
+ // signature: func (*Encoder) Encode(v interface{}) error
hasQualifiedName("encoding/xml", "Encoder", "Encode") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Encoder).EncodeElement(v interface{}, start StartElement) error
+ // signature: func (*Encoder) EncodeElement(v interface{}, start StartElement) error
hasQualifiedName("encoding/xml", "Encoder", "EncodeElement") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Encoder).EncodeToken(t Token) error
+ // signature: func (*Encoder) EncodeToken(t Token) error
hasQualifiedName("encoding/xml", "Encoder", "EncodeToken") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Encoder).Indent(prefix string, indent string)
+ // signature: func (*Encoder) Indent(prefix string, indent string)
hasQualifiedName("encoding/xml", "Encoder", "Indent") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (ProcInst).Copy() ProcInst
+ // signature: func (ProcInst) Copy() ProcInst
hasQualifiedName("encoding/xml", "ProcInst", "Copy") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (StartElement).Copy() StartElement
+ // signature: func (StartElement) Copy() StartElement
hasQualifiedName("encoding/xml", "StartElement", "Copy") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Marshaler).MarshalXML(e *Encoder, start StartElement) error
+ // signature: func (Marshaler) MarshalXML(e *Encoder, start StartElement) error
this.implements("encoding/xml", "Marshaler", "MarshalXML") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (TokenReader).Token() (Token, error)
+ // signature: func (TokenReader) Token() (Token, error)
this.implements("encoding/xml", "TokenReader", "Token") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (Unmarshaler).UnmarshalXML(d *Decoder, start StartElement) error
+ // signature: func (Unmarshaler) UnmarshalXML(d *Decoder, start StartElement) error
this.implements("encoding/xml", "Unmarshaler", "UnmarshalXML") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Expvar.qll b/ql/src/semmle/go/frameworks/stdlib/Expvar.qll
index 1132a4f2350..01fbda900f4 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Expvar.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Expvar.qll
@@ -11,27 +11,27 @@ module Expvar {
FunctionOutput outp;
MethodModels() {
- // signature: func (Func).Value() interface{}
+ // signature: func (Func) Value() interface{}
hasQualifiedName("expvar", "Func", "Value") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Map).Get(key string) Var
+ // signature: func (*Map) Get(key string) Var
hasQualifiedName("expvar", "Map", "Get") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Map).Set(key string, av Var)
+ // signature: func (*Map) Set(key string, av Var)
hasQualifiedName("expvar", "Map", "Set") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*String).Set(value string)
+ // signature: func (*String) Set(value string)
hasQualifiedName("expvar", "String", "Set") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*String).Value() string
+ // signature: func (*String) Value() string
hasQualifiedName("expvar", "String", "Value") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Var).String() string
+ // signature: func (Var) String() string
implements("expvar", "Var", "String") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Fmt.qll b/ql/src/semmle/go/frameworks/stdlib/Fmt.qll
index f3151c579d3..41a833c122a 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Fmt.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Fmt.qll
@@ -137,23 +137,23 @@ module Fmt {
FunctionOutput outp;
MethodModels() {
- // signature: func (GoStringer).GoString() string
+ // signature: func (GoStringer) GoString() string
implements("fmt", "GoStringer", "GoString") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (ScanState).Read(buf []byte) (n int, err error)
+ // signature: func (ScanState) Read(buf []byte) (n int, err error)
implements("fmt", "ScanState", "Read") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (Stringer).String() string
+ // signature: func (Stringer) String() string
implements("fmt", "Stringer", "String") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (ScanState).Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
+ // signature: func (ScanState) Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
implements("fmt", "ScanState", "Token") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (State).Write(b []byte) (n int, err error)
+ // signature: func (State) Write(b []byte) (n int, err error)
this.implements("fmt", "State", "Write") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/HtmlTemplate.qll b/ql/src/semmle/go/frameworks/stdlib/HtmlTemplate.qll
index 45a7532afdb..54f3b959593 100644
--- a/ql/src/semmle/go/frameworks/stdlib/HtmlTemplate.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/HtmlTemplate.qll
@@ -68,11 +68,11 @@ module HtmlTemplate {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Template).Execute(wr io.Writer, data interface{}) error
+ // signature: func (*Template) Execute(wr io.Writer, data interface{}) error
hasQualifiedName("html/template", "Template", "Execute") and
(inp.isParameter(1) and outp.isParameter(0))
or
- // signature: func (*Template).ExecuteTemplate(wr io.Writer, name string, data interface{}) error
+ // signature: func (*Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error
hasQualifiedName("html/template", "Template", "ExecuteTemplate") and
(inp.isParameter(2) and outp.isParameter(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Io.qll b/ql/src/semmle/go/frameworks/stdlib/Io.qll
index 968f45dfe9b..ffd95a660e0 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Io.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Io.qll
@@ -81,31 +81,31 @@ module Io {
FunctionOutput outp;
MethodModels() {
- // signature: func (Reader).Read(p []byte) (n int, err error)
+ // signature: func (Reader) Read(p []byte) (n int, err error)
implements("io", "Reader", "Read") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (ReaderAt).ReadAt(p []byte, off int64) (n int, err error)
+ // signature: func (ReaderAt) ReadAt(p []byte, off int64) (n int, err error)
implements("io", "ReaderAt", "ReadAt") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (ReaderFrom).ReadFrom(r Reader) (n int64, err error)
+ // signature: func (ReaderFrom) ReadFrom(r Reader) (n int64, err error)
implements("io", "ReaderFrom", "ReadFrom") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Writer).Write(p []byte) (n int, err error)
+ // signature: func (Writer) Write(p []byte) (n int, err error)
implements("io", "Writer", "Write") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (WriterAt).WriteAt(p []byte, off int64) (n int, err error)
+ // signature: func (WriterAt) WriteAt(p []byte, off int64) (n int, err error)
implements("io", "WriterAt", "WriteAt") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (StringWriter).WriteString(s string) (n int, err error)
+ // signature: func (StringWriter) WriteString(s string) (n int, err error)
implements("io", "StringWriter", "WriteString") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (WriterTo).WriteTo(w Writer) (n int64, err error)
+ // signature: func (WriterTo) WriteTo(w Writer) (n int64, err error)
implements("io", "WriterTo", "WriteTo") and
(inp.isReceiver() and outp.isParameter(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/IoFs.qll b/ql/src/semmle/go/frameworks/stdlib/IoFs.qll
index 310d6da5749..ea6f1be33b0 100644
--- a/ql/src/semmle/go/frameworks/stdlib/IoFs.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/IoFs.qll
@@ -16,6 +16,10 @@ module IoFs {
FunctionOutput outp;
FunctionModels() {
+ //signature: func FileInfoToDirEntry(info FileInfo) DirEntry
+ this.hasQualifiedName(packagePath(), "FileInfoToDirEntry") and
+ (inp.isParameter(0) and outp.isResult())
+ or
//signature: func Glob(fsys FS, pattern string) (matches []string, err error)
this.hasQualifiedName(packagePath(), "Glob") and
(inp.isParameter(0) and outp.isResult(0))
@@ -60,35 +64,35 @@ module IoFs {
FunctionOutput outp;
MethodModels() {
- //signature: func (DirEntry).Name() string
+ //signature: func (DirEntry) Name() string
this.implements(packagePath(), "DirEntry", "Name") and
(inp.isReceiver() and outp.isResult())
or
- //signature: func (DirEntry).Info() (FileInfo, error)
+ //signature: func (DirEntry) Info() (FileInfo, error)
this.implements(packagePath(), "DirEntry", "Info") and
(inp.isReceiver() and outp.isResult(0))
or
- //signature: func (FS).Open(name string) (File, error)
+ //signature: func (FS) Open(name string) (File, error)
this.implements(packagePath(), "FS", "Open") and
(inp.isReceiver() and outp.isResult(0))
or
- //signature: func (GlobFS).Glob(pattern string) ([]string, error)
+ //signature: func (GlobFS) Glob(pattern string) ([]string, error)
this.implements(packagePath(), "GlobFS", "Glob") and
(inp.isReceiver() and outp.isResult(0))
or
- //signature: func (ReadDirFS).ReadDir(name string) ([]DirEntry, error)
+ //signature: func (ReadDirFS) ReadDir(name string) ([]DirEntry, error)
this.implements(packagePath(), "ReadDirFS", "ReadDir") and
(inp.isReceiver() and outp.isResult(0))
or
- //signature: func (ReadFileFS).ReadFile(name string) ([]byte, error)
+ //signature: func (ReadFileFS) ReadFile(name string) ([]byte, error)
this.implements(packagePath(), "ReadFileFS", "ReadFile") and
(inp.isReceiver() and outp.isResult(0))
or
- //signature: func (SubFS).Sub(dir string) (FS, error)
+ //signature: func (SubFS) Sub(dir string) (FS, error)
this.implements(packagePath(), "SubFS", "Sub") and
(inp.isReceiver() and outp.isResult(0))
or
- //signature: func (File).Read([]byte) (int, error)
+ //signature: func (File) Read([]byte) (int, error)
this.implements(packagePath(), "File", "Read") and
(inp.isReceiver() and outp.isParameter(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Log.qll b/ql/src/semmle/go/frameworks/stdlib/Log.qll
index f6b2dcfbd03..9d4c677be50 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Log.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Log.qll
@@ -51,51 +51,51 @@ module Log {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Logger).Fatal(v ...interface{})
+ // signature: func (*Logger) Fatal(v ...interface{})
hasQualifiedName("log", "Logger", "Fatal") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Fatalf(format string, v ...interface{})
+ // signature: func (*Logger) Fatalf(format string, v ...interface{})
hasQualifiedName("log", "Logger", "Fatalf") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Fatalln(v ...interface{})
+ // signature: func (*Logger) Fatalln(v ...interface{})
hasQualifiedName("log", "Logger", "Fatalln") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Panic(v ...interface{})
+ // signature: func (*Logger) Panic(v ...interface{})
hasQualifiedName("log", "Logger", "Panic") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Panicf(format string, v ...interface{})
+ // signature: func (*Logger) Panicf(format string, v ...interface{})
hasQualifiedName("log", "Logger", "Panicf") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Panicln(v ...interface{})
+ // signature: func (*Logger) Panicln(v ...interface{})
hasQualifiedName("log", "Logger", "Panicln") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Print(v ...interface{})
+ // signature: func (*Logger) Print(v ...interface{})
hasQualifiedName("log", "Logger", "Print") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Printf(format string, v ...interface{})
+ // signature: func (*Logger) Printf(format string, v ...interface{})
hasQualifiedName("log", "Logger", "Printf") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).Println(v ...interface{})
+ // signature: func (*Logger) Println(v ...interface{})
hasQualifiedName("log", "Logger", "Println") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Logger).SetOutput(w io.Writer)
+ // signature: func (*Logger) SetOutput(w io.Writer)
hasQualifiedName("log", "Logger", "SetOutput") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Logger).SetPrefix(prefix string)
+ // signature: func (*Logger) SetPrefix(prefix string)
hasQualifiedName("log", "Logger", "SetPrefix") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Logger).Writer() io.Writer
+ // signature: func (*Logger) Writer() io.Writer
hasQualifiedName("log", "Logger", "Writer") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Mime.qll b/ql/src/semmle/go/frameworks/stdlib/Mime.qll
index 34117d0f1ec..b04acdf4e6f 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Mime.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Mime.qll
@@ -30,15 +30,15 @@ module Mime {
FunctionOutput outp;
MethodModels() {
- // signature: func (*WordDecoder).Decode(word string) (string, error)
+ // signature: func (*WordDecoder) Decode(word string) (string, error)
hasQualifiedName("mime", "WordDecoder", "Decode") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (*WordDecoder).DecodeHeader(header string) (string, error)
+ // signature: func (*WordDecoder) DecodeHeader(header string) (string, error)
hasQualifiedName("mime", "WordDecoder", "DecodeHeader") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (WordEncoder).Encode(charset string, s string) string
+ // signature: func (WordEncoder) Encode(charset string, s string) string
hasQualifiedName("mime", "WordEncoder", "Encode") and
(inp.isParameter(1) and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/MimeMultipart.qll b/ql/src/semmle/go/frameworks/stdlib/MimeMultipart.qll
index 9de15b824be..3f384b29454 100644
--- a/ql/src/semmle/go/frameworks/stdlib/MimeMultipart.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/MimeMultipart.qll
@@ -30,43 +30,43 @@ module MimeMultipart {
FunctionOutput outp;
MethodModels() {
- // signature: func (*FileHeader).Open() (File, error)
+ // signature: func (*FileHeader) Open() (File, error)
hasQualifiedName("mime/multipart", "FileHeader", "Open") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Part).FileName() string
+ // signature: func (*Part) FileName() string
hasQualifiedName("mime/multipart", "Part", "FileName") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Part).FormName() string
+ // signature: func (*Part) FormName() string
hasQualifiedName("mime/multipart", "Part", "FormName") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).NextPart() (*Part, error)
+ // signature: func (*Reader) NextPart() (*Part, error)
hasQualifiedName("mime/multipart", "Reader", "NextPart") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).NextRawPart() (*Part, error)
+ // signature: func (*Reader) NextRawPart() (*Part, error)
hasQualifiedName("mime/multipart", "Reader", "NextRawPart") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadForm(maxMemory int64) (*Form, error)
+ // signature: func (*Reader) ReadForm(maxMemory int64) (*Form, error)
hasQualifiedName("mime/multipart", "Reader", "ReadForm") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Writer).CreateFormField(fieldname string) (io.Writer, error)
+ // signature: func (*Writer) CreateFormField(fieldname string) (io.Writer, error)
hasQualifiedName("mime/multipart", "Writer", "CreateFormField") and
(inp.isResult(0) and outp.isReceiver())
or
- // signature: func (*Writer).CreateFormFile(fieldname string, filename string) (io.Writer, error)
+ // signature: func (*Writer) CreateFormFile(fieldname string, filename string) (io.Writer, error)
hasQualifiedName("mime/multipart", "Writer", "CreateFormFile") and
(inp.isResult(0) and outp.isReceiver())
or
- // signature: func (*Writer).CreatePart(header net/textproto.MIMEHeader) (io.Writer, error)
+ // signature: func (*Writer) CreatePart(header net/textproto.MIMEHeader) (io.Writer, error)
hasQualifiedName("mime/multipart", "Writer", "CreatePart") and
(inp.isResult(0) and outp.isReceiver())
or
- // signature: func (*Writer).WriteField(fieldname string, value string) error
+ // signature: func (*Writer) WriteField(fieldname string, value string) error
hasQualifiedName("mime/multipart", "Writer", "WriteField") and
(inp.isParameter(_) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Net.qll b/ql/src/semmle/go/frameworks/stdlib/Net.qll
index 0efc51218e2..96cf161ade6 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Net.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Net.qll
@@ -54,15 +54,15 @@ module Net {
FunctionOutput outp;
MethodModels() {
- // signature: func (*IPConn).ReadFromIP(b []byte) (int, *IPAddr, error)
+ // signature: func (*IPConn) ReadFromIP(b []byte) (int, *IPAddr, error)
hasQualifiedName("net", "IPConn", "ReadFromIP") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*IPConn).ReadMsgIP(b []byte, oob []byte) (n int, oobn int, flags int, addr *IPAddr, err error)
+ // signature: func (*IPConn) ReadMsgIP(b []byte, oob []byte) (n int, oobn int, flags int, addr *IPAddr, err error)
hasQualifiedName("net", "IPConn", "ReadMsgIP") and
(inp.isReceiver() and outp.isParameter(_))
or
- // signature: func (*IPConn).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*IPConn) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("net", "IPConn", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -70,15 +70,15 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*IPConn).WriteMsgIP(b []byte, oob []byte, addr *IPAddr) (n int, oobn int, err error)
+ // signature: func (*IPConn) WriteMsgIP(b []byte, oob []byte, addr *IPAddr) (n int, oobn int, err error)
hasQualifiedName("net", "IPConn", "WriteMsgIP") and
(inp.isParameter([0, 1]) and outp.isReceiver())
or
- // signature: func (*IPConn).WriteToIP(b []byte, addr *IPAddr) (int, error)
+ // signature: func (*IPConn) WriteToIP(b []byte, addr *IPAddr) (int, error)
hasQualifiedName("net", "IPConn", "WriteToIP") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*TCPConn).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*TCPConn) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("net", "TCPConn", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -86,7 +86,7 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*TCPListener).File() (f *os.File, err error)
+ // signature: func (*TCPListener) File() (f *os.File, err error)
hasQualifiedName("net", "TCPListener", "File") and
(
inp.isReceiver() and outp.isResult(0)
@@ -94,7 +94,7 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*TCPListener).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*TCPListener) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("net", "TCPListener", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -102,15 +102,15 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*UDPConn).ReadFromUDP(b []byte) (int, *UDPAddr, error)
+ // signature: func (*UDPConn) ReadFromUDP(b []byte) (int, *UDPAddr, error)
hasQualifiedName("net", "UDPConn", "ReadFromUDP") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*UDPConn).ReadMsgUDP(b []byte, oob []byte) (n int, oobn int, flags int, addr *UDPAddr, err error)
+ // signature: func (*UDPConn) ReadMsgUDP(b []byte, oob []byte) (n int, oobn int, flags int, addr *UDPAddr, err error)
hasQualifiedName("net", "UDPConn", "ReadMsgUDP") and
(inp.isReceiver() and outp.isParameter(_))
or
- // signature: func (*UDPConn).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*UDPConn) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("net", "UDPConn", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -118,23 +118,23 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*UDPConn).WriteMsgUDP(b []byte, oob []byte, addr *UDPAddr) (n int, oobn int, err error)
+ // signature: func (*UDPConn) WriteMsgUDP(b []byte, oob []byte, addr *UDPAddr) (n int, oobn int, err error)
hasQualifiedName("net", "UDPConn", "WriteMsgUDP") and
(inp.isParameter([0, 1]) and outp.isReceiver())
or
- // signature: func (*UDPConn).WriteToUDP(b []byte, addr *UDPAddr) (int, error)
+ // signature: func (*UDPConn) WriteToUDP(b []byte, addr *UDPAddr) (int, error)
hasQualifiedName("net", "UDPConn", "WriteToUDP") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*UnixConn).ReadFromUnix(b []byte) (int, *UnixAddr, error)
+ // signature: func (*UnixConn) ReadFromUnix(b []byte) (int, *UnixAddr, error)
hasQualifiedName("net", "UnixConn", "ReadFromUnix") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*UnixConn).ReadMsgUnix(b []byte, oob []byte) (n int, oobn int, flags int, addr *UnixAddr, err error)
+ // signature: func (*UnixConn) ReadMsgUnix(b []byte, oob []byte) (n int, oobn int, flags int, addr *UnixAddr, err error)
hasQualifiedName("net", "UnixConn", "ReadMsgUnix") and
(inp.isReceiver() and outp.isParameter(_))
or
- // signature: func (*UnixConn).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*UnixConn) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("net", "UnixConn", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -142,15 +142,15 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*UnixConn).WriteMsgUnix(b []byte, oob []byte, addr *UnixAddr) (n int, oobn int, err error)
+ // signature: func (*UnixConn) WriteMsgUnix(b []byte, oob []byte, addr *UnixAddr) (n int, oobn int, err error)
hasQualifiedName("net", "UnixConn", "WriteMsgUnix") and
(inp.isParameter([0, 1]) and outp.isReceiver())
or
- // signature: func (*UnixConn).WriteToUnix(b []byte, addr *UnixAddr) (int, error)
+ // signature: func (*UnixConn) WriteToUnix(b []byte, addr *UnixAddr) (int, error)
hasQualifiedName("net", "UnixConn", "WriteToUnix") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*UnixListener).File() (f *os.File, err error)
+ // signature: func (*UnixListener) File() (f *os.File, err error)
hasQualifiedName("net", "UnixListener", "File") and
(
inp.isReceiver() and outp.isResult(0)
@@ -158,7 +158,7 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*UnixListener).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*UnixListener) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("net", "UnixListener", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -166,23 +166,23 @@ module Net {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (Conn).Read(b []byte) (n int, err error)
+ // signature: func (Conn) Read(b []byte) (n int, err error)
implements("net", "Conn", "Read") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (PacketConn).ReadFrom(p []byte) (n int, addr Addr, err error)
+ // signature: func (PacketConn) ReadFrom(p []byte) (n int, addr Addr, err error)
implements("net", "PacketConn", "ReadFrom") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (Addr).String() string
+ // signature: func (Addr) String() string
implements("net", "Addr", "String") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Conn).Write(b []byte) (n int, err error)
+ // signature: func (Conn) Write(b []byte) (n int, err error)
implements("net", "Conn", "Write") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (PacketConn).WriteTo(p []byte, addr Addr) (n int, err error)
+ // signature: func (PacketConn) WriteTo(p []byte, addr Addr) (n int, err error)
implements("net", "PacketConn", "WriteTo") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/NetHttp.qll b/ql/src/semmle/go/frameworks/stdlib/NetHttp.qll
index cb38284d116..23549f2fd4e 100644
--- a/ql/src/semmle/go/frameworks/stdlib/NetHttp.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/NetHttp.qll
@@ -326,63 +326,63 @@ module NetHttp {
FunctionOutput outp;
MethodModels() {
- // signature: func (Header).Add(key string, value string)
+ // signature: func (Header) Add(key string, value string)
hasQualifiedName("net/http", "Header", "Add") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (Header).Clone() Header
+ // signature: func (Header) Clone() Header
hasQualifiedName("net/http", "Header", "Clone") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Header).Get(key string) string
+ // signature: func (Header) Get(key string) string
hasQualifiedName("net/http", "Header", "Get") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Header).Set(key string, value string)
+ // signature: func (Header) Set(key string, value string)
hasQualifiedName("net/http", "Header", "Set") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (Header).Values(key string) []string
+ // signature: func (Header) Values(key string) []string
hasQualifiedName("net/http", "Header", "Values") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Header).Write(w io.Writer) error
+ // signature: func (Header) Write(w io.Writer) error
hasQualifiedName("net/http", "Header", "Write") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (Header).WriteSubset(w io.Writer, exclude map[string]bool) error
+ // signature: func (Header) WriteSubset(w io.Writer, exclude map[string]bool) error
hasQualifiedName("net/http", "Header", "WriteSubset") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Request).AddCookie(c *Cookie)
+ // signature: func (*Request) AddCookie(c *Cookie)
hasQualifiedName("net/http", "Request", "AddCookie") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Request).Clone(ctx context.Context) *Request
+ // signature: func (*Request) Clone(ctx context.Context) *Request
hasQualifiedName("net/http", "Request", "Clone") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Request).Write(w io.Writer) error
+ // signature: func (*Request) Write(w io.Writer) error
hasQualifiedName("net/http", "Request", "Write") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Request).WriteProxy(w io.Writer) error
+ // signature: func (*Request) WriteProxy(w io.Writer) error
hasQualifiedName("net/http", "Request", "WriteProxy") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Response).Write(w io.Writer) error
+ // signature: func (*Response) Write(w io.Writer) error
hasQualifiedName("net/http", "Response", "Write") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (*Transport).Clone() *Transport
+ // signature: func (*Transport) Clone() *Transport
hasQualifiedName("net/http", "Transport", "Clone") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Hijacker).Hijack() (net.Conn, *bufio.ReadWriter, error)
+ // signature: func (Hijacker) Hijack() (net.Conn, *bufio.ReadWriter, error)
implements("net/http", "Hijacker", "Hijack") and
(inp.isReceiver() and outp.isResult([0, 1]))
or
- // signature: func (ResponseWriter).Write([]byte) (int, error)
+ // signature: func (ResponseWriter) Write([]byte) (int, error)
implements("net/http", "ResponseWriter", "Write") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/NetHttpHttputil.qll b/ql/src/semmle/go/frameworks/stdlib/NetHttpHttputil.qll
index 116f9bdc9c5..aa7668d46b8 100644
--- a/ql/src/semmle/go/frameworks/stdlib/NetHttpHttputil.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/NetHttpHttputil.qll
@@ -58,7 +58,7 @@ module NetHttpHttputil {
FunctionOutput outp;
MethodModels() {
- // signature: func (*ClientConn).Hijack() (c net.Conn, r *bufio.Reader)
+ // signature: func (*ClientConn) Hijack() (c net.Conn, r *bufio.Reader)
hasQualifiedName("net/http/httputil", "ClientConn", "Hijack") and
(
inp.isReceiver() and outp.isResult(_)
@@ -66,7 +66,7 @@ module NetHttpHttputil {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (*ServerConn).Hijack() (net.Conn, *bufio.Reader)
+ // signature: func (*ServerConn) Hijack() (net.Conn, *bufio.Reader)
hasQualifiedName("net/http/httputil", "ServerConn", "Hijack") and
(
inp.isReceiver() and outp.isResult(_)
@@ -74,11 +74,11 @@ module NetHttpHttputil {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (BufferPool).Get() []byte
+ // signature: func (BufferPool) Get() []byte
implements("net/http/httputil", "BufferPool", "Get") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (BufferPool).Put([]byte)
+ // signature: func (BufferPool) Put([]byte)
implements("net/http/httputil", "BufferPool", "Put") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/NetMail.qll b/ql/src/semmle/go/frameworks/stdlib/NetMail.qll
index 3f9ce44e80a..20e94219752 100644
--- a/ql/src/semmle/go/frameworks/stdlib/NetMail.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/NetMail.qll
@@ -34,15 +34,15 @@ module NetMail {
FunctionOutput outp;
MethodModels() {
- // signature: func (*AddressParser).Parse(address string) (*Address, error)
+ // signature: func (*AddressParser) Parse(address string) (*Address, error)
hasQualifiedName("net/mail", "AddressParser", "Parse") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (*AddressParser).ParseList(list string) ([]*Address, error)
+ // signature: func (*AddressParser) ParseList(list string) ([]*Address, error)
hasQualifiedName("net/mail", "AddressParser", "ParseList") and
(inp.isParameter(0) and outp.isResult(0))
or
- // signature: func (Header).Get(key string) string
+ // signature: func (Header) Get(key string) string
hasQualifiedName("net/mail", "Header", "Get") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/NetTextproto.qll b/ql/src/semmle/go/frameworks/stdlib/NetTextproto.qll
index b31a57fb248..7704b5486f9 100644
--- a/ql/src/semmle/go/frameworks/stdlib/NetTextproto.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/NetTextproto.qll
@@ -50,67 +50,67 @@ module NetTextproto {
FunctionOutput outp;
MethodModels() {
- // signature: func (MIMEHeader).Add(key string, value string)
+ // signature: func (MIMEHeader) Add(key string, value string)
hasQualifiedName("net/textproto", "MIMEHeader", "Add") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (MIMEHeader).Get(key string) string
+ // signature: func (MIMEHeader) Get(key string) string
hasQualifiedName("net/textproto", "MIMEHeader", "Get") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (MIMEHeader).Set(key string, value string)
+ // signature: func (MIMEHeader) Set(key string, value string)
hasQualifiedName("net/textproto", "MIMEHeader", "Set") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (MIMEHeader).Values(key string) []string
+ // signature: func (MIMEHeader) Values(key string) []string
hasQualifiedName("net/textproto", "MIMEHeader", "Values") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Reader).DotReader() io.Reader
+ // signature: func (*Reader) DotReader() io.Reader
hasQualifiedName("net/textproto", "Reader", "DotReader") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Reader).ReadCodeLine(expectCode int) (code int, message string, err error)
+ // signature: func (*Reader) ReadCodeLine(expectCode int) (code int, message string, err error)
hasQualifiedName("net/textproto", "Reader", "ReadCodeLine") and
(inp.isReceiver() and outp.isResult(1))
or
- // signature: func (*Reader).ReadContinuedLine() (string, error)
+ // signature: func (*Reader) ReadContinuedLine() (string, error)
hasQualifiedName("net/textproto", "Reader", "ReadContinuedLine") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadContinuedLineBytes() ([]byte, error)
+ // signature: func (*Reader) ReadContinuedLineBytes() ([]byte, error)
hasQualifiedName("net/textproto", "Reader", "ReadContinuedLineBytes") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadDotBytes() ([]byte, error)
+ // signature: func (*Reader) ReadDotBytes() ([]byte, error)
hasQualifiedName("net/textproto", "Reader", "ReadDotBytes") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadDotLines() ([]string, error)
+ // signature: func (*Reader) ReadDotLines() ([]string, error)
hasQualifiedName("net/textproto", "Reader", "ReadDotLines") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadLine() (string, error)
+ // signature: func (*Reader) ReadLine() (string, error)
hasQualifiedName("net/textproto", "Reader", "ReadLine") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadLineBytes() ([]byte, error)
+ // signature: func (*Reader) ReadLineBytes() ([]byte, error)
hasQualifiedName("net/textproto", "Reader", "ReadLineBytes") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadMIMEHeader() (MIMEHeader, error)
+ // signature: func (*Reader) ReadMIMEHeader() (MIMEHeader, error)
hasQualifiedName("net/textproto", "Reader", "ReadMIMEHeader") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Reader).ReadResponse(expectCode int) (code int, message string, err error)
+ // signature: func (*Reader) ReadResponse(expectCode int) (code int, message string, err error)
hasQualifiedName("net/textproto", "Reader", "ReadResponse") and
(inp.isReceiver() and outp.isResult(1))
or
- // signature: func (*Writer).DotWriter() io.WriteCloser
+ // signature: func (*Writer) DotWriter() io.WriteCloser
hasQualifiedName("net/textproto", "Writer", "DotWriter") and
(inp.isResult() and outp.isReceiver())
or
- // signature: func (*Writer).PrintfLine(format string, args ...interface{}) error
+ // signature: func (*Writer) PrintfLine(format string, args ...interface{}) error
hasQualifiedName("net/textproto", "Writer", "PrintfLine") and
(inp.isParameter(_) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Os.qll b/ql/src/semmle/go/frameworks/stdlib/Os.qll
index a5b94f3a471..a022b416d9e 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Os.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Os.qll
@@ -110,11 +110,11 @@ module Os {
FunctionOutput outp;
MethodModels() {
- // signature: func (*File).Fd() uintptr
+ // signature: func (*File) Fd() uintptr
hasQualifiedName("os", "File", "Fd") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*File).SyscallConn() (syscall.RawConn, error)
+ // signature: func (*File) SyscallConn() (syscall.RawConn, error)
hasQualifiedName("os", "File", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
diff --git a/ql/src/semmle/go/frameworks/stdlib/Reflect.qll b/ql/src/semmle/go/frameworks/stdlib/Reflect.qll
index 46948a57148..150c3ae798e 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Reflect.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Reflect.qll
@@ -42,139 +42,139 @@ module Reflect {
FunctionOutput outp;
MethodModels() {
- // signature: func (*MapIter).Key() Value
+ // signature: func (*MapIter) Key() Value
hasQualifiedName("reflect", "MapIter", "Key") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*MapIter).Value() Value
+ // signature: func (*MapIter) Value() Value
hasQualifiedName("reflect", "MapIter", "Value") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (StructTag).Get(key string) string
+ // signature: func (StructTag) Get(key string) string
hasQualifiedName("reflect", "StructTag", "Get") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (StructTag).Lookup(key string) (value string, ok bool)
+ // signature: func (StructTag) Lookup(key string) (value string, ok bool)
hasQualifiedName("reflect", "StructTag", "Lookup") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (Value).Addr() Value
+ // signature: func (Value) Addr() Value
hasQualifiedName("reflect", "Value", "Addr") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Bytes() []byte
+ // signature: func (Value) Bytes() []byte
hasQualifiedName("reflect", "Value", "Bytes") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Convert(t Type) Value
+ // signature: func (Value) Convert(t Type) Value
hasQualifiedName("reflect", "Value", "Convert") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Elem() Value
+ // signature: func (Value) Elem() Value
hasQualifiedName("reflect", "Value", "Elem") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Field(i int) Value
+ // signature: func (Value) Field(i int) Value
hasQualifiedName("reflect", "Value", "Field") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).FieldByIndex(index []int) Value
+ // signature: func (Value) FieldByIndex(index []int) Value
hasQualifiedName("reflect", "Value", "FieldByIndex") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).FieldByName(name string) Value
+ // signature: func (Value) FieldByName(name string) Value
hasQualifiedName("reflect", "Value", "FieldByName") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).FieldByNameFunc(match func(string) bool) Value
+ // signature: func (Value) FieldByNameFunc(match func(string) bool) Value
hasQualifiedName("reflect", "Value", "FieldByNameFunc") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Index(i int) Value
+ // signature: func (Value) Index(i int) Value
hasQualifiedName("reflect", "Value", "Index") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Interface() (i interface{})
+ // signature: func (Value) Interface() (i interface{})
hasQualifiedName("reflect", "Value", "Interface") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).InterfaceData() [2]uintptr
+ // signature: func (Value) InterfaceData() [2]uintptr
hasQualifiedName("reflect", "Value", "InterfaceData") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).MapIndex(key Value) Value
+ // signature: func (Value) MapIndex(key Value) Value
hasQualifiedName("reflect", "Value", "MapIndex") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).MapKeys() []Value
+ // signature: func (Value) MapKeys() []Value
hasQualifiedName("reflect", "Value", "MapKeys") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).MapRange() *MapIter
+ // signature: func (Value) MapRange() *MapIter
hasQualifiedName("reflect", "Value", "MapRange") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Method(i int) Value
+ // signature: func (Value) Method(i int) Value
hasQualifiedName("reflect", "Value", "Method") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).MethodByName(name string) Value
+ // signature: func (Value) MethodByName(name string) Value
hasQualifiedName("reflect", "Value", "MethodByName") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Pointer() uintptr
+ // signature: func (Value) Pointer() uintptr
hasQualifiedName("reflect", "Value", "Pointer") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Recv() (x Value, ok bool)
+ // signature: func (Value) Recv() (x Value, ok bool)
hasQualifiedName("reflect", "Value", "Recv") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (Value).Send(x Value)
+ // signature: func (Value) Send(x Value)
hasQualifiedName("reflect", "Value", "Send") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Value).Set(x Value)
+ // signature: func (Value) Set(x Value)
hasQualifiedName("reflect", "Value", "Set") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Value).SetBytes(x []byte)
+ // signature: func (Value) SetBytes(x []byte)
hasQualifiedName("reflect", "Value", "SetBytes") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Value).SetMapIndex(key Value, elem Value)
+ // signature: func (Value) SetMapIndex(key Value, elem Value)
hasQualifiedName("reflect", "Value", "SetMapIndex") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (Value).SetPointer(x unsafe.Pointer)
+ // signature: func (Value) SetPointer(x unsafe.Pointer)
hasQualifiedName("reflect", "Value", "SetPointer") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Value).SetString(x string)
+ // signature: func (Value) SetString(x string)
hasQualifiedName("reflect", "Value", "SetString") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Value).Slice(i int, j int) Value
+ // signature: func (Value) Slice(i int, j int) Value
hasQualifiedName("reflect", "Value", "Slice") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).Slice3(i int, j int, k int) Value
+ // signature: func (Value) Slice3(i int, j int, k int) Value
hasQualifiedName("reflect", "Value", "Slice3") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).String() string
+ // signature: func (Value) String() string
hasQualifiedName("reflect", "Value", "String") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (Value).TryRecv() (x Value, ok bool)
+ // signature: func (Value) TryRecv() (x Value, ok bool)
hasQualifiedName("reflect", "Value", "TryRecv") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (Value).TrySend(x Value) bool
+ // signature: func (Value) TrySend(x Value) bool
hasQualifiedName("reflect", "Value", "TrySend") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (Value).UnsafeAddr() uintptr
+ // signature: func (Value) UnsafeAddr() uintptr
hasQualifiedName("reflect", "Value", "UnsafeAddr") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Regexp.qll b/ql/src/semmle/go/frameworks/stdlib/Regexp.qll
index c83d950df39..bd12c50fd20 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Regexp.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Regexp.qll
@@ -85,77 +85,77 @@ module Regexp {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Regexp).Expand(dst []byte, template []byte, src []byte, match []int) []byte
+ // signature: func (*Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
hasQualifiedName("regexp", "Regexp", "Expand") and
(
inp.isParameter([1, 2]) and
(outp.isParameter(0) or outp.isResult())
)
or
- // signature: func (*Regexp).ExpandString(dst []byte, template string, src string, match []int) []byte
+ // signature: func (*Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
hasQualifiedName("regexp", "Regexp", "ExpandString") and
(
inp.isParameter([1, 2]) and
(outp.isParameter(0) or outp.isResult())
)
or
- // signature: func (*Regexp).Find(b []byte) []byte
+ // signature: func (*Regexp) Find(b []byte) []byte
hasQualifiedName("regexp", "Regexp", "Find") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindAll(b []byte, n int) [][]byte
+ // signature: func (*Regexp) FindAll(b []byte, n int) [][]byte
hasQualifiedName("regexp", "Regexp", "FindAll") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindAllString(s string, n int) []string
+ // signature: func (*Regexp) FindAllString(s string, n int) []string
hasQualifiedName("regexp", "Regexp", "FindAllString") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindAllStringSubmatch(s string, n int) [][]string
+ // signature: func (*Regexp) FindAllStringSubmatch(s string, n int) [][]string
hasQualifiedName("regexp", "Regexp", "FindAllStringSubmatch") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindAllSubmatch(b []byte, n int) [][][]byte
+ // signature: func (*Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
hasQualifiedName("regexp", "Regexp", "FindAllSubmatch") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindString(s string) string
+ // signature: func (*Regexp) FindString(s string) string
hasQualifiedName("regexp", "Regexp", "FindString") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindStringSubmatch(s string) []string
+ // signature: func (*Regexp) FindStringSubmatch(s string) []string
hasQualifiedName("regexp", "Regexp", "FindStringSubmatch") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).FindSubmatch(b []byte) [][]byte
+ // signature: func (*Regexp) FindSubmatch(b []byte) [][]byte
hasQualifiedName("regexp", "Regexp", "FindSubmatch") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Regexp).ReplaceAll(src []byte, repl []byte) []byte
+ // signature: func (*Regexp) ReplaceAll(src []byte, repl []byte) []byte
hasQualifiedName("regexp", "Regexp", "ReplaceAll") and
(inp.isParameter(_) and outp.isResult())
or
- // signature: func (*Regexp).ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
+ // signature: func (*Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
hasQualifiedName("regexp", "Regexp", "ReplaceAllFunc") and
(inp.isParameter(_) and outp.isResult())
or
- // signature: func (*Regexp).ReplaceAllLiteral(src []byte, repl []byte) []byte
+ // signature: func (*Regexp) ReplaceAllLiteral(src []byte, repl []byte) []byte
hasQualifiedName("regexp", "Regexp", "ReplaceAllLiteral") and
(inp.isParameter(_) and outp.isResult())
or
- // signature: func (*Regexp).ReplaceAllLiteralString(src string, repl string) string
+ // signature: func (*Regexp) ReplaceAllLiteralString(src string, repl string) string
hasQualifiedName("regexp", "Regexp", "ReplaceAllLiteralString") and
(inp.isParameter(_) and outp.isResult())
or
- // signature: func (*Regexp).ReplaceAllString(src string, repl string) string
+ // signature: func (*Regexp) ReplaceAllString(src string, repl string) string
hasQualifiedName("regexp", "Regexp", "ReplaceAllString") and
(inp.isParameter(_) and outp.isResult())
or
- // signature: func (*Regexp).ReplaceAllStringFunc(src string, repl func(string) string) string
+ // signature: func (*Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string
hasQualifiedName("regexp", "Regexp", "ReplaceAllStringFunc") and
(inp.isParameter(_) and outp.isResult())
or
- // signature: func (*Regexp).Split(s string, n int) []string
+ // signature: func (*Regexp) Split(s string, n int) []string
hasQualifiedName("regexp", "Regexp", "Split") and
(inp.isParameter(0) and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Strconv.qll b/ql/src/semmle/go/frameworks/stdlib/Strconv.qll
index 7ad757e2580..14a5f4f29c4 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Strconv.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Strconv.qll
@@ -56,6 +56,10 @@ module Strconv {
hasQualifiedName("strconv", "Quote") and
(inp.isParameter(0) and outp.isResult())
or
+ // signature: func QuotedPrefix(s string) (string, error)
+ hasQualifiedName("strconv", "QuotedPrefix") and
+ (inp.isParameter(0) and outp.isResult(0))
+ or
// signature: func QuoteToASCII(s string) string
hasQualifiedName("strconv", "QuoteToASCII") and
(inp.isParameter(0) and outp.isResult())
diff --git a/ql/src/semmle/go/frameworks/stdlib/Strings.qll b/ql/src/semmle/go/frameworks/stdlib/Strings.qll
index f704634ff9b..07a2dcf23df 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Strings.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Strings.qll
@@ -142,15 +142,15 @@ module Strings {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Reader).Reset(s string)
+ // signature: func (*Reader) Reset(s string)
hasQualifiedName("strings", "Reader", "Reset") and
(inp.isParameter(0) and outp.isReceiver())
or
- // signature: func (*Replacer).Replace(s string) string
+ // signature: func (*Replacer) Replace(s string) string
hasQualifiedName("strings", "Replacer", "Replace") and
(inp.isParameter(0) and outp.isResult())
or
- // signature: func (*Replacer).WriteString(w io.Writer, s string) (n int, err error)
+ // signature: func (*Replacer) WriteString(w io.Writer, s string) (n int, err error)
hasQualifiedName("strings", "Replacer", "WriteString") and
(inp.isParameter(1) and outp.isParameter(0))
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Sync.qll b/ql/src/semmle/go/frameworks/stdlib/Sync.qll
index 3e7a5b8f0f6..b82e1e59804 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Sync.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Sync.qll
@@ -11,11 +11,11 @@ module Sync {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Map).Load(key interface{}) (value interface{}, ok bool)
+ // signature: func (*Map) Load(key interface{}) (value interface{}, ok bool)
hasQualifiedName("sync", "Map", "Load") and
(inp.isReceiver() and outp.isResult(0))
or
- // signature: func (*Map).LoadOrStore(key interface{}, value interface{}) (actual interface{}, loaded bool)
+ // signature: func (*Map) LoadOrStore(key interface{}, value interface{}) (actual interface{}, loaded bool)
hasQualifiedName("sync", "Map", "LoadOrStore") and
(
inp.isReceiver() and outp.isResult(0)
@@ -24,15 +24,15 @@ module Sync {
(outp.isReceiver() or outp.isResult(0))
)
or
- // signature: func (*Map).Store(key interface{}, value interface{})
+ // signature: func (*Map) Store(key interface{}, value interface{})
hasQualifiedName("sync", "Map", "Store") and
(inp.isParameter(_) and outp.isReceiver())
or
- // signature: func (*Pool).Get() interface{}
+ // signature: func (*Pool) Get() interface{}
hasQualifiedName("sync", "Pool", "Get") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Pool).Put(x interface{})
+ // signature: func (*Pool) Put(x interface{})
hasQualifiedName("sync", "Pool", "Put") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/SyncAtomic.qll b/ql/src/semmle/go/frameworks/stdlib/SyncAtomic.qll
index 35f16ba15a6..373ea1d71ca 100644
--- a/ql/src/semmle/go/frameworks/stdlib/SyncAtomic.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/SyncAtomic.qll
@@ -69,11 +69,11 @@ module SyncAtomic {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Value).Load() (x interface{})
+ // signature: func (*Value) Load() (x interface{})
hasQualifiedName("sync/atomic", "Value", "Load") and
(inp.isReceiver() and outp.isResult())
or
- // signature: func (*Value).Store(x interface{})
+ // signature: func (*Value) Store(x interface{})
hasQualifiedName("sync/atomic", "Value", "Store") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/Syscall.qll b/ql/src/semmle/go/frameworks/stdlib/Syscall.qll
index e70591da381..7652a58b6e4 100644
--- a/ql/src/semmle/go/frameworks/stdlib/Syscall.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/Syscall.qll
@@ -42,11 +42,11 @@ module Syscall {
FunctionOutput outp;
MethodModels() {
- // signature: func (RawConn).Read(f func(fd uintptr) (done bool)) error
+ // signature: func (RawConn) Read(f func(fd uintptr) (done bool)) error
implements("syscall", "RawConn", "Read") and
(inp.isReceiver() and outp.isParameter(0))
or
- // signature: func (Conn).SyscallConn() (RawConn, error)
+ // signature: func (Conn) SyscallConn() (RawConn, error)
implements("syscall", "Conn", "SyscallConn") and
(
inp.isReceiver() and outp.isResult(0)
@@ -54,7 +54,7 @@ module Syscall {
inp.isResult(0) and outp.isReceiver()
)
or
- // signature: func (RawConn).Write(f func(fd uintptr) (done bool)) error
+ // signature: func (RawConn) Write(f func(fd uintptr) (done bool)) error
implements("syscall", "RawConn", "Write") and
(inp.isParameter(0) and outp.isReceiver())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/TextScanner.qll b/ql/src/semmle/go/frameworks/stdlib/TextScanner.qll
index c97104d6ac4..54864078e49 100644
--- a/ql/src/semmle/go/frameworks/stdlib/TextScanner.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/TextScanner.qll
@@ -11,14 +11,14 @@ module TextScanner {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Scanner).Init(src io.Reader) *Scanner
+ // signature: func (*Scanner) Init(src io.Reader) *Scanner
hasQualifiedName("text/scanner", "Scanner", "Init") and
(
inp.isParameter(0) and
(outp.isReceiver() or outp.isResult())
)
or
- // signature: func (*Scanner).TokenText() string
+ // signature: func (*Scanner) TokenText() string
hasQualifiedName("text/scanner", "Scanner", "TokenText") and
(inp.isReceiver() and outp.isResult())
}
diff --git a/ql/src/semmle/go/frameworks/stdlib/TextTabwriter.qll b/ql/src/semmle/go/frameworks/stdlib/TextTabwriter.qll
index b4928eeb028..5d40f38b72e 100644
--- a/ql/src/semmle/go/frameworks/stdlib/TextTabwriter.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/TextTabwriter.qll
@@ -26,7 +26,7 @@ module TextTabwriter {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Writer).Init(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer
+ // signature: func (*Writer) Init(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer
hasQualifiedName("text/tabwriter", "Writer", "Init") and
(
(inp.isReceiver() or inp.isResult()) and
diff --git a/ql/src/semmle/go/frameworks/stdlib/TextTemplate.qll b/ql/src/semmle/go/frameworks/stdlib/TextTemplate.qll
index 7b17a1679b9..d32630b56cc 100644
--- a/ql/src/semmle/go/frameworks/stdlib/TextTemplate.qll
+++ b/ql/src/semmle/go/frameworks/stdlib/TextTemplate.qll
@@ -87,11 +87,11 @@ module TextTemplate {
FunctionOutput outp;
MethodModels() {
- // signature: func (*Template).Execute(wr io.Writer, data interface{}) error
+ // signature: func (*Template) Execute(wr io.Writer, data interface{}) error
hasQualifiedName("text/template", "Template", "Execute") and
(inp.isParameter(1) and outp.isParameter(0))
or
- // signature: func (*Template).ExecuteTemplate(wr io.Writer, name string, data interface{}) error
+ // signature: func (*Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error
hasQualifiedName("text/template", "Template", "ExecuteTemplate") and
(inp.isParameter(2) and outp.isParameter(0))
}
diff --git a/ql/test/experimental/CWE-326/InsufficientKeySize.qlref b/ql/test/experimental/CWE-326/InsufficientKeySize.qlref
deleted file mode 100644
index 0eb444e257a..00000000000
--- a/ql/test/experimental/CWE-326/InsufficientKeySize.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/CWE-326/InsufficientKeySize.ql
diff --git a/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected b/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected
new file mode 100644
index 00000000000..bb197203f22
--- /dev/null
+++ b/ql/test/experimental/CWE-400/DatabaseCallInLoop.expected
@@ -0,0 +1,13 @@
+edges
+| DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First |
+| test.go:10:1:12:1 | function declaration | test.go:11:2:11:13 | call to Take |
+| test.go:14:1:16:1 | function declaration | test.go:15:2:15:13 | call to runQuery |
+| test.go:15:2:15:13 | call to runQuery | test.go:10:1:12:1 | function declaration |
+| test.go:20:2:22:2 | for statement | test.go:21:3:21:14 | call to runQuery |
+| test.go:21:3:21:14 | call to runQuery | test.go:10:1:12:1 | function declaration |
+| test.go:24:2:26:2 | for statement | test.go:25:3:25:17 | call to runRunQuery |
+| test.go:25:3:25:17 | call to runRunQuery | test.go:14:1:16:1 | function declaration |
+#select
+| DatabaseCallInLoop.go:9:3:9:41 | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | DatabaseCallInLoop.go:9:3:9:41 | call to First | $@ is called in $@ | DatabaseCallInLoop.go:9:3:9:41 | call to First | call to First | DatabaseCallInLoop.go:7:2:11:2 | range statement | a loop |
+| test.go:11:2:11:13 | call to Take | test.go:20:2:22:2 | for statement | test.go:11:2:11:13 | call to Take | $@ is called in $@ | test.go:11:2:11:13 | call to Take | call to Take | test.go:20:2:22:2 | for statement | a loop |
+| test.go:11:2:11:13 | call to Take | test.go:24:2:26:2 | for statement | test.go:11:2:11:13 | call to Take | $@ is called in $@ | test.go:11:2:11:13 | call to Take | call to Take | test.go:24:2:26:2 | for statement | a loop |
diff --git a/ql/test/experimental/CWE-400/DatabaseCallInLoop.go b/ql/test/experimental/CWE-400/DatabaseCallInLoop.go
new file mode 100644
index 00000000000..138bbbcd9d4
--- /dev/null
+++ b/ql/test/experimental/CWE-400/DatabaseCallInLoop.go
@@ -0,0 +1,13 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUsers(db *gorm.DB, names []string) []User {
+ res := make([]User, 0, len(names))
+ for _, name := range names {
+ var user User
+ db.Where("name = ?", name).First(&user)
+ res = append(res, user)
+ }
+ return res
+}
diff --git a/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref b/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref
new file mode 100644
index 00000000000..63f27c9b41f
--- /dev/null
+++ b/ql/test/experimental/CWE-400/DatabaseCallInLoop.qlref
@@ -0,0 +1 @@
+experimental/CWE-400/DatabaseCallInLoop.ql
diff --git a/ql/test/experimental/CWE-400/DatabaseCallInLoopGood.go b/ql/test/experimental/CWE-400/DatabaseCallInLoopGood.go
new file mode 100644
index 00000000000..22928a6abc2
--- /dev/null
+++ b/ql/test/experimental/CWE-400/DatabaseCallInLoopGood.go
@@ -0,0 +1,9 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUsersGood(db *gorm.DB, names []string) []User {
+ res := make([]User, 0, len(names))
+ db.Where("name IN ?", names).Find(&res)
+ return res
+}
diff --git a/ql/test/experimental/CWE-400/go.mod b/ql/test/experimental/CWE-400/go.mod
new file mode 100644
index 00000000000..8fa98bf285f
--- /dev/null
+++ b/ql/test/experimental/CWE-400/go.mod
@@ -0,0 +1,5 @@
+module query-tests/databasecallinloop
+
+go 1.16
+
+require gorm.io/gorm v1.21.12
diff --git a/ql/test/experimental/CWE-400/test.go b/ql/test/experimental/CWE-400/test.go
new file mode 100644
index 00000000000..725fb541b38
--- /dev/null
+++ b/ql/test/experimental/CWE-400/test.go
@@ -0,0 +1,27 @@
+package main
+
+import "gorm.io/gorm"
+
+type User struct {
+ Id int64
+ Name string
+}
+
+func runQuery(db *gorm.DB) {
+ db.Take(nil)
+}
+
+func runRunQuery(db *gorm.DB) {
+ runQuery(db)
+}
+
+func main() {
+ var db *gorm.DB
+ for i := 0; i < 10; i++ {
+ runQuery(db)
+ }
+
+ for i := 10; i > 0; i-- {
+ runRunQuery(db)
+ }
+}
diff --git a/ql/test/experimental/CWE-400/vendor/gorm.io/gorm/License b/ql/test/experimental/CWE-400/vendor/gorm.io/gorm/License
new file mode 100644
index 00000000000..037e1653e69
--- /dev/null
+++ b/ql/test/experimental/CWE-400/vendor/gorm.io/gorm/License
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-NOW Jinzhu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/ql/test/experimental/CWE-400/vendor/gorm.io/gorm/stub.go b/ql/test/experimental/CWE-400/vendor/gorm.io/gorm/stub.go
new file mode 100644
index 00000000000..dd9f079c446
--- /dev/null
+++ b/ql/test/experimental/CWE-400/vendor/gorm.io/gorm/stub.go
@@ -0,0 +1,803 @@
+// Code generated by depstubber. DO NOT EDIT.
+// This is a simple stub for gorm.io/gorm, strictly for use in testing.
+
+// See the LICENSE file for information about the licensing of the original library.
+// Source: gorm.io/gorm (exports: DB; functions: )
+
+// Package gorm is a stub of gorm.io/gorm, generated by depstubber.
+package gorm
+
+import (
+ context "context"
+ sql "database/sql"
+ reflect "reflect"
+ strings "strings"
+ sync "sync"
+ time "time"
+)
+
+type Association struct {
+ DB *DB
+ Relationship interface{}
+ Error error
+}
+
+func (_ *Association) Append(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Association) Clear() error {
+ return nil
+}
+
+func (_ *Association) Count() int64 {
+ return 0
+}
+
+func (_ *Association) Delete(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Association) Find(_ interface{}, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Association) Replace(_ ...interface{}) error {
+ return nil
+}
+
+type ColumnType interface {
+ DatabaseTypeName() string
+ DecimalSize() (int64, int64, bool)
+ Length() (int64, bool)
+ Name() string
+ Nullable() (bool, bool)
+}
+
+type Config struct {
+ SkipDefaultTransaction bool
+ NamingStrategy interface{}
+ FullSaveAssociations bool
+ Logger interface{}
+ NowFunc func() time.Time
+ DryRun bool
+ PrepareStmt bool
+ DisableAutomaticPing bool
+ DisableForeignKeyConstraintWhenMigrating bool
+ DisableNestedTransaction bool
+ AllowGlobalUpdate bool
+ QueryFields bool
+ CreateBatchSize int
+ ClauseBuilders map[string]interface{}
+ ConnPool ConnPool
+ Dialector Dialector
+ Plugins map[string]Plugin
+}
+
+func (_ Config) BindVarTo(_ interface{}, _ *Statement, _ interface{}) {}
+
+func (_ Config) DataTypeOf(_ interface{}) string {
+ return ""
+}
+
+func (_ Config) DefaultValueOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ Config) Explain(_ string, _ ...interface{}) string {
+ return ""
+}
+
+func (_ Config) Initialize(_ *DB) error {
+ return nil
+}
+
+func (_ Config) Migrator(_ *DB) Migrator {
+ return nil
+}
+
+func (_ Config) Name() string {
+ return ""
+}
+
+func (_ Config) QuoteTo(_ interface{}, _ string) {}
+
+func (_ *Config) AfterInitialize(_ *DB) error {
+ return nil
+}
+
+func (_ *Config) Apply(_ *Config) error {
+ return nil
+}
+
+type ConnPool interface {
+ ExecContext(_ context.Context, _ string, _ ...interface{}) (sql.Result, error)
+ PrepareContext(_ context.Context, _ string) (*sql.Stmt, error)
+ QueryContext(_ context.Context, _ string, _ ...interface{}) (*sql.Rows, error)
+ QueryRowContext(_ context.Context, _ string, _ ...interface{}) *sql.Row
+}
+
+type DB struct {
+ Config *Config
+ Error error
+ RowsAffected int64
+ Statement *Statement
+}
+
+func (_ DB) AfterInitialize(_ *DB) error {
+ return nil
+}
+
+func (_ DB) Apply(_ *Config) error {
+ return nil
+}
+
+func (_ DB) BindVarTo(_ interface{}, _ *Statement, _ interface{}) {}
+
+func (_ DB) DataTypeOf(_ interface{}) string {
+ return ""
+}
+
+func (_ DB) DefaultValueOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ DB) Explain(_ string, _ ...interface{}) string {
+ return ""
+}
+
+func (_ DB) Initialize(_ *DB) error {
+ return nil
+}
+
+func (_ DB) Name() string {
+ return ""
+}
+
+func (_ DB) QuoteTo(_ interface{}, _ string) {}
+
+func (_ *DB) AddError(_ error) error {
+ return nil
+}
+
+func (_ *DB) Assign(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Association(_ string) *Association {
+ return nil
+}
+
+func (_ *DB) Attrs(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) AutoMigrate(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *DB) Begin(_ ...*sql.TxOptions) *DB {
+ return nil
+}
+
+func (_ *DB) Callback() interface{} {
+ return nil
+}
+
+func (_ *DB) Clauses(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Commit() *DB {
+ return nil
+}
+
+func (_ *DB) Count(_ *int64) *DB {
+ return nil
+}
+
+func (_ *DB) Create(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) CreateInBatches(_ interface{}, _ int) *DB {
+ return nil
+}
+
+func (_ *DB) DB() (*sql.DB, error) {
+ return nil, nil
+}
+
+func (_ *DB) Debug() *DB {
+ return nil
+}
+
+func (_ *DB) Delete(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Distinct(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Exec(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Find(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) FindInBatches(_ interface{}, _ int, _ func(*DB, int) error) *DB {
+ return nil
+}
+
+func (_ *DB) First(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) FirstOrCreate(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) FirstOrInit(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Get(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ *DB) Group(_ string) *DB {
+ return nil
+}
+
+func (_ *DB) Having(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) InstanceGet(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ *DB) InstanceSet(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Joins(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Last(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Limit(_ int) *DB {
+ return nil
+}
+
+func (_ *DB) Migrator() Migrator {
+ return nil
+}
+
+func (_ *DB) Model(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Not(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Offset(_ int) *DB {
+ return nil
+}
+
+func (_ *DB) Omit(_ ...string) *DB {
+ return nil
+}
+
+func (_ *DB) Or(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Order(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Pluck(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Preload(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Raw(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Rollback() *DB {
+ return nil
+}
+
+func (_ *DB) RollbackTo(_ string) *DB {
+ return nil
+}
+
+func (_ *DB) Row() *sql.Row {
+ return nil
+}
+
+func (_ *DB) Rows() (*sql.Rows, error) {
+ return nil, nil
+}
+
+func (_ *DB) Save(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) SavePoint(_ string) *DB {
+ return nil
+}
+
+func (_ *DB) Scan(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) ScanRows(_ *sql.Rows, _ interface{}) error {
+ return nil
+}
+
+func (_ *DB) Scopes(_ ...func(*DB) *DB) *DB {
+ return nil
+}
+
+func (_ *DB) Select(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Session(_ *Session) *DB {
+ return nil
+}
+
+func (_ *DB) Set(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) SetupJoinTable(_ interface{}, _ string, _ interface{}) error {
+ return nil
+}
+
+func (_ *DB) Table(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Take(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Transaction(_ func(*DB) error, _ ...*sql.TxOptions) error {
+ return nil
+}
+
+func (_ *DB) Unscoped() *DB {
+ return nil
+}
+
+func (_ *DB) Update(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) UpdateColumn(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) UpdateColumns(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Updates(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Use(_ Plugin) error {
+ return nil
+}
+
+func (_ *DB) Where(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) WithContext(_ context.Context) *DB {
+ return nil
+}
+
+type Dialector interface {
+ BindVarTo(_ interface{}, _ *Statement, _ interface{})
+ DataTypeOf(_ interface{}) string
+ DefaultValueOf(_ interface{}) interface{}
+ Explain(_ string, _ ...interface{}) string
+ Initialize(_ *DB) error
+ Migrator(_ *DB) Migrator
+ Name() string
+ QuoteTo(_ interface{}, _ string)
+}
+
+type Migrator interface {
+ AddColumn(_ interface{}, _ string) error
+ AlterColumn(_ interface{}, _ string) error
+ AutoMigrate(_ ...interface{}) error
+ ColumnTypes(_ interface{}) ([]ColumnType, error)
+ CreateConstraint(_ interface{}, _ string) error
+ CreateIndex(_ interface{}, _ string) error
+ CreateTable(_ ...interface{}) error
+ CreateView(_ string, _ ViewOption) error
+ CurrentDatabase() string
+ DropColumn(_ interface{}, _ string) error
+ DropConstraint(_ interface{}, _ string) error
+ DropIndex(_ interface{}, _ string) error
+ DropTable(_ ...interface{}) error
+ DropView(_ string) error
+ FullDataTypeOf(_ interface{}) interface{}
+ HasColumn(_ interface{}, _ string) bool
+ HasConstraint(_ interface{}, _ string) bool
+ HasIndex(_ interface{}, _ string) bool
+ HasTable(_ interface{}) bool
+ MigrateColumn(_ interface{}, _ interface{}, _ ColumnType) error
+ RenameColumn(_ interface{}, _ string, _ string) error
+ RenameIndex(_ interface{}, _ string, _ string) error
+ RenameTable(_ interface{}, _ interface{}) error
+}
+
+type Plugin interface {
+ Initialize(_ *DB) error
+ Name() string
+}
+
+type Session struct {
+ DryRun bool
+ PrepareStmt bool
+ NewDB bool
+ SkipHooks bool
+ SkipDefaultTransaction bool
+ DisableNestedTransaction bool
+ AllowGlobalUpdate bool
+ FullSaveAssociations bool
+ QueryFields bool
+ Context context.Context
+ Logger interface{}
+ NowFunc func() time.Time
+ CreateBatchSize int
+}
+
+type Statement struct {
+ DB *DB
+ TableExpr interface{}
+ Table string
+ Model interface{}
+ Unscoped bool
+ Dest interface{}
+ ReflectValue reflect.Value
+ Clauses map[string]interface{}
+ BuildClauses []string
+ Distinct bool
+ Selects []string
+ Omits []string
+ Joins []interface{}
+ Preloads map[string][]interface{}
+ Settings sync.Map
+ ConnPool ConnPool
+ Schema interface{}
+ Context context.Context
+ RaiseErrorOnNotFound bool
+ SkipHooks bool
+ SQL strings.Builder
+ Vars []interface{}
+ CurDestIndex int
+}
+
+func (_ Statement) AddError(_ error) error {
+ return nil
+}
+
+func (_ Statement) AfterInitialize(_ *DB) error {
+ return nil
+}
+
+func (_ Statement) Apply(_ *Config) error {
+ return nil
+}
+
+func (_ Statement) Assign(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Association(_ string) *Association {
+ return nil
+}
+
+func (_ Statement) Attrs(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) AutoMigrate(_ ...interface{}) error {
+ return nil
+}
+
+func (_ Statement) Begin(_ ...*sql.TxOptions) *DB {
+ return nil
+}
+
+func (_ Statement) BindVarTo(_ interface{}, _ *Statement, _ interface{}) {}
+
+func (_ Statement) Callback() interface{} {
+ return nil
+}
+
+func (_ Statement) Commit() *DB {
+ return nil
+}
+
+func (_ Statement) Count(_ *int64) *DB {
+ return nil
+}
+
+func (_ Statement) Create(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) CreateInBatches(_ interface{}, _ int) *DB {
+ return nil
+}
+
+func (_ Statement) DataTypeOf(_ interface{}) string {
+ return ""
+}
+
+func (_ Statement) Debug() *DB {
+ return nil
+}
+
+func (_ Statement) DefaultValueOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ Statement) Delete(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Exec(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Explain(_ string, _ ...interface{}) string {
+ return ""
+}
+
+func (_ Statement) Find(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) FindInBatches(_ interface{}, _ int, _ func(*DB, int) error) *DB {
+ return nil
+}
+
+func (_ Statement) First(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) FirstOrCreate(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) FirstOrInit(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Get(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ Statement) Group(_ string) *DB {
+ return nil
+}
+
+func (_ Statement) Having(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Initialize(_ *DB) error {
+ return nil
+}
+
+func (_ Statement) InstanceGet(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ Statement) InstanceSet(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Last(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Limit(_ int) *DB {
+ return nil
+}
+
+func (_ Statement) Migrator() Migrator {
+ return nil
+}
+
+func (_ Statement) Name() string {
+ return ""
+}
+
+func (_ Statement) Not(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Offset(_ int) *DB {
+ return nil
+}
+
+func (_ Statement) Omit(_ ...string) *DB {
+ return nil
+}
+
+func (_ Statement) Or(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Order(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Pluck(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Preload(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Raw(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Rollback() *DB {
+ return nil
+}
+
+func (_ Statement) RollbackTo(_ string) *DB {
+ return nil
+}
+
+func (_ Statement) Row() *sql.Row {
+ return nil
+}
+
+func (_ Statement) Rows() (*sql.Rows, error) {
+ return nil, nil
+}
+
+func (_ Statement) Save(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) SavePoint(_ string) *DB {
+ return nil
+}
+
+func (_ Statement) Scan(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) ScanRows(_ *sql.Rows, _ interface{}) error {
+ return nil
+}
+
+func (_ Statement) Scopes(_ ...func(*DB) *DB) *DB {
+ return nil
+}
+
+func (_ Statement) Select(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Session(_ *Session) *DB {
+ return nil
+}
+
+func (_ Statement) Set(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) SetupJoinTable(_ interface{}, _ string, _ interface{}) error {
+ return nil
+}
+
+func (_ Statement) Take(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Transaction(_ func(*DB) error, _ ...*sql.TxOptions) error {
+ return nil
+}
+
+func (_ Statement) Update(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) UpdateColumn(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) UpdateColumns(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Updates(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Use(_ Plugin) error {
+ return nil
+}
+
+func (_ Statement) Where(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) WithContext(_ context.Context) *DB {
+ return nil
+}
+
+func (_ *Statement) AddClause(_ interface{}) {}
+
+func (_ *Statement) AddClauseIfNotExists(_ interface{}) {}
+
+func (_ *Statement) AddVar(_ interface{}, _ ...interface{}) {}
+
+func (_ *Statement) Build(_ ...string) {}
+
+func (_ *Statement) BuildCondition(_ interface{}, _ ...interface{}) []interface{} {
+ return nil
+}
+
+func (_ *Statement) Changed(_ ...string) bool {
+ return false
+}
+
+func (_ *Statement) Parse(_ interface{}) error {
+ return nil
+}
+
+func (_ *Statement) Quote(_ interface{}) string {
+ return ""
+}
+
+func (_ *Statement) QuoteTo(_ interface{}, _ interface{}) {}
+
+func (_ *Statement) SelectAndOmitColumns(_ bool, _ bool) (map[string]bool, bool) {
+ return nil, false
+}
+
+func (_ *Statement) SetColumn(_ string, _ interface{}, _ ...bool) {}
+
+func (_ *Statement) WriteByte(_ byte) error {
+ return nil
+}
+
+func (_ *Statement) WriteQuoted(_ interface{}) {}
+
+func (_ *Statement) WriteString(_ string) (int, error) {
+ return 0, nil
+}
+
+type ViewOption struct {
+ Replace bool
+ CheckOption string
+ Query *DB
+}
diff --git a/ql/test/experimental/CWE-400/vendor/modules.txt b/ql/test/experimental/CWE-400/vendor/modules.txt
new file mode 100644
index 00000000000..52a1f62b367
--- /dev/null
+++ b/ql/test/experimental/CWE-400/vendor/modules.txt
@@ -0,0 +1,3 @@
+# gorm.io/gorm v1.21.12
+## explicit
+gorm.io/gorm
diff --git a/ql/test/experimental/InconsistentCode/DeferInLoop.expected b/ql/test/experimental/InconsistentCode/DeferInLoop.expected
new file mode 100644
index 00000000000..8652787cc06
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/DeferInLoop.expected
@@ -0,0 +1,6 @@
+| DeferInLoop.go:8:3:8:20 | defer statement | This defer statement is in a $@. | DeferInLoop.go:6:2:13:2 | range statement | loop |
+| test.go:6:3:6:14 | defer statement | This defer statement is in a $@. | test.go:5:2:7:2 | range statement | loop |
+| test.go:11:4:11:15 | defer statement | This defer statement is in a $@. | test.go:9:2:13:2 | range statement | loop |
+| test.go:16:3:16:14 | defer statement | This defer statement is in a $@. | test.go:15:2:17:2 | for statement | loop |
+| test.go:20:3:20:14 | defer statement | This defer statement is in a $@. | test.go:19:2:21:2 | for statement | loop |
+| test.go:24:3:24:14 | defer statement | This defer statement is in a $@. | test.go:23:2:25:2 | for statement | loop |
diff --git a/ql/test/experimental/InconsistentCode/DeferInLoop.go b/ql/test/experimental/InconsistentCode/DeferInLoop.go
new file mode 100644
index 00000000000..1b57d1855b4
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/DeferInLoop.go
@@ -0,0 +1,14 @@
+package main
+
+import "os"
+
+func openFiles(filenames []string) {
+ for _, filename := range filenames {
+ file, err := os.Open(filename)
+ defer file.Close()
+ if err != nil {
+ // handle error
+ }
+ // work on file
+ }
+}
diff --git a/ql/test/experimental/InconsistentCode/DeferInLoop.qlref b/ql/test/experimental/InconsistentCode/DeferInLoop.qlref
new file mode 100644
index 00000000000..e50bcf4fdf6
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/DeferInLoop.qlref
@@ -0,0 +1 @@
+experimental/InconsistentCode/DeferInLoop.ql
diff --git a/ql/test/experimental/InconsistentCode/DeferInLoopGood.go b/ql/test/experimental/InconsistentCode/DeferInLoopGood.go
new file mode 100644
index 00000000000..d28bc8e4cb9
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/DeferInLoopGood.go
@@ -0,0 +1,18 @@
+package main
+
+import "os"
+
+func openFile(filename string) {
+ file, err := os.Open(filename)
+ defer file.Close()
+ if err != nil {
+ // handle error
+ }
+ // work on file
+}
+
+func openFilesGood(filenames []string) {
+ for _, filename := range filenames {
+ openFile(filename)
+ }
+}
diff --git a/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.expected b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.expected
new file mode 100644
index 00000000000..4d75b035fec
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.expected
@@ -0,0 +1 @@
+| GORMErrorNotChecked.go:7:2:7:40 | call to First | This call appears to interact with the database without checking whether an error was encountered. |
diff --git a/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go
new file mode 100644
index 00000000000..422e49b5f10
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.go
@@ -0,0 +1,9 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUserId(db *gorm.DB, name string) int64 {
+ var user User
+ db.Where("name = ?", name).First(&user)
+ return user.Id
+}
diff --git a/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qhelp b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qhelp
new file mode 100644
index 00000000000..1f64e06dc19
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qhelp
@@ -0,0 +1,35 @@
+
+
+
+
+GORM errors are returned as a field of the return value instead of a separate return value.
+
+It is therefore very easy to miss that an error may occur and omit error handling routines.
+
+
+
+Ensure that GORM errors are checked.
+
+
+
+
+In the example below,
+
+
+
+The corrected version of user checks err before using ptr.
+
+
+
+
+
+
+
+ The Go Blog:
+ Error handling and Go.
+
+
+
+
diff --git a/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref
new file mode 100644
index 00000000000..b52256ad539
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/GORMErrorNotChecked.qlref
@@ -0,0 +1 @@
+experimental/InconsistentCode/GORMErrorNotChecked.ql
diff --git a/ql/test/experimental/InconsistentCode/GORMErrorNotCheckedGood.go b/ql/test/experimental/InconsistentCode/GORMErrorNotCheckedGood.go
new file mode 100644
index 00000000000..551e06fb66a
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/GORMErrorNotCheckedGood.go
@@ -0,0 +1,11 @@
+package main
+
+import "gorm.io/gorm"
+
+func getUserIdGood(db *gorm.DB, name string) int64 {
+ var user User
+ if err := db.Where("name = ?", name).First(&user).Error; err != nil {
+ // handle errors
+ }
+ return user.Id
+}
diff --git a/ql/test/experimental/InconsistentCode/go.mod b/ql/test/experimental/InconsistentCode/go.mod
new file mode 100644
index 00000000000..e3b89d1ab9f
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/go.mod
@@ -0,0 +1,5 @@
+module query-tests/gormerrornotchecked
+
+go 1.16
+
+require gorm.io/gorm v1.21.12
diff --git a/ql/test/experimental/InconsistentCode/test.go b/ql/test/experimental/InconsistentCode/test.go
new file mode 100644
index 00000000000..1dc64350bd4
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/test.go
@@ -0,0 +1,26 @@
+package main
+
+func test() {
+ var xs []int
+ for _ = range xs {
+ defer test() // not ok
+ }
+
+ for _ = range xs {
+ if true {
+ defer test() // not ok
+ }
+ }
+
+ for i := 0; i < 10; i++ {
+ defer test()
+ }
+
+ for true {
+ defer test() // not ok
+ }
+
+ for false {
+ defer test() // fine but caught
+ }
+}
diff --git a/ql/test/experimental/InconsistentCode/util.go b/ql/test/experimental/InconsistentCode/util.go
new file mode 100644
index 00000000000..0074e1f23f1
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/util.go
@@ -0,0 +1,9 @@
+package main
+
+type User struct {
+ Id int64
+ Name string
+}
+
+func main() {
+}
diff --git a/ql/test/experimental/InconsistentCode/vendor/gorm.io/gorm/License b/ql/test/experimental/InconsistentCode/vendor/gorm.io/gorm/License
new file mode 100644
index 00000000000..037e1653e69
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/vendor/gorm.io/gorm/License
@@ -0,0 +1,21 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-NOW Jinzhu
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
diff --git a/ql/test/experimental/InconsistentCode/vendor/gorm.io/gorm/stub.go b/ql/test/experimental/InconsistentCode/vendor/gorm.io/gorm/stub.go
new file mode 100644
index 00000000000..dd9f079c446
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/vendor/gorm.io/gorm/stub.go
@@ -0,0 +1,803 @@
+// Code generated by depstubber. DO NOT EDIT.
+// This is a simple stub for gorm.io/gorm, strictly for use in testing.
+
+// See the LICENSE file for information about the licensing of the original library.
+// Source: gorm.io/gorm (exports: DB; functions: )
+
+// Package gorm is a stub of gorm.io/gorm, generated by depstubber.
+package gorm
+
+import (
+ context "context"
+ sql "database/sql"
+ reflect "reflect"
+ strings "strings"
+ sync "sync"
+ time "time"
+)
+
+type Association struct {
+ DB *DB
+ Relationship interface{}
+ Error error
+}
+
+func (_ *Association) Append(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Association) Clear() error {
+ return nil
+}
+
+func (_ *Association) Count() int64 {
+ return 0
+}
+
+func (_ *Association) Delete(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Association) Find(_ interface{}, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Association) Replace(_ ...interface{}) error {
+ return nil
+}
+
+type ColumnType interface {
+ DatabaseTypeName() string
+ DecimalSize() (int64, int64, bool)
+ Length() (int64, bool)
+ Name() string
+ Nullable() (bool, bool)
+}
+
+type Config struct {
+ SkipDefaultTransaction bool
+ NamingStrategy interface{}
+ FullSaveAssociations bool
+ Logger interface{}
+ NowFunc func() time.Time
+ DryRun bool
+ PrepareStmt bool
+ DisableAutomaticPing bool
+ DisableForeignKeyConstraintWhenMigrating bool
+ DisableNestedTransaction bool
+ AllowGlobalUpdate bool
+ QueryFields bool
+ CreateBatchSize int
+ ClauseBuilders map[string]interface{}
+ ConnPool ConnPool
+ Dialector Dialector
+ Plugins map[string]Plugin
+}
+
+func (_ Config) BindVarTo(_ interface{}, _ *Statement, _ interface{}) {}
+
+func (_ Config) DataTypeOf(_ interface{}) string {
+ return ""
+}
+
+func (_ Config) DefaultValueOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ Config) Explain(_ string, _ ...interface{}) string {
+ return ""
+}
+
+func (_ Config) Initialize(_ *DB) error {
+ return nil
+}
+
+func (_ Config) Migrator(_ *DB) Migrator {
+ return nil
+}
+
+func (_ Config) Name() string {
+ return ""
+}
+
+func (_ Config) QuoteTo(_ interface{}, _ string) {}
+
+func (_ *Config) AfterInitialize(_ *DB) error {
+ return nil
+}
+
+func (_ *Config) Apply(_ *Config) error {
+ return nil
+}
+
+type ConnPool interface {
+ ExecContext(_ context.Context, _ string, _ ...interface{}) (sql.Result, error)
+ PrepareContext(_ context.Context, _ string) (*sql.Stmt, error)
+ QueryContext(_ context.Context, _ string, _ ...interface{}) (*sql.Rows, error)
+ QueryRowContext(_ context.Context, _ string, _ ...interface{}) *sql.Row
+}
+
+type DB struct {
+ Config *Config
+ Error error
+ RowsAffected int64
+ Statement *Statement
+}
+
+func (_ DB) AfterInitialize(_ *DB) error {
+ return nil
+}
+
+func (_ DB) Apply(_ *Config) error {
+ return nil
+}
+
+func (_ DB) BindVarTo(_ interface{}, _ *Statement, _ interface{}) {}
+
+func (_ DB) DataTypeOf(_ interface{}) string {
+ return ""
+}
+
+func (_ DB) DefaultValueOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ DB) Explain(_ string, _ ...interface{}) string {
+ return ""
+}
+
+func (_ DB) Initialize(_ *DB) error {
+ return nil
+}
+
+func (_ DB) Name() string {
+ return ""
+}
+
+func (_ DB) QuoteTo(_ interface{}, _ string) {}
+
+func (_ *DB) AddError(_ error) error {
+ return nil
+}
+
+func (_ *DB) Assign(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Association(_ string) *Association {
+ return nil
+}
+
+func (_ *DB) Attrs(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) AutoMigrate(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *DB) Begin(_ ...*sql.TxOptions) *DB {
+ return nil
+}
+
+func (_ *DB) Callback() interface{} {
+ return nil
+}
+
+func (_ *DB) Clauses(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Commit() *DB {
+ return nil
+}
+
+func (_ *DB) Count(_ *int64) *DB {
+ return nil
+}
+
+func (_ *DB) Create(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) CreateInBatches(_ interface{}, _ int) *DB {
+ return nil
+}
+
+func (_ *DB) DB() (*sql.DB, error) {
+ return nil, nil
+}
+
+func (_ *DB) Debug() *DB {
+ return nil
+}
+
+func (_ *DB) Delete(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Distinct(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Exec(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Find(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) FindInBatches(_ interface{}, _ int, _ func(*DB, int) error) *DB {
+ return nil
+}
+
+func (_ *DB) First(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) FirstOrCreate(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) FirstOrInit(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Get(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ *DB) Group(_ string) *DB {
+ return nil
+}
+
+func (_ *DB) Having(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) InstanceGet(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ *DB) InstanceSet(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Joins(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Last(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Limit(_ int) *DB {
+ return nil
+}
+
+func (_ *DB) Migrator() Migrator {
+ return nil
+}
+
+func (_ *DB) Model(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Not(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Offset(_ int) *DB {
+ return nil
+}
+
+func (_ *DB) Omit(_ ...string) *DB {
+ return nil
+}
+
+func (_ *DB) Or(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Order(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Pluck(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Preload(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Raw(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Rollback() *DB {
+ return nil
+}
+
+func (_ *DB) RollbackTo(_ string) *DB {
+ return nil
+}
+
+func (_ *DB) Row() *sql.Row {
+ return nil
+}
+
+func (_ *DB) Rows() (*sql.Rows, error) {
+ return nil, nil
+}
+
+func (_ *DB) Save(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) SavePoint(_ string) *DB {
+ return nil
+}
+
+func (_ *DB) Scan(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) ScanRows(_ *sql.Rows, _ interface{}) error {
+ return nil
+}
+
+func (_ *DB) Scopes(_ ...func(*DB) *DB) *DB {
+ return nil
+}
+
+func (_ *DB) Select(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Session(_ *Session) *DB {
+ return nil
+}
+
+func (_ *DB) Set(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) SetupJoinTable(_ interface{}, _ string, _ interface{}) error {
+ return nil
+}
+
+func (_ *DB) Table(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Take(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Transaction(_ func(*DB) error, _ ...*sql.TxOptions) error {
+ return nil
+}
+
+func (_ *DB) Unscoped() *DB {
+ return nil
+}
+
+func (_ *DB) Update(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) UpdateColumn(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) UpdateColumns(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Updates(_ interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) Use(_ Plugin) error {
+ return nil
+}
+
+func (_ *DB) Where(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ *DB) WithContext(_ context.Context) *DB {
+ return nil
+}
+
+type Dialector interface {
+ BindVarTo(_ interface{}, _ *Statement, _ interface{})
+ DataTypeOf(_ interface{}) string
+ DefaultValueOf(_ interface{}) interface{}
+ Explain(_ string, _ ...interface{}) string
+ Initialize(_ *DB) error
+ Migrator(_ *DB) Migrator
+ Name() string
+ QuoteTo(_ interface{}, _ string)
+}
+
+type Migrator interface {
+ AddColumn(_ interface{}, _ string) error
+ AlterColumn(_ interface{}, _ string) error
+ AutoMigrate(_ ...interface{}) error
+ ColumnTypes(_ interface{}) ([]ColumnType, error)
+ CreateConstraint(_ interface{}, _ string) error
+ CreateIndex(_ interface{}, _ string) error
+ CreateTable(_ ...interface{}) error
+ CreateView(_ string, _ ViewOption) error
+ CurrentDatabase() string
+ DropColumn(_ interface{}, _ string) error
+ DropConstraint(_ interface{}, _ string) error
+ DropIndex(_ interface{}, _ string) error
+ DropTable(_ ...interface{}) error
+ DropView(_ string) error
+ FullDataTypeOf(_ interface{}) interface{}
+ HasColumn(_ interface{}, _ string) bool
+ HasConstraint(_ interface{}, _ string) bool
+ HasIndex(_ interface{}, _ string) bool
+ HasTable(_ interface{}) bool
+ MigrateColumn(_ interface{}, _ interface{}, _ ColumnType) error
+ RenameColumn(_ interface{}, _ string, _ string) error
+ RenameIndex(_ interface{}, _ string, _ string) error
+ RenameTable(_ interface{}, _ interface{}) error
+}
+
+type Plugin interface {
+ Initialize(_ *DB) error
+ Name() string
+}
+
+type Session struct {
+ DryRun bool
+ PrepareStmt bool
+ NewDB bool
+ SkipHooks bool
+ SkipDefaultTransaction bool
+ DisableNestedTransaction bool
+ AllowGlobalUpdate bool
+ FullSaveAssociations bool
+ QueryFields bool
+ Context context.Context
+ Logger interface{}
+ NowFunc func() time.Time
+ CreateBatchSize int
+}
+
+type Statement struct {
+ DB *DB
+ TableExpr interface{}
+ Table string
+ Model interface{}
+ Unscoped bool
+ Dest interface{}
+ ReflectValue reflect.Value
+ Clauses map[string]interface{}
+ BuildClauses []string
+ Distinct bool
+ Selects []string
+ Omits []string
+ Joins []interface{}
+ Preloads map[string][]interface{}
+ Settings sync.Map
+ ConnPool ConnPool
+ Schema interface{}
+ Context context.Context
+ RaiseErrorOnNotFound bool
+ SkipHooks bool
+ SQL strings.Builder
+ Vars []interface{}
+ CurDestIndex int
+}
+
+func (_ Statement) AddError(_ error) error {
+ return nil
+}
+
+func (_ Statement) AfterInitialize(_ *DB) error {
+ return nil
+}
+
+func (_ Statement) Apply(_ *Config) error {
+ return nil
+}
+
+func (_ Statement) Assign(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Association(_ string) *Association {
+ return nil
+}
+
+func (_ Statement) Attrs(_ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) AutoMigrate(_ ...interface{}) error {
+ return nil
+}
+
+func (_ Statement) Begin(_ ...*sql.TxOptions) *DB {
+ return nil
+}
+
+func (_ Statement) BindVarTo(_ interface{}, _ *Statement, _ interface{}) {}
+
+func (_ Statement) Callback() interface{} {
+ return nil
+}
+
+func (_ Statement) Commit() *DB {
+ return nil
+}
+
+func (_ Statement) Count(_ *int64) *DB {
+ return nil
+}
+
+func (_ Statement) Create(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) CreateInBatches(_ interface{}, _ int) *DB {
+ return nil
+}
+
+func (_ Statement) DataTypeOf(_ interface{}) string {
+ return ""
+}
+
+func (_ Statement) Debug() *DB {
+ return nil
+}
+
+func (_ Statement) DefaultValueOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ Statement) Delete(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Exec(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Explain(_ string, _ ...interface{}) string {
+ return ""
+}
+
+func (_ Statement) Find(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) FindInBatches(_ interface{}, _ int, _ func(*DB, int) error) *DB {
+ return nil
+}
+
+func (_ Statement) First(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) FirstOrCreate(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) FirstOrInit(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Get(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ Statement) Group(_ string) *DB {
+ return nil
+}
+
+func (_ Statement) Having(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Initialize(_ *DB) error {
+ return nil
+}
+
+func (_ Statement) InstanceGet(_ string) (interface{}, bool) {
+ return nil, false
+}
+
+func (_ Statement) InstanceSet(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Last(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Limit(_ int) *DB {
+ return nil
+}
+
+func (_ Statement) Migrator() Migrator {
+ return nil
+}
+
+func (_ Statement) Name() string {
+ return ""
+}
+
+func (_ Statement) Not(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Offset(_ int) *DB {
+ return nil
+}
+
+func (_ Statement) Omit(_ ...string) *DB {
+ return nil
+}
+
+func (_ Statement) Or(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Order(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Pluck(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Preload(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Raw(_ string, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Rollback() *DB {
+ return nil
+}
+
+func (_ Statement) RollbackTo(_ string) *DB {
+ return nil
+}
+
+func (_ Statement) Row() *sql.Row {
+ return nil
+}
+
+func (_ Statement) Rows() (*sql.Rows, error) {
+ return nil, nil
+}
+
+func (_ Statement) Save(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) SavePoint(_ string) *DB {
+ return nil
+}
+
+func (_ Statement) Scan(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) ScanRows(_ *sql.Rows, _ interface{}) error {
+ return nil
+}
+
+func (_ Statement) Scopes(_ ...func(*DB) *DB) *DB {
+ return nil
+}
+
+func (_ Statement) Select(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Session(_ *Session) *DB {
+ return nil
+}
+
+func (_ Statement) Set(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) SetupJoinTable(_ interface{}, _ string, _ interface{}) error {
+ return nil
+}
+
+func (_ Statement) Take(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Transaction(_ func(*DB) error, _ ...*sql.TxOptions) error {
+ return nil
+}
+
+func (_ Statement) Update(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) UpdateColumn(_ string, _ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) UpdateColumns(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Updates(_ interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) Use(_ Plugin) error {
+ return nil
+}
+
+func (_ Statement) Where(_ interface{}, _ ...interface{}) *DB {
+ return nil
+}
+
+func (_ Statement) WithContext(_ context.Context) *DB {
+ return nil
+}
+
+func (_ *Statement) AddClause(_ interface{}) {}
+
+func (_ *Statement) AddClauseIfNotExists(_ interface{}) {}
+
+func (_ *Statement) AddVar(_ interface{}, _ ...interface{}) {}
+
+func (_ *Statement) Build(_ ...string) {}
+
+func (_ *Statement) BuildCondition(_ interface{}, _ ...interface{}) []interface{} {
+ return nil
+}
+
+func (_ *Statement) Changed(_ ...string) bool {
+ return false
+}
+
+func (_ *Statement) Parse(_ interface{}) error {
+ return nil
+}
+
+func (_ *Statement) Quote(_ interface{}) string {
+ return ""
+}
+
+func (_ *Statement) QuoteTo(_ interface{}, _ interface{}) {}
+
+func (_ *Statement) SelectAndOmitColumns(_ bool, _ bool) (map[string]bool, bool) {
+ return nil, false
+}
+
+func (_ *Statement) SetColumn(_ string, _ interface{}, _ ...bool) {}
+
+func (_ *Statement) WriteByte(_ byte) error {
+ return nil
+}
+
+func (_ *Statement) WriteQuoted(_ interface{}) {}
+
+func (_ *Statement) WriteString(_ string) (int, error) {
+ return 0, nil
+}
+
+type ViewOption struct {
+ Replace bool
+ CheckOption string
+ Query *DB
+}
diff --git a/ql/test/experimental/InconsistentCode/vendor/modules.txt b/ql/test/experimental/InconsistentCode/vendor/modules.txt
new file mode 100644
index 00000000000..52a1f62b367
--- /dev/null
+++ b/ql/test/experimental/InconsistentCode/vendor/modules.txt
@@ -0,0 +1,3 @@
+# gorm.io/gorm v1.21.12
+## explicit
+gorm.io/gorm
diff --git a/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected b/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected
index b78781de117..fc69f87cc3f 100644
--- a/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected
+++ b/ql/test/extractor-tests/diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected
@@ -1,5 +1,9 @@
+| -:0:0:0:0 | package ; expected main |
| broken2/test1.go:4:2:4:2 | undeclared name: fmt |
| broken2/test1.go:5:2:5:2 | undeclared name: fmt |
| broken2/test1.go:5:14:5:14 | undeclared name: a |
| broken2/test.go:3:1:3:1 | expected 'package', found pac |
+| broken2/test.go:3:1:3:1 | expected 'package', found pac |
+| broken2/test.go:3:4:3:4 | expected 'IDENT', found newline |
+| broken2/test.go:3:5:3:5 | expected ';', found 'EOF' |
| broken/test.go:7:1:7:1 | expected declaration, found This |
diff --git a/ql/test/extractor-tests/go1.17/CFG.expected b/ql/test/extractor-tests/go1.17/CFG.expected
new file mode 100644
index 00000000000..a918d87337c
--- /dev/null
+++ b/ql/test/extractor-tests/go1.17/CFG.expected
@@ -0,0 +1,64 @@
+nodes
+edges
+| conversions.go:0:0:0:0 | entry | conversions.go:3:1:3:15 | skip |
+| conversions.go:3:1:3:15 | skip | conversions.go:5:6:5:8 | skip |
+| conversions.go:5:1:5:1 | entry | conversions.go:5:10:5:10 | argument corresponding to _ |
+| conversions.go:5:1:5:29 | function declaration | conversions.go:7:6:7:9 | skip |
+| conversions.go:5:6:5:8 | skip | conversions.go:5:1:5:29 | function declaration |
+| conversions.go:5:10:5:10 | argument corresponding to _ | conversions.go:5:10:5:10 | initialization of _ |
+| conversions.go:5:10:5:10 | initialization of _ | conversions.go:5:28:5:29 | skip |
+| conversions.go:5:28:5:29 | skip | conversions.go:5:29:5:29 | exit |
+| conversions.go:7:1:7:1 | entry | conversions.go:8:6:8:6 | skip |
+| conversions.go:7:1:26:1 | function declaration | conversions.go:0:0:0:0 | exit |
+| conversions.go:7:6:7:9 | skip | conversions.go:7:1:26:1 | function declaration |
+| conversions.go:8:6:8:6 | assignment to a | conversions.go:10:2:10:2 | skip |
+| conversions.go:8:6:8:6 | skip | conversions.go:8:6:8:6 | zero value for a |
+| conversions.go:8:6:8:6 | zero value for a | conversions.go:8:6:8:6 | assignment to a |
+| conversions.go:10:2:10:2 | assignment to b | conversions.go:11:2:11:4 | use |
+| conversions.go:10:2:10:2 | skip | conversions.go:10:7:10:16 | selection of Add |
+| conversions.go:10:7:10:16 | selection of Add | conversions.go:10:18:10:18 | a |
+| conversions.go:10:7:10:23 | call to Add | conversions.go:10:2:10:2 | assignment to b |
+| conversions.go:10:18:10:18 | a | conversions.go:10:21:10:22 | 10 |
+| conversions.go:10:21:10:22 | 10 | conversions.go:10:7:10:23 | call to Add |
+| conversions.go:11:2:11:4 | use | conversions.go:11:6:11:6 | b |
+| conversions.go:11:2:11:7 | call to use | conversions.go:13:6:13:8 | skip |
+| conversions.go:11:2:11:7 | call to use | conversions.go:26:1:26:1 | exit |
+| conversions.go:11:6:11:6 | b | conversions.go:11:2:11:7 | call to use |
+| conversions.go:13:6:13:8 | assignment to arr | conversions.go:14:2:14:6 | skip |
+| conversions.go:13:6:13:8 | skip | conversions.go:13:6:13:8 | zero value for arr |
+| conversions.go:13:6:13:8 | zero value for arr | conversions.go:13:6:13:8 | assignment to arr |
+| conversions.go:14:2:14:6 | assignment to slice | conversions.go:17:2:17:4 | skip |
+| conversions.go:14:2:14:6 | skip | conversions.go:14:11:14:22 | selection of Slice |
+| conversions.go:14:11:14:22 | selection of Slice | conversions.go:14:24:14:26 | arr |
+| conversions.go:14:11:14:31 | call to Slice | conversions.go:14:2:14:6 | assignment to slice |
+| conversions.go:14:24:14:26 | arr | conversions.go:14:29:14:30 | 20 |
+| conversions.go:14:29:14:30 | 20 | conversions.go:14:11:14:31 | call to Slice |
+| conversions.go:17:2:17:4 | assignment to ptr | conversions.go:18:2:18:4 | use |
+| conversions.go:17:2:17:4 | skip | conversions.go:17:20:17:24 | slice |
+| conversions.go:17:9:17:25 | type conversion | conversions.go:17:2:17:4 | assignment to ptr |
+| conversions.go:17:9:17:25 | type conversion | conversions.go:26:1:26:1 | exit |
+| conversions.go:17:20:17:24 | slice | conversions.go:17:9:17:25 | type conversion |
+| conversions.go:18:2:18:4 | use | conversions.go:18:6:18:8 | ptr |
+| conversions.go:18:2:18:9 | call to use | conversions.go:21:2:21:4 | skip |
+| conversions.go:18:2:18:9 | call to use | conversions.go:26:1:26:1 | exit |
+| conversions.go:18:6:18:8 | ptr | conversions.go:18:2:18:9 | call to use |
+| conversions.go:21:2:21:4 | assignment to str | conversions.go:22:2:22:6 | skip |
+| conversions.go:21:2:21:4 | skip | conversions.go:21:9:21:18 | "a string" |
+| conversions.go:21:9:21:18 | "a string" | conversions.go:21:2:21:4 | assignment to str |
+| conversions.go:22:2:22:6 | assignment to bytes | conversions.go:23:2:23:4 | use |
+| conversions.go:22:2:22:6 | skip | conversions.go:22:18:22:20 | str |
+| conversions.go:22:11:22:21 | type conversion | conversions.go:22:2:22:6 | assignment to bytes |
+| conversions.go:22:18:22:20 | str | conversions.go:22:11:22:21 | type conversion |
+| conversions.go:23:2:23:4 | use | conversions.go:23:6:23:10 | bytes |
+| conversions.go:23:2:23:11 | call to use | conversions.go:24:2:24:6 | skip |
+| conversions.go:23:2:23:11 | call to use | conversions.go:26:1:26:1 | exit |
+| conversions.go:23:6:23:10 | bytes | conversions.go:23:2:23:11 | call to use |
+| conversions.go:24:2:24:6 | assignment to runes | conversions.go:25:2:25:4 | use |
+| conversions.go:24:2:24:6 | skip | conversions.go:24:18:24:20 | str |
+| conversions.go:24:11:24:21 | type conversion | conversions.go:24:2:24:6 | assignment to runes |
+| conversions.go:24:18:24:20 | str | conversions.go:24:11:24:21 | type conversion |
+| conversions.go:25:2:25:4 | use | conversions.go:25:6:25:10 | runes |
+| conversions.go:25:2:25:11 | call to use | conversions.go:26:1:26:1 | exit |
+| conversions.go:25:6:25:10 | runes | conversions.go:25:2:25:11 | call to use |
+#select
+| |
diff --git a/ql/test/extractor-tests/go1.17/CFG.ql b/ql/test/extractor-tests/go1.17/CFG.ql
new file mode 100644
index 00000000000..5db94a8ad39
--- /dev/null
+++ b/ql/test/extractor-tests/go1.17/CFG.ql
@@ -0,0 +1,9 @@
+import go
+
+query predicate nodes(ControlFlow::Node nd) { none() }
+
+query predicate edges(ControlFlow::Node pred, ControlFlow::Node succ) {
+ succ = pred.getASuccessor()
+}
+
+select ""
diff --git a/ql/test/extractor-tests/go1.17/conversions.go b/ql/test/extractor-tests/go1.17/conversions.go
new file mode 100644
index 00000000000..2439a2e567c
--- /dev/null
+++ b/ql/test/extractor-tests/go1.17/conversions.go
@@ -0,0 +1,26 @@
+package main
+
+import "unsafe"
+
+func use(_ ...interface{}) {}
+
+func main() {
+ var a unsafe.Pointer
+
+ b := unsafe.Add(a, 10)
+ use(b)
+
+ var arr *int
+ slice := unsafe.Slice(arr, 20)
+
+ // may panic
+ ptr := (*[10]int)(slice)
+ use(ptr)
+
+ // cannot panic
+ str := "a string"
+ bytes := []byte(str)
+ use(bytes)
+ runes := []rune(str)
+ use(runes)
+}
diff --git a/ql/test/extractor-tests/go1.17/go.mod b/ql/test/extractor-tests/go1.17/go.mod
new file mode 100644
index 00000000000..682337bee86
--- /dev/null
+++ b/ql/test/extractor-tests/go1.17/go.mod
@@ -0,0 +1,3 @@
+module extractor-tests/go117
+
+go 1.17
diff --git a/ql/test/library-tests/semmle/go/Files/CONSISTENCY/UnexpectedFrontendErrors.expected b/ql/test/library-tests/semmle/go/Files/CONSISTENCY/UnexpectedFrontendErrors.expected
index 8f5c8cc5d4b..6a47139fb8d 100644
--- a/ql/test/library-tests/semmle/go/Files/CONSISTENCY/UnexpectedFrontendErrors.expected
+++ b/ql/test/library-tests/semmle/go/Files/CONSISTENCY/UnexpectedFrontendErrors.expected
@@ -1 +1,5 @@
+| -:0:0:0:0 | package ; expected nonexistent |
+| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected ';', found 'EOF' |
+| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected 'IDENT', found 'EOF' |
+| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected 'package', found 'EOF' |
| vendor/github.com/github/nonexistent/bad.go:1:57:1:57 | expected 'package', found 'EOF' |
diff --git a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.expected b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.expected
index 615418114ba..4e62ba42deb 100644
--- a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.expected
+++ b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.expected
@@ -1,4 +1,1410 @@
-nodes
edges
+| DuplicateSwitchCase.go:0:0:0:0 | entry | DuplicateSwitchCase.go:3:6:3:15 | skip |
+| DuplicateSwitchCase.go:3:1:3:1 | entry | DuplicateSwitchCase.go:3:17:3:19 | argument corresponding to msg |
+| DuplicateSwitchCase.go:3:1:12:1 | function declaration | DuplicateSwitchCase.go:14:6:14:10 | skip |
+| DuplicateSwitchCase.go:3:6:3:15 | skip | DuplicateSwitchCase.go:3:1:12:1 | function declaration |
+| DuplicateSwitchCase.go:3:17:3:19 | argument corresponding to msg | DuplicateSwitchCase.go:3:17:3:19 | initialization of msg |
+| DuplicateSwitchCase.go:3:17:3:19 | initialization of msg | DuplicateSwitchCase.go:4:2:4:2 | true |
+| DuplicateSwitchCase.go:4:2:4:2 | true | DuplicateSwitchCase.go:5:7:5:9 | msg |
+| DuplicateSwitchCase.go:5:7:5:9 | msg | DuplicateSwitchCase.go:5:14:5:20 | "start" |
+| DuplicateSwitchCase.go:5:7:5:20 | ...==... | DuplicateSwitchCase.go:5:7:5:20 | case ...==... |
+| DuplicateSwitchCase.go:5:7:5:20 | case ...==... | DuplicateSwitchCase.go:5:20:5:20 | ...==... is false |
+| DuplicateSwitchCase.go:5:7:5:20 | case ...==... | DuplicateSwitchCase.go:5:20:5:20 | ...==... is true |
+| DuplicateSwitchCase.go:5:14:5:20 | "start" | DuplicateSwitchCase.go:5:7:5:20 | ...==... |
+| DuplicateSwitchCase.go:5:20:5:20 | ...==... is false | DuplicateSwitchCase.go:7:7:7:9 | msg |
+| DuplicateSwitchCase.go:5:20:5:20 | ...==... is true | DuplicateSwitchCase.go:6:3:6:7 | start |
+| DuplicateSwitchCase.go:6:3:6:7 | start | DuplicateSwitchCase.go:6:3:6:9 | call to start |
+| DuplicateSwitchCase.go:6:3:6:9 | call to start | DuplicateSwitchCase.go:12:1:12:1 | exit |
+| DuplicateSwitchCase.go:7:7:7:9 | msg | DuplicateSwitchCase.go:7:14:7:20 | "start" |
+| DuplicateSwitchCase.go:7:7:7:20 | ...==... | DuplicateSwitchCase.go:7:7:7:20 | case ...==... |
+| DuplicateSwitchCase.go:7:7:7:20 | case ...==... | DuplicateSwitchCase.go:7:20:7:20 | ...==... is false |
+| DuplicateSwitchCase.go:7:7:7:20 | case ...==... | DuplicateSwitchCase.go:7:20:7:20 | ...==... is true |
+| DuplicateSwitchCase.go:7:14:7:20 | "start" | DuplicateSwitchCase.go:7:7:7:20 | ...==... |
+| DuplicateSwitchCase.go:7:20:7:20 | ...==... is false | DuplicateSwitchCase.go:10:3:10:7 | panic |
+| DuplicateSwitchCase.go:7:20:7:20 | ...==... is true | DuplicateSwitchCase.go:8:3:8:6 | stop |
+| DuplicateSwitchCase.go:8:3:8:6 | stop | DuplicateSwitchCase.go:8:3:8:8 | call to stop |
+| DuplicateSwitchCase.go:8:3:8:8 | call to stop | DuplicateSwitchCase.go:12:1:12:1 | exit |
+| DuplicateSwitchCase.go:10:3:10:7 | panic | DuplicateSwitchCase.go:10:9:10:33 | "Message not understood." |
+| DuplicateSwitchCase.go:10:3:10:34 | call to panic | DuplicateSwitchCase.go:12:1:12:1 | exit |
+| DuplicateSwitchCase.go:10:9:10:33 | "Message not understood." | DuplicateSwitchCase.go:10:3:10:34 | call to panic |
+| DuplicateSwitchCase.go:14:1:14:1 | entry | DuplicateSwitchCase.go:14:14:14:15 | skip |
+| DuplicateSwitchCase.go:14:1:14:15 | function declaration | DuplicateSwitchCase.go:16:6:16:9 | skip |
+| DuplicateSwitchCase.go:14:6:14:10 | skip | DuplicateSwitchCase.go:14:1:14:15 | function declaration |
+| DuplicateSwitchCase.go:14:14:14:15 | skip | DuplicateSwitchCase.go:14:15:14:15 | exit |
+| DuplicateSwitchCase.go:16:1:16:1 | entry | DuplicateSwitchCase.go:16:13:16:14 | skip |
+| DuplicateSwitchCase.go:16:1:16:14 | function declaration | DuplicateSwitchCase.go:0:0:0:0 | exit |
+| DuplicateSwitchCase.go:16:6:16:9 | skip | DuplicateSwitchCase.go:16:1:16:14 | function declaration |
+| DuplicateSwitchCase.go:16:13:16:14 | skip | DuplicateSwitchCase.go:16:14:16:14 | exit |
+| equalitytests.go:0:0:0:0 | entry | equalitytests.go:3:1:5:1 | skip |
+| equalitytests.go:3:1:5:1 | skip | equalitytests.go:7:1:9:1 | skip |
+| equalitytests.go:7:1:9:1 | skip | equalitytests.go:11:6:11:18 | skip |
+| equalitytests.go:11:1:11:1 | entry | equalitytests.go:11:20:11:21 | argument corresponding to i1 |
+| equalitytests.go:11:1:13:1 | function declaration | equalitytests.go:0:0:0:0 | exit |
+| equalitytests.go:11:6:11:18 | skip | equalitytests.go:11:1:13:1 | function declaration |
+| equalitytests.go:11:20:11:21 | argument corresponding to i1 | equalitytests.go:11:20:11:21 | initialization of i1 |
+| equalitytests.go:11:20:11:21 | initialization of i1 | equalitytests.go:11:28:11:29 | argument corresponding to i2 |
+| equalitytests.go:11:28:11:29 | argument corresponding to i2 | equalitytests.go:11:28:11:29 | initialization of i2 |
+| equalitytests.go:11:28:11:29 | initialization of i2 | equalitytests.go:11:36:11:37 | argument corresponding to e1 |
+| equalitytests.go:11:36:11:37 | argument corresponding to e1 | equalitytests.go:11:36:11:37 | initialization of e1 |
+| equalitytests.go:11:36:11:37 | initialization of e1 | equalitytests.go:11:46:11:47 | argument corresponding to e2 |
+| equalitytests.go:11:46:11:47 | argument corresponding to e2 | equalitytests.go:11:46:11:47 | initialization of e2 |
+| equalitytests.go:11:46:11:47 | initialization of e2 | equalitytests.go:11:56:11:57 | argument corresponding to s1 |
+| equalitytests.go:11:56:11:57 | argument corresponding to s1 | equalitytests.go:11:56:11:57 | initialization of s1 |
+| equalitytests.go:11:56:11:57 | initialization of s1 | equalitytests.go:11:83:11:84 | argument corresponding to s2 |
+| equalitytests.go:11:83:11:84 | argument corresponding to s2 | equalitytests.go:11:83:11:84 | initialization of s2 |
+| equalitytests.go:11:83:11:84 | initialization of s2 | equalitytests.go:11:110:11:111 | argument corresponding to s3 |
+| equalitytests.go:11:110:11:111 | argument corresponding to s3 | equalitytests.go:11:110:11:111 | initialization of s3 |
+| equalitytests.go:11:110:11:111 | initialization of s3 | equalitytests.go:11:134:11:135 | argument corresponding to s4 |
+| equalitytests.go:11:134:11:135 | argument corresponding to s4 | equalitytests.go:11:134:11:135 | initialization of s4 |
+| equalitytests.go:11:134:11:135 | initialization of s4 | equalitytests.go:11:158:11:159 | argument corresponding to a1 |
+| equalitytests.go:11:158:11:159 | argument corresponding to a1 | equalitytests.go:11:158:11:159 | initialization of a1 |
+| equalitytests.go:11:158:11:159 | initialization of a1 | equalitytests.go:11:171:11:172 | argument corresponding to a2 |
+| equalitytests.go:11:171:11:172 | argument corresponding to a2 | equalitytests.go:11:171:11:172 | initialization of a2 |
+| equalitytests.go:11:171:11:172 | initialization of a2 | equalitytests.go:11:184:11:185 | argument corresponding to a3 |
+| equalitytests.go:11:184:11:185 | argument corresponding to a3 | equalitytests.go:11:184:11:185 | initialization of a3 |
+| equalitytests.go:11:184:11:185 | initialization of a3 | equalitytests.go:11:195:11:196 | argument corresponding to a4 |
+| equalitytests.go:11:195:11:196 | argument corresponding to a4 | equalitytests.go:11:195:11:196 | initialization of a4 |
+| equalitytests.go:11:195:11:196 | initialization of a4 | equalitytests.go:12:9:12:10 | i1 |
+| equalitytests.go:12:2:12:76 | return statement | equalitytests.go:13:1:13:1 | exit |
+| equalitytests.go:12:9:12:10 | i1 | equalitytests.go:12:15:12:16 | i2 |
+| equalitytests.go:12:9:12:16 | ...==... | equalitytests.go:12:16:12:16 | ...==... is false |
+| equalitytests.go:12:9:12:16 | ...==... | equalitytests.go:12:16:12:16 | ...==... is true |
+| equalitytests.go:12:9:12:76 | ...&&... | equalitytests.go:12:2:12:76 | return statement |
+| equalitytests.go:12:15:12:16 | i2 | equalitytests.go:12:9:12:16 | ...==... |
+| equalitytests.go:12:16:12:16 | ...==... is false | equalitytests.go:12:28:12:28 | ...&&... is false |
+| equalitytests.go:12:16:12:16 | ...==... is true | equalitytests.go:12:21:12:22 | e1 |
+| equalitytests.go:12:21:12:22 | e1 | equalitytests.go:12:27:12:28 | e2 |
+| equalitytests.go:12:21:12:28 | ...==... | equalitytests.go:12:28:12:28 | ...&&... is false |
+| equalitytests.go:12:21:12:28 | ...==... | equalitytests.go:12:28:12:28 | ...&&... is true |
+| equalitytests.go:12:21:12:28 | ...==... | equalitytests.go:13:1:13:1 | exit |
+| equalitytests.go:12:27:12:28 | e2 | equalitytests.go:12:21:12:28 | ...==... |
+| equalitytests.go:12:28:12:28 | ...&&... is false | equalitytests.go:12:40:12:40 | ...&&... is false |
+| equalitytests.go:12:28:12:28 | ...&&... is true | equalitytests.go:12:33:12:34 | s1 |
+| equalitytests.go:12:33:12:34 | s1 | equalitytests.go:12:39:12:40 | s2 |
+| equalitytests.go:12:33:12:40 | ...==... | equalitytests.go:12:40:12:40 | ...&&... is false |
+| equalitytests.go:12:33:12:40 | ...==... | equalitytests.go:12:40:12:40 | ...&&... is true |
+| equalitytests.go:12:33:12:40 | ...==... | equalitytests.go:13:1:13:1 | exit |
+| equalitytests.go:12:39:12:40 | s2 | equalitytests.go:12:33:12:40 | ...==... |
+| equalitytests.go:12:40:12:40 | ...&&... is false | equalitytests.go:12:52:12:52 | ...&&... is false |
+| equalitytests.go:12:40:12:40 | ...&&... is true | equalitytests.go:12:45:12:46 | s3 |
+| equalitytests.go:12:45:12:46 | s3 | equalitytests.go:12:51:12:52 | s4 |
+| equalitytests.go:12:45:12:52 | ...==... | equalitytests.go:12:52:12:52 | ...&&... is false |
+| equalitytests.go:12:45:12:52 | ...==... | equalitytests.go:12:52:12:52 | ...&&... is true |
+| equalitytests.go:12:45:12:52 | ...==... | equalitytests.go:13:1:13:1 | exit |
+| equalitytests.go:12:51:12:52 | s4 | equalitytests.go:12:45:12:52 | ...==... |
+| equalitytests.go:12:52:12:52 | ...&&... is false | equalitytests.go:12:64:12:64 | ...&&... is false |
+| equalitytests.go:12:52:12:52 | ...&&... is true | equalitytests.go:12:57:12:58 | a1 |
+| equalitytests.go:12:57:12:58 | a1 | equalitytests.go:12:63:12:64 | a2 |
+| equalitytests.go:12:57:12:64 | ...==... | equalitytests.go:12:64:12:64 | ...&&... is false |
+| equalitytests.go:12:57:12:64 | ...==... | equalitytests.go:12:64:12:64 | ...&&... is true |
+| equalitytests.go:12:57:12:64 | ...==... | equalitytests.go:13:1:13:1 | exit |
+| equalitytests.go:12:63:12:64 | a2 | equalitytests.go:12:57:12:64 | ...==... |
+| equalitytests.go:12:64:12:64 | ...&&... is false | equalitytests.go:12:9:12:76 | ...&&... |
+| equalitytests.go:12:64:12:64 | ...&&... is true | equalitytests.go:12:69:12:70 | a3 |
+| equalitytests.go:12:69:12:70 | a3 | equalitytests.go:12:75:12:76 | a4 |
+| equalitytests.go:12:69:12:76 | ...==... | equalitytests.go:12:9:12:76 | ...&&... |
+| equalitytests.go:12:69:12:76 | ...==... | equalitytests.go:13:1:13:1 | exit |
+| equalitytests.go:12:75:12:76 | a4 | equalitytests.go:12:69:12:76 | ...==... |
+| exprs.go:0:0:0:0 | entry | exprs.go:3:1:3:29 | skip |
+| exprs.go:3:1:3:29 | skip | exprs.go:5:6:5:9 | skip |
+| exprs.go:5:1:5:1 | entry | exprs.go:6:6:6:6 | skip |
+| exprs.go:5:1:26:1 | function declaration | exprs.go:28:6:28:10 | skip |
+| exprs.go:5:6:5:9 | skip | exprs.go:5:1:26:1 | function declaration |
+| exprs.go:6:6:6:6 | assignment to i | exprs.go:6:9:6:9 | assignment to j |
+| exprs.go:6:6:6:6 | skip | exprs.go:6:9:6:9 | skip |
+| exprs.go:6:9:6:9 | assignment to j | exprs.go:7:6:7:6 | skip |
+| exprs.go:6:9:6:9 | skip | exprs.go:6:13:6:13 | 0 |
+| exprs.go:6:13:6:13 | 0 | exprs.go:6:16:6:26 | ...+... |
+| exprs.go:6:16:6:26 | ...+... | exprs.go:6:6:6:6 | assignment to i |
+| exprs.go:7:6:7:6 | assignment to k | exprs.go:8:2:8:2 | skip |
+| exprs.go:7:6:7:6 | skip | exprs.go:7:10:7:10 | i |
+| exprs.go:7:10:7:10 | i | exprs.go:7:14:7:14 | 2 |
+| exprs.go:7:10:7:16 | ...+... | exprs.go:7:6:7:6 | assignment to k |
+| exprs.go:7:14:7:14 | 2 | exprs.go:7:16:7:16 | j |
+| exprs.go:7:14:7:16 | ...*... | exprs.go:7:10:7:16 | ...+... |
+| exprs.go:7:16:7:16 | j | exprs.go:7:14:7:16 | ...*... |
+| exprs.go:8:2:8:2 | assignment to s | exprs.go:9:2:9:3 | skip |
+| exprs.go:8:2:8:2 | skip | exprs.go:8:7:8:12 | "k = " |
+| exprs.go:8:7:8:12 | "k = " | exprs.go:8:23:8:23 | k |
+| exprs.go:8:7:8:24 | ...+... | exprs.go:8:2:8:2 | assignment to s |
+| exprs.go:8:16:8:24 | type conversion | exprs.go:8:7:8:24 | ...+... |
+| exprs.go:8:23:8:23 | k | exprs.go:8:16:8:24 | type conversion |
+| exprs.go:9:2:9:3 | assignment to fn | exprs.go:10:2:10:8 | skip |
+| exprs.go:9:2:9:3 | skip | exprs.go:9:8:9:61 | function literal |
+| exprs.go:9:8:9:8 | entry | exprs.go:9:13:9:13 | argument corresponding to a |
+| exprs.go:9:8:9:61 | function literal | exprs.go:9:2:9:3 | assignment to fn |
+| exprs.go:9:13:9:13 | argument corresponding to a | exprs.go:9:13:9:13 | initialization of a |
+| exprs.go:9:13:9:13 | initialization of a | exprs.go:9:16:9:16 | argument corresponding to b |
+| exprs.go:9:16:9:16 | argument corresponding to b | exprs.go:9:16:9:16 | initialization of b |
+| exprs.go:9:16:9:16 | initialization of b | exprs.go:9:23:9:23 | argument corresponding to z |
+| exprs.go:9:23:9:23 | argument corresponding to z | exprs.go:9:23:9:23 | initialization of z |
+| exprs.go:9:23:9:23 | initialization of z | exprs.go:9:48:9:48 | a |
+| exprs.go:9:41:9:59 | return statement | exprs.go:9:61:9:61 | exit |
+| exprs.go:9:48:9:48 | a | exprs.go:9:50:9:50 | b |
+| exprs.go:9:48:9:50 | ...*... | exprs.go:9:58:9:58 | z |
+| exprs.go:9:48:9:59 | ...<... | exprs.go:9:41:9:59 | return statement |
+| exprs.go:9:50:9:50 | b | exprs.go:9:48:9:50 | ...*... |
+| exprs.go:9:54:9:59 | type conversion | exprs.go:9:48:9:59 | ...<... |
+| exprs.go:9:58:9:58 | z | exprs.go:9:54:9:59 | type conversion |
+| exprs.go:10:2:10:8 | assignment to struct1 | exprs.go:11:2:11:8 | skip |
+| exprs.go:10:2:10:8 | skip | exprs.go:10:13:10:32 | struct literal |
+| exprs.go:10:13:10:32 | struct literal | exprs.go:10:2:10:8 | assignment to struct1 |
+| exprs.go:11:2:11:8 | assignment to struct2 | exprs.go:15:2:15:8 | skip |
+| exprs.go:11:2:11:8 | skip | exprs.go:11:13:14:21 | struct literal |
+| exprs.go:11:13:14:21 | struct literal | exprs.go:14:4:14:4 | k |
+| exprs.go:14:4:14:4 | init of k | exprs.go:14:7:14:8 | fn |
+| exprs.go:14:4:14:4 | k | exprs.go:14:4:14:4 | init of k |
+| exprs.go:14:7:14:8 | fn | exprs.go:14:10:14:10 | i |
+| exprs.go:14:7:14:20 | call to fn | exprs.go:14:7:14:20 | init of call to fn |
+| exprs.go:14:7:14:20 | call to fn | exprs.go:26:1:26:1 | exit |
+| exprs.go:14:7:14:20 | init of call to fn | exprs.go:11:2:11:8 | assignment to struct2 |
+| exprs.go:14:10:14:10 | i | exprs.go:14:13:14:13 | j |
+| exprs.go:14:13:14:13 | j | exprs.go:14:16:14:19 | .../... |
+| exprs.go:14:16:14:19 | .../... | exprs.go:14:7:14:20 | call to fn |
+| exprs.go:15:2:15:8 | assignment to struct3 | exprs.go:16:2:16:5 | skip |
+| exprs.go:15:2:15:8 | skip | exprs.go:15:13:15:58 | struct literal |
+| exprs.go:15:13:15:58 | struct literal | exprs.go:15:35:15:41 | struct1 |
+| exprs.go:15:32:15:43 | init of key-value pair | exprs.go:15:49:15:55 | struct2 |
+| exprs.go:15:35:15:41 | struct1 | exprs.go:15:35:15:43 | selection of x |
+| exprs.go:15:35:15:43 | selection of x | exprs.go:15:32:15:43 | init of key-value pair |
+| exprs.go:15:46:15:57 | init of key-value pair | exprs.go:15:2:15:8 | assignment to struct3 |
+| exprs.go:15:49:15:55 | struct2 | exprs.go:15:49:15:57 | selection of x |
+| exprs.go:15:49:15:57 | selection of x | exprs.go:15:46:15:57 | init of key-value pair |
+| exprs.go:16:2:16:5 | assignment to arr1 | exprs.go:17:2:17:5 | skip |
+| exprs.go:16:2:16:5 | skip | exprs.go:16:10:16:26 | array literal |
+| exprs.go:16:10:16:26 | array literal | exprs.go:16:17:16:17 | element index |
+| exprs.go:16:17:16:17 | element index | exprs.go:16:17:16:23 | struct3 |
+| exprs.go:16:17:16:23 | struct3 | exprs.go:16:17:16:25 | selection of x |
+| exprs.go:16:17:16:25 | init of selection of x | exprs.go:16:2:16:5 | assignment to arr1 |
+| exprs.go:16:17:16:25 | selection of x | exprs.go:16:17:16:25 | init of selection of x |
+| exprs.go:17:2:17:5 | assignment to arr2 | exprs.go:18:2:18:4 | skip |
+| exprs.go:17:2:17:5 | skip | exprs.go:17:10:17:40 | array literal |
+| exprs.go:17:10:17:40 | array literal | exprs.go:17:19:17:19 | element index |
+| exprs.go:17:19:17:19 | element index | exprs.go:17:19:17:25 | struct3 |
+| exprs.go:17:19:17:25 | struct3 | exprs.go:17:19:17:27 | selection of x |
+| exprs.go:17:19:17:27 | init of selection of x | exprs.go:17:30:17:30 | 2 |
+| exprs.go:17:19:17:27 | selection of x | exprs.go:17:19:17:27 | init of selection of x |
+| exprs.go:17:30:17:30 | 2 | exprs.go:17:33:17:36 | arr1 |
+| exprs.go:17:30:17:39 | init of key-value pair | exprs.go:17:2:17:5 | assignment to arr2 |
+| exprs.go:17:33:17:36 | arr1 | exprs.go:17:38:17:38 | 0 |
+| exprs.go:17:33:17:39 | index expression | exprs.go:17:30:17:39 | init of key-value pair |
+| exprs.go:17:33:17:39 | index expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:17:38:17:38 | 0 | exprs.go:17:33:17:39 | index expression |
+| exprs.go:18:2:18:4 | assignment to slc | exprs.go:19:2:19:3 | skip |
+| exprs.go:18:2:18:4 | skip | exprs.go:18:9:18:22 | slice literal |
+| exprs.go:18:9:18:22 | slice literal | exprs.go:18:18:18:18 | element index |
+| exprs.go:18:18:18:18 | element index | exprs.go:18:18:18:18 | s |
+| exprs.go:18:18:18:18 | init of s | exprs.go:18:21:18:21 | element index |
+| exprs.go:18:18:18:18 | s | exprs.go:18:18:18:18 | init of s |
+| exprs.go:18:21:18:21 | element index | exprs.go:18:21:18:21 | s |
+| exprs.go:18:21:18:21 | init of s | exprs.go:18:2:18:4 | assignment to slc |
+| exprs.go:18:21:18:21 | s | exprs.go:18:21:18:21 | init of s |
+| exprs.go:19:2:19:3 | assignment to mp | exprs.go:20:2:20:5 | skip |
+| exprs.go:19:2:19:3 | skip | exprs.go:19:8:19:38 | map literal |
+| exprs.go:19:8:19:38 | map literal | exprs.go:19:23:19:25 | slc |
+| exprs.go:19:23:19:25 | slc | exprs.go:19:27:19:27 | 0 |
+| exprs.go:19:23:19:28 | index expression | exprs.go:19:31:19:34 | arr2 |
+| exprs.go:19:23:19:28 | index expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:19:23:19:37 | init of key-value pair | exprs.go:19:2:19:3 | assignment to mp |
+| exprs.go:19:27:19:27 | 0 | exprs.go:19:23:19:28 | index expression |
+| exprs.go:19:31:19:34 | arr2 | exprs.go:19:36:19:36 | 1 |
+| exprs.go:19:31:19:37 | index expression | exprs.go:19:23:19:37 | init of key-value pair |
+| exprs.go:19:31:19:37 | index expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:19:36:19:36 | 1 | exprs.go:19:31:19:37 | index expression |
+| exprs.go:20:2:20:5 | assignment to slc2 | exprs.go:21:2:21:5 | skip |
+| exprs.go:20:2:20:5 | skip | exprs.go:20:10:20:12 | slc |
+| exprs.go:20:10:20:12 | slc | exprs.go:20:14:20:14 | 1 |
+| exprs.go:20:10:20:19 | slice expression | exprs.go:20:2:20:5 | assignment to slc2 |
+| exprs.go:20:10:20:19 | slice expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:20:14:20:14 | 1 | exprs.go:20:16:20:16 | 2 |
+| exprs.go:20:16:20:16 | 2 | exprs.go:20:18:20:18 | 3 |
+| exprs.go:20:18:20:18 | 3 | exprs.go:20:10:20:19 | slice expression |
+| exprs.go:21:2:21:5 | assignment to slc3 | exprs.go:22:2:22:5 | skip |
+| exprs.go:21:2:21:5 | skip | exprs.go:21:10:21:13 | slc2 |
+| exprs.go:21:10:21:13 | slc2 | exprs.go:21:10:21:19 | 0 |
+| exprs.go:21:10:21:19 | 0 | exprs.go:21:16:21:16 | 2 |
+| exprs.go:21:10:21:19 | slice expression | exprs.go:21:2:21:5 | assignment to slc3 |
+| exprs.go:21:10:21:19 | slice expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:21:16:21:16 | 2 | exprs.go:21:18:21:18 | 3 |
+| exprs.go:21:18:21:18 | 3 | exprs.go:21:10:21:19 | slice expression |
+| exprs.go:22:2:22:5 | assignment to slc4 | exprs.go:23:2:23:5 | skip |
+| exprs.go:22:2:22:5 | skip | exprs.go:22:10:22:13 | slc3 |
+| exprs.go:22:10:22:13 | slc3 | exprs.go:22:15:22:15 | 0 |
+| exprs.go:22:10:22:18 | cap | exprs.go:22:10:22:18 | slice expression |
+| exprs.go:22:10:22:18 | slice expression | exprs.go:22:2:22:5 | assignment to slc4 |
+| exprs.go:22:10:22:18 | slice expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:22:15:22:15 | 0 | exprs.go:22:17:22:17 | 2 |
+| exprs.go:22:17:22:17 | 2 | exprs.go:22:10:22:18 | cap |
+| exprs.go:23:2:23:5 | assignment to slc5 | exprs.go:24:2:24:5 | skip |
+| exprs.go:23:2:23:5 | skip | exprs.go:23:10:23:13 | slc4 |
+| exprs.go:23:10:23:13 | slc4 | exprs.go:23:15:23:15 | 0 |
+| exprs.go:23:10:23:17 | cap | exprs.go:23:10:23:17 | slice expression |
+| exprs.go:23:10:23:17 | len | exprs.go:23:10:23:17 | cap |
+| exprs.go:23:10:23:17 | slice expression | exprs.go:23:2:23:5 | assignment to slc5 |
+| exprs.go:23:10:23:17 | slice expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:23:15:23:15 | 0 | exprs.go:23:10:23:17 | len |
+| exprs.go:24:2:24:5 | assignment to slc6 | exprs.go:25:9:25:34 | struct literal |
+| exprs.go:24:2:24:5 | skip | exprs.go:24:10:24:13 | slc5 |
+| exprs.go:24:10:24:13 | slc5 | exprs.go:24:10:24:17 | 0 |
+| exprs.go:24:10:24:17 | 0 | exprs.go:24:16:24:16 | 2 |
+| exprs.go:24:10:24:17 | cap | exprs.go:24:10:24:17 | slice expression |
+| exprs.go:24:10:24:17 | slice expression | exprs.go:24:2:24:5 | assignment to slc6 |
+| exprs.go:24:10:24:17 | slice expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:24:16:24:16 | 2 | exprs.go:24:10:24:17 | cap |
+| exprs.go:25:2:25:34 | return statement | exprs.go:26:1:26:1 | exit |
+| exprs.go:25:9:25:34 | struct literal | exprs.go:25:15:25:16 | mp |
+| exprs.go:25:15:25:16 | mp | exprs.go:25:18:25:18 | s |
+| exprs.go:25:15:25:19 | index expression | exprs.go:25:15:25:19 | init of index expression |
+| exprs.go:25:15:25:19 | index expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:25:15:25:19 | init of index expression | exprs.go:25:22:25:24 | len |
+| exprs.go:25:18:25:18 | s | exprs.go:25:15:25:19 | index expression |
+| exprs.go:25:22:25:24 | len | exprs.go:25:26:25:29 | slc6 |
+| exprs.go:25:22:25:33 | call to len | exprs.go:25:22:25:33 | init of call to len |
+| exprs.go:25:22:25:33 | init of call to len | exprs.go:25:2:25:34 | return statement |
+| exprs.go:25:26:25:29 | slc6 | exprs.go:25:31:25:31 | 0 |
+| exprs.go:25:26:25:32 | index expression | exprs.go:25:22:25:33 | call to len |
+| exprs.go:25:26:25:32 | index expression | exprs.go:26:1:26:1 | exit |
+| exprs.go:25:31:25:31 | 0 | exprs.go:25:26:25:32 | index expression |
+| exprs.go:28:1:28:1 | entry | exprs.go:28:12:28:14 | argument corresponding to arg |
+| exprs.go:28:1:30:1 | function declaration | exprs.go:32:6:32:10 | skip |
+| exprs.go:28:6:28:10 | skip | exprs.go:28:1:30:1 | function declaration |
+| exprs.go:28:12:28:14 | argument corresponding to arg | exprs.go:28:12:28:14 | initialization of arg |
+| exprs.go:28:12:28:14 | initialization of arg | exprs.go:29:9:29:11 | arg |
+| exprs.go:29:2:29:21 | return statement | exprs.go:30:1:30:1 | exit |
+| exprs.go:29:9:29:11 | arg | exprs.go:29:9:29:19 | type assertion |
+| exprs.go:29:9:29:19 | type assertion | exprs.go:29:9:29:21 | selection of x |
+| exprs.go:29:9:29:19 | type assertion | exprs.go:30:1:30:1 | exit |
+| exprs.go:29:9:29:21 | selection of x | exprs.go:29:2:29:21 | return statement |
+| exprs.go:32:1:32:1 | entry | exprs.go:32:12:32:14 | argument corresponding to arg |
+| exprs.go:32:1:37:1 | function declaration | exprs.go:39:6:39:10 | skip |
+| exprs.go:32:6:32:10 | skip | exprs.go:32:1:37:1 | function declaration |
+| exprs.go:32:12:32:14 | argument corresponding to arg | exprs.go:32:12:32:14 | initialization of arg |
+| exprs.go:32:12:32:14 | initialization of arg | exprs.go:33:5:33:5 | skip |
+| exprs.go:33:5:33:5 | assignment to p | exprs.go:33:5:33:24 | ... := ...[1] |
+| exprs.go:33:5:33:5 | skip | exprs.go:33:8:33:9 | skip |
+| exprs.go:33:5:33:24 | ... := ...[0] | exprs.go:33:5:33:5 | assignment to p |
+| exprs.go:33:5:33:24 | ... := ...[1] | exprs.go:33:8:33:9 | assignment to ok |
+| exprs.go:33:8:33:9 | assignment to ok | exprs.go:33:27:33:28 | ok |
+| exprs.go:33:8:33:9 | skip | exprs.go:33:14:33:16 | arg |
+| exprs.go:33:14:33:16 | arg | exprs.go:33:14:33:24 | type assertion |
+| exprs.go:33:14:33:24 | type assertion | exprs.go:33:5:33:24 | ... := ...[0] |
+| exprs.go:33:27:33:28 | ok | exprs.go:33:28:33:28 | ok is false |
+| exprs.go:33:27:33:28 | ok | exprs.go:33:28:33:28 | ok is true |
+| exprs.go:33:28:33:28 | ok is false | exprs.go:36:9:36:10 | -... |
+| exprs.go:33:28:33:28 | ok is true | exprs.go:34:10:34:10 | p |
+| exprs.go:34:3:34:12 | return statement | exprs.go:37:1:37:1 | exit |
+| exprs.go:34:10:34:10 | p | exprs.go:34:10:34:12 | selection of x |
+| exprs.go:34:10:34:12 | selection of x | exprs.go:34:3:34:12 | return statement |
+| exprs.go:36:2:36:10 | return statement | exprs.go:37:1:37:1 | exit |
+| exprs.go:36:9:36:10 | -... | exprs.go:36:2:36:10 | return statement |
+| exprs.go:39:1:39:1 | entry | exprs.go:39:12:39:14 | argument corresponding to arg |
+| exprs.go:39:1:47:1 | function declaration | exprs.go:49:6:49:8 | skip |
+| exprs.go:39:6:39:10 | skip | exprs.go:39:1:47:1 | function declaration |
+| exprs.go:39:12:39:14 | argument corresponding to arg | exprs.go:39:12:39:14 | initialization of arg |
+| exprs.go:39:12:39:14 | initialization of arg | exprs.go:40:6:40:6 | skip |
+| exprs.go:40:6:40:6 | assignment to p | exprs.go:41:6:41:7 | skip |
+| exprs.go:40:6:40:6 | skip | exprs.go:40:6:40:6 | zero value for p |
+| exprs.go:40:6:40:6 | zero value for p | exprs.go:40:6:40:6 | assignment to p |
+| exprs.go:41:6:41:7 | assignment to ok | exprs.go:42:2:42:2 | skip |
+| exprs.go:41:6:41:7 | skip | exprs.go:41:6:41:7 | zero value for ok |
+| exprs.go:41:6:41:7 | zero value for ok | exprs.go:41:6:41:7 | assignment to ok |
+| exprs.go:42:2:42:2 | assignment to p | exprs.go:42:2:42:20 | ... = ...[1] |
+| exprs.go:42:2:42:2 | skip | exprs.go:42:5:42:6 | skip |
+| exprs.go:42:2:42:20 | ... = ...[0] | exprs.go:42:2:42:2 | assignment to p |
+| exprs.go:42:2:42:20 | ... = ...[1] | exprs.go:42:5:42:6 | assignment to ok |
+| exprs.go:42:5:42:6 | assignment to ok | exprs.go:43:5:43:6 | ok |
+| exprs.go:42:5:42:6 | skip | exprs.go:42:10:42:12 | arg |
+| exprs.go:42:10:42:12 | arg | exprs.go:42:10:42:20 | type assertion |
+| exprs.go:42:10:42:20 | type assertion | exprs.go:42:2:42:20 | ... = ...[0] |
+| exprs.go:43:5:43:6 | ok | exprs.go:43:6:43:6 | ok is false |
+| exprs.go:43:5:43:6 | ok | exprs.go:43:6:43:6 | ok is true |
+| exprs.go:43:6:43:6 | ok is false | exprs.go:46:9:46:10 | -... |
+| exprs.go:43:6:43:6 | ok is true | exprs.go:44:10:44:10 | p |
+| exprs.go:44:3:44:12 | return statement | exprs.go:47:1:47:1 | exit |
+| exprs.go:44:10:44:10 | p | exprs.go:44:10:44:12 | selection of x |
+| exprs.go:44:10:44:12 | selection of x | exprs.go:44:3:44:12 | return statement |
+| exprs.go:46:2:46:10 | return statement | exprs.go:47:1:47:1 | exit |
+| exprs.go:46:9:46:10 | -... | exprs.go:46:2:46:10 | return statement |
+| exprs.go:49:1:49:1 | entry | exprs.go:49:10:49:11 | argument corresponding to xs |
+| exprs.go:49:1:54:1 | function declaration | exprs.go:56:6:56:9 | skip |
+| exprs.go:49:6:49:8 | skip | exprs.go:49:1:54:1 | function declaration |
+| exprs.go:49:10:49:11 | argument corresponding to xs | exprs.go:49:10:49:11 | initialization of xs |
+| exprs.go:49:10:49:11 | initialization of xs | exprs.go:49:21:49:23 | zero value for res |
+| exprs.go:49:21:49:23 | implicit read of res | exprs.go:54:1:54:1 | exit |
+| exprs.go:49:21:49:23 | initialization of res | exprs.go:50:6:50:6 | skip |
+| exprs.go:49:21:49:23 | zero value for res | exprs.go:49:21:49:23 | initialization of res |
+| exprs.go:50:6:50:6 | assignment to i | exprs.go:50:14:50:14 | i |
+| exprs.go:50:6:50:6 | skip | exprs.go:50:11:50:11 | 0 |
+| exprs.go:50:11:50:11 | 0 | exprs.go:50:6:50:6 | assignment to i |
+| exprs.go:50:14:50:14 | i | exprs.go:50:18:50:20 | len |
+| exprs.go:50:14:50:24 | ...<... | exprs.go:50:24:50:24 | ...<... is false |
+| exprs.go:50:14:50:24 | ...<... | exprs.go:50:24:50:24 | ...<... is true |
+| exprs.go:50:18:50:20 | len | exprs.go:50:22:50:23 | xs |
+| exprs.go:50:18:50:24 | call to len | exprs.go:50:14:50:24 | ...<... |
+| exprs.go:50:22:50:23 | xs | exprs.go:50:18:50:24 | call to len |
+| exprs.go:50:24:50:24 | ...<... is false | exprs.go:53:2:53:7 | return statement |
+| exprs.go:50:24:50:24 | ...<... is true | exprs.go:51:3:51:5 | res |
+| exprs.go:50:27:50:27 | i | exprs.go:50:27:50:29 | 1 |
+| exprs.go:50:27:50:29 | 1 | exprs.go:50:27:50:29 | rhs of increment statement |
+| exprs.go:50:27:50:29 | increment statement | exprs.go:50:14:50:14 | i |
+| exprs.go:50:27:50:29 | rhs of increment statement | exprs.go:50:27:50:29 | increment statement |
+| exprs.go:51:3:51:5 | assignment to res | exprs.go:50:27:50:27 | i |
+| exprs.go:51:3:51:5 | res | exprs.go:51:10:51:11 | xs |
+| exprs.go:51:3:51:14 | ... += ... | exprs.go:51:3:51:5 | assignment to res |
+| exprs.go:51:10:51:11 | xs | exprs.go:51:13:51:13 | i |
+| exprs.go:51:10:51:14 | index expression | exprs.go:51:3:51:14 | ... += ... |
+| exprs.go:51:10:51:14 | index expression | exprs.go:54:1:54:1 | exit |
+| exprs.go:51:13:51:13 | i | exprs.go:51:10:51:14 | index expression |
+| exprs.go:53:2:53:7 | return statement | exprs.go:49:21:49:23 | implicit read of res |
+| exprs.go:56:1:56:1 | entry | exprs.go:56:11:56:12 | argument corresponding to xs |
+| exprs.go:56:1:58:1 | function declaration | exprs.go:60:6:60:9 | skip |
+| exprs.go:56:6:56:9 | skip | exprs.go:56:1:58:1 | function declaration |
+| exprs.go:56:11:56:12 | argument corresponding to xs | exprs.go:56:11:56:12 | initialization of xs |
+| exprs.go:56:11:56:12 | initialization of xs | exprs.go:57:9:57:11 | sum |
+| exprs.go:57:2:57:15 | return statement | exprs.go:58:1:58:1 | exit |
+| exprs.go:57:9:57:11 | sum | exprs.go:57:13:57:14 | xs |
+| exprs.go:57:9:57:15 | call to sum | exprs.go:57:2:57:15 | return statement |
+| exprs.go:57:9:57:15 | call to sum | exprs.go:58:1:58:1 | exit |
+| exprs.go:57:13:57:14 | xs | exprs.go:57:9:57:15 | call to sum |
+| exprs.go:60:1:60:1 | entry | exprs.go:61:9:61:22 | slice literal |
+| exprs.go:60:1:62:1 | function declaration | exprs.go:64:5:64:5 | skip |
+| exprs.go:60:6:60:9 | skip | exprs.go:60:1:62:1 | function declaration |
+| exprs.go:61:2:61:22 | return statement | exprs.go:62:1:62:1 | exit |
+| exprs.go:61:9:61:22 | slice literal | exprs.go:61:15:61:15 | element index |
+| exprs.go:61:15:61:15 | 1 | exprs.go:61:15:61:15 | init of 1 |
+| exprs.go:61:15:61:15 | element index | exprs.go:61:15:61:15 | 1 |
+| exprs.go:61:15:61:15 | init of 1 | exprs.go:61:18:61:18 | element index |
+| exprs.go:61:18:61:18 | 2 | exprs.go:61:18:61:18 | init of 2 |
+| exprs.go:61:18:61:18 | element index | exprs.go:61:18:61:18 | 2 |
+| exprs.go:61:18:61:18 | init of 2 | exprs.go:61:21:61:21 | element index |
+| exprs.go:61:21:61:21 | 3 | exprs.go:61:21:61:21 | init of 3 |
+| exprs.go:61:21:61:21 | element index | exprs.go:61:21:61:21 | 3 |
+| exprs.go:61:21:61:21 | init of 3 | exprs.go:61:2:61:22 | return statement |
+| exprs.go:64:5:64:5 | assignment to s | exprs.go:65:5:65:6 | skip |
+| exprs.go:64:5:64:5 | skip | exprs.go:64:9:64:11 | sum |
+| exprs.go:64:9:64:11 | sum | exprs.go:64:13:64:16 | ints |
+| exprs.go:64:9:64:19 | call to sum | exprs.go:0:0:0:0 | exit |
+| exprs.go:64:9:64:19 | call to sum | exprs.go:64:5:64:5 | assignment to s |
+| exprs.go:64:13:64:16 | ints | exprs.go:64:13:64:18 | call to ints |
+| exprs.go:64:13:64:18 | call to ints | exprs.go:0:0:0:0 | exit |
+| exprs.go:64:13:64:18 | call to ints | exprs.go:64:9:64:19 | call to sum |
+| exprs.go:65:5:65:6 | assignment to s2 | exprs.go:67:6:67:8 | skip |
+| exprs.go:65:5:65:6 | skip | exprs.go:65:10:65:13 | sum2 |
+| exprs.go:65:10:65:13 | sum2 | exprs.go:65:15:65:18 | ints |
+| exprs.go:65:10:65:24 | call to sum2 | exprs.go:0:0:0:0 | exit |
+| exprs.go:65:10:65:24 | call to sum2 | exprs.go:65:5:65:6 | assignment to s2 |
+| exprs.go:65:15:65:18 | ints | exprs.go:65:15:65:20 | call to ints |
+| exprs.go:65:15:65:20 | call to ints | exprs.go:0:0:0:0 | exit |
+| exprs.go:65:15:65:20 | call to ints | exprs.go:65:10:65:24 | call to sum2 |
+| exprs.go:67:1:67:1 | entry | exprs.go:67:10:67:10 | argument corresponding to x |
+| exprs.go:67:1:69:1 | function declaration | exprs.go:71:6:71:8 | skip |
+| exprs.go:67:6:67:8 | skip | exprs.go:67:1:69:1 | function declaration |
+| exprs.go:67:10:67:10 | argument corresponding to x | exprs.go:67:10:67:10 | initialization of x |
+| exprs.go:67:10:67:10 | initialization of x | exprs.go:67:13:67:13 | argument corresponding to y |
+| exprs.go:67:13:67:13 | argument corresponding to y | exprs.go:67:13:67:13 | initialization of y |
+| exprs.go:67:13:67:13 | initialization of y | exprs.go:68:9:68:9 | x |
+| exprs.go:68:2:68:13 | return statement | exprs.go:69:1:69:1 | exit |
+| exprs.go:68:9:68:9 | x | exprs.go:68:13:68:13 | y |
+| exprs.go:68:9:68:13 | ...+... | exprs.go:68:2:68:13 | return statement |
+| exprs.go:68:13:68:13 | y | exprs.go:68:9:68:13 | ...+... |
+| exprs.go:71:1:71:1 | entry | exprs.go:72:9:72:9 | 1 |
+| exprs.go:71:1:73:1 | function declaration | exprs.go:75:5:75:6 | skip |
+| exprs.go:71:6:71:8 | skip | exprs.go:71:1:73:1 | function declaration |
+| exprs.go:72:2:72:12 | return statement | exprs.go:73:1:73:1 | exit |
+| exprs.go:72:9:72:9 | 1 | exprs.go:72:12:72:12 | 2 |
+| exprs.go:72:12:72:12 | 2 | exprs.go:72:2:72:12 | return statement |
+| exprs.go:75:5:75:6 | assignment to s3 | exprs.go:77:6:77:10 | skip |
+| exprs.go:75:5:75:6 | skip | exprs.go:75:10:75:12 | add |
+| exprs.go:75:10:75:12 | add | exprs.go:75:14:75:16 | gen |
+| exprs.go:75:10:75:19 | call to add | exprs.go:0:0:0:0 | exit |
+| exprs.go:75:10:75:19 | call to add | exprs.go:75:5:75:6 | assignment to s3 |
+| exprs.go:75:10:75:19 | call to add[0] | exprs.go:75:10:75:19 | call to add[1] |
+| exprs.go:75:10:75:19 | call to add[1] | exprs.go:75:10:75:19 | call to add |
+| exprs.go:75:14:75:16 | gen | exprs.go:75:14:75:18 | call to gen |
+| exprs.go:75:14:75:18 | call to gen | exprs.go:0:0:0:0 | exit |
+| exprs.go:75:14:75:18 | call to gen | exprs.go:75:10:75:19 | call to add[0] |
+| exprs.go:77:1:77:1 | entry | exprs.go:77:12:77:12 | argument corresponding to x |
+| exprs.go:77:1:79:1 | function declaration | exprs.go:81:6:81:16 | skip |
+| exprs.go:77:6:77:10 | skip | exprs.go:77:1:79:1 | function declaration |
+| exprs.go:77:12:77:12 | argument corresponding to x | exprs.go:77:12:77:12 | initialization of x |
+| exprs.go:77:12:77:12 | initialization of x | exprs.go:77:15:77:15 | argument corresponding to y |
+| exprs.go:77:15:77:15 | argument corresponding to y | exprs.go:77:15:77:15 | initialization of y |
+| exprs.go:77:15:77:15 | initialization of y | exprs.go:77:18:77:18 | argument corresponding to z |
+| exprs.go:77:18:77:18 | argument corresponding to z | exprs.go:77:18:77:18 | initialization of z |
+| exprs.go:77:18:77:18 | initialization of z | exprs.go:78:11:78:11 | x |
+| exprs.go:78:2:78:22 | return statement | exprs.go:79:1:79:1 | exit |
+| exprs.go:78:9:78:17 | !... | exprs.go:78:17:78:17 | !... is false |
+| exprs.go:78:9:78:17 | !... | exprs.go:78:17:78:17 | !... is true |
+| exprs.go:78:9:78:22 | ...\|\|... | exprs.go:78:2:78:22 | return statement |
+| exprs.go:78:11:78:11 | x | exprs.go:78:11:78:11 | x is false |
+| exprs.go:78:11:78:11 | x | exprs.go:78:11:78:11 | x is true |
+| exprs.go:78:11:78:11 | x is false | exprs.go:78:11:78:16 | ...&&... |
+| exprs.go:78:11:78:11 | x is true | exprs.go:78:16:78:16 | y |
+| exprs.go:78:11:78:16 | ...&&... | exprs.go:78:9:78:17 | !... |
+| exprs.go:78:16:78:16 | y | exprs.go:78:11:78:16 | ...&&... |
+| exprs.go:78:17:78:17 | !... is false | exprs.go:78:22:78:22 | z |
+| exprs.go:78:17:78:17 | !... is true | exprs.go:78:9:78:22 | ...\|\|... |
+| exprs.go:78:22:78:22 | z | exprs.go:78:9:78:22 | ...\|\|... |
+| exprs.go:81:1:81:1 | entry | exprs.go:81:18:81:19 | argument corresponding to ch |
+| exprs.go:81:1:87:1 | function declaration | exprs.go:89:7:89:9 | skip |
+| exprs.go:81:6:81:16 | skip | exprs.go:81:1:87:1 | function declaration |
+| exprs.go:81:18:81:19 | argument corresponding to ch | exprs.go:81:18:81:19 | initialization of ch |
+| exprs.go:81:18:81:19 | initialization of ch | exprs.go:82:2:82:4 | skip |
+| exprs.go:82:2:82:4 | assignment to val | exprs.go:82:2:82:16 | ... := ...[1] |
+| exprs.go:82:2:82:4 | skip | exprs.go:82:7:82:8 | skip |
+| exprs.go:82:2:82:16 | ... := ...[0] | exprs.go:82:2:82:4 | assignment to val |
+| exprs.go:82:2:82:16 | ... := ...[1] | exprs.go:82:7:82:8 | assignment to ok |
+| exprs.go:82:7:82:8 | assignment to ok | exprs.go:83:5:83:6 | ok |
+| exprs.go:82:7:82:8 | skip | exprs.go:82:15:82:16 | ch |
+| exprs.go:82:13:82:16 | <-... | exprs.go:82:2:82:16 | ... := ...[0] |
+| exprs.go:82:15:82:16 | ch | exprs.go:82:13:82:16 | <-... |
+| exprs.go:83:5:83:6 | ok | exprs.go:83:6:83:6 | ok is false |
+| exprs.go:83:5:83:6 | ok | exprs.go:83:6:83:6 | ok is true |
+| exprs.go:83:6:83:6 | ok is false | exprs.go:86:2:86:6 | panic |
+| exprs.go:83:6:83:6 | ok is true | exprs.go:84:10:84:12 | val |
+| exprs.go:84:3:84:12 | return statement | exprs.go:87:1:87:1 | exit |
+| exprs.go:84:10:84:12 | val | exprs.go:84:3:84:12 | return statement |
+| exprs.go:86:2:86:6 | panic | exprs.go:86:8:86:17 | "No value" |
+| exprs.go:86:2:86:18 | call to panic | exprs.go:87:1:87:1 | exit |
+| exprs.go:86:8:86:17 | "No value" | exprs.go:86:2:86:18 | call to panic |
+| exprs.go:89:7:89:9 | assignment to one | exprs.go:91:5:91:5 | skip |
+| exprs.go:89:7:89:9 | skip | exprs.go:89:13:89:13 | 1 |
+| exprs.go:89:13:89:13 | 1 | exprs.go:89:7:89:9 | assignment to one |
+| exprs.go:91:5:91:5 | assignment to a | exprs.go:93:6:93:11 | skip |
+| exprs.go:91:5:91:5 | skip | exprs.go:91:9:91:25 | slice literal |
+| exprs.go:91:9:91:25 | slice literal | exprs.go:91:15:91:21 | ...+... |
+| exprs.go:91:15:91:21 | ...+... | exprs.go:91:24:91:24 | 2 |
+| exprs.go:91:15:91:24 | init of key-value pair | exprs.go:91:5:91:5 | assignment to a |
+| exprs.go:91:24:91:24 | 2 | exprs.go:91:15:91:24 | init of key-value pair |
+| exprs.go:93:1:93:1 | entry | exprs.go:93:13:93:13 | argument corresponding to x |
+| exprs.go:93:1:95:1 | function declaration | exprs.go:0:0:0:0 | exit |
+| exprs.go:93:6:93:11 | skip | exprs.go:93:1:95:1 | function declaration |
+| exprs.go:93:13:93:13 | argument corresponding to x | exprs.go:93:13:93:13 | initialization of x |
+| exprs.go:93:13:93:13 | initialization of x | exprs.go:93:16:93:16 | argument corresponding to y |
+| exprs.go:93:16:93:16 | argument corresponding to y | exprs.go:93:16:93:16 | initialization of y |
+| exprs.go:93:16:93:16 | initialization of y | exprs.go:93:19:93:19 | argument corresponding to z |
+| exprs.go:93:19:93:19 | argument corresponding to z | exprs.go:93:19:93:19 | initialization of z |
+| exprs.go:93:19:93:19 | initialization of z | exprs.go:94:10:94:10 | x |
+| exprs.go:94:2:94:21 | return statement | exprs.go:95:1:95:1 | exit |
+| exprs.go:94:9:94:21 | ...\|\|... | exprs.go:94:2:94:21 | return statement |
+| exprs.go:94:10:94:10 | x | exprs.go:94:10:94:10 | x is false |
+| exprs.go:94:10:94:10 | x | exprs.go:94:10:94:10 | x is true |
+| exprs.go:94:10:94:10 | x is false | exprs.go:94:16:94:16 | (...) is false |
+| exprs.go:94:10:94:10 | x is true | exprs.go:94:15:94:15 | y |
+| exprs.go:94:15:94:15 | y | exprs.go:94:16:94:16 | (...) is false |
+| exprs.go:94:15:94:15 | y | exprs.go:94:16:94:16 | (...) is true |
+| exprs.go:94:16:94:16 | (...) is false | exprs.go:94:21:94:21 | z |
+| exprs.go:94:16:94:16 | (...) is true | exprs.go:94:9:94:21 | ...\|\|... |
+| exprs.go:94:21:94:21 | z | exprs.go:94:9:94:21 | ...\|\|... |
+| hello.go:0:0:0:0 | entry | hello.go:3:1:3:12 | skip |
+| hello.go:3:1:3:12 | skip | hello.go:5:7:5:13 | skip |
+| hello.go:5:7:5:13 | assignment to message | hello.go:7:6:7:13 | skip |
+| hello.go:5:7:5:13 | skip | hello.go:5:17:5:31 | "Hello, world!" |
+| hello.go:5:17:5:31 | "Hello, world!" | hello.go:5:7:5:13 | assignment to message |
+| hello.go:7:1:7:1 | entry | hello.go:8:2:8:12 | selection of Println |
+| hello.go:7:1:9:1 | function declaration | hello.go:0:0:0:0 | exit |
+| hello.go:7:6:7:13 | skip | hello.go:7:1:9:1 | function declaration |
+| hello.go:8:2:8:12 | selection of Println | hello.go:8:14:8:20 | message |
+| hello.go:8:2:8:21 | call to Println | hello.go:9:1:9:1 | exit |
+| hello.go:8:14:8:20 | message | hello.go:8:2:8:21 | call to Println |
+| main.go:0:0:0:0 | entry | main.go:3:1:6:1 | skip |
+| main.go:3:1:6:1 | skip | main.go:8:6:8:9 | skip |
+| main.go:8:1:8:1 | entry | main.go:9:9:9:20 | selection of Float64 |
+| main.go:8:1:10:1 | function declaration | main.go:12:6:12:9 | skip |
+| main.go:8:6:8:9 | skip | main.go:8:1:10:1 | function declaration |
+| main.go:9:2:9:29 | return statement | main.go:10:1:10:1 | exit |
+| main.go:9:9:9:20 | selection of Float64 | main.go:9:9:9:22 | call to Float64 |
+| main.go:9:9:9:22 | call to Float64 | main.go:9:27:9:29 | 0.5 |
+| main.go:9:9:9:22 | call to Float64 | main.go:10:1:10:1 | exit |
+| main.go:9:9:9:29 | ...>=... | main.go:9:2:9:29 | return statement |
+| main.go:9:27:9:29 | 0.5 | main.go:9:9:9:29 | ...>=... |
+| main.go:12:1:12:1 | entry | main.go:13:6:13:6 | skip |
+| main.go:12:1:24:1 | function declaration | main.go:26:6:26:8 | skip |
+| main.go:12:6:12:9 | skip | main.go:12:1:24:1 | function declaration |
+| main.go:13:6:13:6 | assignment to x | main.go:14:2:14:2 | skip |
+| main.go:13:6:13:6 | skip | main.go:13:6:13:6 | zero value for x |
+| main.go:13:6:13:6 | zero value for x | main.go:13:6:13:6 | assignment to x |
+| main.go:14:2:14:2 | assignment to y | main.go:15:2:15:10 | selection of Print |
+| main.go:14:2:14:2 | skip | main.go:14:7:14:8 | 23 |
+| main.go:14:7:14:8 | 23 | main.go:14:2:14:2 | assignment to y |
+| main.go:15:2:15:10 | selection of Print | main.go:15:12:15:12 | x |
+| main.go:15:2:15:16 | call to Print | main.go:16:5:16:8 | cond |
+| main.go:15:2:15:16 | call to Print | main.go:24:1:24:1 | exit |
+| main.go:15:12:15:12 | x | main.go:15:15:15:15 | y |
+| main.go:15:15:15:15 | y | main.go:15:2:15:16 | call to Print |
+| main.go:16:5:16:8 | cond | main.go:16:5:16:10 | call to cond |
+| main.go:16:5:16:10 | call to cond | main.go:16:10:16:10 | call to cond is false |
+| main.go:16:5:16:10 | call to cond | main.go:16:10:16:10 | call to cond is true |
+| main.go:16:5:16:10 | call to cond | main.go:24:1:24:1 | exit |
+| main.go:16:10:16:10 | call to cond is false | main.go:19:2:19:10 | selection of Print |
+| main.go:16:10:16:10 | call to cond is true | main.go:17:3:17:3 | y |
+| main.go:17:3:17:3 | assignment to y | main.go:19:2:19:10 | selection of Print |
+| main.go:17:3:17:3 | y | main.go:17:8:17:9 | 19 |
+| main.go:17:3:17:9 | ... += ... | main.go:17:3:17:3 | assignment to y |
+| main.go:17:8:17:9 | 19 | main.go:17:3:17:9 | ... += ... |
+| main.go:19:2:19:10 | selection of Print | main.go:19:12:19:12 | x |
+| main.go:19:2:19:16 | call to Print | main.go:20:5:20:8 | cond |
+| main.go:19:2:19:16 | call to Print | main.go:24:1:24:1 | exit |
+| main.go:19:12:19:12 | x | main.go:19:15:19:15 | y |
+| main.go:19:15:19:15 | y | main.go:19:2:19:16 | call to Print |
+| main.go:20:5:20:8 | cond | main.go:20:5:20:10 | call to cond |
+| main.go:20:5:20:10 | call to cond | main.go:20:10:20:10 | call to cond is false |
+| main.go:20:5:20:10 | call to cond | main.go:20:10:20:10 | call to cond is true |
+| main.go:20:5:20:10 | call to cond | main.go:24:1:24:1 | exit |
+| main.go:20:10:20:10 | call to cond is false | main.go:23:2:23:10 | selection of Print |
+| main.go:20:10:20:10 | call to cond is true | main.go:21:3:21:3 | skip |
+| main.go:21:3:21:3 | assignment to x | main.go:23:2:23:10 | selection of Print |
+| main.go:21:3:21:3 | skip | main.go:21:7:21:7 | y |
+| main.go:21:7:21:7 | y | main.go:21:3:21:3 | assignment to x |
+| main.go:23:2:23:10 | selection of Print | main.go:23:12:23:12 | x |
+| main.go:23:2:23:16 | call to Print | main.go:24:1:24:1 | exit |
+| main.go:23:12:23:12 | x | main.go:23:15:23:15 | y |
+| main.go:23:15:23:15 | y | main.go:23:2:23:16 | call to Print |
+| main.go:26:1:26:1 | entry | main.go:26:10:26:10 | argument corresponding to x |
+| main.go:26:1:32:1 | function declaration | main.go:34:6:34:9 | skip |
+| main.go:26:6:26:8 | skip | main.go:26:1:32:1 | function declaration |
+| main.go:26:10:26:10 | argument corresponding to x | main.go:26:10:26:10 | initialization of x |
+| main.go:26:10:26:10 | initialization of x | main.go:27:2:27:2 | skip |
+| main.go:27:2:27:2 | assignment to a | main.go:27:5:27:5 | assignment to b |
+| main.go:27:2:27:2 | skip | main.go:27:5:27:5 | skip |
+| main.go:27:5:27:5 | assignment to b | main.go:28:5:28:8 | cond |
+| main.go:27:5:27:5 | skip | main.go:27:10:27:10 | x |
+| main.go:27:10:27:10 | x | main.go:27:13:27:13 | 0 |
+| main.go:27:13:27:13 | 0 | main.go:27:2:27:2 | assignment to a |
+| main.go:28:5:28:8 | cond | main.go:28:5:28:10 | call to cond |
+| main.go:28:5:28:10 | call to cond | main.go:28:10:28:10 | call to cond is false |
+| main.go:28:5:28:10 | call to cond | main.go:28:10:28:10 | call to cond is true |
+| main.go:28:5:28:10 | call to cond | main.go:32:1:32:1 | exit |
+| main.go:28:10:28:10 | call to cond is false | main.go:31:9:31:9 | a |
+| main.go:28:10:28:10 | call to cond is true | main.go:29:3:29:3 | skip |
+| main.go:29:3:29:3 | assignment to a | main.go:29:6:29:6 | assignment to b |
+| main.go:29:3:29:3 | skip | main.go:29:6:29:6 | skip |
+| main.go:29:6:29:6 | assignment to b | main.go:31:9:31:9 | a |
+| main.go:29:6:29:6 | skip | main.go:29:10:29:10 | b |
+| main.go:29:10:29:10 | b | main.go:29:13:29:13 | a |
+| main.go:29:13:29:13 | a | main.go:29:3:29:3 | assignment to a |
+| main.go:31:2:31:12 | return statement | main.go:32:1:32:1 | exit |
+| main.go:31:9:31:9 | a | main.go:31:12:31:12 | b |
+| main.go:31:12:31:12 | b | main.go:31:2:31:12 | return statement |
+| main.go:34:1:34:1 | entry | main.go:34:11:34:11 | argument corresponding to x |
+| main.go:34:1:36:1 | function declaration | main.go:38:6:38:8 | skip |
+| main.go:34:6:34:9 | skip | main.go:34:1:36:1 | function declaration |
+| main.go:34:11:34:11 | argument corresponding to x | main.go:34:11:34:11 | initialization of x |
+| main.go:34:11:34:11 | initialization of x | main.go:35:3:35:3 | x |
+| main.go:35:2:35:3 | assignment to star expression | main.go:36:1:36:1 | exit |
+| main.go:35:2:35:3 | star expression | main.go:35:8:35:9 | 19 |
+| main.go:35:2:35:3 | star expression | main.go:36:1:36:1 | exit |
+| main.go:35:2:35:9 | ... += ... | main.go:35:2:35:3 | assignment to star expression |
+| main.go:35:3:35:3 | x | main.go:35:2:35:3 | star expression |
+| main.go:35:8:35:9 | 19 | main.go:35:2:35:9 | ... += ... |
+| main.go:38:1:38:1 | entry | main.go:39:2:39:2 | skip |
+| main.go:38:1:45:1 | function declaration | main.go:47:6:47:8 | skip |
+| main.go:38:6:38:8 | skip | main.go:38:1:45:1 | function declaration |
+| main.go:39:2:39:2 | assignment to x | main.go:40:2:40:4 | skip |
+| main.go:39:2:39:2 | skip | main.go:39:7:39:8 | 23 |
+| main.go:39:7:39:8 | 23 | main.go:39:2:39:2 | assignment to x |
+| main.go:40:2:40:4 | assignment to ptr | main.go:41:5:41:8 | cond |
+| main.go:40:2:40:4 | skip | main.go:40:10:40:10 | x |
+| main.go:40:9:40:10 | &... | main.go:40:2:40:4 | assignment to ptr |
+| main.go:40:10:40:10 | x | main.go:40:9:40:10 | &... |
+| main.go:41:5:41:8 | cond | main.go:41:5:41:10 | call to cond |
+| main.go:41:5:41:10 | call to cond | main.go:41:10:41:10 | call to cond is false |
+| main.go:41:5:41:10 | call to cond | main.go:41:10:41:10 | call to cond is true |
+| main.go:41:5:41:10 | call to cond | main.go:45:1:45:1 | exit |
+| main.go:41:10:41:10 | call to cond is false | main.go:44:2:44:10 | selection of Print |
+| main.go:41:10:41:10 | call to cond is true | main.go:42:3:42:6 | bump |
+| main.go:42:3:42:6 | bump | main.go:42:8:42:10 | ptr |
+| main.go:42:3:42:11 | call to bump | main.go:44:2:44:10 | selection of Print |
+| main.go:42:3:42:11 | call to bump | main.go:45:1:45:1 | exit |
+| main.go:42:8:42:10 | ptr | main.go:42:3:42:11 | call to bump |
+| main.go:44:2:44:10 | selection of Print | main.go:44:12:44:12 | x |
+| main.go:44:2:44:13 | call to Print | main.go:45:1:45:1 | exit |
+| main.go:44:12:44:12 | x | main.go:44:2:44:13 | call to Print |
+| main.go:47:1:47:1 | entry | main.go:47:13:47:18 | zero value for result |
+| main.go:47:1:50:1 | function declaration | main.go:52:6:52:9 | skip |
+| main.go:47:6:47:8 | skip | main.go:47:1:50:1 | function declaration |
+| main.go:47:13:47:18 | implicit read of result | main.go:50:1:50:1 | exit |
+| main.go:47:13:47:18 | initialization of result | main.go:48:2:48:7 | skip |
+| main.go:47:13:47:18 | zero value for result | main.go:47:13:47:18 | initialization of result |
+| main.go:48:2:48:7 | assignment to result | main.go:49:2:49:7 | return statement |
+| main.go:48:2:48:7 | skip | main.go:48:11:48:12 | 42 |
+| main.go:48:11:48:12 | 42 | main.go:48:2:48:7 | assignment to result |
+| main.go:49:2:49:7 | return statement | main.go:47:13:47:18 | implicit read of result |
+| main.go:52:1:52:1 | entry | main.go:52:14:52:19 | zero value for result |
+| main.go:52:1:54:1 | function declaration | main.go:56:6:56:10 | skip |
+| main.go:52:6:52:9 | skip | main.go:52:1:54:1 | function declaration |
+| main.go:52:14:52:19 | implicit read of result | main.go:54:1:54:1 | exit |
+| main.go:52:14:52:19 | initialization of result | main.go:53:2:53:7 | return statement |
+| main.go:52:14:52:19 | zero value for result | main.go:52:14:52:19 | initialization of result |
+| main.go:53:2:53:7 | return statement | main.go:52:14:52:19 | implicit read of result |
+| main.go:56:1:56:1 | entry | main.go:57:6:57:6 | skip |
+| main.go:56:1:80:1 | function declaration | main.go:82:6:82:13 | skip |
+| main.go:56:6:56:10 | skip | main.go:56:1:80:1 | function declaration |
+| main.go:57:6:57:6 | assignment to x | main.go:58:6:58:9 | cond |
+| main.go:57:6:57:6 | skip | main.go:57:6:57:6 | zero value for x |
+| main.go:57:6:57:6 | zero value for x | main.go:57:6:57:6 | assignment to x |
+| main.go:58:6:58:9 | cond | main.go:58:6:58:11 | call to cond |
+| main.go:58:6:58:11 | call to cond | main.go:58:11:58:11 | call to cond is false |
+| main.go:58:6:58:11 | call to cond | main.go:58:11:58:11 | call to cond is true |
+| main.go:58:6:58:11 | call to cond | main.go:80:1:80:1 | exit |
+| main.go:58:11:58:11 | call to cond is false | main.go:61:2:61:10 | selection of Print |
+| main.go:58:11:58:11 | call to cond is true | main.go:59:3:59:3 | skip |
+| main.go:59:3:59:3 | assignment to x | main.go:58:6:58:9 | cond |
+| main.go:59:3:59:3 | skip | main.go:59:7:59:7 | 2 |
+| main.go:59:7:59:7 | 2 | main.go:59:3:59:3 | assignment to x |
+| main.go:61:2:61:10 | selection of Print | main.go:61:12:61:12 | x |
+| main.go:61:2:61:13 | call to Print | main.go:63:2:63:2 | skip |
+| main.go:61:2:61:13 | call to Print | main.go:80:1:80:1 | exit |
+| main.go:61:12:61:12 | x | main.go:61:2:61:13 | call to Print |
+| main.go:63:2:63:2 | assignment to y | main.go:64:6:64:6 | skip |
+| main.go:63:2:63:2 | skip | main.go:63:7:63:7 | 1 |
+| main.go:63:7:63:7 | 1 | main.go:63:2:63:2 | assignment to y |
+| main.go:64:6:64:6 | assignment to i | main.go:65:6:65:9 | cond |
+| main.go:64:6:64:6 | skip | main.go:64:11:64:11 | 0 |
+| main.go:64:11:64:11 | 0 | main.go:64:6:64:6 | assignment to i |
+| main.go:64:16:64:16 | i | main.go:64:16:64:18 | 1 |
+| main.go:64:16:64:18 | 1 | main.go:64:16:64:18 | rhs of increment statement |
+| main.go:64:16:64:18 | increment statement | main.go:65:6:65:9 | cond |
+| main.go:64:16:64:18 | rhs of increment statement | main.go:64:16:64:18 | increment statement |
+| main.go:65:6:65:9 | cond | main.go:65:6:65:11 | call to cond |
+| main.go:65:6:65:11 | call to cond | main.go:65:11:65:11 | call to cond is false |
+| main.go:65:6:65:11 | call to cond | main.go:65:11:65:11 | call to cond is true |
+| main.go:65:6:65:11 | call to cond | main.go:80:1:80:1 | exit |
+| main.go:65:11:65:11 | call to cond is false | main.go:68:3:68:3 | skip |
+| main.go:65:11:65:11 | call to cond is true | main.go:66:4:66:8 | skip |
+| main.go:66:4:66:8 | skip | main.go:70:2:70:10 | selection of Print |
+| main.go:68:3:68:3 | assignment to y | main.go:64:16:64:16 | i |
+| main.go:68:3:68:3 | skip | main.go:68:7:68:7 | 2 |
+| main.go:68:7:68:7 | 2 | main.go:68:3:68:3 | assignment to y |
+| main.go:70:2:70:10 | selection of Print | main.go:70:12:70:12 | y |
+| main.go:70:2:70:13 | call to Print | main.go:72:2:72:2 | skip |
+| main.go:70:2:70:13 | call to Print | main.go:80:1:80:1 | exit |
+| main.go:70:12:70:12 | y | main.go:70:2:70:13 | call to Print |
+| main.go:72:2:72:2 | assignment to z | main.go:73:6:73:6 | skip |
+| main.go:72:2:72:2 | skip | main.go:72:7:72:7 | 1 |
+| main.go:72:7:72:7 | 1 | main.go:72:2:72:2 | assignment to z |
+| main.go:73:6:73:6 | assignment to i | main.go:74:3:74:3 | skip |
+| main.go:73:6:73:6 | skip | main.go:73:11:73:11 | 0 |
+| main.go:73:11:73:11 | 0 | main.go:73:6:73:6 | assignment to i |
+| main.go:73:16:73:16 | i | main.go:73:16:73:18 | 1 |
+| main.go:73:16:73:18 | 1 | main.go:73:16:73:18 | rhs of increment statement |
+| main.go:73:16:73:18 | increment statement | main.go:74:3:74:3 | skip |
+| main.go:73:16:73:18 | rhs of increment statement | main.go:73:16:73:18 | increment statement |
+| main.go:74:3:74:3 | assignment to z | main.go:75:6:75:9 | cond |
+| main.go:74:3:74:3 | skip | main.go:74:7:74:7 | 2 |
+| main.go:74:7:74:7 | 2 | main.go:74:3:74:3 | assignment to z |
+| main.go:75:6:75:9 | cond | main.go:75:6:75:11 | call to cond |
+| main.go:75:6:75:11 | call to cond | main.go:75:11:75:11 | call to cond is false |
+| main.go:75:6:75:11 | call to cond | main.go:75:11:75:11 | call to cond is true |
+| main.go:75:6:75:11 | call to cond | main.go:80:1:80:1 | exit |
+| main.go:75:11:75:11 | call to cond is false | main.go:73:16:73:16 | i |
+| main.go:75:11:75:11 | call to cond is true | main.go:76:4:76:8 | skip |
+| main.go:76:4:76:8 | skip | main.go:79:2:79:10 | selection of Print |
+| main.go:79:2:79:10 | selection of Print | main.go:79:12:79:12 | z |
+| main.go:79:2:79:13 | call to Print | main.go:80:1:80:1 | exit |
+| main.go:79:12:79:12 | z | main.go:79:2:79:13 | call to Print |
+| main.go:82:1:82:1 | entry | main.go:82:18:82:18 | zero value for a |
+| main.go:82:1:86:1 | function declaration | main.go:88:6:88:23 | skip |
+| main.go:82:6:82:13 | skip | main.go:82:1:86:1 | function declaration |
+| main.go:82:18:82:18 | implicit read of a | main.go:82:25:82:25 | implicit read of b |
+| main.go:82:18:82:18 | initialization of a | main.go:82:25:82:25 | zero value for b |
+| main.go:82:18:82:18 | zero value for a | main.go:82:18:82:18 | initialization of a |
+| main.go:82:25:82:25 | implicit read of b | main.go:86:1:86:1 | exit |
+| main.go:82:25:82:25 | initialization of b | main.go:83:2:83:2 | skip |
+| main.go:82:25:82:25 | zero value for b | main.go:82:25:82:25 | initialization of b |
+| main.go:83:2:83:2 | assignment to x | main.go:84:2:84:2 | skip |
+| main.go:83:2:83:2 | skip | main.go:83:7:83:8 | 23 |
+| main.go:83:7:83:8 | 23 | main.go:83:2:83:2 | assignment to x |
+| main.go:84:2:84:2 | assignment to x | main.go:84:5:84:5 | assignment to a |
+| main.go:84:2:84:2 | skip | main.go:84:5:84:5 | skip |
+| main.go:84:5:84:5 | assignment to a | main.go:85:2:85:7 | return statement |
+| main.go:84:5:84:5 | skip | main.go:84:9:84:9 | x |
+| main.go:84:9:84:9 | x | main.go:84:11:84:12 | 19 |
+| main.go:84:9:84:12 | ...+... | main.go:84:15:84:15 | x |
+| main.go:84:11:84:12 | 19 | main.go:84:9:84:12 | ...+... |
+| main.go:84:15:84:15 | x | main.go:84:2:84:2 | assignment to x |
+| main.go:85:2:85:7 | return statement | main.go:82:18:82:18 | implicit read of a |
+| main.go:88:1:88:1 | entry | main.go:88:25:88:25 | argument corresponding to x |
+| main.go:88:1:96:1 | function declaration | main.go:0:0:0:0 | exit |
+| main.go:88:6:88:23 | skip | main.go:88:1:96:1 | function declaration |
+| main.go:88:25:88:25 | argument corresponding to x | main.go:88:25:88:25 | initialization of x |
+| main.go:88:25:88:25 | initialization of x | main.go:89:2:89:2 | skip |
+| main.go:89:2:89:2 | assignment to a | main.go:89:5:89:5 | assignment to b |
+| main.go:89:2:89:2 | skip | main.go:89:5:89:5 | skip |
+| main.go:89:5:89:5 | assignment to b | main.go:90:5:90:8 | cond |
+| main.go:89:5:89:5 | skip | main.go:89:10:89:10 | x |
+| main.go:89:10:89:10 | x | main.go:89:13:89:13 | 0 |
+| main.go:89:13:89:13 | 0 | main.go:89:2:89:2 | assignment to a |
+| main.go:90:5:90:8 | cond | main.go:90:5:90:10 | call to cond |
+| main.go:90:5:90:10 | call to cond | main.go:90:10:90:10 | call to cond is false |
+| main.go:90:5:90:10 | call to cond | main.go:90:10:90:10 | call to cond is true |
+| main.go:90:5:90:10 | call to cond | main.go:96:1:96:1 | exit |
+| main.go:90:10:90:10 | call to cond is false | main.go:93:3:93:3 | skip |
+| main.go:90:10:90:10 | call to cond is true | main.go:91:3:91:3 | skip |
+| main.go:91:3:91:3 | assignment to a | main.go:95:9:95:9 | a |
+| main.go:91:3:91:3 | skip | main.go:91:6:91:6 | skip |
+| main.go:91:6:91:6 | skip | main.go:91:10:91:10 | b |
+| main.go:91:10:91:10 | b | main.go:91:13:91:13 | a |
+| main.go:91:13:91:13 | a | main.go:91:3:91:3 | assignment to a |
+| main.go:93:3:93:3 | skip | main.go:93:6:93:6 | skip |
+| main.go:93:6:93:6 | assignment to b | main.go:95:9:95:9 | a |
+| main.go:93:6:93:6 | skip | main.go:93:10:93:10 | b |
+| main.go:93:10:93:10 | b | main.go:93:13:93:13 | a |
+| main.go:93:13:93:13 | a | main.go:93:6:93:6 | assignment to b |
+| main.go:95:2:95:12 | return statement | main.go:96:1:96:1 | exit |
+| main.go:95:9:95:9 | a | main.go:95:12:95:12 | b |
+| main.go:95:12:95:12 | b | main.go:95:2:95:12 | return statement |
+| noretfunctions.go:0:0:0:0 | entry | noretfunctions.go:3:1:6:1 | skip |
+| noretfunctions.go:3:1:6:1 | skip | noretfunctions.go:8:6:8:12 | skip |
+| noretfunctions.go:8:1:8:1 | entry | noretfunctions.go:9:2:9:8 | selection of Exit |
+| noretfunctions.go:8:1:10:1 | function declaration | noretfunctions.go:12:6:12:11 | skip |
+| noretfunctions.go:8:6:8:12 | skip | noretfunctions.go:8:1:10:1 | function declaration |
+| noretfunctions.go:9:2:9:8 | selection of Exit | noretfunctions.go:9:10:9:10 | 1 |
+| noretfunctions.go:9:2:9:11 | call to Exit | noretfunctions.go:10:1:10:1 | exit |
+| noretfunctions.go:9:10:9:10 | 1 | noretfunctions.go:9:2:9:11 | call to Exit |
+| noretfunctions.go:12:1:12:1 | entry | noretfunctions.go:12:13:12:13 | argument corresponding to x |
+| noretfunctions.go:12:1:16:1 | function declaration | noretfunctions.go:18:6:18:12 | skip |
+| noretfunctions.go:12:6:12:11 | skip | noretfunctions.go:12:1:16:1 | function declaration |
+| noretfunctions.go:12:13:12:13 | argument corresponding to x | noretfunctions.go:12:13:12:13 | initialization of x |
+| noretfunctions.go:12:13:12:13 | initialization of x | noretfunctions.go:13:5:13:5 | x |
+| noretfunctions.go:13:5:13:5 | x | noretfunctions.go:13:10:13:10 | 0 |
+| noretfunctions.go:13:5:13:10 | ...!=... | noretfunctions.go:13:10:13:10 | ...!=... is false |
+| noretfunctions.go:13:5:13:10 | ...!=... | noretfunctions.go:13:10:13:10 | ...!=... is true |
+| noretfunctions.go:13:10:13:10 | 0 | noretfunctions.go:13:5:13:10 | ...!=... |
+| noretfunctions.go:13:10:13:10 | ...!=... is false | noretfunctions.go:16:1:16:1 | exit |
+| noretfunctions.go:13:10:13:10 | ...!=... is true | noretfunctions.go:14:3:14:9 | selection of Exit |
+| noretfunctions.go:14:3:14:9 | selection of Exit | noretfunctions.go:14:11:14:11 | x |
+| noretfunctions.go:14:3:14:12 | call to Exit | noretfunctions.go:16:1:16:1 | exit |
+| noretfunctions.go:14:11:14:11 | x | noretfunctions.go:14:3:14:12 | call to Exit |
+| noretfunctions.go:18:1:18:1 | entry | noretfunctions.go:18:16:18:17 | skip |
+| noretfunctions.go:18:1:18:17 | function declaration | noretfunctions.go:20:6:20:22 | skip |
+| noretfunctions.go:18:6:18:12 | skip | noretfunctions.go:18:1:18:17 | function declaration |
+| noretfunctions.go:18:16:18:17 | skip | noretfunctions.go:18:17:18:17 | exit |
+| noretfunctions.go:20:1:20:1 | entry | noretfunctions.go:21:2:21:10 | selection of Fatal |
+| noretfunctions.go:20:1:22:1 | function declaration | noretfunctions.go:24:6:24:23 | skip |
+| noretfunctions.go:20:6:20:22 | skip | noretfunctions.go:20:1:22:1 | function declaration |
+| noretfunctions.go:21:2:21:10 | selection of Fatal | noretfunctions.go:21:12:21:18 | "Oh no" |
+| noretfunctions.go:21:2:21:19 | call to Fatal | noretfunctions.go:22:1:22:1 | exit |
+| noretfunctions.go:21:12:21:18 | "Oh no" | noretfunctions.go:21:2:21:19 | call to Fatal |
+| noretfunctions.go:24:1:24:1 | entry | noretfunctions.go:25:2:25:11 | selection of Fatalf |
+| noretfunctions.go:24:1:26:1 | function declaration | noretfunctions.go:0:0:0:0 | exit |
+| noretfunctions.go:24:6:24:23 | skip | noretfunctions.go:24:1:26:1 | function declaration |
+| noretfunctions.go:25:2:25:11 | selection of Fatalf | noretfunctions.go:25:13:25:30 | "It's as I feared" |
+| noretfunctions.go:25:2:25:31 | call to Fatalf | noretfunctions.go:26:1:26:1 | exit |
+| noretfunctions.go:25:13:25:30 | "It's as I feared" | noretfunctions.go:25:2:25:31 | call to Fatalf |
+| stmts2.go:0:0:0:0 | entry | stmts2.go:3:6:3:11 | skip |
+| stmts2.go:3:1:3:1 | entry | stmts2.go:4:2:4:2 | skip |
+| stmts2.go:3:1:7:1 | function declaration | stmts2.go:9:6:9:11 | skip |
+| stmts2.go:3:6:3:11 | skip | stmts2.go:3:1:7:1 | function declaration |
+| stmts2.go:4:2:4:2 | skip | stmts2.go:4:6:4:10 | test7 |
+| stmts2.go:4:6:4:10 | test7 | stmts2.go:4:12:4:12 | 0 |
+| stmts2.go:4:6:4:13 | call to test7 | stmts2.go:5:6:5:6 | skip |
+| stmts2.go:4:6:4:13 | call to test7 | stmts2.go:7:1:7:1 | exit |
+| stmts2.go:4:12:4:12 | 0 | stmts2.go:4:6:4:13 | call to test7 |
+| stmts2.go:5:6:5:6 | skip | stmts2.go:5:10:5:14 | test7 |
+| stmts2.go:5:10:5:14 | test7 | stmts2.go:5:16:5:16 | 1 |
+| stmts2.go:5:10:5:17 | call to test7 | stmts2.go:6:9:6:9 | 2 |
+| stmts2.go:5:10:5:17 | call to test7 | stmts2.go:7:1:7:1 | exit |
+| stmts2.go:5:16:5:16 | 1 | stmts2.go:5:10:5:17 | call to test7 |
+| stmts2.go:6:2:6:9 | return statement | stmts2.go:7:1:7:1 | exit |
+| stmts2.go:6:9:6:9 | 2 | stmts2.go:6:2:6:9 | return statement |
+| stmts2.go:9:1:9:1 | entry | stmts2.go:10:2:10:2 | skip |
+| stmts2.go:9:1:13:1 | function declaration | stmts2.go:15:6:15:11 | skip |
+| stmts2.go:9:6:9:11 | skip | stmts2.go:9:1:13:1 | function declaration |
+| stmts2.go:10:2:10:2 | skip | stmts2.go:10:5:10:5 | skip |
+| stmts2.go:10:2:10:14 | ... := ...[0] | stmts2.go:10:2:10:14 | ... := ...[1] |
+| stmts2.go:10:2:10:14 | ... := ...[1] | stmts2.go:10:5:10:5 | assignment to x |
+| stmts2.go:10:5:10:5 | assignment to x | stmts2.go:11:6:11:6 | skip |
+| stmts2.go:10:5:10:5 | skip | stmts2.go:10:10:10:12 | gen |
+| stmts2.go:10:10:10:12 | gen | stmts2.go:10:10:10:14 | call to gen |
+| stmts2.go:10:10:10:14 | call to gen | stmts2.go:10:2:10:14 | ... := ...[0] |
+| stmts2.go:10:10:10:14 | call to gen | stmts2.go:13:1:13:1 | exit |
+| stmts2.go:11:6:11:6 | skip | stmts2.go:11:9:11:9 | skip |
+| stmts2.go:11:6:11:17 | value declaration specifier[0] | stmts2.go:11:6:11:17 | value declaration specifier[1] |
+| stmts2.go:11:6:11:17 | value declaration specifier[1] | stmts2.go:11:9:11:9 | assignment to y |
+| stmts2.go:11:9:11:9 | assignment to y | stmts2.go:12:9:12:9 | x |
+| stmts2.go:11:9:11:9 | skip | stmts2.go:11:13:11:15 | gen |
+| stmts2.go:11:13:11:15 | gen | stmts2.go:11:13:11:17 | call to gen |
+| stmts2.go:11:13:11:17 | call to gen | stmts2.go:11:6:11:17 | value declaration specifier[0] |
+| stmts2.go:11:13:11:17 | call to gen | stmts2.go:13:1:13:1 | exit |
+| stmts2.go:12:2:12:13 | return statement | stmts2.go:13:1:13:1 | exit |
+| stmts2.go:12:9:12:9 | x | stmts2.go:12:13:12:13 | y |
+| stmts2.go:12:9:12:13 | ...+... | stmts2.go:12:2:12:13 | return statement |
+| stmts2.go:12:13:12:13 | y | stmts2.go:12:9:12:13 | ...+... |
+| stmts2.go:15:1:15:1 | entry | stmts2.go:15:13:15:14 | argument corresponding to ch |
+| stmts2.go:15:1:28:1 | function declaration | stmts2.go:30:6:30:12 | skip |
+| stmts2.go:15:6:15:11 | skip | stmts2.go:15:1:28:1 | function declaration |
+| stmts2.go:15:13:15:14 | argument corresponding to ch | stmts2.go:15:13:15:14 | initialization of ch |
+| stmts2.go:15:13:15:14 | initialization of ch | stmts2.go:17:13:17:14 | ch |
+| stmts2.go:16:2:26:2 | select statement | stmts2.go:17:11:17:14 | <-... |
+| stmts2.go:16:2:26:2 | select statement | stmts2.go:18:15:18:18 | <-... |
+| stmts2.go:16:2:26:2 | select statement | stmts2.go:20:15:20:18 | <-... |
+| stmts2.go:16:2:26:2 | select statement | stmts2.go:25:14:25:17 | <-... |
+| stmts2.go:17:2:17:15 | skip | stmts2.go:27:9:27:9 | 1 |
+| stmts2.go:17:7:17:7 | skip | stmts2.go:17:2:17:15 | skip |
+| stmts2.go:17:11:17:14 | <-... | stmts2.go:17:7:17:7 | skip |
+| stmts2.go:17:13:17:14 | ch | stmts2.go:18:17:18:18 | ch |
+| stmts2.go:18:7:18:7 | assignment to x | stmts2.go:18:7:18:18 | ... := ...[1] |
+| stmts2.go:18:7:18:7 | skip | stmts2.go:18:10:18:10 | skip |
+| stmts2.go:18:7:18:18 | ... := ...[0] | stmts2.go:18:7:18:7 | assignment to x |
+| stmts2.go:18:7:18:18 | ... := ...[1] | stmts2.go:19:10:19:10 | x |
+| stmts2.go:18:10:18:10 | skip | stmts2.go:18:7:18:18 | ... := ...[0] |
+| stmts2.go:18:15:18:18 | <-... | stmts2.go:18:7:18:7 | skip |
+| stmts2.go:18:17:18:18 | ch | stmts2.go:20:17:20:18 | ch |
+| stmts2.go:19:3:19:10 | return statement | stmts2.go:28:1:28:1 | exit |
+| stmts2.go:19:10:19:10 | x | stmts2.go:19:3:19:10 | return statement |
+| stmts2.go:20:7:20:7 | skip | stmts2.go:20:10:20:10 | skip |
+| stmts2.go:20:7:20:18 | ... := ...[0] | stmts2.go:20:7:20:18 | ... := ...[1] |
+| stmts2.go:20:7:20:18 | ... := ...[1] | stmts2.go:20:10:20:10 | assignment to y |
+| stmts2.go:20:10:20:10 | assignment to y | stmts2.go:21:6:21:6 | y |
+| stmts2.go:20:10:20:10 | skip | stmts2.go:20:7:20:18 | ... := ...[0] |
+| stmts2.go:20:15:20:18 | <-... | stmts2.go:20:7:20:7 | skip |
+| stmts2.go:20:17:20:18 | ch | stmts2.go:25:16:25:17 | ch |
+| stmts2.go:21:6:21:6 | y | stmts2.go:21:6:21:6 | y is false |
+| stmts2.go:21:6:21:6 | y | stmts2.go:21:6:21:6 | y is true |
+| stmts2.go:21:6:21:6 | y is false | stmts2.go:24:10:24:10 | 0 |
+| stmts2.go:21:6:21:6 | y is true | stmts2.go:22:4:22:8 | skip |
+| stmts2.go:22:4:22:8 | skip | stmts2.go:27:9:27:9 | 1 |
+| stmts2.go:24:3:24:10 | return statement | stmts2.go:28:1:28:1 | exit |
+| stmts2.go:24:10:24:10 | 0 | stmts2.go:24:3:24:10 | return statement |
+| stmts2.go:25:2:25:18 | skip | stmts2.go:27:9:27:9 | 1 |
+| stmts2.go:25:7:25:7 | skip | stmts2.go:25:10:25:10 | skip |
+| stmts2.go:25:7:25:17 | ... = ...[0] | stmts2.go:25:7:25:17 | ... = ...[1] |
+| stmts2.go:25:7:25:17 | ... = ...[1] | stmts2.go:25:2:25:18 | skip |
+| stmts2.go:25:10:25:10 | skip | stmts2.go:25:7:25:17 | ... = ...[0] |
+| stmts2.go:25:14:25:17 | <-... | stmts2.go:25:7:25:7 | skip |
+| stmts2.go:25:16:25:17 | ch | stmts2.go:16:2:26:2 | select statement |
+| stmts2.go:27:2:27:9 | return statement | stmts2.go:28:1:28:1 | exit |
+| stmts2.go:27:9:27:9 | 1 | stmts2.go:27:2:27:9 | return statement |
+| stmts2.go:30:1:30:1 | entry | stmts2.go:31:2:31:2 | skip |
+| stmts2.go:30:1:34:1 | function declaration | stmts2.go:0:0:0:0 | exit |
+| stmts2.go:30:6:30:12 | skip | stmts2.go:30:1:34:1 | function declaration |
+| stmts2.go:31:2:31:2 | assignment to x | stmts2.go:31:2:31:14 | ... := ...[1] |
+| stmts2.go:31:2:31:2 | skip | stmts2.go:31:5:31:5 | skip |
+| stmts2.go:31:2:31:14 | ... := ...[0] | stmts2.go:31:2:31:2 | assignment to x |
+| stmts2.go:31:2:31:14 | ... := ...[1] | stmts2.go:32:6:32:6 | skip |
+| stmts2.go:31:5:31:5 | skip | stmts2.go:31:10:31:12 | gen |
+| stmts2.go:31:10:31:12 | gen | stmts2.go:31:10:31:14 | call to gen |
+| stmts2.go:31:10:31:14 | call to gen | stmts2.go:31:2:31:14 | ... := ...[0] |
+| stmts2.go:31:10:31:14 | call to gen | stmts2.go:34:1:34:1 | exit |
+| stmts2.go:32:6:32:6 | assignment to y | stmts2.go:32:6:32:17 | value declaration specifier[1] |
+| stmts2.go:32:6:32:6 | skip | stmts2.go:32:9:32:9 | skip |
+| stmts2.go:32:6:32:17 | value declaration specifier[0] | stmts2.go:32:6:32:6 | assignment to y |
+| stmts2.go:32:6:32:17 | value declaration specifier[1] | stmts2.go:33:9:33:9 | x |
+| stmts2.go:32:9:32:9 | skip | stmts2.go:32:13:32:15 | gen |
+| stmts2.go:32:13:32:15 | gen | stmts2.go:32:13:32:17 | call to gen |
+| stmts2.go:32:13:32:17 | call to gen | stmts2.go:32:6:32:17 | value declaration specifier[0] |
+| stmts2.go:32:13:32:17 | call to gen | stmts2.go:34:1:34:1 | exit |
+| stmts2.go:33:2:33:13 | return statement | stmts2.go:34:1:34:1 | exit |
+| stmts2.go:33:9:33:9 | x | stmts2.go:33:13:33:13 | y |
+| stmts2.go:33:9:33:13 | ...+... | stmts2.go:33:2:33:13 | return statement |
+| stmts2.go:33:13:33:13 | y | stmts2.go:33:9:33:13 | ...+... |
+| stmts3.go:0:0:0:0 | entry | stmts3.go:3:1:3:13 | skip |
+| stmts3.go:3:1:3:13 | skip | stmts3.go:5:6:5:11 | skip |
+| stmts3.go:5:1:5:1 | entry | stmts3.go:7:3:7:5 | skip |
+| stmts3.go:5:1:12:1 | function declaration | stmts3.go:14:6:14:11 | skip |
+| stmts3.go:5:6:5:11 | skip | stmts3.go:5:1:12:1 | function declaration |
+| stmts3.go:7:3:7:5 | assignment to red | stmts3.go:8:3:8:7 | skip |
+| stmts3.go:7:3:7:5 | skip | stmts3.go:7:9:7:12 | iota |
+| stmts3.go:7:9:7:12 | iota | stmts3.go:7:3:7:5 | assignment to red |
+| stmts3.go:8:3:8:7 | assignment to green | stmts3.go:9:3:9:6 | skip |
+| stmts3.go:8:3:8:7 | skip | stmts3.go:8:3:8:7 | zero value for green |
+| stmts3.go:8:3:8:7 | zero value for green | stmts3.go:8:3:8:7 | assignment to green |
+| stmts3.go:9:3:9:6 | assignment to blue | stmts3.go:11:9:11:26 | ...-... |
+| stmts3.go:9:3:9:6 | skip | stmts3.go:9:3:9:6 | zero value for blue |
+| stmts3.go:9:3:9:6 | zero value for blue | stmts3.go:9:3:9:6 | assignment to blue |
+| stmts3.go:11:2:11:26 | return statement | stmts3.go:12:1:12:1 | exit |
+| stmts3.go:11:9:11:26 | ...-... | stmts3.go:11:2:11:26 | return statement |
+| stmts3.go:14:1:14:1 | entry | stmts3.go:14:13:14:13 | argument corresponding to x |
+| stmts3.go:14:1:16:1 | function declaration | stmts3.go:18:6:18:11 | skip |
+| stmts3.go:14:6:14:11 | skip | stmts3.go:14:1:16:1 | function declaration |
+| stmts3.go:14:13:14:13 | argument corresponding to x | stmts3.go:14:13:14:13 | initialization of x |
+| stmts3.go:14:13:14:13 | initialization of x | stmts3.go:15:3:15:3 | x |
+| stmts3.go:15:2:15:3 | assignment to star expression | stmts3.go:16:1:16:1 | exit |
+| stmts3.go:15:2:15:3 | skip | stmts3.go:15:7:15:8 | 42 |
+| stmts3.go:15:2:15:3 | skip | stmts3.go:16:1:16:1 | exit |
+| stmts3.go:15:3:15:3 | x | stmts3.go:15:2:15:3 | skip |
+| stmts3.go:15:7:15:8 | 42 | stmts3.go:15:2:15:3 | assignment to star expression |
+| stmts3.go:18:1:18:1 | entry | stmts3.go:19:2:19:11 | skip |
+| stmts3.go:18:1:20:1 | function declaration | stmts3.go:0:0:0:0 | exit |
+| stmts3.go:18:6:18:11 | skip | stmts3.go:18:1:20:1 | function declaration |
+| stmts3.go:19:2:19:11 | assignment to Usage | stmts3.go:20:1:20:1 | exit |
+| stmts3.go:19:2:19:11 | skip | stmts3.go:19:15:19:23 | function literal |
+| stmts3.go:19:15:19:15 | entry | stmts3.go:19:22:19:23 | skip |
+| stmts3.go:19:15:19:23 | function literal | stmts3.go:19:2:19:11 | assignment to Usage |
+| stmts3.go:19:22:19:23 | skip | stmts3.go:19:23:19:23 | exit |
+| stmts4.go:0:0:0:0 | entry | stmts4.go:3:5:3:5 | skip |
+| stmts4.go:3:5:3:5 | skip | stmts4.go:3:5:3:5 | zero value for _ |
+| stmts4.go:3:5:3:5 | zero value for _ | stmts4.go:5:6:5:11 | skip |
+| stmts4.go:5:1:5:26 | function declaration | stmts4.go:0:0:0:0 | exit |
+| stmts4.go:5:6:5:11 | skip | stmts4.go:5:1:5:26 | function declaration |
+| stmts5.go:0:0:0:0 | entry | stmts5.go:3:1:5:1 | skip |
+| stmts5.go:3:1:5:1 | skip | stmts5.go:7:17:7:20 | skip |
+| stmts5.go:7:1:7:1 | entry | stmts5.go:7:7:7:8 | argument corresponding to me |
+| stmts5.go:7:1:9:1 | function declaration | stmts5.go:11:14:11:16 | skip |
+| stmts5.go:7:7:7:8 | argument corresponding to me | stmts5.go:7:7:7:8 | initialization of me |
+| stmts5.go:7:7:7:8 | initialization of me | stmts5.go:7:22:7:26 | argument corresponding to other |
+| stmts5.go:7:17:7:20 | skip | stmts5.go:7:1:9:1 | function declaration |
+| stmts5.go:7:22:7:26 | argument corresponding to other | stmts5.go:7:22:7:26 | initialization of other |
+| stmts5.go:7:22:7:26 | initialization of other | stmts5.go:8:2:8:3 | me |
+| stmts5.go:8:2:8:3 | me | stmts5.go:8:2:8:7 | selection of val |
+| stmts5.go:8:2:8:7 | assignment to field val | stmts5.go:9:1:9:1 | exit |
+| stmts5.go:8:2:8:7 | selection of val | stmts5.go:8:12:8:16 | other |
+| stmts5.go:8:2:8:16 | ... += ... | stmts5.go:8:2:8:7 | assignment to field val |
+| stmts5.go:8:12:8:16 | other | stmts5.go:8:2:8:16 | ... += ... |
+| stmts5.go:11:1:11:1 | entry | stmts5.go:11:20:12:1 | skip |
+| stmts5.go:11:1:12:1 | function declaration | stmts5.go:0:0:0:0 | exit |
+| stmts5.go:11:14:11:16 | skip | stmts5.go:11:1:12:1 | function declaration |
+| stmts5.go:11:20:12:1 | skip | stmts5.go:12:1:12:1 | exit |
+| stmts6.go:0:0:0:0 | entry | stmts6.go:3:6:3:11 | skip |
+| stmts6.go:3:1:3:1 | entry | stmts6.go:4:5:4:8 | true |
+| stmts6.go:3:1:8:1 | function declaration | stmts6.go:0:0:0:0 | exit |
+| stmts6.go:3:6:3:11 | skip | stmts6.go:3:1:8:1 | function declaration |
+| stmts6.go:4:5:4:8 | true | stmts6.go:4:8:4:8 | true is true |
+| stmts6.go:4:8:4:8 | true is false | stmts6.go:7:9:7:10 | 23 |
+| stmts6.go:4:8:4:8 | true is true | stmts6.go:5:10:5:11 | 42 |
+| stmts6.go:5:3:5:11 | return statement | stmts6.go:8:1:8:1 | exit |
+| stmts6.go:5:10:5:11 | 42 | stmts6.go:5:3:5:11 | return statement |
+| stmts6.go:7:9:7:10 | 23 | stmts6.go:7:2:7:10 | return statement |
+| stmts7.go:0:0:0:0 | entry | stmts7.go:3:1:3:12 | skip |
+| stmts7.go:3:1:3:12 | skip | stmts7.go:5:6:5:17 | skip |
+| stmts7.go:5:1:5:1 | entry | stmts7.go:6:2:6:5 | skip |
+| stmts7.go:5:1:8:1 | function declaration | stmts7.go:10:6:10:15 | skip |
+| stmts7.go:5:6:5:17 | skip | stmts7.go:5:1:8:1 | function declaration |
+| stmts7.go:6:2:6:5 | assignment to blah | stmts7.go:7:2:7:12 | selection of Println |
+| stmts7.go:6:2:6:5 | skip | stmts7.go:6:10:6:16 | recover |
+| stmts7.go:6:10:6:16 | recover | stmts7.go:6:10:6:18 | call to recover |
+| stmts7.go:6:10:6:18 | call to recover | stmts7.go:6:2:6:5 | assignment to blah |
+| stmts7.go:7:2:7:12 | selection of Println | stmts7.go:7:14:7:26 | "recovered: " |
+| stmts7.go:7:2:7:33 | call to Println | stmts7.go:8:1:8:1 | exit |
+| stmts7.go:7:14:7:26 | "recovered: " | stmts7.go:7:29:7:32 | blah |
+| stmts7.go:7:29:7:32 | blah | stmts7.go:7:2:7:33 | call to Println |
+| stmts7.go:10:1:10:1 | entry | stmts7.go:11:8:11:19 | recoverPanic |
+| stmts7.go:10:1:13:1 | function declaration | stmts7.go:15:1:17:1 | skip |
+| stmts7.go:10:6:10:15 | skip | stmts7.go:10:1:13:1 | function declaration |
+| stmts7.go:11:2:11:21 | defer statement | stmts7.go:12:2:12:6 | panic |
+| stmts7.go:11:8:11:19 | recoverPanic | stmts7.go:11:2:11:21 | defer statement |
+| stmts7.go:11:8:11:21 | call to recoverPanic | stmts7.go:13:1:13:1 | exit |
+| stmts7.go:12:2:12:6 | panic | stmts7.go:12:8:12:9 | "" |
+| stmts7.go:12:2:12:10 | call to panic | stmts7.go:11:8:11:21 | call to recoverPanic |
+| stmts7.go:12:8:12:9 | "" | stmts7.go:12:2:12:10 | call to panic |
+| stmts7.go:15:1:17:1 | skip | stmts7.go:19:26:19:28 | skip |
+| stmts7.go:19:1:19:1 | entry | stmts7.go:19:7:19:13 | argument corresponding to methods |
+| stmts7.go:19:1:21:1 | function declaration | stmts7.go:23:6:23:14 | skip |
+| stmts7.go:19:7:19:13 | argument corresponding to methods | stmts7.go:19:7:19:13 | initialization of methods |
+| stmts7.go:19:7:19:13 | initialization of methods | stmts7.go:20:2:20:8 | methods |
+| stmts7.go:19:26:19:28 | skip | stmts7.go:19:1:21:1 | function declaration |
+| stmts7.go:20:2:20:8 | implicit dereference | stmts7.go:20:2:20:11 | selection of fn |
+| stmts7.go:20:2:20:8 | implicit dereference | stmts7.go:21:1:21:1 | exit |
+| stmts7.go:20:2:20:8 | methods | stmts7.go:20:2:20:8 | implicit dereference |
+| stmts7.go:20:2:20:11 | selection of fn | stmts7.go:20:2:20:13 | call to fn |
+| stmts7.go:20:2:20:13 | call to fn | stmts7.go:21:1:21:1 | exit |
+| stmts7.go:23:1:23:1 | entry | stmts7.go:23:16:23:23 | argument corresponding to callback |
+| stmts7.go:23:1:28:1 | function declaration | stmts7.go:0:0:0:0 | exit |
+| stmts7.go:23:6:23:14 | skip | stmts7.go:23:1:28:1 | function declaration |
+| stmts7.go:23:16:23:23 | argument corresponding to callback | stmts7.go:23:16:23:23 | initialization of callback |
+| stmts7.go:23:16:23:23 | initialization of callback | stmts7.go:24:8:24:15 | callback |
+| stmts7.go:24:2:24:20 | defer statement | stmts7.go:25:10:25:17 | callback |
+| stmts7.go:24:8:24:15 | callback | stmts7.go:24:8:24:18 | selection of fn |
+| stmts7.go:24:8:24:18 | selection of fn | stmts7.go:24:2:24:20 | defer statement |
+| stmts7.go:24:8:24:20 | call to fn | stmts7.go:28:1:28:1 | exit |
+| stmts7.go:25:2:25:23 | defer statement | stmts7.go:26:2:26:12 | selection of Println |
+| stmts7.go:25:8:25:18 | implicit dereference | stmts7.go:24:8:24:20 | call to fn |
+| stmts7.go:25:8:25:18 | implicit dereference | stmts7.go:25:8:25:21 | selection of fn |
+| stmts7.go:25:8:25:21 | selection of fn | stmts7.go:25:2:25:23 | defer statement |
+| stmts7.go:25:8:25:23 | call to fn | stmts7.go:24:8:24:20 | call to fn |
+| stmts7.go:25:9:25:17 | &... | stmts7.go:25:8:25:18 | implicit dereference |
+| stmts7.go:25:10:25:17 | callback | stmts7.go:25:9:25:17 | &... |
+| stmts7.go:26:2:26:12 | selection of Println | stmts7.go:26:14:26:30 | "print something" |
+| stmts7.go:26:2:26:31 | call to Println | stmts7.go:25:8:25:23 | call to fn |
+| stmts7.go:26:2:26:31 | call to Println | stmts7.go:27:9:27:13 | false |
+| stmts7.go:26:14:26:30 | "print something" | stmts7.go:26:2:26:31 | call to Println |
+| stmts7.go:27:2:27:13 | return statement | stmts7.go:25:8:25:23 | call to fn |
+| stmts7.go:27:9:27:13 | false | stmts7.go:27:2:27:13 | return statement |
+| stmts8.go:0:0:0:0 | entry | stmts8.go:3:6:3:11 | skip |
+| stmts8.go:3:1:3:1 | entry | stmts8.go:3:13:3:13 | argument corresponding to x |
+| stmts8.go:3:1:7:1 | function declaration | stmts8.go:9:6:9:12 | skip |
+| stmts8.go:3:6:3:11 | skip | stmts8.go:3:1:7:1 | function declaration |
+| stmts8.go:3:13:3:13 | argument corresponding to x | stmts8.go:3:13:3:13 | initialization of x |
+| stmts8.go:3:13:3:13 | initialization of x | stmts8.go:4:2:4:2 | skip |
+| stmts8.go:4:2:4:2 | assignment to y | stmts8.go:5:2:5:2 | skip |
+| stmts8.go:4:2:4:2 | skip | stmts8.go:4:7:4:7 | x |
+| stmts8.go:4:7:4:7 | x | stmts8.go:4:12:4:12 | 5 |
+| stmts8.go:4:7:4:12 | ...>>... | stmts8.go:4:2:4:2 | assignment to y |
+| stmts8.go:4:12:4:12 | 5 | stmts8.go:4:7:4:12 | ...>>... |
+| stmts8.go:5:2:5:2 | assignment to z | stmts8.go:6:9:6:9 | z |
+| stmts8.go:5:2:5:2 | skip | stmts8.go:5:7:5:7 | x |
+| stmts8.go:5:7:5:7 | x | stmts8.go:5:12:5:12 | 1 |
+| stmts8.go:5:7:5:13 | ...%... | stmts8.go:5:2:5:2 | assignment to z |
+| stmts8.go:5:12:5:12 | 1 | stmts8.go:5:7:5:13 | ...%... |
+| stmts8.go:6:2:6:17 | return statement | stmts8.go:7:1:7:1 | exit |
+| stmts8.go:6:9:6:9 | z | stmts8.go:6:12:6:12 | y |
+| stmts8.go:6:12:6:12 | y | stmts8.go:6:16:6:17 | 13 |
+| stmts8.go:6:12:6:17 | ...%... | stmts8.go:6:2:6:17 | return statement |
+| stmts8.go:6:16:6:17 | 13 | stmts8.go:6:12:6:17 | ...%... |
+| stmts8.go:9:1:9:1 | entry | stmts8.go:10:5:10:9 | linux |
+| stmts8.go:9:1:14:1 | function declaration | stmts8.go:0:0:0:0 | exit |
+| stmts8.go:9:6:9:12 | skip | stmts8.go:9:1:14:1 | function declaration |
+| stmts8.go:10:5:10:9 | linux | stmts8.go:10:9:10:9 | linux is false |
+| stmts8.go:10:5:10:9 | linux | stmts8.go:10:9:10:9 | linux is true |
+| stmts8.go:10:9:10:9 | linux is false | stmts8.go:13:9:13:13 | false |
+| stmts8.go:10:9:10:9 | linux is true | stmts8.go:11:10:11:13 | true |
+| stmts8.go:11:3:11:13 | return statement | stmts8.go:14:1:14:1 | exit |
+| stmts8.go:11:10:11:13 | true | stmts8.go:11:3:11:13 | return statement |
+| stmts8.go:13:2:13:13 | return statement | stmts8.go:14:1:14:1 | exit |
+| stmts8.go:13:9:13:13 | false | stmts8.go:13:2:13:13 | return statement |
+| stmts.go:0:0:0:0 | entry | stmts.go:3:1:3:12 | skip |
+| stmts.go:3:1:3:12 | skip | stmts.go:10:6:10:10 | skip |
+| stmts.go:10:1:10:1 | entry | stmts.go:10:12:10:12 | argument corresponding to b |
+| stmts.go:10:1:43:1 | function declaration | stmts.go:46:6:46:10 | skip |
+| stmts.go:10:6:10:10 | skip | stmts.go:10:1:43:1 | function declaration |
+| stmts.go:10:12:10:12 | argument corresponding to b | stmts.go:10:12:10:12 | initialization of b |
+| stmts.go:10:12:10:12 | initialization of b | stmts.go:12:7:12:7 | b |
+| stmts.go:12:6:12:7 | !... | stmts.go:12:7:12:7 | !... is false |
+| stmts.go:12:6:12:7 | !... | stmts.go:12:7:12:7 | !... is true |
+| stmts.go:12:7:12:7 | !... is false | stmts.go:15:3:16:3 | skip |
+| stmts.go:12:7:12:7 | !... is true | stmts.go:13:4:13:13 | skip |
+| stmts.go:12:7:12:7 | b | stmts.go:12:6:12:7 | !... |
+| stmts.go:13:4:13:13 | skip | stmts.go:23:6:23:9 | true |
+| stmts.go:15:3:16:3 | skip | stmts.go:17:3:17:3 | skip |
+| stmts.go:17:3:17:3 | skip | stmts.go:20:2:20:12 | selection of Println |
+| stmts.go:20:2:20:12 | selection of Println | stmts.go:20:14:20:17 | "Hi" |
+| stmts.go:20:2:20:18 | call to Println | stmts.go:23:6:23:9 | true |
+| stmts.go:20:2:20:18 | call to Println | stmts.go:43:1:43:1 | exit |
+| stmts.go:20:14:20:17 | "Hi" | stmts.go:20:2:20:18 | call to Println |
+| stmts.go:23:6:23:9 | true | stmts.go:23:9:23:9 | true is true |
+| stmts.go:23:9:23:9 | true is false | stmts.go:39:2:39:2 | skip |
+| stmts.go:23:9:23:9 | true is true | stmts.go:24:7:24:7 | skip |
+| stmts.go:24:7:24:7 | assignment to i | stmts.go:24:15:24:15 | i |
+| stmts.go:24:7:24:7 | skip | stmts.go:24:12:24:12 | 0 |
+| stmts.go:24:12:24:12 | 0 | stmts.go:24:7:24:7 | assignment to i |
+| stmts.go:24:15:24:15 | i | stmts.go:24:19:24:20 | 10 |
+| stmts.go:24:15:24:20 | ...<... | stmts.go:24:20:24:20 | ...<... is false |
+| stmts.go:24:15:24:20 | ...<... | stmts.go:24:20:24:20 | ...<... is true |
+| stmts.go:24:19:24:20 | 10 | stmts.go:24:15:24:20 | ...<... |
+| stmts.go:24:20:24:20 | ...<... is false | stmts.go:23:6:23:9 | true |
+| stmts.go:24:20:24:20 | ...<... is true | stmts.go:25:7:25:7 | skip |
+| stmts.go:24:23:24:23 | i | stmts.go:24:23:24:25 | 1 |
+| stmts.go:24:23:24:25 | 1 | stmts.go:24:23:24:25 | rhs of increment statement |
+| stmts.go:24:23:24:25 | increment statement | stmts.go:24:15:24:15 | i |
+| stmts.go:24:23:24:25 | rhs of increment statement | stmts.go:24:23:24:25 | increment statement |
+| stmts.go:25:7:25:7 | assignment to j | stmts.go:25:19:25:19 | j |
+| stmts.go:25:7:25:7 | skip | stmts.go:25:12:25:12 | i |
+| stmts.go:25:12:25:12 | i | stmts.go:25:16:25:16 | 1 |
+| stmts.go:25:12:25:16 | ...-... | stmts.go:25:7:25:7 | assignment to j |
+| stmts.go:25:16:25:16 | 1 | stmts.go:25:12:25:16 | ...-... |
+| stmts.go:25:19:25:19 | j | stmts.go:25:23:25:23 | 5 |
+| stmts.go:25:19:25:23 | ...>... | stmts.go:25:23:25:23 | ...>... is false |
+| stmts.go:25:19:25:23 | ...>... | stmts.go:25:23:25:23 | ...>... is true |
+| stmts.go:25:23:25:23 | 5 | stmts.go:25:19:25:23 | ...>... |
+| stmts.go:25:23:25:23 | ...>... is false | stmts.go:27:14:27:14 | i |
+| stmts.go:25:23:25:23 | ...>... is true | stmts.go:26:5:26:15 | skip |
+| stmts.go:26:5:26:15 | skip | stmts.go:39:2:39:2 | skip |
+| stmts.go:27:14:27:14 | i | stmts.go:27:18:27:18 | 3 |
+| stmts.go:27:14:27:18 | ...<... | stmts.go:27:18:27:18 | ...<... is false |
+| stmts.go:27:14:27:18 | ...<... | stmts.go:27:18:27:18 | ...<... is true |
+| stmts.go:27:18:27:18 | 3 | stmts.go:27:14:27:18 | ...<... |
+| stmts.go:27:18:27:18 | ...<... is false | stmts.go:29:14:29:14 | i |
+| stmts.go:27:18:27:18 | ...<... is true | stmts.go:28:5:28:9 | skip |
+| stmts.go:28:5:28:9 | skip | stmts.go:23:6:23:9 | true |
+| stmts.go:29:14:29:14 | i | stmts.go:29:19:29:19 | 9 |
+| stmts.go:29:14:29:19 | ...!=... | stmts.go:29:19:29:19 | ...!=... is false |
+| stmts.go:29:14:29:19 | ...!=... | stmts.go:29:19:29:19 | ...!=... is true |
+| stmts.go:29:19:29:19 | 9 | stmts.go:29:14:29:19 | ...!=... |
+| stmts.go:29:19:29:19 | ...!=... is false | stmts.go:31:14:31:14 | i |
+| stmts.go:29:19:29:19 | ...!=... is true | stmts.go:30:5:30:18 | skip |
+| stmts.go:30:5:30:18 | skip | stmts.go:23:6:23:9 | true |
+| stmts.go:31:14:31:14 | i | stmts.go:31:19:31:19 | 4 |
+| stmts.go:31:14:31:19 | ...>=... | stmts.go:31:19:31:19 | ...>=... is false |
+| stmts.go:31:14:31:19 | ...>=... | stmts.go:31:19:31:19 | ...>=... is true |
+| stmts.go:31:19:31:19 | 4 | stmts.go:31:14:31:19 | ...>=... |
+| stmts.go:31:19:31:19 | ...>=... is false | stmts.go:34:5:34:12 | skip |
+| stmts.go:31:19:31:19 | ...>=... is true | stmts.go:32:5:32:14 | skip |
+| stmts.go:32:5:32:14 | skip | stmts.go:23:6:23:9 | true |
+| stmts.go:34:5:34:12 | skip | stmts.go:24:23:24:23 | i |
+| stmts.go:39:2:39:2 | assignment to k | stmts.go:41:3:41:12 | skip |
+| stmts.go:39:2:39:2 | skip | stmts.go:39:7:39:7 | 9 |
+| stmts.go:39:7:39:7 | 9 | stmts.go:39:2:39:2 | assignment to k |
+| stmts.go:40:10:40:10 | k | stmts.go:40:10:40:12 | 1 |
+| stmts.go:40:10:40:12 | 1 | stmts.go:40:10:40:12 | rhs of increment statement |
+| stmts.go:40:10:40:12 | increment statement | stmts.go:41:3:41:12 | skip |
+| stmts.go:40:10:40:12 | rhs of increment statement | stmts.go:40:10:40:12 | increment statement |
+| stmts.go:41:3:41:12 | skip | stmts.go:23:6:23:9 | true |
+| stmts.go:46:1:46:1 | entry | stmts.go:46:12:46:14 | argument corresponding to ch1 |
+| stmts.go:46:1:62:1 | function declaration | stmts.go:65:6:65:10 | skip |
+| stmts.go:46:6:46:10 | skip | stmts.go:46:1:62:1 | function declaration |
+| stmts.go:46:12:46:14 | argument corresponding to ch1 | stmts.go:46:12:46:14 | initialization of ch1 |
+| stmts.go:46:12:46:14 | initialization of ch1 | stmts.go:46:26:46:28 | argument corresponding to ch2 |
+| stmts.go:46:26:46:28 | argument corresponding to ch2 | stmts.go:46:26:46:28 | initialization of ch2 |
+| stmts.go:46:26:46:28 | initialization of ch2 | stmts.go:47:6:47:6 | skip |
+| stmts.go:47:6:47:6 | assignment to a | stmts.go:48:6:48:6 | skip |
+| stmts.go:47:6:47:6 | skip | stmts.go:47:6:47:6 | zero value for a |
+| stmts.go:47:6:47:6 | zero value for a | stmts.go:47:6:47:6 | assignment to a |
+| stmts.go:48:6:48:6 | assignment to w | stmts.go:51:9:51:11 | ch1 |
+| stmts.go:48:6:48:6 | skip | stmts.go:48:6:48:6 | zero value for w |
+| stmts.go:48:6:48:6 | zero value for w | stmts.go:48:6:48:6 | assignment to w |
+| stmts.go:50:2:59:2 | select statement | stmts.go:51:7:51:11 | <-... |
+| stmts.go:50:2:59:2 | select statement | stmts.go:53:17:53:21 | <-... |
+| stmts.go:50:2:59:2 | select statement | stmts.go:57:3:57:13 | selection of Println |
+| stmts.go:50:2:59:2 | select statement | stmts.go:58:7:58:15 | send statement |
+| stmts.go:51:7:51:11 | <-... | stmts.go:52:3:52:13 | selection of Println |
+| stmts.go:51:9:51:11 | ch1 | stmts.go:53:19:53:21 | ch2 |
+| stmts.go:52:3:52:13 | selection of Println | stmts.go:52:15:52:30 | "Heard from ch1" |
+| stmts.go:52:3:52:31 | call to Println | stmts.go:61:2:61:10 | select statement |
+| stmts.go:52:3:52:31 | call to Println | stmts.go:62:1:62:1 | exit |
+| stmts.go:52:15:52:30 | "Heard from ch1" | stmts.go:52:3:52:31 | call to Println |
+| stmts.go:53:7:53:7 | a | stmts.go:53:9:53:9 | 0 |
+| stmts.go:53:7:53:10 | assignment to element | stmts.go:53:7:53:21 | ... = ...[1] |
+| stmts.go:53:7:53:10 | skip | stmts.go:53:13:53:13 | skip |
+| stmts.go:53:7:53:10 | skip | stmts.go:62:1:62:1 | exit |
+| stmts.go:53:7:53:21 | ... = ...[0] | stmts.go:53:7:53:10 | assignment to element |
+| stmts.go:53:7:53:21 | ... = ...[1] | stmts.go:53:13:53:13 | assignment to w |
+| stmts.go:53:9:53:9 | 0 | stmts.go:53:7:53:10 | skip |
+| stmts.go:53:13:53:13 | assignment to w | stmts.go:54:3:54:13 | selection of Println |
+| stmts.go:53:13:53:13 | skip | stmts.go:53:7:53:21 | ... = ...[0] |
+| stmts.go:53:17:53:21 | <-... | stmts.go:53:7:53:7 | a |
+| stmts.go:53:19:53:21 | ch2 | stmts.go:58:7:58:9 | ch1 |
+| stmts.go:54:3:54:13 | selection of Println | stmts.go:54:15:54:15 | a |
+| stmts.go:54:3:54:16 | call to Println | stmts.go:55:3:55:13 | selection of Println |
+| stmts.go:54:3:54:16 | call to Println | stmts.go:62:1:62:1 | exit |
+| stmts.go:54:15:54:15 | a | stmts.go:54:3:54:16 | call to Println |
+| stmts.go:55:3:55:13 | selection of Println | stmts.go:55:15:55:15 | w |
+| stmts.go:55:3:55:16 | call to Println | stmts.go:61:2:61:10 | select statement |
+| stmts.go:55:3:55:16 | call to Println | stmts.go:62:1:62:1 | exit |
+| stmts.go:55:15:55:15 | w | stmts.go:55:3:55:16 | call to Println |
+| stmts.go:57:3:57:13 | selection of Println | stmts.go:57:3:57:15 | call to Println |
+| stmts.go:57:3:57:15 | call to Println | stmts.go:61:2:61:10 | select statement |
+| stmts.go:57:3:57:15 | call to Println | stmts.go:62:1:62:1 | exit |
+| stmts.go:58:2:58:16 | skip | stmts.go:61:2:61:10 | select statement |
+| stmts.go:58:7:58:9 | ch1 | stmts.go:58:14:58:15 | 42 |
+| stmts.go:58:7:58:15 | send statement | stmts.go:58:2:58:16 | skip |
+| stmts.go:58:7:58:15 | send statement | stmts.go:62:1:62:1 | exit |
+| stmts.go:58:14:58:15 | 42 | stmts.go:50:2:59:2 | select statement |
+| stmts.go:65:1:65:1 | entry | stmts.go:65:12:65:12 | argument corresponding to x |
+| stmts.go:65:1:72:1 | function declaration | stmts.go:75:6:75:10 | skip |
+| stmts.go:65:6:65:10 | skip | stmts.go:65:1:72:1 | function declaration |
+| stmts.go:65:12:65:12 | argument corresponding to x | stmts.go:65:12:65:12 | initialization of x |
+| stmts.go:65:12:65:12 | initialization of x | stmts.go:66:5:66:5 | x |
+| stmts.go:66:5:66:5 | x | stmts.go:66:9:66:9 | 0 |
+| stmts.go:66:5:66:9 | ...>... | stmts.go:66:9:66:9 | ...>... is false |
+| stmts.go:66:5:66:9 | ...>... | stmts.go:66:9:66:9 | ...>... is true |
+| stmts.go:66:9:66:9 | 0 | stmts.go:66:5:66:9 | ...>... |
+| stmts.go:66:9:66:9 | ...>... is false | stmts.go:69:9:69:34 | function literal |
+| stmts.go:66:9:66:9 | ...>... is true | stmts.go:67:9:67:33 | function literal |
+| stmts.go:67:3:67:35 | defer statement | stmts.go:71:9:71:10 | 42 |
+| stmts.go:67:9:67:9 | entry | stmts.go:67:18:67:28 | selection of Println |
+| stmts.go:67:9:67:33 | function literal | stmts.go:67:3:67:35 | defer statement |
+| stmts.go:67:9:67:35 | function call | stmts.go:72:1:72:1 | exit |
+| stmts.go:67:18:67:28 | selection of Println | stmts.go:67:30:67:30 | x |
+| stmts.go:67:18:67:31 | call to Println | stmts.go:67:33:67:33 | exit |
+| stmts.go:67:30:67:30 | x | stmts.go:67:18:67:31 | call to Println |
+| stmts.go:69:3:69:36 | defer statement | stmts.go:71:9:71:10 | 42 |
+| stmts.go:69:9:69:9 | entry | stmts.go:69:18:69:28 | selection of Println |
+| stmts.go:69:9:69:34 | function literal | stmts.go:69:3:69:36 | defer statement |
+| stmts.go:69:9:69:36 | function call | stmts.go:72:1:72:1 | exit |
+| stmts.go:69:18:69:28 | selection of Println | stmts.go:69:31:69:31 | x |
+| stmts.go:69:18:69:32 | call to Println | stmts.go:69:34:69:34 | exit |
+| stmts.go:69:30:69:31 | -... | stmts.go:69:18:69:32 | call to Println |
+| stmts.go:69:31:69:31 | x | stmts.go:69:30:69:31 | -... |
+| stmts.go:71:2:71:10 | return statement | stmts.go:67:9:67:35 | function call |
+| stmts.go:71:2:71:10 | return statement | stmts.go:69:9:69:36 | function call |
+| stmts.go:71:9:71:10 | 42 | stmts.go:71:2:71:10 | return statement |
+| stmts.go:75:1:75:1 | entry | stmts.go:75:12:75:12 | argument corresponding to x |
+| stmts.go:75:1:109:1 | function declaration | stmts.go:112:6:112:10 | skip |
+| stmts.go:75:6:75:10 | skip | stmts.go:75:1:109:1 | function declaration |
+| stmts.go:75:12:75:12 | argument corresponding to x | stmts.go:75:12:75:12 | initialization of x |
+| stmts.go:75:12:75:12 | initialization of x | stmts.go:76:9:76:9 | x |
+| stmts.go:76:9:76:9 | x | stmts.go:79:9:79:9 | skip |
+| stmts.go:79:9:79:9 | assignment to y | stmts.go:79:17:79:17 | y |
+| stmts.go:79:9:79:9 | skip | stmts.go:79:14:79:14 | x |
+| stmts.go:79:14:79:14 | x | stmts.go:79:9:79:9 | assignment to y |
+| stmts.go:79:17:79:17 | y | stmts.go:79:21:79:22 | 19 |
+| stmts.go:79:17:79:22 | ...-... | stmts.go:81:3:81:7 | test5 |
+| stmts.go:79:21:79:22 | 19 | stmts.go:79:17:79:22 | ...-... |
+| stmts.go:81:3:81:7 | test5 | stmts.go:81:9:81:13 | false |
+| stmts.go:81:3:81:14 | call to test5 | stmts.go:109:1:109:1 | exit |
+| stmts.go:81:9:81:13 | false | stmts.go:81:3:81:14 | call to test5 |
+| stmts.go:84:9:84:9 | x | stmts.go:85:7:85:7 | 1 |
+| stmts.go:84:9:84:9 | x | stmts.go:90:9:90:9 | x |
+| stmts.go:85:2:85:8 | skip | stmts.go:90:9:90:9 | x |
+| stmts.go:85:7:85:7 | 1 | stmts.go:85:7:85:7 | case 1 |
+| stmts.go:85:7:85:7 | case 1 | stmts.go:85:2:85:8 | skip |
+| stmts.go:85:7:85:7 | case 1 | stmts.go:86:7:86:7 | 2 |
+| stmts.go:86:7:86:7 | 2 | stmts.go:86:7:86:7 | case 2 |
+| stmts.go:86:7:86:7 | case 2 | stmts.go:86:10:86:10 | 3 |
+| stmts.go:86:7:86:7 | case 2 | stmts.go:87:3:87:7 | test5 |
+| stmts.go:86:10:86:10 | 3 | stmts.go:86:10:86:10 | case 3 |
+| stmts.go:86:10:86:10 | case 3 | stmts.go:87:3:87:7 | test5 |
+| stmts.go:86:10:86:10 | case 3 | stmts.go:90:9:90:9 | x |
+| stmts.go:87:3:87:7 | test5 | stmts.go:87:9:87:12 | true |
+| stmts.go:87:9:87:12 | true | stmts.go:87:3:87:13 | call to test5 |
+| stmts.go:90:9:90:9 | x | stmts.go:91:7:91:7 | 1 |
+| stmts.go:90:9:90:9 | x | stmts.go:98:9:98:9 | x |
+| stmts.go:91:7:91:7 | 1 | stmts.go:91:7:91:7 | case 1 |
+| stmts.go:91:7:91:7 | case 1 | stmts.go:92:3:92:7 | test5 |
+| stmts.go:91:7:91:7 | case 1 | stmts.go:94:7:94:11 | ...-... |
+| stmts.go:92:3:92:7 | test5 | stmts.go:92:9:92:13 | false |
+| stmts.go:92:9:92:13 | false | stmts.go:92:3:92:14 | call to test5 |
+| stmts.go:93:3:93:13 | skip | stmts.go:95:3:95:7 | test5 |
+| stmts.go:94:7:94:11 | ...-... | stmts.go:94:7:94:11 | case ...-... |
+| stmts.go:94:7:94:11 | case ...-... | stmts.go:95:3:95:7 | test5 |
+| stmts.go:94:7:94:11 | case ...-... | stmts.go:98:9:98:9 | x |
+| stmts.go:95:3:95:7 | test5 | stmts.go:95:9:95:12 | true |
+| stmts.go:95:9:95:12 | true | stmts.go:95:3:95:13 | call to test5 |
+| stmts.go:98:9:98:9 | x | stmts.go:100:7:100:7 | 2 |
+| stmts.go:99:2:99:9 | skip | stmts.go:104:2:104:2 | true |
+| stmts.go:100:7:100:7 | 2 | stmts.go:100:7:100:7 | case 2 |
+| stmts.go:100:7:100:7 | case 2 | stmts.go:99:2:99:9 | skip |
+| stmts.go:100:7:100:7 | case 2 | stmts.go:101:3:101:7 | test5 |
+| stmts.go:101:3:101:7 | test5 | stmts.go:101:9:101:12 | true |
+| stmts.go:101:9:101:12 | true | stmts.go:101:3:101:13 | call to test5 |
+| stmts.go:104:2:104:2 | true | stmts.go:107:7:107:10 | true |
+| stmts.go:107:7:107:10 | case true | stmts.go:107:10:107:10 | true is false |
+| stmts.go:107:7:107:10 | case true | stmts.go:107:10:107:10 | true is true |
+| stmts.go:107:7:107:10 | true | stmts.go:107:7:107:10 | case true |
+| stmts.go:107:10:107:10 | true is false | stmts.go:106:3:106:7 | skip |
+| stmts.go:107:10:107:10 | true is true | stmts.go:107:2:107:11 | skip |
+| stmts.go:112:1:112:1 | entry | stmts.go:112:12:112:12 | argument corresponding to x |
+| stmts.go:112:1:125:1 | function declaration | stmts.go:128:6:128:11 | skip |
+| stmts.go:112:6:112:10 | skip | stmts.go:112:1:125:1 | function declaration |
+| stmts.go:112:12:112:12 | argument corresponding to x | stmts.go:112:12:112:12 | initialization of x |
+| stmts.go:112:12:112:12 | initialization of x | stmts.go:113:9:113:9 | skip |
+| stmts.go:113:9:113:9 | assignment to y | stmts.go:114:7:114:11 | case error |
+| stmts.go:113:9:113:9 | assignment to y | stmts.go:121:9:121:9 | skip |
+| stmts.go:113:9:113:9 | skip | stmts.go:113:14:113:14 | x |
+| stmts.go:113:14:113:14 | x | stmts.go:113:14:113:21 | type assertion |
+| stmts.go:113:14:113:21 | type assertion | stmts.go:113:9:113:9 | assignment to y |
+| stmts.go:114:7:114:11 | case error | stmts.go:114:14:114:19 | case string |
+| stmts.go:114:7:114:11 | case error | stmts.go:115:3:115:13 | selection of Println |
+| stmts.go:114:14:114:19 | case string | stmts.go:115:3:115:13 | selection of Println |
+| stmts.go:114:14:114:19 | case string | stmts.go:116:7:116:13 | case float32 |
+| stmts.go:115:3:115:13 | selection of Println | stmts.go:115:15:115:15 | y |
+| stmts.go:115:3:115:16 | call to Println | stmts.go:121:9:121:9 | skip |
+| stmts.go:115:3:115:16 | call to Println | stmts.go:125:1:125:1 | exit |
+| stmts.go:115:15:115:15 | y | stmts.go:115:3:115:16 | call to Println |
+| stmts.go:116:7:116:13 | case float32 | stmts.go:117:3:117:7 | test5 |
+| stmts.go:116:7:116:13 | case float32 | stmts.go:121:9:121:9 | skip |
+| stmts.go:117:3:117:7 | test5 | stmts.go:117:9:117:12 | true |
+| stmts.go:117:3:117:13 | call to test5 | stmts.go:125:1:125:1 | exit |
+| stmts.go:117:9:117:12 | true | stmts.go:117:3:117:13 | call to test5 |
+| stmts.go:118:3:118:7 | test5 | stmts.go:118:9:118:13 | false |
+| stmts.go:118:9:118:13 | false | stmts.go:118:3:118:14 | call to test5 |
+| stmts.go:121:9:121:9 | assignment to y | stmts.go:121:17:121:17 | y |
+| stmts.go:121:9:121:9 | skip | stmts.go:121:14:121:14 | x |
+| stmts.go:121:14:121:14 | x | stmts.go:121:9:121:9 | assignment to y |
+| stmts.go:121:17:121:17 | y | stmts.go:121:17:121:24 | type assertion |
+| stmts.go:121:17:121:24 | type assertion | stmts.go:123:3:123:7 | test5 |
+| stmts.go:123:3:123:7 | test5 | stmts.go:123:9:123:13 | false |
+| stmts.go:123:3:123:14 | call to test5 | stmts.go:125:1:125:1 | exit |
+| stmts.go:123:9:123:13 | false | stmts.go:123:3:123:14 | call to test5 |
+| stmts.go:128:1:128:1 | entry | stmts.go:128:13:128:13 | argument corresponding to f |
+| stmts.go:128:1:130:1 | function declaration | stmts.go:133:6:133:11 | skip |
+| stmts.go:128:6:128:11 | skip | stmts.go:128:1:130:1 | function declaration |
+| stmts.go:128:13:128:13 | argument corresponding to f | stmts.go:128:13:128:13 | initialization of f |
+| stmts.go:128:13:128:13 | initialization of f | stmts.go:129:5:129:5 | f |
+| stmts.go:129:2:129:7 | go statement | stmts.go:130:1:130:1 | exit |
+| stmts.go:129:5:129:5 | f | stmts.go:129:2:129:7 | go statement |
+| stmts.go:133:1:133:1 | entry | stmts.go:133:13:133:14 | argument corresponding to xs |
+| stmts.go:133:1:147:1 | function declaration | stmts.go:0:0:0:0 | exit |
+| stmts.go:133:6:133:11 | skip | stmts.go:133:1:147:1 | function declaration |
+| stmts.go:133:13:133:14 | argument corresponding to xs | stmts.go:133:13:133:14 | initialization of xs |
+| stmts.go:133:13:133:14 | initialization of xs | stmts.go:134:17:134:18 | xs |
+| stmts.go:134:2:139:2 | range statement[0] | stmts.go:134:6:134:6 | assignment to x |
+| stmts.go:134:6:134:6 | assignment to x | stmts.go:135:6:135:6 | x |
+| stmts.go:134:6:134:6 | skip | stmts.go:134:2:139:2 | range statement[0] |
+| stmts.go:134:17:134:18 | next key-value pair in range | stmts.go:134:6:134:6 | skip |
+| stmts.go:134:17:134:18 | next key-value pair in range | stmts.go:141:20:141:21 | xs |
+| stmts.go:134:17:134:18 | xs | stmts.go:134:17:134:18 | next key-value pair in range |
+| stmts.go:135:6:135:6 | x | stmts.go:135:10:135:10 | 5 |
+| stmts.go:135:6:135:10 | ...>... | stmts.go:135:10:135:10 | ...>... is false |
+| stmts.go:135:6:135:10 | ...>... | stmts.go:135:10:135:10 | ...>... is true |
+| stmts.go:135:10:135:10 | 5 | stmts.go:135:6:135:10 | ...>... |
+| stmts.go:135:10:135:10 | ...>... is false | stmts.go:138:3:138:11 | selection of Print |
+| stmts.go:135:10:135:10 | ...>... is true | stmts.go:136:4:136:11 | skip |
+| stmts.go:136:4:136:11 | skip | stmts.go:134:17:134:18 | next key-value pair in range |
+| stmts.go:138:3:138:11 | selection of Print | stmts.go:138:13:138:13 | x |
+| stmts.go:138:3:138:14 | call to Print | stmts.go:134:17:134:18 | next key-value pair in range |
+| stmts.go:138:3:138:14 | call to Print | stmts.go:147:1:147:1 | exit |
+| stmts.go:138:13:138:13 | x | stmts.go:138:3:138:14 | call to Print |
+| stmts.go:141:2:143:2 | range statement[0] | stmts.go:141:2:143:2 | range statement[1] |
+| stmts.go:141:2:143:2 | range statement[1] | stmts.go:141:6:141:6 | assignment to i |
+| stmts.go:141:6:141:6 | assignment to i | stmts.go:141:9:141:9 | assignment to v |
+| stmts.go:141:6:141:6 | skip | stmts.go:141:9:141:9 | skip |
+| stmts.go:141:9:141:9 | assignment to v | stmts.go:142:3:142:11 | selection of Print |
+| stmts.go:141:9:141:9 | skip | stmts.go:141:2:143:2 | range statement[0] |
+| stmts.go:141:20:141:21 | next key-value pair in range | stmts.go:141:6:141:6 | skip |
+| stmts.go:141:20:141:21 | next key-value pair in range | stmts.go:145:12:145:13 | xs |
+| stmts.go:141:20:141:21 | xs | stmts.go:141:20:141:21 | next key-value pair in range |
+| stmts.go:142:3:142:11 | selection of Print | stmts.go:142:13:142:13 | i |
+| stmts.go:142:3:142:17 | call to Print | stmts.go:141:20:141:21 | next key-value pair in range |
+| stmts.go:142:3:142:17 | call to Print | stmts.go:147:1:147:1 | exit |
+| stmts.go:142:13:142:13 | i | stmts.go:142:16:142:16 | v |
+| stmts.go:142:16:142:16 | v | stmts.go:142:3:142:17 | call to Print |
+| stmts.go:145:12:145:13 | next key-value pair in range | stmts.go:145:15:146:2 | skip |
+| stmts.go:145:12:145:13 | next key-value pair in range | stmts.go:147:1:147:1 | exit |
+| stmts.go:145:12:145:13 | xs | stmts.go:145:12:145:13 | next key-value pair in range |
+| stmts.go:145:15:146:2 | skip | stmts.go:145:12:145:13 | next key-value pair in range |
+| tst.go:0:0:0:0 | entry | tst.go:3:6:3:10 | skip |
+| tst.go:3:1:3:1 | entry | tst.go:3:12:3:12 | argument corresponding to x |
+| tst.go:3:1:12:1 | function declaration | tst.go:14:6:14:11 | skip |
+| tst.go:3:6:3:10 | skip | tst.go:3:1:12:1 | function declaration |
+| tst.go:3:12:3:12 | argument corresponding to x | tst.go:3:12:3:12 | initialization of x |
+| tst.go:3:12:3:12 | initialization of x | tst.go:4:2:4:2 | true |
+| tst.go:4:2:4:2 | true | tst.go:5:7:5:7 | x |
+| tst.go:5:2:5:13 | skip | tst.go:12:1:12:1 | exit |
+| tst.go:5:7:5:7 | x | tst.go:5:11:5:12 | 23 |
+| tst.go:5:7:5:12 | ...<... | tst.go:5:7:5:12 | case ...<... |
+| tst.go:5:7:5:12 | case ...<... | tst.go:5:12:5:12 | ...<... is false |
+| tst.go:5:7:5:12 | case ...<... | tst.go:5:12:5:12 | ...<... is true |
+| tst.go:5:11:5:12 | 23 | tst.go:5:7:5:12 | ...<... |
+| tst.go:5:12:5:12 | ...<... is false | tst.go:7:7:7:7 | x |
+| tst.go:5:12:5:12 | ...<... is true | tst.go:5:2:5:13 | skip |
+| tst.go:7:2:7:13 | skip | tst.go:12:1:12:1 | exit |
+| tst.go:7:7:7:7 | x | tst.go:7:11:7:12 | 42 |
+| tst.go:7:7:7:12 | ...<... | tst.go:7:7:7:12 | case ...<... |
+| tst.go:7:7:7:12 | case ...<... | tst.go:7:12:7:12 | ...<... is false |
+| tst.go:7:7:7:12 | case ...<... | tst.go:7:12:7:12 | ...<... is true |
+| tst.go:7:11:7:12 | 42 | tst.go:7:7:7:12 | ...<... |
+| tst.go:7:12:7:12 | ...<... is false | tst.go:9:7:9:7 | x |
+| tst.go:7:12:7:12 | ...<... is true | tst.go:7:2:7:13 | skip |
+| tst.go:9:2:9:13 | skip | tst.go:12:1:12:1 | exit |
+| tst.go:9:7:9:7 | x | tst.go:9:11:9:12 | 23 |
+| tst.go:9:7:9:12 | ...<... | tst.go:9:7:9:12 | case ...<... |
+| tst.go:9:7:9:12 | case ...<... | tst.go:9:12:9:12 | ...<... is false |
+| tst.go:9:7:9:12 | case ...<... | tst.go:9:12:9:12 | ...<... is true |
+| tst.go:9:11:9:12 | 23 | tst.go:9:7:9:12 | ...<... |
+| tst.go:9:12:9:12 | ...<... is false | tst.go:12:1:12:1 | exit |
+| tst.go:9:12:9:12 | ...<... is true | tst.go:9:2:9:13 | skip |
+| tst.go:14:1:14:1 | entry | tst.go:14:13:14:17 | argument corresponding to value |
+| tst.go:14:1:21:1 | function declaration | tst.go:23:6:23:11 | skip |
+| tst.go:14:6:14:11 | skip | tst.go:14:1:21:1 | function declaration |
+| tst.go:14:13:14:17 | argument corresponding to value | tst.go:14:13:14:17 | initialization of value |
+| tst.go:14:13:14:17 | initialization of value | tst.go:15:2:15:2 | true |
+| tst.go:15:2:15:2 | true | tst.go:16:7:16:11 | value |
+| tst.go:16:2:16:34 | skip | tst.go:21:1:21:1 | exit |
+| tst.go:16:7:16:11 | value | tst.go:16:15:16:33 | ...*... |
+| tst.go:16:7:16:33 | ...<... | tst.go:16:7:16:33 | case ...<... |
+| tst.go:16:7:16:33 | case ...<... | tst.go:16:33:16:33 | ...<... is false |
+| tst.go:16:7:16:33 | case ...<... | tst.go:16:33:16:33 | ...<... is true |
+| tst.go:16:15:16:33 | ...*... | tst.go:16:7:16:33 | ...<... |
+| tst.go:16:33:16:33 | ...<... is false | tst.go:18:7:18:11 | value |
+| tst.go:16:33:16:33 | ...<... is true | tst.go:16:2:16:34 | skip |
+| tst.go:18:2:18:39 | skip | tst.go:21:1:21:1 | exit |
+| tst.go:18:7:18:11 | value | tst.go:18:15:18:38 | ...*... |
+| tst.go:18:7:18:38 | ...<... | tst.go:18:7:18:38 | case ...<... |
+| tst.go:18:7:18:38 | case ...<... | tst.go:18:38:18:38 | ...<... is false |
+| tst.go:18:7:18:38 | case ...<... | tst.go:18:38:18:38 | ...<... is true |
+| tst.go:18:15:18:38 | ...*... | tst.go:18:7:18:38 | ...<... |
+| tst.go:18:38:18:38 | ...<... is false | tst.go:21:1:21:1 | exit |
+| tst.go:18:38:18:38 | ...<... is true | tst.go:18:2:18:39 | skip |
+| tst.go:23:1:23:1 | entry | tst.go:24:2:24:2 | true |
+| tst.go:23:1:26:1 | function declaration | tst.go:28:6:28:11 | skip |
+| tst.go:23:6:23:11 | skip | tst.go:23:1:26:1 | function declaration |
+| tst.go:24:2:24:2 | true | tst.go:26:1:26:1 | exit |
+| tst.go:28:1:28:1 | entry | tst.go:29:2:29:2 | true |
+| tst.go:28:1:32:1 | function declaration | tst.go:0:0:0:0 | exit |
+| tst.go:28:6:28:11 | skip | tst.go:28:1:32:1 | function declaration |
+| tst.go:29:2:29:2 | true | tst.go:30:2:30:9 | skip |
+| tst.go:30:2:30:9 | skip | tst.go:32:1:32:1 | exit |
#select
| |
diff --git a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.ql b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.ql
index 144a01f2aa5..3f0afd67cae 100644
--- a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.ql
+++ b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CFG.ql
@@ -1,10 +1,9 @@
import go
-query predicate nodes(ControlFlow::Node nd) { none() }
-
query predicate edges(ControlFlow::Node pred, ControlFlow::Node succ) {
- none()
- // succ = pred.getASuccessor()
+ not succ.getFile().hasBuildConstraints() and
+ not pred.getFile().hasBuildConstraints() and
+ succ = pred.getASuccessor()
}
select ""
diff --git a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/linux.go b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/linux.go
index 66c40b54084..4f8f6b615fe 100644
--- a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/linux.go
+++ b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/linux.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package main
diff --git a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/nonlinux.go b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/nonlinux.go
index 3347a26fa7a..e0ec489338f 100644
--- a/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/nonlinux.go
+++ b/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/nonlinux.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package main
diff --git a/ql/test/library-tests/semmle/go/frameworks/SQL/go.mod b/ql/test/library-tests/semmle/go/frameworks/SQL/go.mod
index 23bb420b262..69db5c96c41 100644
--- a/ql/test/library-tests/semmle/go/frameworks/SQL/go.mod
+++ b/ql/test/library-tests/semmle/go/frameworks/SQL/go.mod
@@ -6,4 +6,9 @@ require (
github.com/Masterminds/squirrel v1.1.0
github.com/go-pg/pg v8.0.6+incompatible
github.com/go-pg/pg/v9 v9.1.3
+ github.com/go-sql-driver/mysql v1.6.0 // indirect
+ github.com/go-xorm/xorm v0.7.9
+ github.com/lib/pq v1.10.2 // indirect
+ github.com/mattn/go-sqlite3 v1.14.7 // indirect
+ xorm.io/xorm v1.1.0
)
diff --git a/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-xorm/xorm/stub.go b/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-xorm/xorm/stub.go
new file mode 100644
index 00000000000..9853e015547
--- /dev/null
+++ b/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/github.com/go-xorm/xorm/stub.go
@@ -0,0 +1,917 @@
+// Code generated by depstubber. DO NOT EDIT.
+// This is a simple stub for github.com/go-xorm/xorm, strictly for use in testing.
+
+// See the LICENSE file for information about the licensing of the original library.
+// Source: github.com/go-xorm/xorm (exports: Engine,Session; functions: )
+
+// Package xorm is a stub of github.com/go-xorm/xorm, generated by depstubber.
+package xorm
+
+import (
+ context "context"
+ sql "database/sql"
+ io "io"
+ reflect "reflect"
+ strings "strings"
+ time "time"
+)
+
+type ContextCache interface {
+ Get(_ string) interface{}
+ Put(_ string, _ interface{})
+}
+
+type Engine struct {
+ ColumnMapper interface{}
+ TableMapper interface{}
+ TagIdentifier string
+ Tables map[reflect.Type]interface{}
+ Cacher interface{}
+ TZLocation *time.Location
+ DatabaseTZ *time.Location
+}
+
+func (_ *Engine) After(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Engine) Alias(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) AllCols() *Session {
+ return nil
+}
+
+func (_ *Engine) Asc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) AutoIncrStr() string {
+ return ""
+}
+
+func (_ *Engine) Before(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Engine) BufferSize(_ int) *Session {
+ return nil
+}
+
+func (_ *Engine) Cascade(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Engine) Charset(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) ClearCache(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) ClearCacheBean(_ interface{}, _ string) error {
+ return nil
+}
+
+func (_ *Engine) Clone() (*Engine, error) {
+ return nil, nil
+}
+
+func (_ *Engine) Close() error {
+ return nil
+}
+
+func (_ *Engine) Cols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) CondDeleted(_ string) interface{} {
+ return nil
+}
+
+func (_ *Engine) Context(_ context.Context) *Session {
+ return nil
+}
+
+func (_ *Engine) Count(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) CreateIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) CreateTables(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) CreateUniques(_ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DB() interface{} {
+ return nil
+}
+
+func (_ *Engine) DBMetas() ([]interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) DataSourceName() string {
+ return ""
+}
+
+func (_ *Engine) Decr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Delete(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) Desc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Dialect() interface{} {
+ return nil
+}
+
+func (_ *Engine) Distinct(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) DriverName() string {
+ return ""
+}
+
+func (_ *Engine) DropIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DropTables(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpAll(_ io.Writer, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpAllToFile(_ string, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpTables(_ []interface{}, _ io.Writer, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpTablesToFile(_ []interface{}, _ string, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) Exec(_ ...interface{}) (sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Engine) Exist(_ ...interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) Find(_ interface{}, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) FindAndCount(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) Get(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) GetCacher(_ string) interface{} {
+ return nil
+}
+
+func (_ *Engine) GetColumnMapper() interface{} {
+ return nil
+}
+
+func (_ *Engine) GetDefaultCacher() interface{} {
+ return nil
+}
+
+func (_ *Engine) GetTZDatabase() *time.Location {
+ return nil
+}
+
+func (_ *Engine) GetTZLocation() *time.Location {
+ return nil
+}
+
+func (_ *Engine) GetTableMapper() interface{} {
+ return nil
+}
+
+func (_ *Engine) GobRegister(_ interface{}) *Engine {
+ return nil
+}
+
+func (_ *Engine) GroupBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) Having(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) ID(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) IDOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ *Engine) IDOfV(_ reflect.Value) interface{} {
+ return nil
+}
+
+func (_ *Engine) Id(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) IdOf(_ interface{}) interface{} {
+ return nil
+}
+
+func (_ *Engine) IdOfV(_ reflect.Value) interface{} {
+ return nil
+}
+
+func (_ *Engine) Import(_ io.Reader) ([]sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Engine) ImportFile(_ string) ([]sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Engine) In(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Incr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Insert(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) InsertOne(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) IsTableEmpty(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) IsTableExist(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) Iterate(_ interface{}, _ IterFunc) error {
+ return nil
+}
+
+func (_ *Engine) Join(_ string, _ interface{}, _ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Limit(_ int, _ ...int) *Session {
+ return nil
+}
+
+func (_ *Engine) Logger() interface{} {
+ return nil
+}
+
+func (_ *Engine) MapCacher(_ interface{}, _ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) MustCols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) NewDB() (interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) NewSession() *Session {
+ return nil
+}
+
+func (_ *Engine) NoAutoCondition(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Engine) NoAutoTime() *Session {
+ return nil
+}
+
+func (_ *Engine) NoCache() *Session {
+ return nil
+}
+
+func (_ *Engine) NoCascade() *Session {
+ return nil
+}
+
+func (_ *Engine) NotIn(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Nullable(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Omit(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) OrderBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) Ping() error {
+ return nil
+}
+
+func (_ *Engine) PingContext(_ context.Context) error {
+ return nil
+}
+
+func (_ *Engine) Prepare() *Session {
+ return nil
+}
+
+func (_ *Engine) Query(_ ...interface{}) ([]map[string][]byte, error) {
+ return nil, nil
+}
+
+func (_ *Engine) QueryInterface(_ ...interface{}) ([]map[string]interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) QueryString(_ ...interface{}) ([]map[string]string, error) {
+ return nil, nil
+}
+
+func (_ *Engine) Quote(_ string) string {
+ return ""
+}
+
+func (_ *Engine) QuoteTo(_ *strings.Builder, _ string) {}
+
+func (_ *Engine) Rows(_ interface{}) (*Rows, error) {
+ return nil, nil
+}
+
+func (_ *Engine) SQL(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) SQLType(_ interface{}) string {
+ return ""
+}
+
+func (_ *Engine) Select(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) SetCacher(_ string, _ interface{}) {}
+
+func (_ *Engine) SetColumnMapper(_ interface{}) {}
+
+func (_ *Engine) SetConnMaxLifetime(_ time.Duration) {}
+
+func (_ *Engine) SetDefaultCacher(_ interface{}) {}
+
+func (_ *Engine) SetDefaultContext(_ context.Context) {}
+
+func (_ *Engine) SetDisableGlobalCache(_ bool) {}
+
+func (_ *Engine) SetExpr(_ string, _ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) SetLogLevel(_ interface{}) {}
+
+func (_ *Engine) SetLogger(_ interface{}) {}
+
+func (_ *Engine) SetMapper(_ interface{}) {}
+
+func (_ *Engine) SetMaxIdleConns(_ int) {}
+
+func (_ *Engine) SetMaxOpenConns(_ int) {}
+
+func (_ *Engine) SetSchema(_ string) {}
+
+func (_ *Engine) SetTZDatabase(_ *time.Location) {}
+
+func (_ *Engine) SetTZLocation(_ *time.Location) {}
+
+func (_ *Engine) SetTableMapper(_ interface{}) {}
+
+func (_ *Engine) ShowExecTime(_ ...bool) {}
+
+func (_ *Engine) ShowSQL(_ ...bool) {}
+
+func (_ *Engine) Sql(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) SqlType(_ interface{}) string {
+ return ""
+}
+
+func (_ *Engine) StoreEngine(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) Sum(_ interface{}, _ string) (float64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) SumInt(_ interface{}, _ string) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) Sums(_ interface{}, _ ...string) ([]float64, error) {
+ return nil, nil
+}
+
+func (_ *Engine) SumsInt(_ interface{}, _ ...string) ([]int64, error) {
+ return nil, nil
+}
+
+func (_ *Engine) SupportInsertMany() bool {
+ return false
+}
+
+func (_ *Engine) Sync(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) Sync2(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) Table(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) TableInfo(_ interface{}) *Table {
+ return nil
+}
+
+func (_ *Engine) TableName(_ interface{}, _ ...bool) string {
+ return ""
+}
+
+func (_ *Engine) Transaction(_ func(*Session) (interface{}, error)) (interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) UnMapType(_ reflect.Type) {}
+
+func (_ *Engine) Unscoped() *Session {
+ return nil
+}
+
+func (_ *Engine) Update(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) UseBool(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Where(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+type IterFunc func(int, interface{}) error
+
+type Rows struct{}
+
+func (_ *Rows) Close() error {
+ return nil
+}
+
+func (_ *Rows) Err() error {
+ return nil
+}
+
+func (_ *Rows) Next() bool {
+ return false
+}
+
+func (_ *Rows) Scan(_ interface{}) error {
+ return nil
+}
+
+type Session struct{}
+
+func (_ *Session) After(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Session) Alias(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) AllCols() *Session {
+ return nil
+}
+
+func (_ *Session) And(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Asc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Before(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Session) Begin() error {
+ return nil
+}
+
+func (_ *Session) BufferSize(_ int) *Session {
+ return nil
+}
+
+func (_ *Session) Cascade(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Session) Charset(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Clone() *Session {
+ return nil
+}
+
+func (_ *Session) Close() {}
+
+func (_ *Session) Cols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Commit() error {
+ return nil
+}
+
+func (_ *Session) Conds() interface{} {
+ return nil
+}
+
+func (_ *Session) Context(_ context.Context) *Session {
+ return nil
+}
+
+func (_ *Session) ContextCache(_ ContextCache) *Session {
+ return nil
+}
+
+func (_ *Session) Count(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) CreateIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) CreateTable(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) CreateUniques(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) DB() interface{} {
+ return nil
+}
+
+func (_ *Session) Decr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Delete(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) Desc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Distinct(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) DropIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) DropTable(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) Exec(_ ...interface{}) (sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Session) Exist(_ ...interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) Find(_ interface{}, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Session) FindAndCount(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) ForUpdate() *Session {
+ return nil
+}
+
+func (_ *Session) Get(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) GroupBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Having(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) ID(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Id(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) In(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Incr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Init() {}
+
+func (_ *Session) Insert(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) InsertMulti(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) InsertOne(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) IsClosed() bool {
+ return false
+}
+
+func (_ *Session) IsTableEmpty(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) IsTableExist(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) Iterate(_ interface{}, _ IterFunc) error {
+ return nil
+}
+
+func (_ *Session) Join(_ string, _ interface{}, _ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) LastSQL() (string, []interface{}) {
+ return "", nil
+}
+
+func (_ *Session) Limit(_ int, _ ...int) *Session {
+ return nil
+}
+
+func (_ *Session) MustCols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) NoAutoCondition(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Session) NoAutoTime() *Session {
+ return nil
+}
+
+func (_ *Session) NoCache() *Session {
+ return nil
+}
+
+func (_ *Session) NoCascade() *Session {
+ return nil
+}
+
+func (_ *Session) NotIn(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Nullable(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Omit(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Or(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) OrderBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Ping() error {
+ return nil
+}
+
+func (_ *Session) PingContext(_ context.Context) error {
+ return nil
+}
+
+func (_ *Session) Prepare() *Session {
+ return nil
+}
+
+func (_ *Session) Query(_ ...interface{}) ([]map[string][]byte, error) {
+ return nil, nil
+}
+
+func (_ *Session) QueryInterface(_ ...interface{}) ([]map[string]interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Session) QuerySliceString(_ ...interface{}) ([][]string, error) {
+ return nil, nil
+}
+
+func (_ *Session) QueryString(_ ...interface{}) ([]map[string]string, error) {
+ return nil, nil
+}
+
+func (_ *Session) Rollback() error {
+ return nil
+}
+
+func (_ *Session) Rows(_ interface{}) (*Rows, error) {
+ return nil, nil
+}
+
+func (_ *Session) SQL(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Select(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) SetExpr(_ string, _ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Sql(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) StoreEngine(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Sum(_ interface{}, _ string) (float64, error) {
+ return 0, nil
+}
+
+func (_ *Session) SumInt(_ interface{}, _ string) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) Sums(_ interface{}, _ ...string) ([]float64, error) {
+ return nil, nil
+}
+
+func (_ *Session) SumsInt(_ interface{}, _ ...string) ([]int64, error) {
+ return nil, nil
+}
+
+func (_ *Session) Sync2(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Session) Table(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Unscoped() *Session {
+ return nil
+}
+
+func (_ *Session) Update(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) UseBool(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Where(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+type Table struct {
+ Table interface{}
+ Name string
+}
+
+func (_ Table) AddColumn(_ interface{}) {}
+
+func (_ Table) AddIndex(_ interface{}) {}
+
+func (_ Table) AutoIncrColumn() interface{} {
+ return nil
+}
+
+func (_ Table) ColumnType(_ string) reflect.Type {
+ return nil
+}
+
+func (_ Table) Columns() []interface{} {
+ return nil
+}
+
+func (_ Table) ColumnsSeq() []string {
+ return nil
+}
+
+func (_ Table) DeletedColumn() interface{} {
+ return nil
+}
+
+func (_ Table) GetColumn(_ string) interface{} {
+ return nil
+}
+
+func (_ Table) GetColumnIdx(_ string, _ int) interface{} {
+ return nil
+}
+
+func (_ Table) PKColumns() []interface{} {
+ return nil
+}
+
+func (_ Table) UpdatedColumn() interface{} {
+ return nil
+}
+
+func (_ Table) VersionColumn() interface{} {
+ return nil
+}
+
+func (_ *Table) IsValid() bool {
+ return false
+}
diff --git a/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/xorm.io/xorm/LICENSE b/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/xorm.io/xorm/LICENSE
new file mode 100644
index 00000000000..84d2ae5386d
--- /dev/null
+++ b/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/xorm.io/xorm/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2013 - 2015 The Xorm Authors
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* Redistributions in binary form must reproduce the above copyright notice,
+ this list of conditions and the following disclaimer in the documentation
+ and/or other materials provided with the distribution.
+
+* Neither the name of the {organization} nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/xorm.io/xorm/stub.go b/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/xorm.io/xorm/stub.go
new file mode 100644
index 00000000000..ccadc994d34
--- /dev/null
+++ b/ql/test/library-tests/semmle/go/frameworks/SQL/vendor/xorm.io/xorm/stub.go
@@ -0,0 +1,824 @@
+// Code generated by depstubber. DO NOT EDIT.
+// This is a simple stub for xorm.io/xorm, strictly for use in testing.
+
+// See the LICENSE file for information about the licensing of the original library.
+// Source: xorm.io/xorm (exports: Engine,Session; functions: )
+
+// Package xorm is a stub of xorm.io/xorm, generated by depstubber.
+package xorm
+
+import (
+ context "context"
+ sql "database/sql"
+ io "io"
+ reflect "reflect"
+ strings "strings"
+ time "time"
+)
+
+type Engine struct {
+ TZLocation *time.Location
+ DatabaseTZ *time.Location
+}
+
+func (_ *Engine) AddHook(_ interface{}) {}
+
+func (_ *Engine) After(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Engine) Alias(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) AllCols() *Session {
+ return nil
+}
+
+func (_ *Engine) Asc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) AutoIncrStr() string {
+ return ""
+}
+
+func (_ *Engine) Before(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Engine) BufferSize(_ int) *Session {
+ return nil
+}
+
+func (_ *Engine) Cascade(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Engine) Charset(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) ClearCache(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) ClearCacheBean(_ interface{}, _ string) error {
+ return nil
+}
+
+func (_ *Engine) Close() error {
+ return nil
+}
+
+func (_ *Engine) Cols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Context(_ context.Context) *Session {
+ return nil
+}
+
+func (_ *Engine) Count(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) CreateIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) CreateTables(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) CreateUniques(_ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DB() interface{} {
+ return nil
+}
+
+func (_ *Engine) DBMetas() ([]interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) DataSourceName() string {
+ return ""
+}
+
+func (_ *Engine) Decr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Delete(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) Desc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Dialect() interface{} {
+ return nil
+}
+
+func (_ *Engine) Distinct(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) DriverName() string {
+ return ""
+}
+
+func (_ *Engine) DropIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DropTables(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpAll(_ io.Writer, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpAllToFile(_ string, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpTables(_ []interface{}, _ io.Writer, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) DumpTablesToFile(_ []interface{}, _ string, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) EnableSessionID(_ bool) {}
+
+func (_ *Engine) Exec(_ ...interface{}) (sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Engine) Exist(_ ...interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) Find(_ interface{}, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) FindAndCount(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) Get(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) GetCacher(_ string) interface{} {
+ return nil
+}
+
+func (_ *Engine) GetColumnMapper() interface{} {
+ return nil
+}
+
+func (_ *Engine) GetDefaultCacher() interface{} {
+ return nil
+}
+
+func (_ *Engine) GetTZDatabase() *time.Location {
+ return nil
+}
+
+func (_ *Engine) GetTZLocation() *time.Location {
+ return nil
+}
+
+func (_ *Engine) GetTableMapper() interface{} {
+ return nil
+}
+
+func (_ *Engine) GroupBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) Having(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) ID(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Import(_ io.Reader) ([]sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Engine) ImportFile(_ string) ([]sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Engine) In(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Incr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Insert(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) InsertOne(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) IsTableEmpty(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) IsTableExist(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Engine) Iterate(_ interface{}, _ IterFunc) error {
+ return nil
+}
+
+func (_ *Engine) Join(_ string, _ interface{}, _ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Limit(_ int, _ ...int) *Session {
+ return nil
+}
+
+func (_ *Engine) Logger() interface{} {
+ return nil
+}
+
+func (_ *Engine) MapCacher(_ interface{}, _ interface{}) error {
+ return nil
+}
+
+func (_ *Engine) MustCols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) NewDB() (interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) NewSession() *Session {
+ return nil
+}
+
+func (_ *Engine) NoAutoCondition(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Engine) NoAutoTime() *Session {
+ return nil
+}
+
+func (_ *Engine) NoCache() *Session {
+ return nil
+}
+
+func (_ *Engine) NoCascade() *Session {
+ return nil
+}
+
+func (_ *Engine) NotIn(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) Nullable(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Omit(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) OrderBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) Ping() error {
+ return nil
+}
+
+func (_ *Engine) PingContext(_ context.Context) error {
+ return nil
+}
+
+func (_ *Engine) Prepare() *Session {
+ return nil
+}
+
+func (_ *Engine) Query(_ ...interface{}) ([]map[string][]byte, error) {
+ return nil, nil
+}
+
+func (_ *Engine) QueryInterface(_ ...interface{}) ([]map[string]interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) QueryString(_ ...interface{}) ([]map[string]string, error) {
+ return nil, nil
+}
+
+func (_ *Engine) Quote(_ string) string {
+ return ""
+}
+
+func (_ *Engine) QuoteTo(_ *strings.Builder, _ string) {}
+
+func (_ *Engine) Rows(_ interface{}) (*Rows, error) {
+ return nil, nil
+}
+
+func (_ *Engine) SQL(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) SQLType(_ interface{}) string {
+ return ""
+}
+
+func (_ *Engine) Select(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) SetCacher(_ string, _ interface{}) {}
+
+func (_ *Engine) SetColumnMapper(_ interface{}) {}
+
+func (_ *Engine) SetConnMaxLifetime(_ time.Duration) {}
+
+func (_ *Engine) SetDefaultCacher(_ interface{}) {}
+
+func (_ *Engine) SetDefaultContext(_ context.Context) {}
+
+func (_ *Engine) SetDisableGlobalCache(_ bool) {}
+
+func (_ *Engine) SetExpr(_ string, _ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) SetLogLevel(_ interface{}) {}
+
+func (_ *Engine) SetLogger(_ interface{}) {}
+
+func (_ *Engine) SetMapper(_ interface{}) {}
+
+func (_ *Engine) SetMaxIdleConns(_ int) {}
+
+func (_ *Engine) SetMaxOpenConns(_ int) {}
+
+func (_ *Engine) SetQuotePolicy(_ interface{}) {}
+
+func (_ *Engine) SetSchema(_ string) {}
+
+func (_ *Engine) SetTZDatabase(_ *time.Location) {}
+
+func (_ *Engine) SetTZLocation(_ *time.Location) {}
+
+func (_ *Engine) SetTableMapper(_ interface{}) {}
+
+func (_ *Engine) SetTagIdentifier(_ string) {}
+
+func (_ *Engine) ShowSQL(_ ...bool) {}
+
+func (_ *Engine) StoreEngine(_ string) *Session {
+ return nil
+}
+
+func (_ *Engine) Sum(_ interface{}, _ string) (float64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) SumInt(_ interface{}, _ string) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) Sums(_ interface{}, _ ...string) ([]float64, error) {
+ return nil, nil
+}
+
+func (_ *Engine) SumsInt(_ interface{}, _ ...string) ([]int64, error) {
+ return nil, nil
+}
+
+func (_ *Engine) Sync(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) Sync2(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Engine) Table(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Engine) TableInfo(_ interface{}) (interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) TableName(_ interface{}, _ ...bool) string {
+ return ""
+}
+
+func (_ *Engine) Transaction(_ func(*Session) (interface{}, error)) (interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Engine) UnMapType(_ reflect.Type) {}
+
+func (_ *Engine) Unscoped() *Session {
+ return nil
+}
+
+func (_ *Engine) Update(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Engine) UseBool(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Engine) Where(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+type IterFunc func(int, interface{}) error
+
+type Rows struct{}
+
+func (_ *Rows) Close() error {
+ return nil
+}
+
+func (_ *Rows) Err() error {
+ return nil
+}
+
+func (_ *Rows) Next() bool {
+ return false
+}
+
+func (_ *Rows) Scan(_ interface{}) error {
+ return nil
+}
+
+type Session struct{}
+
+func (_ *Session) After(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Session) Alias(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) AllCols() *Session {
+ return nil
+}
+
+func (_ *Session) And(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Asc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Before(_ func(interface{})) *Session {
+ return nil
+}
+
+func (_ *Session) Begin() error {
+ return nil
+}
+
+func (_ *Session) BufferSize(_ int) *Session {
+ return nil
+}
+
+func (_ *Session) Cascade(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Session) Charset(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Close() error {
+ return nil
+}
+
+func (_ *Session) Cols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Commit() error {
+ return nil
+}
+
+func (_ *Session) Conds() interface{} {
+ return nil
+}
+
+func (_ *Session) Context(_ context.Context) *Session {
+ return nil
+}
+
+func (_ *Session) ContextCache(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Count(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) CreateIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) CreateTable(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) CreateUniques(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) DB() interface{} {
+ return nil
+}
+
+func (_ *Session) Decr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Delete(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) Desc(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Distinct(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) DropIndexes(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) DropTable(_ interface{}) error {
+ return nil
+}
+
+func (_ *Session) Engine() *Engine {
+ return nil
+}
+
+func (_ *Session) Exec(_ ...interface{}) (sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Session) Exist(_ ...interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) Find(_ interface{}, _ ...interface{}) error {
+ return nil
+}
+
+func (_ *Session) FindAndCount(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) ForUpdate() *Session {
+ return nil
+}
+
+func (_ *Session) Get(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) GroupBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Having(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) ID(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Import(_ io.Reader) ([]sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Session) ImportFile(_ string) ([]sql.Result, error) {
+ return nil, nil
+}
+
+func (_ *Session) In(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Incr(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Insert(_ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) InsertMulti(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) InsertOne(_ interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) IsClosed() bool {
+ return false
+}
+
+func (_ *Session) IsInTx() bool {
+ return false
+}
+
+func (_ *Session) IsTableEmpty(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) IsTableExist(_ interface{}) (bool, error) {
+ return false, nil
+}
+
+func (_ *Session) Iterate(_ interface{}, _ IterFunc) error {
+ return nil
+}
+
+func (_ *Session) Join(_ string, _ interface{}, _ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) LastSQL() (string, []interface{}) {
+ return "", nil
+}
+
+func (_ *Session) Limit(_ int, _ ...int) *Session {
+ return nil
+}
+
+func (_ *Session) MustCols(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) MustLogSQL(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Session) NoAutoCondition(_ ...bool) *Session {
+ return nil
+}
+
+func (_ *Session) NoAutoTime() *Session {
+ return nil
+}
+
+func (_ *Session) NoCache() *Session {
+ return nil
+}
+
+func (_ *Session) NoCascade() *Session {
+ return nil
+}
+
+func (_ *Session) NotIn(_ string, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Nullable(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Omit(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Or(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) OrderBy(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Ping() error {
+ return nil
+}
+
+func (_ *Session) PingContext(_ context.Context) error {
+ return nil
+}
+
+func (_ *Session) Prepare() *Session {
+ return nil
+}
+
+func (_ *Session) Query(_ ...interface{}) ([]map[string][]byte, error) {
+ return nil, nil
+}
+
+func (_ *Session) QueryInterface(_ ...interface{}) ([]map[string]interface{}, error) {
+ return nil, nil
+}
+
+func (_ *Session) QuerySliceString(_ ...interface{}) ([][]string, error) {
+ return nil, nil
+}
+
+func (_ *Session) QueryString(_ ...interface{}) ([]map[string]string, error) {
+ return nil, nil
+}
+
+func (_ *Session) Rollback() error {
+ return nil
+}
+
+func (_ *Session) Rows(_ interface{}) (*Rows, error) {
+ return nil, nil
+}
+
+func (_ *Session) SQL(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Select(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) SetExpr(_ string, _ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) StoreEngine(_ string) *Session {
+ return nil
+}
+
+func (_ *Session) Sum(_ interface{}, _ string) (float64, error) {
+ return 0, nil
+}
+
+func (_ *Session) SumInt(_ interface{}, _ string) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) Sums(_ interface{}, _ ...string) ([]float64, error) {
+ return nil, nil
+}
+
+func (_ *Session) SumsInt(_ interface{}, _ ...string) ([]int64, error) {
+ return nil, nil
+}
+
+func (_ *Session) Sync2(_ ...interface{}) error {
+ return nil
+}
+
+func (_ *Session) Table(_ interface{}) *Session {
+ return nil
+}
+
+func (_ *Session) Unscoped() *Session {
+ return nil
+}
+
+func (_ *Session) Update(_ interface{}, _ ...interface{}) (int64, error) {
+ return 0, nil
+}
+
+func (_ *Session) UseBool(_ ...string) *Session {
+ return nil
+}
+
+func (_ *Session) Where(_ interface{}, _ ...interface{}) *Session {
+ return nil
+}
diff --git a/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go b/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go
new file mode 100644
index 00000000000..3aa8857a61b
--- /dev/null
+++ b/ql/test/library-tests/semmle/go/frameworks/SQL/xorm.go
@@ -0,0 +1,77 @@
+package main
+
+//go:generate depstubber -vendor xorm.io/xorm Engine,Session
+//go:generate depstubber -vendor github.com/go-xorm/xorm Engine,Session
+
+import (
+ xorm1 "github.com/go-xorm/xorm"
+ xorm2 "xorm.io/xorm"
+)
+
+func xormtest() {
+ query := "UntrustedString"
+
+ engine1 := xorm1.Engine{}
+ engine1.Query(query) // $querystring=query
+ engine1.QueryString(query) // $querystring=query
+ engine1.QueryInterface(query) // $querystring=query
+ engine1.SQL(query) // $querystring=query
+ engine1.Where(query) // $querystring=query
+ engine1.Alias(query) // $querystring=query
+ engine1.NotIn(query) // $querystring=query
+ engine1.In(query) // $querystring=query
+ engine1.Select(query) // $querystring=query
+ engine1.SetExpr(query, nil) // $querystring=query
+ engine1.OrderBy(query) // $querystring=query
+ engine1.Having(query) // $querystring=query
+ engine1.GroupBy(query) // $querystring=query
+
+ engine2 := xorm2.Engine{}
+ engine2.Query(query) // $querystring=query
+ engine2.QueryString(query) // $querystring=query
+ engine2.QueryInterface(query) // $querystring=query
+ engine2.SQL(query) // $querystring=query
+ engine2.Where(query) // $querystring=query
+ engine2.Alias(query) // $querystring=query
+ engine2.NotIn(query) // $querystring=query
+ engine2.In(query) // $querystring=query
+ engine2.Select(query) // $querystring=query
+ engine2.SetExpr(query, nil) // $querystring=query
+ engine2.OrderBy(query) // $querystring=query
+ engine2.Having(query) // $querystring=query
+ engine2.GroupBy(query) // $querystring=query
+
+ session1 := xorm1.Session{}
+ session1.Query(query) // $querystring=query
+ session1.QueryString(query) // $querystring=query
+ session1.QueryInterface(query) // $querystring=query
+ session1.SQL(query) // $querystring=query
+ session1.Where(query) // $querystring=query
+ session1.Alias(query) // $querystring=query
+ session1.NotIn(query) // $querystring=query
+ session1.In(query) // $querystring=query
+ session1.Select(query) // $querystring=query
+ session1.SetExpr(query, nil) // $querystring=query
+ session1.OrderBy(query) // $querystring=query
+ session1.Having(query) // $querystring=query
+ session1.GroupBy(query) // $querystring=query
+ session1.And(query) // $querystring=query
+ session1.Or(query) // $querystring=query
+
+ session2 := xorm2.Session{}
+ session2.Query(query) // $querystring=query
+ session2.QueryString(query) // $querystring=query
+ session2.QueryInterface(query) // $querystring=query
+ session2.SQL(query) // $querystring=query
+ session2.Where(query) // $querystring=query
+ session2.Alias(query) // $querystring=query
+ session2.NotIn(query) // $querystring=query
+ session2.In(query) // $querystring=query
+ session2.Select(query) // $querystring=query
+ session2.SetExpr(query, nil) // $querystring=query
+ session2.OrderBy(query) // $querystring=query
+ session2.Having(query) // $querystring=query
+ session2.GroupBy(query) // $querystring=query
+ session2.And(query) // $querystring=query
+ session2.Or(query) // $querystring=query
+}
diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZip.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZip.go
index 6cbbfcb77e2..f968c5c11e0 100644
--- a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZip.go
+++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/ArchiveZip.go
@@ -40,6 +40,19 @@ func TaintStepTest_ArchiveZipFileOpen_B0I0O0(sourceCQL interface{}) interface{}
return intoReadCloser483
}
+func TaintStepTest_ArchiveZipFileOpenRaw_B0I0O0(sourceCQL interface{}) interface{} {
+ fromFile127 := sourceCQL.(zip.File)
+ intoReadCloser483, _ := fromFile127.OpenRaw()
+ return intoReadCloser483
+}
+
+func TaintStepTest_ArchiveZipWriterCopy_B0I0O0(sourceCQL interface{}) interface{} {
+ fromFile127 := sourceCQL.(*zip.File)
+ var intoWriter982 zip.Writer
+ intoWriter982.Copy(fromFile127)
+ return intoWriter982
+}
+
func TaintStepTest_ArchiveZipWriterCreate_B0I0O0(sourceCQL interface{}) interface{} {
fromWriter989 := sourceCQL.(io.Writer)
var intoWriter982 zip.Writer
@@ -48,6 +61,14 @@ func TaintStepTest_ArchiveZipWriterCreate_B0I0O0(sourceCQL interface{}) interfac
return intoWriter982
}
+func TaintStepTest_ArchiveZipWriterCreateRaw_B0I0O0(sourceCQL interface{}) interface{} {
+ fromWriter989 := sourceCQL.(io.Writer)
+ var intoWriter982 zip.Writer
+ intermediateCQL, _ := intoWriter982.CreateRaw(nil)
+ link(fromWriter989, intermediateCQL)
+ return intoWriter982
+}
+
func TaintStepTest_ArchiveZipWriterCreateHeader_B0I0O0(sourceCQL interface{}) interface{} {
fromWriter417 := sourceCQL.(io.Writer)
var intoWriter584 zip.Writer
diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoFs.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoFs.go
index 9eea2dc516f..4b910200841 100644
--- a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoFs.go
+++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/IoFs.go
@@ -11,6 +11,11 @@ func walkDirCallback(path string, d fs.DirEntry, _ error) error {
}
func steps() {
+ {
+ source := newSource(16).(fs.FileInfo)
+ out := fs.FileInfoToDirEntry(source)
+ sink(16, out)
+ }
{
source := newSource(0).(fs.FS)
out, _ := fs.Glob(source, "*")
diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Strconv.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Strconv.go
index da01b976862..d7f84f6c031 100644
--- a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Strconv.go
+++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Strconv.go
@@ -46,6 +46,12 @@ func TaintStepTest_StrconvQuote_B0I0O0(sourceCQL interface{}) interface{} {
return intoString584
}
+func TaintStepTest_StrconvQuotedPrefix_B0I0O0(sourceCQL interface{}) interface{} {
+ fromString417 := sourceCQL.(string)
+ intoString584, _ := strconv.QuotedPrefix(fromString417)
+ return intoString584
+}
+
func TaintStepTest_StrconvQuoteToASCII_B0I0O0(sourceCQL interface{}) interface{} {
fromString991 := sourceCQL.(string)
intoString881 := strconv.QuoteToASCII(fromString991)
diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Syscall_non_win.go b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Syscall_non_win.go
index c2d7f55e259..06db4fa3c0b 100644
--- a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Syscall_non_win.go
+++ b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/Syscall_non_win.go
@@ -1,5 +1,6 @@
// Code generated by https://github.com/gagliardetto/codebox. DO NOT EDIT.
+//go:build !windows
// +build !windows
package main
diff --git a/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/m b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/m
new file mode 100755
index 00000000000..b0d3e8c228e
Binary files /dev/null and b/ql/test/library-tests/semmle/go/frameworks/StdlibTaintFlow/m differ
diff --git a/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected b/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected
index dfd4a4ff15d..7c7600b70da 100644
--- a/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected
+++ b/ql/test/query-tests/Diagnostics/CONSISTENCY/UnexpectedFrontendErrors.expected
@@ -1,3 +1,9 @@
| -:0:0:0:0 | malformed import path "github.com/github/codeql-go/ql/test/query-tests/Diagnostics/invalid{": invalid char '{' |
+| -:0:0:0:0 | package ; expected main |
| bad.go:3:1:3:1 | expected 'package', found avvu |
+| bad.go:3:1:3:1 | expected 'package', found avvu |
+| bad.go:3:5:3:5 | expected 'IDENT', found newline |
+| bad.go:5:1:5:1 | expected ';', found wnvwun |
+| badimport.go:6:2:6:2 | invalid import path (invalid character U+007B '{') |
+| badimport.go:6:2:6:2 | invalid import path: "github.com/pkg{}" |
| type.go:11:9:11:9 | cannot use v (variable of type V) as T value in argument to takesT |
diff --git a/ql/test/query-tests/Diagnostics/ExtractionErrors.expected b/ql/test/query-tests/Diagnostics/ExtractionErrors.expected
index 4154baaaccd..50b08606056 100644
--- a/ql/test/query-tests/Diagnostics/ExtractionErrors.expected
+++ b/ql/test/query-tests/Diagnostics/ExtractionErrors.expected
@@ -1,3 +1,8 @@
+| Extraction failed in query-tests/Diagnostics/badimport.go with error invalid import path (invalid character U+007B '{') | 2 |
+| Extraction failed in query-tests/Diagnostics/badimport.go with error invalid import path: "github.com/pkg{}" | 2 |
| Extraction failed in query-tests/Diagnostics/type.go with error cannot use v (variable of type V) as T value in argument to takesT | 2 |
+| Extraction failed with error expected ';', found wnvwun | 2 |
+| Extraction failed with error expected 'IDENT', found newline | 2 |
| Extraction failed with error expected 'package', found avvu | 2 |
| Extraction failed with error malformed import path "github.com/github/codeql-go/ql/test/query-tests/Diagnostics/invalid{": invalid char '{' | 2 |
+| Extraction failed with error package ; expected main | 2 |
diff --git a/ql/test/query-tests/RedundantCode/CompareIdenticalValues/constants.go b/ql/test/query-tests/RedundantCode/CompareIdenticalValues/constants.go
index d999a815ecf..50ec41c081c 100644
--- a/ql/test/query-tests/RedundantCode/CompareIdenticalValues/constants.go
+++ b/ql/test/query-tests/RedundantCode/CompareIdenticalValues/constants.go
@@ -1,4 +1,5 @@
-// +build linux, amd64
+//go:build (linux && ignore) || amd64
+// +build linux,ignore amd64
package main
diff --git a/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst.go b/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst.go
index a81e4c931b0..485ee15fe8c 100644
--- a/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst.go
+++ b/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst.go
@@ -1,3 +1,4 @@
+//go:build linux
// +build linux
package main
diff --git a/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst_nonlinux.go b/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst_nonlinux.go
index 43bd1a07ad6..2326c147a9a 100644
--- a/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst_nonlinux.go
+++ b/ql/test/query-tests/RedundantCode/ExprHasNoEffect/tst_nonlinux.go
@@ -1,3 +1,4 @@
+//go:build !linux
// +build !linux
package main
diff --git a/ql/test/experimental/CWE-326/InsufficientKeySize.expected b/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected
similarity index 100%
rename from ql/test/experimental/CWE-326/InsufficientKeySize.expected
rename to ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected
diff --git a/ql/test/experimental/CWE-326/InsufficientKeySize.go b/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.go
similarity index 100%
rename from ql/test/experimental/CWE-326/InsufficientKeySize.go
rename to ql/test/query-tests/Security/CWE-326/InsufficientKeySize.go
diff --git a/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref b/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref
new file mode 100644
index 00000000000..fbb59dd4be6
--- /dev/null
+++ b/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.qlref
@@ -0,0 +1 @@
+Security/CWE-326/InsufficientKeySize.ql
diff --git a/ql/test/query-tests/Security/CWE-681/Test32BitArchitectureBuildConstraints.go b/ql/test/query-tests/Security/CWE-681/Test32BitArchitectureBuildConstraints.go
index 11e317d46cd..2914e2178e9 100644
--- a/ql/test/query-tests/Security/CWE-681/Test32BitArchitectureBuildConstraints.go
+++ b/ql/test/query-tests/Security/CWE-681/Test32BitArchitectureBuildConstraints.go
@@ -1,3 +1,4 @@
+//go:build (386 || amd64p32 || arm || armbe || mips || mipsle || mips64p32 || mips64p32le || ppc || s390 || sparc) && gc && go1.4
// +build 386 amd64p32 arm armbe mips mipsle mips64p32 mips64p32le ppc s390 sparc
// +build gc
// +build go1.4
diff --git a/ql/test/query-tests/Security/CWE-681/Test64BitArchitectureBuildConstraints.go b/ql/test/query-tests/Security/CWE-681/Test64BitArchitectureBuildConstraints.go
index 82bd2965cee..8c1e23fe721 100644
--- a/ql/test/query-tests/Security/CWE-681/Test64BitArchitectureBuildConstraints.go
+++ b/ql/test/query-tests/Security/CWE-681/Test64BitArchitectureBuildConstraints.go
@@ -1,3 +1,4 @@
+//go:build (amd64 || arm64 || arm64be || ppc64 || ppc64le || mips64 || mips64le || s390x || sparc64) && gc && go1.4
// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le s390x sparc64
// +build gc
// +build go1.4
diff --git a/ql/test/query-tests/Security/CWE-681/TestNoArchitectureBuildConstraints.go b/ql/test/query-tests/Security/CWE-681/TestNoArchitectureBuildConstraints.go
index 98cb6abdd61..905ee836b9b 100644
--- a/ql/test/query-tests/Security/CWE-681/TestNoArchitectureBuildConstraints.go
+++ b/ql/test/query-tests/Security/CWE-681/TestNoArchitectureBuildConstraints.go
@@ -1,5 +1,5 @@
-// +build gc
-// +build go1.4
+//go:build gc && go1.4
+// +build gc,go1.4
package main
diff --git a/ql/test/query-tests/Security/CWE-681/TestOldBuildConstraints.go b/ql/test/query-tests/Security/CWE-681/TestOldBuildConstraints.go
new file mode 100644
index 00000000000..e7f6b058ed7
--- /dev/null
+++ b/ql/test/query-tests/Security/CWE-681/TestOldBuildConstraints.go
@@ -0,0 +1,29 @@
+// autoformat-ignore (gofmt adds new style build constraints)
+// +build amd64 arm64 arm64be ppc64 ppc64le mips64 mips64le s390x sparc64
+// +build gc
+// +build go1.4
+
+package main
+
+import (
+ "strconv"
+)
+
+func oldTestIntSink64() {
+ {
+ parsed, err := strconv.ParseInt("3456", 10, 64)
+ if err != nil {
+ panic(err)
+ }
+ _ = int(parsed) // OK
+ _ = uint(parsed) // OK
+ }
+ {
+ parsed, err := strconv.ParseUint("3456", 10, 64)
+ if err != nil {
+ panic(err)
+ }
+ _ = int(parsed) // OK
+ _ = uint(parsed) // OK
+ }
+}
diff --git a/ql/test/query-tests/Summary/CONSISTENCY/UnexpectedFrontendErrors.expected b/ql/test/query-tests/Summary/CONSISTENCY/UnexpectedFrontendErrors.expected
index a17dae68734..d4dff7b992f 100644
--- a/ql/test/query-tests/Summary/CONSISTENCY/UnexpectedFrontendErrors.expected
+++ b/ql/test/query-tests/Summary/CONSISTENCY/UnexpectedFrontendErrors.expected
@@ -1 +1,5 @@
+| -:0:0:0:0 | package ; expected main |
+| empty-file.go:1:1:1:1 | expected ';', found 'EOF' |
+| empty-file.go:1:1:1:1 | expected 'IDENT', found 'EOF' |
+| empty-file.go:1:1:1:1 | expected 'package', found 'EOF' |
| empty-file.go:1:1:1:1 | expected 'package', found 'EOF' |
diff --git a/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/go.dbscheme b/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/go.dbscheme
new file mode 100644
index 00000000000..2842941c6f9
--- /dev/null
+++ b/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/go.dbscheme
@@ -0,0 +1,528 @@
+/** Auto-generated dbscheme; do not edit. */
+
+
+/** Duplicate code **/
+
+duplicateCode(
+ unique int id : @duplication,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+similarCode(
+ unique int id : @similarity,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+@duplication_or_similarity = @duplication | @similarity;
+
+tokens(
+ int id : @duplication_or_similarity ref,
+ int offset : int ref,
+ int beginLine : int ref,
+ int beginColumn : int ref,
+ int endLine : int ref,
+ int endColumn : int ref);
+
+/** External data **/
+
+externalData(
+ int id : @externalDataElement,
+ varchar(900) path : string ref,
+ int column: int ref,
+ varchar(900) value : string ref
+);
+
+snapshotDate(unique date snapshotDate : date ref);
+
+sourceLocationPrefix(varchar(900) prefix : string ref);
+
+
+/*
+ * 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;
+
+compilations(unique int id: @compilation, string cwd: string ref);
+
+#keyset[id, num]
+compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
+
+#keyset[id, num, kind]
+compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
+
+diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
+
+compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
+
+#keyset[id, num]
+compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file 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 ref);
+
+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);
+
+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);
+
+containerparent(int parent: @container ref, unique int child: @container ref);
+
+has_location(unique int locatable: @locatable ref, int location: @location ref);
+
+#keyset[parent, idx]
+comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
+
+comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
+
+doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
+
+#keyset[parent, idx]
+exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
+
+literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
+
+constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
+
+fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
+
+scopes(unique int id: @scope, int kind: int ref);
+
+scopenesting(unique int inner: @scope ref, int outer: @scope ref);
+
+scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
+
+objects(unique int id: @object, int kind: int ref, string name: string ref);
+
+objectscopes(unique int object: @object ref, int scope: @scope ref);
+
+objecttypes(unique int object: @object ref, int tp: @type ref);
+
+methodreceivers(unique int method: @object ref, int receiver: @object ref);
+
+fieldstructs(unique int field: @object ref, int struct: @structtype ref);
+
+methodhosts(int method: @object ref, int host: @namedtype ref);
+
+defs(int ident: @ident ref, int object: @object ref);
+
+uses(int ident: @ident ref, int object: @object ref);
+
+types(unique int id: @type, int kind: int ref);
+
+type_of(unique int expr: @expr ref, int tp: @type ref);
+
+typename(unique int tp: @type ref, string name: string ref);
+
+key_type(unique int map: @maptype ref, int tp: @type ref);
+
+element_type(unique int container: @containertype ref, int tp: @type ref);
+
+base_type(unique int ptr: @pointertype ref, int tp: @type ref);
+
+underlying_type(unique int named: @namedtype ref, int tp: @type ref);
+
+#keyset[parent, index]
+component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
+
+array_length(unique int tp: @arraytype ref, string len: string ref);
+
+type_objects(unique int tp: @type ref, int object: @object ref);
+
+packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
+
+#keyset[parent, idx]
+modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
+
+#keyset[package, idx]
+errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
+ string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
+
+has_ellipsis(int id: @callorconversionexpr ref);
+
+@container = @file | @folder;
+
+@locatable = @xmllocatable | @node | @localscope;
+
+@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
+ | @comment_group | @comment;
+
+@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
+
+@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
+
+@modexprparent = @file | @modexpr;
+
+@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
+
+@stmtparent = @funcdef | @stmt | @decl;
+
+@declparent = @file | @declstmt;
+
+@funcdef = @funclit | @funcdecl;
+
+@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
+
+@location = @location_default;
+
+@sourceline = @locatable;
+
+case @comment.kind of
+ 0 = @slashslashcomment
+| 1 = @slashstarcomment;
+
+case @expr.kind of
+ 0 = @badexpr
+| 1 = @ident
+| 2 = @ellipsis
+| 3 = @intlit
+| 4 = @floatlit
+| 5 = @imaglit
+| 6 = @charlit
+| 7 = @stringlit
+| 8 = @funclit
+| 9 = @compositelit
+| 10 = @parenexpr
+| 11 = @selectorexpr
+| 12 = @indexexpr
+| 13 = @sliceexpr
+| 14 = @typeassertexpr
+| 15 = @callorconversionexpr
+| 16 = @starexpr
+| 17 = @keyvalueexpr
+| 18 = @arraytypeexpr
+| 19 = @structtypeexpr
+| 20 = @functypeexpr
+| 21 = @interfacetypeexpr
+| 22 = @maptypeexpr
+| 23 = @plusexpr
+| 24 = @minusexpr
+| 25 = @notexpr
+| 26 = @complementexpr
+| 27 = @derefexpr
+| 28 = @addressexpr
+| 29 = @arrowexpr
+| 30 = @lorexpr
+| 31 = @landexpr
+| 32 = @eqlexpr
+| 33 = @neqexpr
+| 34 = @lssexpr
+| 35 = @leqexpr
+| 36 = @gtrexpr
+| 37 = @geqexpr
+| 38 = @addexpr
+| 39 = @subexpr
+| 40 = @orexpr
+| 41 = @xorexpr
+| 42 = @mulexpr
+| 43 = @quoexpr
+| 44 = @remexpr
+| 45 = @shlexpr
+| 46 = @shrexpr
+| 47 = @andexpr
+| 48 = @andnotexpr
+| 49 = @sendchantypeexpr
+| 50 = @recvchantypeexpr
+| 51 = @sendrcvchantypeexpr;
+
+@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
+
+@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
+
+@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
+
+@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
+
+@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
+
+@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
+
+@logicalunaryexpr = @notexpr;
+
+@bitwiseunaryexpr = @complementexpr;
+
+@arithmeticunaryexpr = @plusexpr | @minusexpr;
+
+@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
+
+@logicalbinaryexpr = @lorexpr | @landexpr;
+
+@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
+
+@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
+
+@shiftexpr = @shlexpr | @shrexpr;
+
+@comparison = @equalitytest | @relationalcomparison;
+
+@equalitytest = @eqlexpr | @neqexpr;
+
+@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
+
+@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
+
+case @stmt.kind of
+ 0 = @badstmt
+| 1 = @declstmt
+| 2 = @emptystmt
+| 3 = @labeledstmt
+| 4 = @exprstmt
+| 5 = @sendstmt
+| 6 = @incstmt
+| 7 = @decstmt
+| 8 = @gostmt
+| 9 = @deferstmt
+| 10 = @returnstmt
+| 11 = @breakstmt
+| 12 = @continuestmt
+| 13 = @gotostmt
+| 14 = @fallthroughstmt
+| 15 = @blockstmt
+| 16 = @ifstmt
+| 17 = @caseclause
+| 18 = @exprswitchstmt
+| 19 = @typeswitchstmt
+| 20 = @commclause
+| 21 = @selectstmt
+| 22 = @forstmt
+| 23 = @rangestmt
+| 24 = @assignstmt
+| 25 = @definestmt
+| 26 = @addassignstmt
+| 27 = @subassignstmt
+| 28 = @mulassignstmt
+| 29 = @quoassignstmt
+| 30 = @remassignstmt
+| 31 = @andassignstmt
+| 32 = @orassignstmt
+| 33 = @xorassignstmt
+| 34 = @shlassignstmt
+| 35 = @shrassignstmt
+| 36 = @andnotassignstmt;
+
+@incdecstmt = @incstmt | @decstmt;
+
+@assignment = @simpleassignstmt | @compoundassignstmt;
+
+@simpleassignstmt = @assignstmt | @definestmt;
+
+@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
+ | @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
+
+@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
+
+@switchstmt = @exprswitchstmt | @typeswitchstmt;
+
+@loopstmt = @forstmt | @rangestmt;
+
+case @decl.kind of
+ 0 = @baddecl
+| 1 = @importdecl
+| 2 = @constdecl
+| 3 = @typedecl
+| 4 = @vardecl
+| 5 = @funcdecl;
+
+@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
+
+case @spec.kind of
+ 0 = @importspec
+| 1 = @valuespec
+| 2 = @typedefspec
+| 3 = @aliasspec;
+
+@typespec = @typedefspec | @aliasspec;
+
+case @object.kind of
+ 0 = @pkgobject
+| 1 = @decltypeobject
+| 2 = @builtintypeobject
+| 3 = @declconstobject
+| 4 = @builtinconstobject
+| 5 = @declvarobject
+| 6 = @declfunctionobject
+| 7 = @builtinfunctionobject
+| 8 = @labelobject;
+
+@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
+
+@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
+
+@typeobject = @decltypeobject | @builtintypeobject;
+
+@valueobject = @constobject | @varobject | @functionobject;
+
+@constobject = @declconstobject | @builtinconstobject;
+
+@varobject = @declvarobject;
+
+@functionobject = @declfunctionobject | @builtinfunctionobject;
+
+case @scope.kind of
+ 0 = @universescope
+| 1 = @packagescope
+| 2 = @localscope;
+
+case @type.kind of
+ 0 = @invalidtype
+| 1 = @boolexprtype
+| 2 = @inttype
+| 3 = @int8type
+| 4 = @int16type
+| 5 = @int32type
+| 6 = @int64type
+| 7 = @uinttype
+| 8 = @uint8type
+| 9 = @uint16type
+| 10 = @uint32type
+| 11 = @uint64type
+| 12 = @uintptrtype
+| 13 = @float32type
+| 14 = @float64type
+| 15 = @complex64type
+| 16 = @complex128type
+| 17 = @stringexprtype
+| 18 = @unsafepointertype
+| 19 = @boolliteraltype
+| 20 = @intliteraltype
+| 21 = @runeliteraltype
+| 22 = @floatliteraltype
+| 23 = @complexliteraltype
+| 24 = @stringliteraltype
+| 25 = @nilliteraltype
+| 26 = @arraytype
+| 27 = @slicetype
+| 28 = @structtype
+| 29 = @pointertype
+| 30 = @interfacetype
+| 31 = @tupletype
+| 32 = @signaturetype
+| 33 = @maptype
+| 34 = @sendchantype
+| 35 = @recvchantype
+| 36 = @sendrcvchantype
+| 37 = @namedtype;
+
+@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
+
+@booltype = @boolexprtype | @boolliteraltype;
+
+@numerictype = @integertype | @floattype | @complextype;
+
+@integertype = @signedintegertype | @unsignedintegertype;
+
+@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
+
+@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
+
+@floattype = @float32type | @float64type | @floatliteraltype;
+
+@complextype = @complex64type | @complex128type | @complexliteraltype;
+
+@stringtype = @stringexprtype | @stringliteraltype;
+
+@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
+ | @stringliteraltype | @nilliteraltype;
+
+@compositetype = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
+
+@containertype = @arraytype | @slicetype | @maptype | @chantype;
+
+@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
+
+case @modexpr.kind of
+ 0 = @modcommentblock
+| 1 = @modline
+| 2 = @modlineblock
+| 3 = @modlparen
+| 4 = @modrparen;
+
+case @error.kind of
+ 0 = @unknownerror
+| 1 = @listerror
+| 2 = @parseerror
+| 3 = @typeerror;
+
diff --git a/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/old.dbscheme b/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/old.dbscheme
new file mode 100644
index 00000000000..b37faf5d62c
--- /dev/null
+++ b/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/old.dbscheme
@@ -0,0 +1,528 @@
+/** Auto-generated dbscheme; do not edit. */
+
+
+/** Duplicate code **/
+
+duplicateCode(
+ unique int id : @duplication,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+similarCode(
+ unique int id : @similarity,
+ varchar(900) relativePath : string ref,
+ int equivClass : int ref);
+
+@duplication_or_similarity = @duplication | @similarity;
+
+tokens(
+ int id : @duplication_or_similarity ref,
+ int offset : int ref,
+ int beginLine : int ref,
+ int beginColumn : int ref,
+ int endLine : int ref,
+ int endColumn : int ref);
+
+/** External data **/
+
+externalData(
+ int id : @externalDataElement,
+ varchar(900) path : string ref,
+ int column: int ref,
+ varchar(900) value : string ref
+);
+
+snapshotDate(unique date snapshotDate : date ref);
+
+sourceLocationPrefix(varchar(900) prefix : string ref);
+
+
+/*
+ * 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;
+
+compilations(unique int id: @compilation, string cwd: string ref);
+
+#keyset[id, num]
+compilation_args(int id: @compilation ref, int num: int ref, string arg: string ref);
+
+#keyset[id, num, kind]
+compilation_time(int id: @compilation ref, int num: int ref, int kind: int ref, float secs: float ref);
+
+diagnostic_for(unique int diagnostic: @diagnostic ref, int compilation: @compilation ref, int file_number: int ref, int file_number_diagnostic_number: int ref);
+
+compilation_finished(unique int id: @compilation ref, float cpu_seconds: float ref, float elapsed_seconds: float ref);
+
+#keyset[id, num]
+compilation_compiling_files(int id: @compilation ref, int num: int ref, int file: @file 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 ref);
+
+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);
+
+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, string simple: string ref, string ext: string ref, int fromSource: int ref);
+
+folders(unique int id: @folder, string name: string ref, string simple: string ref);
+
+containerparent(int parent: @container ref, unique int child: @container ref);
+
+has_location(unique int locatable: @locatable ref, int location: @location ref);
+
+#keyset[parent, idx]
+comment_groups(unique int id: @comment_group, int parent: @file ref, int idx: int ref);
+
+comments(unique int id: @comment, int kind: int ref, int parent: @comment_group ref, int idx: int ref, string text: string ref);
+
+doc_comments(unique int node: @documentable ref, int comment: @comment_group ref);
+
+#keyset[parent, idx]
+exprs(unique int id: @expr, int kind: int ref, int parent: @exprparent ref, int idx: int ref);
+
+literals(unique int expr: @expr ref, string value: string ref, string raw: string ref);
+
+constvalues(unique int expr: @expr ref, string value: string ref, string exact: string ref);
+
+fields(unique int id: @field, int parent: @fieldparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+stmts(unique int id: @stmt, int kind: int ref, int parent: @stmtparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+decls(unique int id: @decl, int kind: int ref, int parent: @declparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+specs(unique int id: @spec, int kind: int ref, int parent: @gendecl ref, int idx: int ref);
+
+scopes(unique int id: @scope, int kind: int ref);
+
+scopenesting(unique int inner: @scope ref, int outer: @scope ref);
+
+scopenodes(unique int node: @scopenode ref, int scope: @localscope ref);
+
+objects(unique int id: @object, int kind: int ref, string name: string ref);
+
+objectscopes(unique int object: @object ref, int scope: @scope ref);
+
+objecttypes(unique int object: @object ref, int tp: @type ref);
+
+methodreceivers(unique int method: @object ref, int receiver: @object ref);
+
+fieldstructs(unique int field: @object ref, int struct: @structtype ref);
+
+methodhosts(int method: @object ref, int host: @namedtype ref);
+
+defs(int ident: @ident ref, int object: @object ref);
+
+uses(int ident: @ident ref, int object: @object ref);
+
+types(unique int id: @type, int kind: int ref);
+
+type_of(unique int expr: @expr ref, int tp: @type ref);
+
+typename(unique int tp: @type ref, string name: string ref);
+
+key_type(unique int map: @maptype ref, int tp: @type ref);
+
+element_type(unique int container: @containertype ref, int tp: @type ref);
+
+base_type(unique int ptr: @pointertype ref, int tp: @type ref);
+
+underlying_type(unique int named: @namedtype ref, int tp: @type ref);
+
+#keyset[parent, index]
+component_types(int parent: @compositetype ref, int index: int ref, string name: string ref, int tp: @type ref);
+
+array_length(unique int tp: @arraytype ref, string len: string ref);
+
+type_objects(unique int tp: @type ref, int object: @object ref);
+
+packages(unique int id: @package, string name: string ref, string path: string ref, int scope: @packagescope ref);
+
+#keyset[parent, idx]
+modexprs(unique int id: @modexpr, int kind: int ref, int parent: @modexprparent ref, int idx: int ref);
+
+#keyset[parent, idx]
+modtokens(string token: string ref, int parent: @modexpr ref, int idx: int ref);
+
+#keyset[package, idx]
+errors(unique int id: @error, int kind: int ref, string msg: string ref, string rawpos: string ref,
+ string file: string ref, int line: int ref, int col: int ref, int package: @package ref, int idx: int ref);
+
+has_ellipsis(int id: @callorconversionexpr ref);
+
+@container = @file | @folder;
+
+@locatable = @xmllocatable | @node | @localscope;
+
+@node = @documentable | @exprparent | @modexprparent | @fieldparent | @stmtparent | @declparent | @scopenode
+ | @comment_group | @comment;
+
+@documentable = @file | @field | @spec | @gendecl | @funcdecl | @modexpr;
+
+@exprparent = @funcdef | @file | @expr | @field | @stmt | @decl | @spec;
+
+@modexprparent = @file | @modexpr;
+
+@fieldparent = @decl | @structtypeexpr | @functypeexpr | @interfacetypeexpr;
+
+@stmtparent = @funcdef | @stmt | @decl;
+
+@declparent = @file | @declstmt;
+
+@funcdef = @funclit | @funcdecl;
+
+@scopenode = @file | @functypeexpr | @blockstmt | @ifstmt | @caseclause | @switchstmt | @commclause | @loopstmt;
+
+@location = @location_default;
+
+@sourceline = @locatable;
+
+case @comment.kind of
+ 0 = @slashslashcomment
+| 1 = @slashstarcomment;
+
+case @expr.kind of
+ 0 = @badexpr
+| 1 = @ident
+| 2 = @ellipsis
+| 3 = @intlit
+| 4 = @floatlit
+| 5 = @imaglit
+| 6 = @charlit
+| 7 = @stringlit
+| 8 = @funclit
+| 9 = @compositelit
+| 10 = @parenexpr
+| 11 = @selectorexpr
+| 12 = @indexexpr
+| 13 = @sliceexpr
+| 14 = @typeassertexpr
+| 15 = @callorconversionexpr
+| 16 = @starexpr
+| 17 = @keyvalueexpr
+| 18 = @arraytypeexpr
+| 19 = @structtypeexpr
+| 20 = @functypeexpr
+| 21 = @interfacetypeexpr
+| 22 = @maptypeexpr
+| 23 = @plusexpr
+| 24 = @minusexpr
+| 25 = @notexpr
+| 26 = @complementexpr
+| 27 = @derefexpr
+| 28 = @addressexpr
+| 29 = @arrowexpr
+| 30 = @lorexpr
+| 31 = @landexpr
+| 32 = @eqlexpr
+| 33 = @neqexpr
+| 34 = @lssexpr
+| 35 = @leqexpr
+| 36 = @gtrexpr
+| 37 = @geqexpr
+| 38 = @addexpr
+| 39 = @subexpr
+| 40 = @orexpr
+| 41 = @xorexpr
+| 42 = @mulexpr
+| 43 = @quoexpr
+| 44 = @remexpr
+| 45 = @shlexpr
+| 46 = @shrexpr
+| 47 = @andexpr
+| 48 = @andnotexpr
+| 49 = @sendchantypeexpr
+| 50 = @recvchantypeexpr
+| 51 = @sendrcvchantypeexpr;
+
+@basiclit = @intlit | @floatlit | @imaglit | @charlit | @stringlit;
+
+@operatorexpr = @logicalexpr | @arithmeticexpr | @bitwiseexpr | @unaryexpr | @binaryexpr;
+
+@logicalexpr = @logicalunaryexpr | @logicalbinaryexpr;
+
+@arithmeticexpr = @arithmeticunaryexpr | @arithmeticbinaryexpr;
+
+@bitwiseexpr = @bitwiseunaryexpr | @bitwisebinaryexpr;
+
+@unaryexpr = @logicalunaryexpr | @bitwiseunaryexpr | @arithmeticunaryexpr | @derefexpr | @addressexpr | @arrowexpr;
+
+@logicalunaryexpr = @notexpr;
+
+@bitwiseunaryexpr = @complementexpr;
+
+@arithmeticunaryexpr = @plusexpr | @minusexpr;
+
+@binaryexpr = @logicalbinaryexpr | @bitwisebinaryexpr | @arithmeticbinaryexpr | @comparison;
+
+@logicalbinaryexpr = @lorexpr | @landexpr;
+
+@bitwisebinaryexpr = @shiftexpr | @orexpr | @xorexpr | @andexpr | @andnotexpr;
+
+@arithmeticbinaryexpr = @addexpr | @subexpr | @mulexpr | @quoexpr | @remexpr;
+
+@shiftexpr = @shlexpr | @shrexpr;
+
+@comparison = @equalitytest | @relationalcomparison;
+
+@equalitytest = @eqlexpr | @neqexpr;
+
+@relationalcomparison = @lssexpr | @leqexpr | @gtrexpr | @geqexpr;
+
+@chantypeexpr = @sendchantypeexpr | @recvchantypeexpr | @sendrcvchantypeexpr;
+
+case @stmt.kind of
+ 0 = @badstmt
+| 1 = @declstmt
+| 2 = @emptystmt
+| 3 = @labeledstmt
+| 4 = @exprstmt
+| 5 = @sendstmt
+| 6 = @incstmt
+| 7 = @decstmt
+| 8 = @gostmt
+| 9 = @deferstmt
+| 10 = @returnstmt
+| 11 = @breakstmt
+| 12 = @continuestmt
+| 13 = @gotostmt
+| 14 = @fallthroughstmt
+| 15 = @blockstmt
+| 16 = @ifstmt
+| 17 = @caseclause
+| 18 = @exprswitchstmt
+| 19 = @typeswitchstmt
+| 20 = @commclause
+| 21 = @selectstmt
+| 22 = @forstmt
+| 23 = @rangestmt
+| 24 = @assignstmt
+| 25 = @definestmt
+| 26 = @addassignstmt
+| 27 = @subassignstmt
+| 28 = @mulassignstmt
+| 29 = @quoassignstmt
+| 30 = @remassignstmt
+| 31 = @andassignstmt
+| 32 = @orassignstmt
+| 33 = @xorassignstmt
+| 34 = @shlassignstmt
+| 35 = @shrassignstmt
+| 36 = @andnotassignstmt;
+
+@incdecstmt = @incstmt | @decstmt;
+
+@assignment = @simpleassignstmt | @compoundassignstmt;
+
+@simpleassignstmt = @assignstmt | @definestmt;
+
+@compoundassignstmt = @addassignstmt | @subassignstmt | @mulassignstmt | @quoassignstmt | @remassignstmt
+ | @andassignstmt | @orassignstmt | @xorassignstmt | @shlassignstmt | @shrassignstmt | @andnotassignstmt;
+
+@branchstmt = @breakstmt | @continuestmt | @gotostmt | @fallthroughstmt;
+
+@switchstmt = @exprswitchstmt | @typeswitchstmt;
+
+@loopstmt = @forstmt | @rangestmt;
+
+case @decl.kind of
+ 0 = @baddecl
+| 1 = @importdecl
+| 2 = @constdecl
+| 3 = @typedecl
+| 4 = @vardecl
+| 5 = @funcdecl;
+
+@gendecl = @importdecl | @constdecl | @typedecl | @vardecl;
+
+case @spec.kind of
+ 0 = @importspec
+| 1 = @valuespec
+| 2 = @typedefspec
+| 3 = @aliasspec;
+
+@typespec = @typedefspec | @aliasspec;
+
+case @object.kind of
+ 0 = @pkgobject
+| 1 = @decltypeobject
+| 2 = @builtintypeobject
+| 3 = @declconstobject
+| 4 = @builtinconstobject
+| 5 = @declvarobject
+| 6 = @declfunctionobject
+| 7 = @builtinfunctionobject
+| 8 = @labelobject;
+
+@declobject = @decltypeobject | @declconstobject | @declvarobject | @declfunctionobject;
+
+@builtinobject = @builtintypeobject | @builtinconstobject | @builtinfunctionobject;
+
+@typeobject = @decltypeobject | @builtintypeobject;
+
+@valueobject = @constobject | @varobject | @functionobject;
+
+@constobject = @declconstobject | @builtinconstobject;
+
+@varobject = @declvarobject;
+
+@functionobject = @declfunctionobject | @builtinfunctionobject;
+
+case @scope.kind of
+ 0 = @universescope
+| 1 = @packagescope
+| 2 = @localscope;
+
+case @type.kind of
+ 0 = @invalidtype
+| 1 = @boolexprtype
+| 2 = @inttype
+| 3 = @int8type
+| 4 = @int16type
+| 5 = @int32type
+| 6 = @int64type
+| 7 = @uinttype
+| 8 = @uint8type
+| 9 = @uint16type
+| 10 = @uint32type
+| 11 = @uint64type
+| 12 = @uintptrtype
+| 13 = @float32type
+| 14 = @float64type
+| 15 = @complex64type
+| 16 = @complex128type
+| 17 = @stringexprtype
+| 18 = @unsafepointertype
+| 19 = @boolliteraltype
+| 20 = @intliteraltype
+| 21 = @runeliteraltype
+| 22 = @floatliteraltype
+| 23 = @complexliteraltype
+| 24 = @stringliteraltype
+| 25 = @nilliteraltype
+| 26 = @arraytype
+| 27 = @slicetype
+| 28 = @structtype
+| 29 = @pointertype
+| 30 = @interfacetype
+| 31 = @tupletype
+| 32 = @signaturetype
+| 33 = @maptype
+| 34 = @sendchantype
+| 35 = @recvchantype
+| 36 = @sendrcvchantype
+| 37 = @namedtype;
+
+@basictype = @booltype | @numerictype | @stringtype | @literaltype | @invalidtype | @unsafepointertype;
+
+@booltype = @boolexprtype | @boolliteraltype;
+
+@numerictype = @integertype | @floattype | @complextype;
+
+@integertype = @signedintegertype | @unsignedintegertype;
+
+@signedintegertype = @inttype | @int8type | @int16type | @int32type | @int64type | @intliteraltype | @runeliteraltype;
+
+@unsignedintegertype = @uinttype | @uint8type | @uint16type | @uint32type | @uint64type | @uintptrtype;
+
+@floattype = @float32type | @float64type | @floatliteraltype;
+
+@complextype = @complex64type | @complex128type | @complexliteraltype;
+
+@stringtype = @stringexprtype | @stringliteraltype;
+
+@literaltype = @boolliteraltype | @intliteraltype | @runeliteraltype | @floatliteraltype | @complexliteraltype
+ | @stringliteraltype | @nilliteraltype;
+
+@compositetype = @containertype | @structtype | @pointertype | @interfacetype | @tupletype | @signaturetype | @namedtype;
+
+@containertype = @arraytype | @slicetype | @maptype | @chantype;
+
+@chantype = @sendchantype | @recvchantype | @sendrcvchantype;
+
+case @modexpr.kind of
+ 0 = @modcommentblock
+| 1 = @modline
+| 2 = @modlineblock
+| 3 = @modlparen
+| 4 = @modrparen;
+
+case @error.kind of
+ 0 = @unknownerror
+| 1 = @listerror
+| 2 = @parseerror
+| 3 = @typeerror;
+
diff --git a/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/upgrade.properties b/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/upgrade.properties
new file mode 100644
index 00000000000..71f3ee178e5
--- /dev/null
+++ b/upgrades/b37faf5d62cccefad9fcfd8f5c026620097b2355/upgrade.properties
@@ -0,0 +1,4 @@
+description: Removed unused column from the `folders` and `files` relations
+compatibility: full
+files.rel: reorder files.rel (int id, string name, string simple, string ext, int fromSource) id name
+folders.rel: reorder folders.rel (int id, string name, string simple) id name
diff --git a/vendor/golang.org/x/mod/modfile/read.go b/vendor/golang.org/x/mod/modfile/read.go
index c1f2008ee4c..956f30cbb39 100644
--- a/vendor/golang.org/x/mod/modfile/read.go
+++ b/vendor/golang.org/x/mod/modfile/read.go
@@ -194,12 +194,15 @@ func (x *FileSyntax) updateLine(line *Line, tokens ...string) {
line.Token = tokens
}
-func (x *FileSyntax) removeLine(line *Line) {
+// markRemoved modifies line so that it (and its end-of-line comment, if any)
+// will be dropped by (*FileSyntax).Cleanup.
+func (line *Line) markRemoved() {
line.Token = nil
+ line.Comments.Suffix = nil
}
// Cleanup cleans up the file syntax x after any edit operations.
-// To avoid quadratic behavior, removeLine marks the line as dead
+// To avoid quadratic behavior, (*Line).markRemoved marks the line as dead
// by setting line.Token = nil but does not remove it from the slice
// in which it appears. After edits have all been indicated,
// calling Cleanup cleans out the dead lines.
@@ -477,9 +480,17 @@ func (in *input) startToken() {
// endToken marks the end of an input token.
// It records the actual token string in tok.text.
+// A single trailing newline (LF or CRLF) will be removed from comment tokens.
func (in *input) endToken(kind tokenKind) {
in.token.kind = kind
text := string(in.tokenStart[:len(in.tokenStart)-len(in.remaining)])
+ if kind.isComment() {
+ if strings.HasSuffix(text, "\r\n") {
+ text = text[:len(text)-2]
+ } else {
+ text = strings.TrimSuffix(text, "\n")
+ }
+ }
in.token.text = text
in.token.endPos = in.pos
}
diff --git a/vendor/golang.org/x/mod/modfile/rule.go b/vendor/golang.org/x/mod/modfile/rule.go
index 91ca6828df0..78f83fa7144 100644
--- a/vendor/golang.org/x/mod/modfile/rule.go
+++ b/vendor/golang.org/x/mod/modfile/rule.go
@@ -30,6 +30,7 @@ import (
"golang.org/x/mod/internal/lazyregexp"
"golang.org/x/mod/module"
+ "golang.org/x/mod/semver"
)
// A File is the parsed, interpreted form of a go.mod file.
@@ -39,14 +40,16 @@ type File struct {
Require []*Require
Exclude []*Exclude
Replace []*Replace
+ Retract []*Retract
Syntax *FileSyntax
}
// A Module is the module statement.
type Module struct {
- Mod module.Version
- Syntax *Line
+ Mod module.Version
+ Deprecated string
+ Syntax *Line
}
// A Go is the go statement.
@@ -55,13 +58,6 @@ type Go struct {
Syntax *Line
}
-// A Require is a single require statement.
-type Require struct {
- Mod module.Version
- Indirect bool // has "// indirect" comment
- Syntax *Line
-}
-
// An Exclude is a single exclude statement.
type Exclude struct {
Mod module.Version
@@ -75,6 +71,108 @@ type Replace struct {
Syntax *Line
}
+// A Retract is a single retract statement.
+type Retract struct {
+ VersionInterval
+ Rationale string
+ Syntax *Line
+}
+
+// A VersionInterval represents a range of versions with upper and lower bounds.
+// Intervals are closed: both bounds are included. When Low is equal to High,
+// the interval may refer to a single version ('v1.2.3') or an interval
+// ('[v1.2.3, v1.2.3]'); both have the same representation.
+type VersionInterval struct {
+ Low, High string
+}
+
+// A Require is a single require statement.
+type Require struct {
+ Mod module.Version
+ Indirect bool // has "// indirect" comment
+ Syntax *Line
+}
+
+func (r *Require) markRemoved() {
+ r.Syntax.markRemoved()
+ *r = Require{}
+}
+
+func (r *Require) setVersion(v string) {
+ r.Mod.Version = v
+
+ if line := r.Syntax; len(line.Token) > 0 {
+ if line.InBlock {
+ // If the line is preceded by an empty line, remove it; see
+ // https://golang.org/issue/33779.
+ if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 {
+ line.Comments.Before = line.Comments.Before[:0]
+ }
+ if len(line.Token) >= 2 { // example.com v1.2.3
+ line.Token[1] = v
+ }
+ } else {
+ if len(line.Token) >= 3 { // require example.com v1.2.3
+ line.Token[2] = v
+ }
+ }
+ }
+}
+
+// setIndirect sets line to have (or not have) a "// indirect" comment.
+func (r *Require) setIndirect(indirect bool) {
+ r.Indirect = indirect
+ line := r.Syntax
+ if isIndirect(line) == indirect {
+ return
+ }
+ if indirect {
+ // Adding comment.
+ if len(line.Suffix) == 0 {
+ // New comment.
+ line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
+ return
+ }
+
+ com := &line.Suffix[0]
+ text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash)))
+ if text == "" {
+ // Empty comment.
+ com.Token = "// indirect"
+ return
+ }
+
+ // Insert at beginning of existing comment.
+ com.Token = "// indirect; " + text
+ return
+ }
+
+ // Removing comment.
+ f := strings.TrimSpace(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
+ if f == "indirect" {
+ // Remove whole comment.
+ line.Suffix = nil
+ return
+ }
+
+ // Remove comment prefix.
+ com := &line.Suffix[0]
+ i := strings.Index(com.Token, "indirect;")
+ com.Token = "//" + com.Token[i+len("indirect;"):]
+}
+
+// isIndirect reports whether line has a "// indirect" comment,
+// meaning it is in go.mod only for its effect on indirect dependencies,
+// so that it can be dropped entirely once the effective version of the
+// indirect dependency reaches the given minimum version.
+func isIndirect(line *Line) bool {
+ if len(line.Suffix) == 0 {
+ return false
+ }
+ f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
+ return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;")
+}
+
func (f *File) AddModuleStmt(path string) error {
if f.Syntax == nil {
f.Syntax = new(FileSyntax)
@@ -108,8 +206,21 @@ func (f *File) AddComment(text string) {
type VersionFixer func(path, version string) (string, error)
-// Parse parses the data, reported in errors as being from file,
-// into a File struct. It applies fix, if non-nil, to canonicalize all module versions found.
+// errDontFix is returned by a VersionFixer to indicate the version should be
+// left alone, even if it's not canonical.
+var dontFixRetract VersionFixer = func(_, vers string) (string, error) {
+ return vers, nil
+}
+
+// Parse parses and returns a go.mod file.
+//
+// file is the name of the file, used in positions and errors.
+//
+// data is the content of the file.
+//
+// fix is an optional function that canonicalizes module versions.
+// If fix is nil, all module versions must be canonical (module.CanonicalVersion
+// must return the same string).
func Parse(file string, data []byte, fix VersionFixer) (*File, error) {
return parseToFile(file, data, fix, true)
}
@@ -125,7 +236,7 @@ func ParseLax(file string, data []byte, fix VersionFixer) (*File, error) {
return parseToFile(file, data, fix, false)
}
-func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File, error) {
+func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (parsed *File, err error) {
fs, err := parse(file, data)
if err != nil {
return nil, err
@@ -133,12 +244,22 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
f := &File{
Syntax: fs,
}
-
var errs ErrorList
+
+ // fix versions in retract directives after the file is parsed.
+ // We need the module path to fix versions, and it might be at the end.
+ defer func() {
+ oldLen := len(errs)
+ f.fixRetract(fix, &errs)
+ if len(errs) > oldLen {
+ parsed, err = nil, errs
+ }
+ }()
+
for _, x := range fs.Stmt {
switch x := x.(type) {
case *Line:
- f.add(&errs, x, x.Token[0], x.Token[1:], fix, strict)
+ f.add(&errs, nil, x, x.Token[0], x.Token[1:], fix, strict)
case *LineBlock:
if len(x.Token) > 1 {
@@ -161,9 +282,9 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
})
}
continue
- case "module", "require", "exclude", "replace":
+ case "module", "require", "exclude", "replace", "retract":
for _, l := range x.Line {
- f.add(&errs, l, x.Token[0], l.Token, fix, strict)
+ f.add(&errs, x, l, x.Token[0], l.Token, fix, strict)
}
}
}
@@ -176,8 +297,9 @@ func parseToFile(file string, data []byte, fix VersionFixer, strict bool) (*File
}
var GoVersionRE = lazyregexp.New(`^([1-9][0-9]*)\.(0|[1-9][0-9]*)$`)
+var laxGoVersionRE = lazyregexp.New(`^v?(([1-9][0-9]*)\.(0|[1-9][0-9]*))([^0-9].*)$`)
-func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
+func (f *File) add(errs *ErrorList, block *LineBlock, line *Line, verb string, args []string, fix VersionFixer, strict bool) {
// If strict is false, this module is a dependency.
// We ignore all unknown directives as well as main-module-only
// directives like replace and exclude. It will work better for
@@ -186,7 +308,7 @@ func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix
// and simply ignore those statements.
if !strict {
switch verb {
- case "module", "require", "go":
+ case "go", "module", "retract", "require":
// want these even for dependency go.mods
default:
return
@@ -226,18 +348,32 @@ func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix
errorf("go directive expects exactly one argument")
return
} else if !GoVersionRE.MatchString(args[0]) {
- errorf("invalid go version '%s': must match format 1.23", args[0])
- return
+ fixed := false
+ if !strict {
+ if m := laxGoVersionRE.FindStringSubmatch(args[0]); m != nil {
+ args[0] = m[1]
+ fixed = true
+ }
+ }
+ if !fixed {
+ errorf("invalid go version '%s': must match format 1.23", args[0])
+ return
+ }
}
f.Go = &Go{Syntax: line}
f.Go.Version = args[0]
+
case "module":
if f.Module != nil {
errorf("repeated module statement")
return
}
- f.Module = &Module{Syntax: line}
+ deprecated := parseDeprecation(block, line)
+ f.Module = &Module{
+ Syntax: line,
+ Deprecated: deprecated,
+ }
if len(args) != 1 {
errorf("usage: module module/path")
return
@@ -248,6 +384,7 @@ func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix
return
}
f.Module.Mod = module.Version{Path: s}
+
case "require", "exclude":
if len(args) != 2 {
errorf("usage: %s module/path v1.2.3", verb)
@@ -284,6 +421,7 @@ func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix
Syntax: line,
})
}
+
case "replace":
arrow := 2
if len(args) >= 2 && args[1] == "=>" {
@@ -347,59 +485,75 @@ func (f *File) add(errs *ErrorList, line *Line, verb string, args []string, fix
New: module.Version{Path: ns, Version: nv},
Syntax: line,
})
+
+ case "retract":
+ rationale := parseDirectiveComment(block, line)
+ vi, err := parseVersionInterval(verb, "", &args, dontFixRetract)
+ if err != nil {
+ if strict {
+ wrapError(err)
+ return
+ } else {
+ // Only report errors parsing intervals in the main module. We may
+ // support additional syntax in the future, such as open and half-open
+ // intervals. Those can't be supported now, because they break the
+ // go.mod parser, even in lax mode.
+ return
+ }
+ }
+ if len(args) > 0 && strict {
+ // In the future, there may be additional information after the version.
+ errorf("unexpected token after version: %q", args[0])
+ return
+ }
+ retract := &Retract{
+ VersionInterval: vi,
+ Rationale: rationale,
+ Syntax: line,
+ }
+ f.Retract = append(f.Retract, retract)
}
}
-// isIndirect reports whether line has a "// indirect" comment,
-// meaning it is in go.mod only for its effect on indirect dependencies,
-// so that it can be dropped entirely once the effective version of the
-// indirect dependency reaches the given minimum version.
-func isIndirect(line *Line) bool {
- if len(line.Suffix) == 0 {
- return false
- }
- f := strings.Fields(strings.TrimPrefix(line.Suffix[0].Token, string(slashSlash)))
- return (len(f) == 1 && f[0] == "indirect" || len(f) > 1 && f[0] == "indirect;")
-}
-
-// setIndirect sets line to have (or not have) a "// indirect" comment.
-func setIndirect(line *Line, indirect bool) {
- if isIndirect(line) == indirect {
+// fixRetract applies fix to each retract directive in f, appending any errors
+// to errs.
+//
+// Most versions are fixed as we parse the file, but for retract directives,
+// the relevant module path is the one specified with the module directive,
+// and that might appear at the end of the file (or not at all).
+func (f *File) fixRetract(fix VersionFixer, errs *ErrorList) {
+ if fix == nil {
return
}
- if indirect {
- // Adding comment.
- if len(line.Suffix) == 0 {
- // New comment.
- line.Suffix = []Comment{{Token: "// indirect", Suffix: true}}
- return
+ path := ""
+ if f.Module != nil {
+ path = f.Module.Mod.Path
+ }
+ var r *Retract
+ wrapError := func(err error) {
+ *errs = append(*errs, Error{
+ Filename: f.Syntax.Name,
+ Pos: r.Syntax.Start,
+ Err: err,
+ })
+ }
+
+ for _, r = range f.Retract {
+ if path == "" {
+ wrapError(errors.New("no module directive found, so retract cannot be used"))
+ return // only print the first one of these
}
- com := &line.Suffix[0]
- text := strings.TrimSpace(strings.TrimPrefix(com.Token, string(slashSlash)))
- if text == "" {
- // Empty comment.
- com.Token = "// indirect"
- return
+ args := r.Syntax.Token
+ if args[0] == "retract" {
+ args = args[1:]
}
-
- // Insert at beginning of existing comment.
- com.Token = "// indirect; " + text
- return
+ vi, err := parseVersionInterval("retract", path, &args, fix)
+ if err != nil {
+ wrapError(err)
+ }
+ r.VersionInterval = vi
}
-
- // Removing comment.
- f := strings.Fields(line.Suffix[0].Token)
- if len(f) == 2 {
- // Remove whole comment.
- line.Suffix = nil
- return
- }
-
- // Remove comment prefix.
- com := &line.Suffix[0]
- i := strings.Index(com.Token, "indirect;")
- com.Token = "//" + com.Token[i+len("indirect;"):]
}
// IsDirectoryPath reports whether the given path should be interpreted
@@ -444,6 +598,53 @@ func AutoQuote(s string) string {
return s
}
+func parseVersionInterval(verb string, path string, args *[]string, fix VersionFixer) (VersionInterval, error) {
+ toks := *args
+ if len(toks) == 0 || toks[0] == "(" {
+ return VersionInterval{}, fmt.Errorf("expected '[' or version")
+ }
+ if toks[0] != "[" {
+ v, err := parseVersion(verb, path, &toks[0], fix)
+ if err != nil {
+ return VersionInterval{}, err
+ }
+ *args = toks[1:]
+ return VersionInterval{Low: v, High: v}, nil
+ }
+ toks = toks[1:]
+
+ if len(toks) == 0 {
+ return VersionInterval{}, fmt.Errorf("expected version after '['")
+ }
+ low, err := parseVersion(verb, path, &toks[0], fix)
+ if err != nil {
+ return VersionInterval{}, err
+ }
+ toks = toks[1:]
+
+ if len(toks) == 0 || toks[0] != "," {
+ return VersionInterval{}, fmt.Errorf("expected ',' after version")
+ }
+ toks = toks[1:]
+
+ if len(toks) == 0 {
+ return VersionInterval{}, fmt.Errorf("expected version after ','")
+ }
+ high, err := parseVersion(verb, path, &toks[0], fix)
+ if err != nil {
+ return VersionInterval{}, err
+ }
+ toks = toks[1:]
+
+ if len(toks) == 0 || toks[0] != "]" {
+ return VersionInterval{}, fmt.Errorf("expected ']' after version")
+ }
+ toks = toks[1:]
+
+ *args = toks
+ return VersionInterval{Low: low, High: high}, nil
+}
+
func parseString(s *string) (string, error) {
t := *s
if strings.HasPrefix(t, `"`) {
@@ -461,6 +662,46 @@ func parseString(s *string) (string, error) {
return t, nil
}
+var deprecatedRE = lazyregexp.New(`(?s)(?:^|\n\n)Deprecated: *(.*?)(?:$|\n\n)`)
+
+// parseDeprecation extracts the text of comments on a "module" directive and
+// extracts a deprecation message from that.
+//
+// A deprecation message is contained in a paragraph within a block of comments
+// that starts with "Deprecated:" (case sensitive). The message runs until the
+// end of the paragraph and does not include the "Deprecated:" prefix. If the
+// comment block has multiple paragraphs that start with "Deprecated:",
+// parseDeprecation returns the message from the first.
+func parseDeprecation(block *LineBlock, line *Line) string {
+ text := parseDirectiveComment(block, line)
+ m := deprecatedRE.FindStringSubmatch(text)
+ if m == nil {
+ return ""
+ }
+ return m[1]
+}
+
+// parseDirectiveComment extracts the text of comments on a directive.
+// If the directive's line does not have comments and is part of a block that
+// does have comments, the block's comments are used.
+func parseDirectiveComment(block *LineBlock, line *Line) string {
+ comments := line.Comment()
+ if block != nil && len(comments.Before) == 0 && len(comments.Suffix) == 0 {
+ comments = block.Comment()
+ }
+ groups := [][]Comment{comments.Before, comments.Suffix}
+ var lines []string
+ for _, g := range groups {
+ for _, c := range g {
+ if !strings.HasPrefix(c.Token, "//") {
+ continue // blank line
+ }
+ lines = append(lines, strings.TrimSpace(strings.TrimPrefix(c.Token, "//")))
+ }
+ }
+ return strings.Join(lines, "\n")
+}
+
type ErrorList []Error
func (e ErrorList) Error() string {
@@ -494,6 +735,8 @@ func (e *Error) Error() string {
var directive string
if e.ModPath != "" {
directive = fmt.Sprintf("%s %s: ", e.Verb, e.ModPath)
+ } else if e.Verb != "" {
+ directive = fmt.Sprintf("%s: ", e.Verb)
}
return pos + directive + e.Err.Error()
@@ -514,8 +757,7 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string
}
}
if fix != nil {
- var err error
- t, err = fix(path, t)
+ fixed, err := fix(path, t)
if err != nil {
if err, ok := err.(*module.ModuleError); ok {
return "", &Error{
@@ -526,19 +768,23 @@ func parseVersion(verb string, path string, s *string, fix VersionFixer) (string
}
return "", err
}
+ t = fixed
+ } else {
+ cv := module.CanonicalVersion(t)
+ if cv == "" {
+ return "", &Error{
+ Verb: verb,
+ ModPath: path,
+ Err: &module.InvalidVersionError{
+ Version: t,
+ Err: errors.New("must be of the form v1.2.3"),
+ },
+ }
+ }
+ t = cv
}
- if v := module.CanonicalVersion(t); v != "" {
- *s = v
- return *s, nil
- }
- return "", &Error{
- Verb: verb,
- ModPath: path,
- Err: &module.InvalidVersionError{
- Version: t,
- Err: errors.New("must be of the form v1.2.3"),
- },
- }
+ *s = t
+ return *s, nil
}
func modulePathMajor(path string) (string, error) {
@@ -585,6 +831,15 @@ func (f *File) Cleanup() {
}
f.Replace = f.Replace[:w]
+ w = 0
+ for _, r := range f.Retract {
+ if r.Low != "" || r.High != "" {
+ f.Retract[w] = r
+ w++
+ }
+ }
+ f.Retract = f.Retract[:w]
+
f.Syntax.Cleanup()
}
@@ -608,6 +863,12 @@ func (f *File) AddGoStmt(version string) error {
return nil
}
+// AddRequire sets the first require line for path to version vers,
+// preserving any existing comments for that line and removing all
+// other lines for path.
+//
+// If no line currently exists for path, AddRequire adds a new line
+// at the end of the last require block.
func (f *File) AddRequire(path, vers string) error {
need := true
for _, r := range f.Require {
@@ -617,7 +878,7 @@ func (f *File) AddRequire(path, vers string) error {
f.Syntax.updateLine(r.Syntax, "require", AutoQuote(path), vers)
need = false
} else {
- f.Syntax.removeLine(r.Syntax)
+ r.Syntax.markRemoved()
*r = Require{}
}
}
@@ -629,69 +890,235 @@ func (f *File) AddRequire(path, vers string) error {
return nil
}
+// AddNewRequire adds a new require line for path at version vers at the end of
+// the last require block, regardless of any existing require lines for path.
func (f *File) AddNewRequire(path, vers string, indirect bool) {
line := f.Syntax.addLine(nil, "require", AutoQuote(path), vers)
- setIndirect(line, indirect)
- f.Require = append(f.Require, &Require{module.Version{Path: path, Version: vers}, indirect, line})
+ r := &Require{
+ Mod: module.Version{Path: path, Version: vers},
+ Syntax: line,
+ }
+ r.setIndirect(indirect)
+ f.Require = append(f.Require, r)
}
+// SetRequire updates the requirements of f to contain exactly req, preserving
+// the existing block structure and line comment contents (except for 'indirect'
+// markings) for the first requirement on each named module path.
+//
+// The Syntax field is ignored for the requirements in req.
+//
+// Any requirements not already present in the file are added to the block
+// containing the last require line.
+//
+// The requirements in req must specify at most one distinct version for each
+// module path.
+//
+// If any existing requirements may be removed, the caller should call Cleanup
+// after all edits are complete.
func (f *File) SetRequire(req []*Require) {
- need := make(map[string]string)
- indirect := make(map[string]bool)
+ type elem struct {
+ version string
+ indirect bool
+ }
+ need := make(map[string]elem)
for _, r := range req {
- need[r.Mod.Path] = r.Mod.Version
- indirect[r.Mod.Path] = r.Indirect
- }
-
- for _, r := range f.Require {
- if v, ok := need[r.Mod.Path]; ok {
- r.Mod.Version = v
- r.Indirect = indirect[r.Mod.Path]
- } else {
- *r = Require{}
+ if prev, dup := need[r.Mod.Path]; dup && prev.version != r.Mod.Version {
+ panic(fmt.Errorf("SetRequire called with conflicting versions for path %s (%s and %s)", r.Mod.Path, prev.version, r.Mod.Version))
}
+ need[r.Mod.Path] = elem{r.Mod.Version, r.Indirect}
}
- var newStmts []Expr
+ // Update or delete the existing Require entries to preserve
+ // only the first for each module path in req.
+ for _, r := range f.Require {
+ e, ok := need[r.Mod.Path]
+ if ok {
+ r.setVersion(e.version)
+ r.setIndirect(e.indirect)
+ } else {
+ r.markRemoved()
+ }
+ delete(need, r.Mod.Path)
+ }
+
+ // Add new entries in the last block of the file for any paths that weren't
+ // already present.
+ //
+ // This step is nondeterministic, but the final result will be deterministic
+ // because we will sort the block.
+ for path, e := range need {
+ f.AddNewRequire(path, e.version, e.indirect)
+ }
+
+ f.SortBlocks()
+}
+
+// SetRequireSeparateIndirect updates the requirements of f to contain the given
+// requirements. Comment contents (except for 'indirect' markings) are retained
+// from the first existing requirement for each module path, and block structure
+// is maintained as long as the indirect markings match.
+//
+// Any requirements on paths not already present in the file are added. Direct
+// requirements are added to the last block containing *any* other direct
+// requirement. Indirect requirements are added to the last block containing
+// *only* other indirect requirements. If no suitable block exists, a new one is
+// added, with the last block containing a direct dependency (if any)
+// immediately before the first block containing only indirect dependencies.
+//
+// The Syntax field is ignored for requirements in the given blocks.
+func (f *File) SetRequireSeparateIndirect(req []*Require) {
+ type modKey struct {
+ path string
+ indirect bool
+ }
+ need := make(map[modKey]string)
+ for _, r := range req {
+ need[modKey{r.Mod.Path, r.Indirect}] = r.Mod.Version
+ }
+
+ comments := make(map[string]Comments)
+ for _, r := range f.Require {
+ v, ok := need[modKey{r.Mod.Path, r.Indirect}]
+ if !ok {
+ if _, ok := need[modKey{r.Mod.Path, !r.Indirect}]; ok {
+ if _, dup := comments[r.Mod.Path]; !dup {
+ comments[r.Mod.Path] = r.Syntax.Comments
+ }
+ }
+ r.markRemoved()
+ continue
+ }
+ r.setVersion(v)
+ delete(need, modKey{r.Mod.Path, r.Indirect})
+ }
+
+ var (
+ lastDirectOrMixedBlock Expr
+ firstIndirectOnlyBlock Expr
+ lastIndirectOnlyBlock Expr
+ )
for _, stmt := range f.Syntax.Stmt {
switch stmt := stmt.(type) {
- case *LineBlock:
- if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
- var newLines []*Line
- for _, line := range stmt.Line {
- if p, err := parseString(&line.Token[0]); err == nil && need[p] != "" {
- if len(line.Comments.Before) == 1 && len(line.Comments.Before[0].Token) == 0 {
- line.Comments.Before = line.Comments.Before[:0]
- }
- line.Token[1] = need[p]
- delete(need, p)
- setIndirect(line, indirect[p])
- newLines = append(newLines, line)
- }
- }
- if len(newLines) == 0 {
- continue // drop stmt
- }
- stmt.Line = newLines
- }
-
case *Line:
- if len(stmt.Token) > 0 && stmt.Token[0] == "require" {
- if p, err := parseString(&stmt.Token[1]); err == nil && need[p] != "" {
- stmt.Token[2] = need[p]
- delete(need, p)
- setIndirect(stmt, indirect[p])
- } else {
- continue // drop stmt
+ if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
+ continue
+ }
+ if isIndirect(stmt) {
+ lastIndirectOnlyBlock = stmt
+ } else {
+ lastDirectOrMixedBlock = stmt
+ }
+ case *LineBlock:
+ if len(stmt.Token) == 0 || stmt.Token[0] != "require" {
+ continue
+ }
+ indirectOnly := true
+ for _, line := range stmt.Line {
+ if len(line.Token) == 0 {
+ continue
+ }
+ if !isIndirect(line) {
+ indirectOnly = false
+ break
+ }
+ }
+ if indirectOnly {
+ lastIndirectOnlyBlock = stmt
+ if firstIndirectOnlyBlock == nil {
+ firstIndirectOnlyBlock = stmt
+ }
+ } else {
+ lastDirectOrMixedBlock = stmt
+ }
+ }
+ }
+
+ isOrContainsStmt := func(stmt Expr, target Expr) bool {
+ if stmt == target {
+ return true
+ }
+ if stmt, ok := stmt.(*LineBlock); ok {
+ if target, ok := target.(*Line); ok {
+ for _, line := range stmt.Line {
+ if line == target {
+ return true
+ }
}
}
}
- newStmts = append(newStmts, stmt)
+ return false
}
- f.Syntax.Stmt = newStmts
- for path, vers := range need {
- f.AddNewRequire(path, vers, indirect[path])
+ addRequire := func(path, vers string, indirect bool, comments Comments) {
+ var line *Line
+ if indirect {
+ if lastIndirectOnlyBlock != nil {
+ line = f.Syntax.addLine(lastIndirectOnlyBlock, "require", path, vers)
+ } else {
+ // Add a new require block after the last direct-only or mixed "require"
+ // block (if any).
+ //
+ // (f.Syntax.addLine would add the line to an existing "require" block if
+ // present, but here the existing "require" blocks are all direct-only, so
+ // we know we need to add a new block instead.)
+ line = &Line{Token: []string{"require", path, vers}}
+ lastIndirectOnlyBlock = line
+ firstIndirectOnlyBlock = line // only block implies first block
+ if lastDirectOrMixedBlock == nil {
+ f.Syntax.Stmt = append(f.Syntax.Stmt, line)
+ } else {
+ for i, stmt := range f.Syntax.Stmt {
+ if isOrContainsStmt(stmt, lastDirectOrMixedBlock) {
+ f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size
+ copy(f.Syntax.Stmt[i+2:], f.Syntax.Stmt[i+1:]) // shuffle elements up
+ f.Syntax.Stmt[i+1] = line
+ break
+ }
+ }
+ }
+ }
+ } else {
+ if lastDirectOrMixedBlock != nil {
+ line = f.Syntax.addLine(lastDirectOrMixedBlock, "require", path, vers)
+ } else {
+ // Add a new require block before the first indirect block (if any).
+ //
+ // That way if the file initially contains only indirect lines,
+ // the direct lines still appear before it: we preserve existing
+ // structure, but only to the extent that that structure already
+ // reflects the direct/indirect split.
+ line = &Line{Token: []string{"require", path, vers}}
+ lastDirectOrMixedBlock = line
+ if firstIndirectOnlyBlock == nil {
+ f.Syntax.Stmt = append(f.Syntax.Stmt, line)
+ } else {
+ for i, stmt := range f.Syntax.Stmt {
+ if isOrContainsStmt(stmt, firstIndirectOnlyBlock) {
+ f.Syntax.Stmt = append(f.Syntax.Stmt, nil) // increase size
+ copy(f.Syntax.Stmt[i+1:], f.Syntax.Stmt[i:]) // shuffle elements up
+ f.Syntax.Stmt[i] = line
+ break
+ }
+ }
+ }
+ }
+ }
+
+ line.Comments.Before = commentsAdd(line.Comments.Before, comments.Before)
+ line.Comments.Suffix = commentsAdd(line.Comments.Suffix, comments.Suffix)
+
+ r := &Require{
+ Mod: module.Version{Path: path, Version: vers},
+ Indirect: indirect,
+ Syntax: line,
+ }
+ r.setIndirect(indirect)
+ f.Require = append(f.Require, r)
+ }
+
+ for k, vers := range need {
+ addRequire(k.path, vers, k.indirect, comments[k.path])
}
f.SortBlocks()
}
@@ -699,14 +1126,20 @@ func (f *File) SetRequire(req []*Require) {
func (f *File) DropRequire(path string) error {
for _, r := range f.Require {
if r.Mod.Path == path {
- f.Syntax.removeLine(r.Syntax)
+ r.Syntax.markRemoved()
*r = Require{}
}
}
return nil
}
+// AddExclude adds a exclude statement to the mod file. Errors if the provided
+// version is not a canonical version string
func (f *File) AddExclude(path, vers string) error {
+ if err := checkCanonicalVersion(path, vers); err != nil {
+ return err
+ }
+
var hint *Line
for _, x := range f.Exclude {
if x.Mod.Path == path && x.Mod.Version == vers {
@@ -724,7 +1157,7 @@ func (f *File) AddExclude(path, vers string) error {
func (f *File) DropExclude(path, vers string) error {
for _, x := range f.Exclude {
if x.Mod.Path == path && x.Mod.Version == vers {
- f.Syntax.removeLine(x.Syntax)
+ x.Syntax.markRemoved()
*x = Exclude{}
}
}
@@ -755,7 +1188,7 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
continue
}
// Already added; delete other replacements for same.
- f.Syntax.removeLine(r.Syntax)
+ r.Syntax.markRemoved()
*r = Replace{}
}
if r.Old.Path == oldPath {
@@ -771,13 +1204,54 @@ func (f *File) AddReplace(oldPath, oldVers, newPath, newVers string) error {
func (f *File) DropReplace(oldPath, oldVers string) error {
for _, r := range f.Replace {
if r.Old.Path == oldPath && r.Old.Version == oldVers {
- f.Syntax.removeLine(r.Syntax)
+ r.Syntax.markRemoved()
*r = Replace{}
}
}
return nil
}
+// AddRetract adds a retract statement to the mod file. Errors if the provided
+// version interval does not consist of canonical version strings
+func (f *File) AddRetract(vi VersionInterval, rationale string) error {
+ var path string
+ if f.Module != nil {
+ path = f.Module.Mod.Path
+ }
+ if err := checkCanonicalVersion(path, vi.High); err != nil {
+ return err
+ }
+ if err := checkCanonicalVersion(path, vi.Low); err != nil {
+ return err
+ }
+
+ r := &Retract{
+ VersionInterval: vi,
+ }
+ if vi.Low == vi.High {
+ r.Syntax = f.Syntax.addLine(nil, "retract", AutoQuote(vi.Low))
+ } else {
+ r.Syntax = f.Syntax.addLine(nil, "retract", "[", AutoQuote(vi.Low), ",", AutoQuote(vi.High), "]")
+ }
+ if rationale != "" {
+ for _, line := range strings.Split(rationale, "\n") {
+ com := Comment{Token: "// " + line}
+ r.Syntax.Comment().Before = append(r.Syntax.Comment().Before, com)
+ }
+ }
+ return nil
+}
+
+func (f *File) DropRetract(vi VersionInterval) error {
+ for _, r := range f.Retract {
+ if r.VersionInterval == vi {
+ r.Syntax.markRemoved()
+ *r = Retract{}
+ }
+ }
+ return nil
+}
+
func (f *File) SortBlocks() {
f.removeDups() // otherwise sorting is unsafe
@@ -786,28 +1260,38 @@ func (f *File) SortBlocks() {
if !ok {
continue
}
- sort.Slice(block.Line, func(i, j int) bool {
- li := block.Line[i]
- lj := block.Line[j]
- for k := 0; k < len(li.Token) && k < len(lj.Token); k++ {
- if li.Token[k] != lj.Token[k] {
- return li.Token[k] < lj.Token[k]
- }
- }
- return len(li.Token) < len(lj.Token)
+ less := lineLess
+ if block.Token[0] == "retract" {
+ less = lineRetractLess
+ }
+ sort.SliceStable(block.Line, func(i, j int) bool {
+ return less(block.Line[i], block.Line[j])
})
}
}
+// removeDups removes duplicate exclude and replace directives.
+//
+// Earlier exclude directives take priority.
+//
+// Later replace directives take priority.
+//
+// require directives are not de-duplicated. That's left up to higher-level
+// logic (MVS).
+//
+// retract directives are not de-duplicated since comments are
+// meaningful, and versions may be retracted multiple times.
func (f *File) removeDups() {
- have := make(map[module.Version]bool)
kill := make(map[*Line]bool)
+
+ // Remove duplicate excludes.
+ haveExclude := make(map[module.Version]bool)
for _, x := range f.Exclude {
- if have[x.Mod] {
+ if haveExclude[x.Mod] {
kill[x.Syntax] = true
continue
}
- have[x.Mod] = true
+ haveExclude[x.Mod] = true
}
var excl []*Exclude
for _, x := range f.Exclude {
@@ -817,15 +1301,16 @@ func (f *File) removeDups() {
}
f.Exclude = excl
- have = make(map[module.Version]bool)
+ // Remove duplicate replacements.
// Later replacements take priority over earlier ones.
+ haveReplace := make(map[module.Version]bool)
for i := len(f.Replace) - 1; i >= 0; i-- {
x := f.Replace[i]
- if have[x.Old] {
+ if haveReplace[x.Old] {
kill[x.Syntax] = true
continue
}
- have[x.Old] = true
+ haveReplace[x.Old] = true
}
var repl []*Replace
for _, x := range f.Replace {
@@ -835,6 +1320,9 @@ func (f *File) removeDups() {
}
f.Replace = repl
+ // Duplicate require and retract directives are not removed.
+
+ // Drop killed statements from the syntax tree.
var stmts []Expr
for _, stmt := range f.Syntax.Stmt {
switch stmt := stmt.(type) {
@@ -858,3 +1346,76 @@ func (f *File) removeDups() {
}
f.Syntax.Stmt = stmts
}
+
+// lineLess returns whether li should be sorted before lj. It sorts
+// lexicographically without assigning any special meaning to tokens.
+func lineLess(li, lj *Line) bool {
+ for k := 0; k < len(li.Token) && k < len(lj.Token); k++ {
+ if li.Token[k] != lj.Token[k] {
+ return li.Token[k] < lj.Token[k]
+ }
+ }
+ return len(li.Token) < len(lj.Token)
+}
+
+// lineRetractLess returns whether li should be sorted before lj for lines in
+// a "retract" block. It treats each line as a version interval. Single versions
+// are compared as if they were intervals with the same low and high version.
+// Intervals are sorted in descending order, first by low version, then by
+// high version, using semver.Compare.
+func lineRetractLess(li, lj *Line) bool {
+ interval := func(l *Line) VersionInterval {
+ if len(l.Token) == 1 {
+ return VersionInterval{Low: l.Token[0], High: l.Token[0]}
+ } else if len(l.Token) == 5 && l.Token[0] == "[" && l.Token[2] == "," && l.Token[4] == "]" {
+ return VersionInterval{Low: l.Token[1], High: l.Token[3]}
+ } else {
+ // Line in unknown format. Treat as an invalid version.
+ return VersionInterval{}
+ }
+ }
+ vii := interval(li)
+ vij := interval(lj)
+ if cmp := semver.Compare(vii.Low, vij.Low); cmp != 0 {
+ return cmp > 0
+ }
+ return semver.Compare(vii.High, vij.High) > 0
+}
+
+// checkCanonicalVersion returns a non-nil error if vers is not a canonical
+// version string or does not match the major version of path.
+//
+// If path is non-empty, the error text suggests a format with a major version
+// corresponding to the path.
+func checkCanonicalVersion(path, vers string) error {
+ _, pathMajor, pathMajorOk := module.SplitPathVersion(path)
+
+ if vers == "" || vers != module.CanonicalVersion(vers) {
+ if pathMajor == "" {
+ return &module.InvalidVersionError{
+ Version: vers,
+ Err: fmt.Errorf("must be of the form v1.2.3"),
+ }
+ }
+ return &module.InvalidVersionError{
+ Version: vers,
+ Err: fmt.Errorf("must be of the form %s.2.3", module.PathMajorPrefix(pathMajor)),
+ }
+ }
+
+ if pathMajorOk {
+ if err := module.CheckPathMajor(vers, pathMajor); err != nil {
+ if pathMajor == "" {
+ // In this context, the user probably wrote "v2.3.4" when they meant
+ // "v2.3.4+incompatible". Suggest that instead of "v0 or v1".
+ return &module.InvalidVersionError{
+ Version: vers,
+ Err: fmt.Errorf("should be %s+incompatible (or module %s/%v)", vers, path, semver.Major(vers)),
+ }
+ }
+ return err
+ }
+ }
+
+ return nil
+}
diff --git a/vendor/golang.org/x/mod/module/module.go b/vendor/golang.org/x/mod/module/module.go
index 6cd37280a85..ba97ac356e9 100644
--- a/vendor/golang.org/x/mod/module/module.go
+++ b/vendor/golang.org/x/mod/module/module.go
@@ -97,6 +97,7 @@ package module
import (
"fmt"
+ "path"
"sort"
"strings"
"unicode"
@@ -191,6 +192,21 @@ func (e *InvalidVersionError) Error() string {
func (e *InvalidVersionError) Unwrap() error { return e.Err }
+// An InvalidPathError indicates a module, import, or file path doesn't
+// satisfy all naming constraints. See CheckPath, CheckImportPath,
+// and CheckFilePath for specific restrictions.
+type InvalidPathError struct {
+ Kind string // "module", "import", or "file"
+ Path string
+ Err error
+}
+
+func (e *InvalidPathError) Error() string {
+ return fmt.Sprintf("malformed %s path %q: %v", e.Kind, e.Path, e.Err)
+}
+
+func (e *InvalidPathError) Unwrap() error { return e.Err }
+
// Check checks that a given module path, version pair is valid.
// In addition to the path being a valid module path
// and the version being a valid semantic version,
@@ -223,14 +239,18 @@ func firstPathOK(r rune) bool {
'a' <= r && r <= 'z'
}
-// pathOK reports whether r can appear in an import path element.
-// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: + - . _ and ~.
-// This matches what "go get" has historically recognized in import paths.
+// modPathOK reports whether r can appear in a module path element.
+// Paths can be ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
+//
+// This matches what "go get" has historically recognized in import paths,
+// and avoids confusing sequences like '%20' or '+' that would change meaning
+// if used in a URL.
+//
// TODO(rsc): We would like to allow Unicode letters, but that requires additional
// care in the safe encoding (see "escaped paths" above).
-func pathOK(r rune) bool {
+func modPathOK(r rune) bool {
if r < utf8.RuneSelf {
- return r == '+' || r == '-' || r == '.' || r == '_' || r == '~' ||
+ return r == '-' || r == '.' || r == '_' || r == '~' ||
'0' <= r && r <= '9' ||
'A' <= r && r <= 'Z' ||
'a' <= r && r <= 'z'
@@ -238,6 +258,17 @@ func pathOK(r rune) bool {
return false
}
+// modPathOK reports whether r can appear in a package import path element.
+//
+// Import paths are intermediate between module paths and file paths: we allow
+// disallow characters that would be confusing or ambiguous as arguments to
+// 'go get' (such as '@' and ' ' ), but allow certain characters that are
+// otherwise-unambiguous on the command line and historically used for some
+// binary names (such as '++' as a suffix for compiler binaries and wrappers).
+func importPathOK(r rune) bool {
+ return modPathOK(r) || r == '+'
+}
+
// fileNameOK reports whether r can appear in a file name.
// For now we allow all Unicode letters but otherwise limit to pathOK plus a few more punctuation characters.
// If we expand the set of allowed characters here, we have to
@@ -269,7 +300,7 @@ func fileNameOK(r rune) bool {
// CheckPath checks that a module path is valid.
// A valid module path is a valid import path, as checked by CheckImportPath,
-// with two additional constraints.
+// with three additional constraints.
// First, the leading path element (up to the first slash, if any),
// by convention a domain name, must contain only lower-case ASCII letters,
// ASCII digits, dots (U+002E), and dashes (U+002D);
@@ -279,30 +310,37 @@ func fileNameOK(r rune) bool {
// and must not contain any dots. For paths beginning with "gopkg.in/",
// this second requirement is replaced by a requirement that the path
// follow the gopkg.in server's conventions.
-func CheckPath(path string) error {
- if err := checkPath(path, false); err != nil {
- return fmt.Errorf("malformed module path %q: %v", path, err)
+// Third, no path element may begin with a dot.
+func CheckPath(path string) (err error) {
+ defer func() {
+ if err != nil {
+ err = &InvalidPathError{Kind: "module", Path: path, Err: err}
+ }
+ }()
+
+ if err := checkPath(path, modulePath); err != nil {
+ return err
}
i := strings.Index(path, "/")
if i < 0 {
i = len(path)
}
if i == 0 {
- return fmt.Errorf("malformed module path %q: leading slash", path)
+ return fmt.Errorf("leading slash")
}
if !strings.Contains(path[:i], ".") {
- return fmt.Errorf("malformed module path %q: missing dot in first path element", path)
+ return fmt.Errorf("missing dot in first path element")
}
if path[0] == '-' {
- return fmt.Errorf("malformed module path %q: leading dash in first path element", path)
+ return fmt.Errorf("leading dash in first path element")
}
for _, r := range path[:i] {
if !firstPathOK(r) {
- return fmt.Errorf("malformed module path %q: invalid char %q in first path element", path, r)
+ return fmt.Errorf("invalid char %q in first path element", r)
}
}
if _, _, ok := SplitPathVersion(path); !ok {
- return fmt.Errorf("malformed module path %q: invalid version", path)
+ return fmt.Errorf("invalid version")
}
return nil
}
@@ -313,36 +351,49 @@ func CheckPath(path string) error {
// separated by slashes (U+002F). (It must not begin with nor end in a slash.)
//
// A valid path element is a non-empty string made up of
-// ASCII letters, ASCII digits, and limited ASCII punctuation: + - . _ and ~.
-// It must not begin or end with a dot (U+002E), nor contain two dots in a row.
+// ASCII letters, ASCII digits, and limited ASCII punctuation: - . _ and ~.
+// It must not end with a dot (U+002E), nor contain two dots in a row.
//
// The element prefix up to the first dot must not be a reserved file name
-// on Windows, regardless of case (CON, com1, NuL, and so on).
+// on Windows, regardless of case (CON, com1, NuL, and so on). The element
+// must not have a suffix of a tilde followed by one or more ASCII digits
+// (to exclude paths elements that look like Windows short-names).
//
// CheckImportPath may be less restrictive in the future, but see the
// top-level package documentation for additional information about
// subtleties of Unicode.
func CheckImportPath(path string) error {
- if err := checkPath(path, false); err != nil {
- return fmt.Errorf("malformed import path %q: %v", path, err)
+ if err := checkPath(path, importPath); err != nil {
+ return &InvalidPathError{Kind: "import", Path: path, Err: err}
}
return nil
}
-// checkPath checks that a general path is valid.
-// It returns an error describing why but not mentioning path.
-// Because these checks apply to both module paths and import paths,
-// the caller is expected to add the "malformed ___ path %q: " prefix.
-// fileName indicates whether the final element of the path is a file name
-// (as opposed to a directory name).
-func checkPath(path string, fileName bool) error {
+// pathKind indicates what kind of path we're checking. Module paths,
+// import paths, and file paths have different restrictions.
+type pathKind int
+
+const (
+ modulePath pathKind = iota
+ importPath
+ filePath
+)
+
+// checkPath checks that a general path is valid. kind indicates what
+// specific constraints should be applied.
+//
+// checkPath returns an error describing why the path is not valid.
+// Because these checks apply to module, import, and file paths,
+// and because other checks may be applied, the caller is expected to wrap
+// this error with InvalidPathError.
+func checkPath(path string, kind pathKind) error {
if !utf8.ValidString(path) {
return fmt.Errorf("invalid UTF-8")
}
if path == "" {
return fmt.Errorf("empty string")
}
- if path[0] == '-' {
+ if path[0] == '-' && kind != filePath {
return fmt.Errorf("leading dash")
}
if strings.Contains(path, "//") {
@@ -354,39 +405,45 @@ func checkPath(path string, fileName bool) error {
elemStart := 0
for i, r := range path {
if r == '/' {
- if err := checkElem(path[elemStart:i], fileName); err != nil {
+ if err := checkElem(path[elemStart:i], kind); err != nil {
return err
}
elemStart = i + 1
}
}
- if err := checkElem(path[elemStart:], fileName); err != nil {
+ if err := checkElem(path[elemStart:], kind); err != nil {
return err
}
return nil
}
// checkElem checks whether an individual path element is valid.
-// fileName indicates whether the element is a file name (not a directory name).
-func checkElem(elem string, fileName bool) error {
+func checkElem(elem string, kind pathKind) error {
if elem == "" {
return fmt.Errorf("empty path element")
}
if strings.Count(elem, ".") == len(elem) {
return fmt.Errorf("invalid path element %q", elem)
}
- if elem[0] == '.' && !fileName {
+ if elem[0] == '.' && kind == modulePath {
return fmt.Errorf("leading dot in path element")
}
if elem[len(elem)-1] == '.' {
return fmt.Errorf("trailing dot in path element")
}
- charOK := pathOK
- if fileName {
- charOK = fileNameOK
- }
for _, r := range elem {
- if !charOK(r) {
+ ok := false
+ switch kind {
+ case modulePath:
+ ok = modPathOK(r)
+ case importPath:
+ ok = importPathOK(r)
+ case filePath:
+ ok = fileNameOK(r)
+ default:
+ panic(fmt.Sprintf("internal error: invalid kind %v", kind))
+ }
+ if !ok {
return fmt.Errorf("invalid char %q", r)
}
}
@@ -402,6 +459,29 @@ func checkElem(elem string, fileName bool) error {
return fmt.Errorf("%q disallowed as path element component on Windows", short)
}
}
+
+ if kind == filePath {
+ // don't check for Windows short-names in file names. They're
+ // only an issue for import paths.
+ return nil
+ }
+
+ // Reject path components that look like Windows short-names.
+ // Those usually end in a tilde followed by one or more ASCII digits.
+ if tilde := strings.LastIndexByte(short, '~'); tilde >= 0 && tilde < len(short)-1 {
+ suffix := short[tilde+1:]
+ suffixIsDigits := true
+ for _, r := range suffix {
+ if r < '0' || r > '9' {
+ suffixIsDigits = false
+ break
+ }
+ }
+ if suffixIsDigits {
+ return fmt.Errorf("trailing tilde and digits in path element")
+ }
+ }
+
return nil
}
@@ -418,8 +498,8 @@ func checkElem(elem string, fileName bool) error {
// top-level package documentation for additional information about
// subtleties of Unicode.
func CheckFilePath(path string) error {
- if err := checkPath(path, true); err != nil {
- return fmt.Errorf("malformed file path %q: %v", path, err)
+ if err := checkPath(path, filePath); err != nil {
+ return &InvalidPathError{Kind: "file", Path: path, Err: err}
}
return nil
}
@@ -621,7 +701,7 @@ func EscapePath(path string) (escaped string, err error) {
// Versions are allowed to be in non-semver form but must be valid file names
// and not contain exclamation marks.
func EscapeVersion(v string) (escaped string, err error) {
- if err := checkElem(v, true); err != nil || strings.Contains(v, "!") {
+ if err := checkElem(v, filePath); err != nil || strings.Contains(v, "!") {
return "", &InvalidVersionError{
Version: v,
Err: fmt.Errorf("disallowed version string"),
@@ -680,7 +760,7 @@ func UnescapeVersion(escaped string) (v string, err error) {
if !ok {
return "", fmt.Errorf("invalid escaped version %q", escaped)
}
- if err := checkElem(v, true); err != nil {
+ if err := checkElem(v, filePath); err != nil {
return "", fmt.Errorf("invalid escaped version %q: %v", v, err)
}
return v, nil
@@ -716,3 +796,49 @@ func unescapeString(escaped string) (string, bool) {
}
return string(buf), true
}
+
+// MatchPrefixPatterns reports whether any path prefix of target matches one of
+// the glob patterns (as defined by path.Match) in the comma-separated globs
+// list. This implements the algorithm used when matching a module path to the
+// GOPRIVATE environment variable, as described by 'go help module-private'.
+//
+// It ignores any empty or malformed patterns in the list.
+func MatchPrefixPatterns(globs, target string) bool {
+ for globs != "" {
+ // Extract next non-empty glob in comma-separated list.
+ var glob string
+ if i := strings.Index(globs, ","); i >= 0 {
+ glob, globs = globs[:i], globs[i+1:]
+ } else {
+ glob, globs = globs, ""
+ }
+ if glob == "" {
+ continue
+ }
+
+ // A glob with N+1 path elements (N slashes) needs to be matched
+ // against the first N+1 path elements of target,
+ // which end just before the N+1'th slash.
+ n := strings.Count(glob, "/")
+ prefix := target
+ // Walk target, counting slashes, truncating at the N+1'th slash.
+ for i := 0; i < len(target); i++ {
+ if target[i] == '/' {
+ if n == 0 {
+ prefix = target[:i]
+ break
+ }
+ n--
+ }
+ }
+ if n > 0 {
+ // Not enough prefix elements.
+ continue
+ }
+ matched, _ := path.Match(glob, prefix)
+ if matched {
+ return true
+ }
+ }
+ return false
+}
diff --git a/vendor/golang.org/x/mod/module/pseudo.go b/vendor/golang.org/x/mod/module/pseudo.go
new file mode 100644
index 00000000000..f04ad378869
--- /dev/null
+++ b/vendor/golang.org/x/mod/module/pseudo.go
@@ -0,0 +1,250 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Pseudo-versions
+//
+// Code authors are expected to tag the revisions they want users to use,
+// including prereleases. However, not all authors tag versions at all,
+// and not all commits a user might want to try will have tags.
+// A pseudo-version is a version with a special form that allows us to
+// address an untagged commit and order that version with respect to
+// other versions we might encounter.
+//
+// A pseudo-version takes one of the general forms:
+//
+// (1) vX.0.0-yyyymmddhhmmss-abcdef123456
+// (2) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456
+// (3) vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible
+// (4) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456
+// (5) vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible
+//
+// If there is no recently tagged version with the right major version vX,
+// then form (1) is used, creating a space of pseudo-versions at the bottom
+// of the vX version range, less than any tagged version, including the unlikely v0.0.0.
+//
+// If the most recent tagged version before the target commit is vX.Y.Z or vX.Y.Z+incompatible,
+// then the pseudo-version uses form (2) or (3), making it a prerelease for the next
+// possible semantic version after vX.Y.Z. The leading 0 segment in the prerelease string
+// ensures that the pseudo-version compares less than possible future explicit prereleases
+// like vX.Y.(Z+1)-rc1 or vX.Y.(Z+1)-1.
+//
+// If the most recent tagged version before the target commit is vX.Y.Z-pre or vX.Y.Z-pre+incompatible,
+// then the pseudo-version uses form (4) or (5), making it a slightly later prerelease.
+
+package module
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "time"
+
+ "golang.org/x/mod/internal/lazyregexp"
+ "golang.org/x/mod/semver"
+)
+
+var pseudoVersionRE = lazyregexp.New(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)
+
+const PseudoVersionTimestampFormat = "20060102150405"
+
+// PseudoVersion returns a pseudo-version for the given major version ("v1")
+// preexisting older tagged version ("" or "v1.2.3" or "v1.2.3-pre"), revision time,
+// and revision identifier (usually a 12-byte commit hash prefix).
+func PseudoVersion(major, older string, t time.Time, rev string) string {
+ if major == "" {
+ major = "v0"
+ }
+ segment := fmt.Sprintf("%s-%s", t.UTC().Format(PseudoVersionTimestampFormat), rev)
+ build := semver.Build(older)
+ older = semver.Canonical(older)
+ if older == "" {
+ return major + ".0.0-" + segment // form (1)
+ }
+ if semver.Prerelease(older) != "" {
+ return older + ".0." + segment + build // form (4), (5)
+ }
+
+ // Form (2), (3).
+ // Extract patch from vMAJOR.MINOR.PATCH
+ i := strings.LastIndex(older, ".") + 1
+ v, patch := older[:i], older[i:]
+
+ // Reassemble.
+ return v + incDecimal(patch) + "-0." + segment + build
+}
+
+// ZeroPseudoVersion returns a pseudo-version with a zero timestamp and
+// revision, which may be used as a placeholder.
+func ZeroPseudoVersion(major string) string {
+ return PseudoVersion(major, "", time.Time{}, "000000000000")
+}
+
+// incDecimal returns the decimal string incremented by 1.
+func incDecimal(decimal string) string {
+ // Scan right to left turning 9s to 0s until you find a digit to increment.
+ digits := []byte(decimal)
+ i := len(digits) - 1
+ for ; i >= 0 && digits[i] == '9'; i-- {
+ digits[i] = '0'
+ }
+ if i >= 0 {
+ digits[i]++
+ } else {
+ // digits is all zeros
+ digits[0] = '1'
+ digits = append(digits, '0')
+ }
+ return string(digits)
+}
+
+// decDecimal returns the decimal string decremented by 1, or the empty string
+// if the decimal is all zeroes.
+func decDecimal(decimal string) string {
+ // Scan right to left turning 0s to 9s until you find a digit to decrement.
+ digits := []byte(decimal)
+ i := len(digits) - 1
+ for ; i >= 0 && digits[i] == '0'; i-- {
+ digits[i] = '9'
+ }
+ if i < 0 {
+ // decimal is all zeros
+ return ""
+ }
+ if i == 0 && digits[i] == '1' && len(digits) > 1 {
+ digits = digits[1:]
+ } else {
+ digits[i]--
+ }
+ return string(digits)
+}
+
+// IsPseudoVersion reports whether v is a pseudo-version.
+func IsPseudoVersion(v string) bool {
+ return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v)
+}
+
+// IsZeroPseudoVersion returns whether v is a pseudo-version with a zero base,
+// timestamp, and revision, as returned by ZeroPseudoVersion.
+func IsZeroPseudoVersion(v string) bool {
+ return v == ZeroPseudoVersion(semver.Major(v))
+}
+
+// PseudoVersionTime returns the time stamp of the pseudo-version v.
+// It returns an error if v is not a pseudo-version or if the time stamp
+// embedded in the pseudo-version is not a valid time.
+func PseudoVersionTime(v string) (time.Time, error) {
+ _, timestamp, _, _, err := parsePseudoVersion(v)
+ if err != nil {
+ return time.Time{}, err
+ }
+ t, err := time.Parse("20060102150405", timestamp)
+ if err != nil {
+ return time.Time{}, &InvalidVersionError{
+ Version: v,
+ Pseudo: true,
+ Err: fmt.Errorf("malformed time %q", timestamp),
+ }
+ }
+ return t, nil
+}
+
+// PseudoVersionRev returns the revision identifier of the pseudo-version v.
+// It returns an error if v is not a pseudo-version.
+func PseudoVersionRev(v string) (rev string, err error) {
+ _, _, rev, _, err = parsePseudoVersion(v)
+ return
+}
+
+// PseudoVersionBase returns the canonical parent version, if any, upon which
+// the pseudo-version v is based.
+//
+// If v has no parent version (that is, if it is "vX.0.0-[…]"),
+// PseudoVersionBase returns the empty string and a nil error.
+func PseudoVersionBase(v string) (string, error) {
+ base, _, _, build, err := parsePseudoVersion(v)
+ if err != nil {
+ return "", err
+ }
+
+ switch pre := semver.Prerelease(base); pre {
+ case "":
+ // vX.0.0-yyyymmddhhmmss-abcdef123456 → ""
+ if build != "" {
+ // Pseudo-versions of the form vX.0.0-yyyymmddhhmmss-abcdef123456+incompatible
+ // are nonsensical: the "vX.0.0-" prefix implies that there is no parent tag,
+ // but the "+incompatible" suffix implies that the major version of
+ // the parent tag is not compatible with the module's import path.
+ //
+ // There are a few such entries in the index generated by proxy.golang.org,
+ // but we believe those entries were generated by the proxy itself.
+ return "", &InvalidVersionError{
+ Version: v,
+ Pseudo: true,
+ Err: fmt.Errorf("lacks base version, but has build metadata %q", build),
+ }
+ }
+ return "", nil
+
+ case "-0":
+ // vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z
+ // vX.Y.(Z+1)-0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z+incompatible
+ base = strings.TrimSuffix(base, pre)
+ i := strings.LastIndexByte(base, '.')
+ if i < 0 {
+ panic("base from parsePseudoVersion missing patch number: " + base)
+ }
+ patch := decDecimal(base[i+1:])
+ if patch == "" {
+ // vX.0.0-0 is invalid, but has been observed in the wild in the index
+ // generated by requests to proxy.golang.org.
+ //
+ // NOTE(bcmills): I cannot find a historical bug that accounts for
+ // pseudo-versions of this form, nor have I seen such versions in any
+ // actual go.mod files. If we find actual examples of this form and a
+ // reasonable theory of how they came into existence, it seems fine to
+ // treat them as equivalent to vX.0.0 (especially since the invalid
+ // pseudo-versions have lower precedence than the real ones). For now, we
+ // reject them.
+ return "", &InvalidVersionError{
+ Version: v,
+ Pseudo: true,
+ Err: fmt.Errorf("version before %s would have negative patch number", base),
+ }
+ }
+ return base[:i+1] + patch + build, nil
+
+ default:
+ // vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456 → vX.Y.Z-pre
+ // vX.Y.Z-pre.0.yyyymmddhhmmss-abcdef123456+incompatible → vX.Y.Z-pre+incompatible
+ if !strings.HasSuffix(base, ".0") {
+ panic(`base from parsePseudoVersion missing ".0" before date: ` + base)
+ }
+ return strings.TrimSuffix(base, ".0") + build, nil
+ }
+}
+
+var errPseudoSyntax = errors.New("syntax error")
+
+func parsePseudoVersion(v string) (base, timestamp, rev, build string, err error) {
+ if !IsPseudoVersion(v) {
+ return "", "", "", "", &InvalidVersionError{
+ Version: v,
+ Pseudo: true,
+ Err: errPseudoSyntax,
+ }
+ }
+ build = semver.Build(v)
+ v = strings.TrimSuffix(v, build)
+ j := strings.LastIndex(v, "-")
+ v, rev = v[:j], v[j+1:]
+ i := strings.LastIndex(v, "-")
+ if j := strings.LastIndex(v, "."); j > i {
+ base = v[:j] // "vX.Y.Z-pre.0" or "vX.Y.(Z+1)-0"
+ timestamp = v[j+1:]
+ } else {
+ base = v[:i] // "vX.0.0"
+ timestamp = v[i+1:]
+ }
+ return base, timestamp, rev, build, nil
+}
diff --git a/vendor/golang.org/x/mod/semver/semver.go b/vendor/golang.org/x/mod/semver/semver.go
index 2988e3cf9c5..7be398f80d3 100644
--- a/vendor/golang.org/x/mod/semver/semver.go
+++ b/vendor/golang.org/x/mod/semver/semver.go
@@ -22,6 +22,8 @@
// as shorthands for vMAJOR.0.0 and vMAJOR.MINOR.0.
package semver
+import "sort"
+
// parsed returns the parsed form of a semantic version string.
type parsed struct {
major string
@@ -138,6 +140,9 @@ func Compare(v, w string) int {
// Max canonicalizes its arguments and then returns the version string
// that compares greater.
+//
+// Deprecated: use Compare instead. In most cases, returning a canonicalized
+// version is not expected or desired.
func Max(v, w string) string {
v = Canonical(v)
w = Canonical(w)
@@ -147,6 +152,24 @@ func Max(v, w string) string {
return w
}
+// ByVersion implements sort.Interface for sorting semantic version strings.
+type ByVersion []string
+
+func (vs ByVersion) Len() int { return len(vs) }
+func (vs ByVersion) Swap(i, j int) { vs[i], vs[j] = vs[j], vs[i] }
+func (vs ByVersion) Less(i, j int) bool {
+ cmp := Compare(vs[i], vs[j])
+ if cmp != 0 {
+ return cmp < 0
+ }
+ return vs[i] < vs[j]
+}
+
+// Sort sorts a list of semantic version strings using ByVersion.
+func Sort(list []string) {
+ sort.Sort(ByVersion(list))
+}
+
func parse(v string) (p parsed, ok bool) {
if v == "" || v[0] != 'v' {
p.err = "missing v prefix"
diff --git a/vendor/golang.org/x/sys/AUTHORS b/vendor/golang.org/x/sys/AUTHORS
new file mode 100644
index 00000000000..15167cd746c
--- /dev/null
+++ b/vendor/golang.org/x/sys/AUTHORS
@@ -0,0 +1,3 @@
+# This source code refers to The Go Authors for copyright purposes.
+# The master list of authors is in the main Go distribution,
+# visible at http://tip.golang.org/AUTHORS.
diff --git a/vendor/golang.org/x/sys/CONTRIBUTORS b/vendor/golang.org/x/sys/CONTRIBUTORS
new file mode 100644
index 00000000000..1c4577e9680
--- /dev/null
+++ b/vendor/golang.org/x/sys/CONTRIBUTORS
@@ -0,0 +1,3 @@
+# This source code was written by the Go contributors.
+# The master list of contributors is in the main Go distribution,
+# visible at http://tip.golang.org/CONTRIBUTORS.
diff --git a/vendor/golang.org/x/sys/LICENSE b/vendor/golang.org/x/sys/LICENSE
new file mode 100644
index 00000000000..6a66aea5eaf
--- /dev/null
+++ b/vendor/golang.org/x/sys/LICENSE
@@ -0,0 +1,27 @@
+Copyright (c) 2009 The Go Authors. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the following disclaimer
+in the documentation and/or other materials provided with the
+distribution.
+ * Neither the name of Google Inc. nor the names of its
+contributors may be used to endorse or promote products derived from
+this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/vendor/golang.org/x/sys/PATENTS b/vendor/golang.org/x/sys/PATENTS
new file mode 100644
index 00000000000..733099041f8
--- /dev/null
+++ b/vendor/golang.org/x/sys/PATENTS
@@ -0,0 +1,22 @@
+Additional IP Rights Grant (Patents)
+
+"This implementation" means the copyrightable works distributed by
+Google as part of the Go project.
+
+Google hereby grants to You a perpetual, worldwide, non-exclusive,
+no-charge, royalty-free, irrevocable (except as stated in this section)
+patent license to make, have made, use, offer to sell, sell, import,
+transfer and otherwise run, modify and propagate the contents of this
+implementation of Go, where such license applies only to those patent
+claims, both currently owned or controlled by Google and acquired in
+the future, licensable by Google that are necessarily infringed by this
+implementation of Go. This grant does not include claims that would be
+infringed only as a consequence of further modification of this
+implementation. If you or your agent or exclusive licensee institute or
+order or agree to the institution of patent litigation against any
+entity (including a cross-claim or counterclaim in a lawsuit) alleging
+that this implementation of Go or any code incorporated within this
+implementation of Go constitutes direct or contributory patent
+infringement, or inducement of patent infringement, then any patent
+rights granted to you under this License for this implementation of Go
+shall terminate as of the date such litigation is filed.
diff --git a/vendor/golang.org/x/sys/execabs/execabs.go b/vendor/golang.org/x/sys/execabs/execabs.go
new file mode 100644
index 00000000000..78192498db0
--- /dev/null
+++ b/vendor/golang.org/x/sys/execabs/execabs.go
@@ -0,0 +1,102 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package execabs is a drop-in replacement for os/exec
+// that requires PATH lookups to find absolute paths.
+// That is, execabs.Command("cmd") runs the same PATH lookup
+// as exec.Command("cmd"), but if the result is a path
+// which is relative, the Run and Start methods will report
+// an error instead of running the executable.
+//
+// See https://blog.golang.org/path-security for more information
+// about when it may be necessary or appropriate to use this package.
+package execabs
+
+import (
+ "context"
+ "fmt"
+ "os/exec"
+ "path/filepath"
+ "reflect"
+ "unsafe"
+)
+
+// ErrNotFound is the error resulting if a path search failed to find an executable file.
+// It is an alias for exec.ErrNotFound.
+var ErrNotFound = exec.ErrNotFound
+
+// Cmd represents an external command being prepared or run.
+// It is an alias for exec.Cmd.
+type Cmd = exec.Cmd
+
+// Error is returned by LookPath when it fails to classify a file as an executable.
+// It is an alias for exec.Error.
+type Error = exec.Error
+
+// An ExitError reports an unsuccessful exit by a command.
+// It is an alias for exec.ExitError.
+type ExitError = exec.ExitError
+
+func relError(file, path string) error {
+ return fmt.Errorf("%s resolves to executable in current directory (.%c%s)", file, filepath.Separator, path)
+}
+
+// LookPath searches for an executable named file in the directories
+// named by the PATH environment variable. If file contains a slash,
+// it is tried directly and the PATH is not consulted. The result will be
+// an absolute path.
+//
+// LookPath differs from exec.LookPath in its handling of PATH lookups,
+// which are used for file names without slashes. If exec.LookPath's
+// PATH lookup would have returned an executable from the current directory,
+// LookPath instead returns an error.
+func LookPath(file string) (string, error) {
+ path, err := exec.LookPath(file)
+ if err != nil {
+ return "", err
+ }
+ if filepath.Base(file) == file && !filepath.IsAbs(path) {
+ return "", relError(file, path)
+ }
+ return path, nil
+}
+
+func fixCmd(name string, cmd *exec.Cmd) {
+ if filepath.Base(name) == name && !filepath.IsAbs(cmd.Path) {
+ // exec.Command was called with a bare binary name and
+ // exec.LookPath returned a path which is not absolute.
+ // Set cmd.lookPathErr and clear cmd.Path so that it
+ // cannot be run.
+ lookPathErr := (*error)(unsafe.Pointer(reflect.ValueOf(cmd).Elem().FieldByName("lookPathErr").Addr().Pointer()))
+ if *lookPathErr == nil {
+ *lookPathErr = relError(name, cmd.Path)
+ }
+ cmd.Path = ""
+ }
+}
+
+// CommandContext is like Command but includes a context.
+//
+// The provided context is used to kill the process (by calling os.Process.Kill)
+// if the context becomes done before the command completes on its own.
+func CommandContext(ctx context.Context, name string, arg ...string) *exec.Cmd {
+ cmd := exec.CommandContext(ctx, name, arg...)
+ fixCmd(name, cmd)
+ return cmd
+
+}
+
+// Command returns the Cmd struct to execute the named program with the given arguments.
+// See exec.Command for most details.
+//
+// Command differs from exec.Command in its handling of PATH lookups,
+// which are used when the program name contains no slashes.
+// If exec.Command would have returned an exec.Cmd configured to run an
+// executable from the current directory, Command instead
+// returns an exec.Cmd that will return an error from Start or Run.
+func Command(name string, arg ...string) *exec.Cmd {
+ cmd := exec.Command(name, arg...)
+ fixCmd(name, cmd)
+ return cmd
+}
diff --git a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
index f8363d8faae..fc8beea5d8a 100644
--- a/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
+++ b/vendor/golang.org/x/tools/go/gcexportdata/gcexportdata.go
@@ -100,10 +100,34 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package,
// Write writes encoded type information for the specified package to out.
// The FileSet provides file position information for named objects.
func Write(out io.Writer, fset *token.FileSet, pkg *types.Package) error {
- b, err := gcimporter.IExportData(fset, pkg)
- if err != nil {
+ if _, err := io.WriteString(out, "i"); err != nil {
return err
}
- _, err = out.Write(b)
- return err
+ return gcimporter.IExportData(out, fset, pkg)
+}
+
+// ReadBundle reads an export bundle from in, decodes it, and returns type
+// information for the packages.
+// File position information is added to fset.
+//
+// ReadBundle may inspect and add to the imports map to ensure that references
+// within the export bundle to other packages are consistent.
+//
+// On return, the state of the reader is undefined.
+//
+// Experimental: This API is experimental and may change in the future.
+func ReadBundle(in io.Reader, fset *token.FileSet, imports map[string]*types.Package) ([]*types.Package, error) {
+ data, err := ioutil.ReadAll(in)
+ if err != nil {
+ return nil, fmt.Errorf("reading export bundle: %v", err)
+ }
+ return gcimporter.IImportBundle(fset, imports, data)
+}
+
+// WriteBundle writes encoded type information for the specified packages to out.
+// The FileSet provides file position information for named objects.
+//
+// Experimental: This API is experimental and may change in the future.
+func WriteBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {
+ return gcimporter.IExportBundle(out, fset, pkgs)
}
diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go
index 4be32a2e55f..d2fc8b6fa3e 100644
--- a/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go
+++ b/vendor/golang.org/x/tools/go/internal/gcimporter/iexport.go
@@ -25,12 +25,25 @@ import (
// 0: Go1.11 encoding
const iexportVersion = 0
-// IExportData returns the binary export data for pkg.
+// Current bundled export format version. Increase with each format change.
+// 0: initial implementation
+const bundleVersion = 0
+
+// IExportData writes indexed export data for pkg to out.
//
// If no file set is provided, position info will be missing.
// The package path of the top-level package will not be recorded,
// so that calls to IImportData can override with a provided package path.
-func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error) {
+func IExportData(out io.Writer, fset *token.FileSet, pkg *types.Package) error {
+ return iexportCommon(out, fset, false, []*types.Package{pkg})
+}
+
+// IExportBundle writes an indexed export bundle for pkgs to out.
+func IExportBundle(out io.Writer, fset *token.FileSet, pkgs []*types.Package) error {
+ return iexportCommon(out, fset, true, pkgs)
+}
+
+func iexportCommon(out io.Writer, fset *token.FileSet, bundle bool, pkgs []*types.Package) (err error) {
defer func() {
if e := recover(); e != nil {
if ierr, ok := e.(internalError); ok {
@@ -43,13 +56,14 @@ func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error)
}()
p := iexporter{
- out: bytes.NewBuffer(nil),
fset: fset,
allPkgs: map[*types.Package]bool{},
stringIndex: map[string]uint64{},
declIndex: map[types.Object]uint64{},
typIndex: map[types.Type]uint64{},
- localpkg: pkg,
+ }
+ if !bundle {
+ p.localpkg = pkgs[0]
}
for i, pt := range predeclared() {
@@ -60,10 +74,20 @@ func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error)
}
// Initialize work queue with exported declarations.
- scope := pkg.Scope()
- for _, name := range scope.Names() {
- if ast.IsExported(name) {
- p.pushDecl(scope.Lookup(name))
+ for _, pkg := range pkgs {
+ scope := pkg.Scope()
+ for _, name := range scope.Names() {
+ if ast.IsExported(name) {
+ p.pushDecl(scope.Lookup(name))
+ }
+ }
+
+ if bundle {
+ // Ensure pkg and its imports are included in the index.
+ p.allPkgs[pkg] = true
+ for _, imp := range pkg.Imports() {
+ p.allPkgs[imp] = true
+ }
}
}
@@ -76,21 +100,35 @@ func IExportData(fset *token.FileSet, pkg *types.Package) (b []byte, err error)
dataLen := uint64(p.data0.Len())
w := p.newWriter()
w.writeIndex(p.declIndex)
+
+ if bundle {
+ w.uint64(uint64(len(pkgs)))
+ for _, pkg := range pkgs {
+ w.pkg(pkg)
+ imps := pkg.Imports()
+ w.uint64(uint64(len(imps)))
+ for _, imp := range imps {
+ w.pkg(imp)
+ }
+ }
+ }
w.flush()
// Assemble header.
var hdr intWriter
- hdr.WriteByte('i')
+ if bundle {
+ hdr.uint64(bundleVersion)
+ }
hdr.uint64(iexportVersion)
hdr.uint64(uint64(p.strings.Len()))
hdr.uint64(dataLen)
// Flush output.
- io.Copy(p.out, &hdr)
- io.Copy(p.out, &p.strings)
- io.Copy(p.out, &p.data0)
+ io.Copy(out, &hdr)
+ io.Copy(out, &p.strings)
+ io.Copy(out, &p.data0)
- return p.out.Bytes(), nil
+ return nil
}
// writeIndex writes out an object index. mainIndex indicates whether
@@ -104,7 +142,9 @@ func (w *exportWriter) writeIndex(index map[types.Object]uint64) {
// For the main index, make sure to include every package that
// we reference, even if we're not exporting (or reexporting)
// any symbols from it.
- pkgObjs[w.p.localpkg] = nil
+ if w.p.localpkg != nil {
+ pkgObjs[w.p.localpkg] = nil
+ }
for pkg := range w.p.allPkgs {
pkgObjs[pkg] = nil
}
@@ -474,10 +514,10 @@ func (w *exportWriter) param(obj types.Object) {
func (w *exportWriter) value(typ types.Type, v constant.Value) {
w.typ(typ, nil)
- switch v.Kind() {
- case constant.Bool:
+ switch b := typ.Underlying().(*types.Basic); b.Info() & types.IsConstType {
+ case types.IsBoolean:
w.bool(constant.BoolVal(v))
- case constant.Int:
+ case types.IsInteger:
var i big.Int
if i64, exact := constant.Int64Val(v); exact {
i.SetInt64(i64)
@@ -487,25 +527,27 @@ func (w *exportWriter) value(typ types.Type, v constant.Value) {
i.SetString(v.ExactString(), 10)
}
w.mpint(&i, typ)
- case constant.Float:
+ case types.IsFloat:
f := constantToFloat(v)
w.mpfloat(f, typ)
- case constant.Complex:
+ case types.IsComplex:
w.mpfloat(constantToFloat(constant.Real(v)), typ)
w.mpfloat(constantToFloat(constant.Imag(v)), typ)
- case constant.String:
+ case types.IsString:
w.string(constant.StringVal(v))
- case constant.Unknown:
- // package contains type errors
default:
- panic(internalErrorf("unexpected value %v (%T)", v, v))
+ if b.Kind() == types.Invalid {
+ // package contains type errors
+ break
+ }
+ panic(internalErrorf("unexpected type %v (%v)", typ, typ.Underlying()))
}
}
// constantToFloat converts a constant.Value with kind constant.Float to a
// big.Float.
func constantToFloat(x constant.Value) *big.Float {
- assert(x.Kind() == constant.Float)
+ x = constant.ToFloat(x)
// Use the same floating-point precision (512) as cmd/compile
// (see Mpprec in cmd/compile/internal/gc/mpfloat.go).
const mpprec = 512
diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go b/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go
index a31a880263e..8ed8bc62d68 100644
--- a/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go
+++ b/vendor/golang.org/x/tools/go/internal/gcimporter/iimport.go
@@ -59,10 +59,23 @@ const (
)
// IImportData imports a package from the serialized package data
-// and returns the number of bytes consumed and a reference to the package.
+// and returns 0 and a reference to the package.
// If the export data version is not recognized or the format is otherwise
// compromised, an error is returned.
-func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (_ int, pkg *types.Package, err error) {
+func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []byte, path string) (int, *types.Package, error) {
+ pkgs, err := iimportCommon(fset, imports, data, false, path)
+ if err != nil {
+ return 0, nil, err
+ }
+ return 0, pkgs[0], nil
+}
+
+// IImportBundle imports a set of packages from the serialized package bundle.
+func IImportBundle(fset *token.FileSet, imports map[string]*types.Package, data []byte) ([]*types.Package, error) {
+ return iimportCommon(fset, imports, data, true, "")
+}
+
+func iimportCommon(fset *token.FileSet, imports map[string]*types.Package, data []byte, bundle bool, path string) (pkgs []*types.Package, err error) {
const currentVersion = 1
version := int64(-1)
defer func() {
@@ -77,6 +90,15 @@ func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []
r := &intReader{bytes.NewReader(data), path}
+ if bundle {
+ bundleVersion := r.uint64()
+ switch bundleVersion {
+ case bundleVersion:
+ default:
+ errorf("unknown bundle format version %d", bundleVersion)
+ }
+ }
+
version = int64(r.uint64())
switch version {
case currentVersion, 0:
@@ -143,39 +165,58 @@ func IImportData(fset *token.FileSet, imports map[string]*types.Package, data []
p.pkgIndex[pkg] = nameIndex
pkgList[i] = pkg
}
- if len(pkgList) == 0 {
- errorf("no packages found for %s", path)
- panic("unreachable")
+
+ if bundle {
+ pkgs = make([]*types.Package, r.uint64())
+ for i := range pkgs {
+ pkg := p.pkgAt(r.uint64())
+ imps := make([]*types.Package, r.uint64())
+ for j := range imps {
+ imps[j] = p.pkgAt(r.uint64())
+ }
+ pkg.SetImports(imps)
+ pkgs[i] = pkg
+ }
+ } else {
+ if len(pkgList) == 0 {
+ errorf("no packages found for %s", path)
+ panic("unreachable")
+ }
+ pkgs = pkgList[:1]
+
+ // record all referenced packages as imports
+ list := append(([]*types.Package)(nil), pkgList[1:]...)
+ sort.Sort(byPath(list))
+ pkgs[0].SetImports(list)
}
- p.ipkg = pkgList[0]
- names := make([]string, 0, len(p.pkgIndex[p.ipkg]))
- for name := range p.pkgIndex[p.ipkg] {
- names = append(names, name)
- }
- sort.Strings(names)
- for _, name := range names {
- p.doDecl(p.ipkg, name)
+
+ for _, pkg := range pkgs {
+ if pkg.Complete() {
+ continue
+ }
+
+ names := make([]string, 0, len(p.pkgIndex[pkg]))
+ for name := range p.pkgIndex[pkg] {
+ names = append(names, name)
+ }
+ sort.Strings(names)
+ for _, name := range names {
+ p.doDecl(pkg, name)
+ }
+
+ // package was imported completely and without errors
+ pkg.MarkComplete()
}
for _, typ := range p.interfaceList {
typ.Complete()
}
- // record all referenced packages as imports
- list := append(([]*types.Package)(nil), pkgList[1:]...)
- sort.Sort(byPath(list))
- p.ipkg.SetImports(list)
-
- // package was imported completely and without errors
- p.ipkg.MarkComplete()
-
- consumed, _ := r.Seek(0, io.SeekCurrent)
- return int(consumed), p.ipkg, nil
+ return pkgs, nil
}
type iimporter struct {
ipath string
- ipkg *types.Package
version int
stringData []byte
@@ -227,9 +268,6 @@ func (p *iimporter) pkgAt(off uint64) *types.Package {
return pkg
}
path := p.stringAt(off)
- if path == p.ipath {
- return p.ipkg
- }
errorf("missing package %q in %q", path, p.ipath)
return nil
}
@@ -435,6 +473,14 @@ func (r *importReader) mpfloat(b *types.Basic) constant.Value {
switch {
case exp > 0:
x = constant.Shift(x, token.SHL, uint(exp))
+ // Ensure that the imported Kind is Float, else this constant may run into
+ // bitsize limits on overlarge integers. Eventually we can instead adopt
+ // the approach of CL 288632, but that CL relies on go/constant APIs that
+ // were introduced in go1.13.
+ //
+ // TODO(rFindley): sync the logic here with tip Go once we no longer
+ // support go1.12.
+ x = constant.ToFloat(x)
case exp < 0:
d := constant.Shift(constant.MakeInt64(1), token.SHL, uint(-exp))
x = constant.BinaryOp(x, token.QUO, d)
diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go b/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go
index 463f2522714..8b163e3d058 100644
--- a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go
+++ b/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface10.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build !go1.11
// +build !go1.11
package gcimporter
diff --git a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go b/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go
index ab28b95cbb8..49984f40fd8 100644
--- a/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go
+++ b/vendor/golang.org/x/tools/go/internal/gcimporter/newInterface11.go
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+//go:build go1.11
// +build go1.11
package gcimporter
diff --git a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
index 35bc6a4127a..18a002f82a1 100644
--- a/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
+++ b/vendor/golang.org/x/tools/go/internal/packagesdriver/sizes.go
@@ -6,12 +6,9 @@
package packagesdriver
import (
- "bytes"
"context"
- "encoding/json"
"fmt"
"go/types"
- "os/exec"
"strings"
"golang.org/x/tools/internal/gocommand"
@@ -19,74 +16,13 @@ import (
var debug = false
-func GetSizes(ctx context.Context, buildFlags, env []string, gocmdRunner *gocommand.Runner, dir string) (types.Sizes, error) {
- // TODO(matloob): Clean this up. This code is mostly a copy of packages.findExternalDriver.
- const toolPrefix = "GOPACKAGESDRIVER="
- tool := ""
- for _, env := range env {
- if val := strings.TrimPrefix(env, toolPrefix); val != env {
- tool = val
- }
- }
-
- if tool == "" {
- var err error
- tool, err = exec.LookPath("gopackagesdriver")
- if err != nil {
- // We did not find the driver, so use "go list".
- tool = "off"
- }
- }
-
- if tool == "off" {
- inv := gocommand.Invocation{
- BuildFlags: buildFlags,
- Env: env,
- WorkingDir: dir,
- }
- return GetSizesGolist(ctx, inv, gocmdRunner)
- }
-
- req, err := json.Marshal(struct {
- Command string `json:"command"`
- Env []string `json:"env"`
- BuildFlags []string `json:"build_flags"`
- }{
- Command: "sizes",
- Env: env,
- BuildFlags: buildFlags,
- })
- if err != nil {
- return nil, fmt.Errorf("failed to encode message to driver tool: %v", err)
- }
-
- buf := new(bytes.Buffer)
- cmd := exec.CommandContext(ctx, tool)
- cmd.Dir = dir
- cmd.Env = env
- cmd.Stdin = bytes.NewReader(req)
- cmd.Stdout = buf
- cmd.Stderr = new(bytes.Buffer)
- if err := cmd.Run(); err != nil {
- return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr)
- }
- var response struct {
- // Sizes, if not nil, is the types.Sizes to use when type checking.
- Sizes *types.StdSizes
- }
- if err := json.Unmarshal(buf.Bytes(), &response); err != nil {
- return nil, err
- }
- return response.Sizes, nil
-}
-
func GetSizesGolist(ctx context.Context, inv gocommand.Invocation, gocmdRunner *gocommand.Runner) (types.Sizes, error) {
inv.Verb = "list"
inv.Args = []string{"-f", "{{context.GOARCH}} {{context.Compiler}}", "--", "unsafe"}
stdout, stderr, friendlyErr, rawErr := gocmdRunner.RunRaw(ctx, inv)
var goarch, compiler string
if rawErr != nil {
- if strings.Contains(rawErr.Error(), "cannot find main module") {
+ if rawErrMsg := rawErr.Error(); strings.Contains(rawErrMsg, "cannot find main module") || strings.Contains(rawErrMsg, "go.mod file not found") {
// User's running outside of a module. All bets are off. Get GOARCH and guess compiler is gc.
// TODO(matloob): Is this a problem in practice?
inv.Verb = "env"
diff --git a/vendor/golang.org/x/tools/go/packages/external.go b/vendor/golang.org/x/tools/go/packages/external.go
index 8c8473fd0bd..7242a0a7d2b 100644
--- a/vendor/golang.org/x/tools/go/packages/external.go
+++ b/vendor/golang.org/x/tools/go/packages/external.go
@@ -12,8 +12,8 @@ import (
"bytes"
"encoding/json"
"fmt"
+ exec "golang.org/x/sys/execabs"
"os"
- "os/exec"
"strings"
)
@@ -89,7 +89,7 @@ func findExternalDriver(cfg *Config) driver {
return nil, fmt.Errorf("%v: %v: %s", tool, err, cmd.Stderr)
}
if len(stderr.Bytes()) != 0 && os.Getenv("GOPACKAGESPRINTDRIVERERRORS") != "" {
- fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd, words...), stderr)
+ fmt.Fprintf(os.Stderr, "%s stderr: <<%s>>\n", cmdDebugStr(cmd), stderr)
}
var response driverResponse
diff --git a/vendor/golang.org/x/tools/go/packages/golist.go b/vendor/golang.org/x/tools/go/packages/golist.go
index 787783cd9f5..0e1e7f11fee 100644
--- a/vendor/golang.org/x/tools/go/packages/golist.go
+++ b/vendor/golang.org/x/tools/go/packages/golist.go
@@ -10,9 +10,9 @@ import (
"encoding/json"
"fmt"
"go/types"
+ "io/ioutil"
"log"
"os"
- "os/exec"
"path"
"path/filepath"
"reflect"
@@ -22,8 +22,10 @@ import (
"sync"
"unicode"
+ exec "golang.org/x/sys/execabs"
"golang.org/x/tools/go/internal/packagesdriver"
"golang.org/x/tools/internal/gocommand"
+ "golang.org/x/tools/internal/packagesinternal"
"golang.org/x/xerrors"
)
@@ -208,56 +210,58 @@ extractQueries:
}
}
- modifiedPkgs, needPkgs, err := state.processGolistOverlay(response)
- if err != nil {
- return nil, err
- }
+ // Only use go/packages' overlay processing if we're using a Go version
+ // below 1.16. Otherwise, go list handles it.
+ if goVersion, err := state.getGoVersion(); err == nil && goVersion < 16 {
+ modifiedPkgs, needPkgs, err := state.processGolistOverlay(response)
+ if err != nil {
+ return nil, err
+ }
- var containsCandidates []string
- if len(containFiles) > 0 {
- containsCandidates = append(containsCandidates, modifiedPkgs...)
- containsCandidates = append(containsCandidates, needPkgs...)
- }
- if err := state.addNeededOverlayPackages(response, needPkgs); err != nil {
- return nil, err
- }
- // Check candidate packages for containFiles.
- if len(containFiles) > 0 {
- for _, id := range containsCandidates {
- pkg, ok := response.seenPackages[id]
- if !ok {
- response.addPackage(&Package{
- ID: id,
- Errors: []Error{
- {
+ var containsCandidates []string
+ if len(containFiles) > 0 {
+ containsCandidates = append(containsCandidates, modifiedPkgs...)
+ containsCandidates = append(containsCandidates, needPkgs...)
+ }
+ if err := state.addNeededOverlayPackages(response, needPkgs); err != nil {
+ return nil, err
+ }
+ // Check candidate packages for containFiles.
+ if len(containFiles) > 0 {
+ for _, id := range containsCandidates {
+ pkg, ok := response.seenPackages[id]
+ if !ok {
+ response.addPackage(&Package{
+ ID: id,
+ Errors: []Error{{
Kind: ListError,
Msg: fmt.Sprintf("package %s expected but not seen", id),
- },
- },
- })
- continue
- }
- for _, f := range containFiles {
- for _, g := range pkg.GoFiles {
- if sameFile(f, g) {
- response.addRoot(id)
+ }},
+ })
+ continue
+ }
+ for _, f := range containFiles {
+ for _, g := range pkg.GoFiles {
+ if sameFile(f, g) {
+ response.addRoot(id)
+ }
}
}
}
}
- }
- // Add root for any package that matches a pattern. This applies only to
- // packages that are modified by overlays, since they are not added as
- // roots automatically.
- for _, pattern := range restPatterns {
- match := matchPattern(pattern)
- for _, pkgID := range modifiedPkgs {
- pkg, ok := response.seenPackages[pkgID]
- if !ok {
- continue
- }
- if match(pkg.PkgPath) {
- response.addRoot(pkg.ID)
+ // Add root for any package that matches a pattern. This applies only to
+ // packages that are modified by overlays, since they are not added as
+ // roots automatically.
+ for _, pattern := range restPatterns {
+ match := matchPattern(pattern)
+ for _, pkgID := range modifiedPkgs {
+ pkg, ok := response.seenPackages[pkgID]
+ if !ok {
+ continue
+ }
+ if match(pkg.PkgPath) {
+ response.addRoot(pkg.ID)
+ }
}
}
}
@@ -410,7 +414,8 @@ type jsonPackage struct {
ForTest string // q in a "p [q.test]" package, else ""
DepOnly bool
- Error *jsonPackageError
+ Error *packagesinternal.PackageError
+ DepsErrors []*packagesinternal.PackageError
}
type jsonPackageError struct {
@@ -562,6 +567,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
OtherFiles: absJoin(p.Dir, otherFiles(p)...),
IgnoredFiles: absJoin(p.Dir, p.IgnoredGoFiles, p.IgnoredOtherFiles),
forTest: p.ForTest,
+ depsErrors: p.DepsErrors,
Module: p.Module,
}
@@ -578,7 +584,7 @@ func (state *golistState) createDriverResponse(words ...string) (*driverResponse
// golang/go#38990: go list silently fails to do cgo processing
pkg.CompiledGoFiles = nil
pkg.Errors = append(pkg.Errors, Error{
- Msg: "go list failed to return CompiledGoFiles; https://golang.org/issue/38990?",
+ Msg: "go list failed to return CompiledGoFiles. This may indicate failure to perform cgo processing; try building at the command line. See https://golang.org/issue/38990.",
Kind: ListError,
})
}
@@ -824,6 +830,7 @@ func (state *golistState) cfgInvocation() gocommand.Invocation {
BuildFlags: cfg.BuildFlags,
ModFile: cfg.modFile,
ModFlag: cfg.modFlag,
+ CleanEnv: cfg.Env != nil,
Env: cfg.Env,
Logf: cfg.Logf,
WorkingDir: cfg.Dir,
@@ -835,13 +842,33 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
cfg := state.cfg
inv := state.cfgInvocation()
+
+ // For Go versions 1.16 and above, `go list` accepts overlays directly via
+ // the -overlay flag. Set it, if it's available.
+ //
+ // The check for "list" is not necessarily required, but we should avoid
+ // getting the go version if possible.
+ if verb == "list" {
+ goVersion, err := state.getGoVersion()
+ if err != nil {
+ return nil, err
+ }
+ if goVersion >= 16 {
+ filename, cleanup, err := state.writeOverlays()
+ if err != nil {
+ return nil, err
+ }
+ defer cleanup()
+ inv.Overlay = filename
+ }
+ }
inv.Verb = verb
inv.Args = args
gocmdRunner := cfg.gocmdRunner
if gocmdRunner == nil {
gocmdRunner = &gocommand.Runner{}
}
- stdout, stderr, _, err := gocmdRunner.RunRaw(cfg.Context, inv)
+ stdout, stderr, friendlyErr, err := gocmdRunner.RunRaw(cfg.Context, inv)
if err != nil {
// Check for 'go' executable not being found.
if ee, ok := err.(*exec.Error); ok && ee.Err == exec.ErrNotFound {
@@ -862,7 +889,7 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
// Related to #24854
if len(stderr.String()) > 0 && strings.Contains(stderr.String(), "unexpected directory layout") {
- return nil, fmt.Errorf("%s", stderr.String())
+ return nil, friendlyErr
}
// Is there an error running the C compiler in cgo? This will be reported in the "Error" field
@@ -878,8 +905,13 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
return unicode.IsOneOf([]*unicode.RangeTable{unicode.L, unicode.M, unicode.N, unicode.P, unicode.S}, r) &&
!strings.ContainsRune("!\"#$%&'()*,:;<=>?[\\]^`{|}\uFFFD", r)
}
+ // golang/go#36770: Handle case where cmd/go prints module download messages before the error.
+ msg := stderr.String()
+ for strings.HasPrefix(msg, "go: downloading") {
+ msg = msg[strings.IndexRune(msg, '\n')+1:]
+ }
if len(stderr.String()) > 0 && strings.HasPrefix(stderr.String(), "# ") {
- msg := stderr.String()[len("# "):]
+ msg := msg[len("# "):]
if strings.HasPrefix(strings.TrimLeftFunc(msg, isPkgPathRune), "\n") {
return stdout, nil
}
@@ -970,12 +1002,73 @@ func (state *golistState) invokeGo(verb string, args ...string) (*bytes.Buffer,
// TODO(matloob): Remove these once we can depend on go list to exit with a zero status with -e even when
// packages don't exist or a build fails.
if !usesExportData(cfg) && !containsGoFile(args) {
- return nil, fmt.Errorf("go %v: %s: %s", args, exitErr, stderr)
+ return nil, friendlyErr
}
}
return stdout, nil
}
+// OverlayJSON is the format overlay files are expected to be in.
+// The Replace map maps from overlaid paths to replacement paths:
+// the Go command will forward all reads trying to open
+// each overlaid path to its replacement path, or consider the overlaid
+// path not to exist if the replacement path is empty.
+//
+// From golang/go#39958.
+type OverlayJSON struct {
+ Replace map[string]string `json:"replace,omitempty"`
+}
+
+// writeOverlays writes out files for go list's -overlay flag, as described
+// above.
+func (state *golistState) writeOverlays() (filename string, cleanup func(), err error) {
+ // Do nothing if there are no overlays in the config.
+ if len(state.cfg.Overlay) == 0 {
+ return "", func() {}, nil
+ }
+ dir, err := ioutil.TempDir("", "gopackages-*")
+ if err != nil {
+ return "", nil, err
+ }
+ // The caller must clean up this directory, unless this function returns an
+ // error.
+ cleanup = func() {
+ os.RemoveAll(dir)
+ }
+ defer func() {
+ if err != nil {
+ cleanup()
+ }
+ }()
+ overlays := map[string]string{}
+ for k, v := range state.cfg.Overlay {
+ // Create a unique filename for the overlaid files, to avoid
+ // creating nested directories.
+ noSeparator := strings.Join(strings.Split(filepath.ToSlash(k), "/"), "")
+ f, err := ioutil.TempFile(dir, fmt.Sprintf("*-%s", noSeparator))
+ if err != nil {
+ return "", func() {}, err
+ }
+ if _, err := f.Write(v); err != nil {
+ return "", func() {}, err
+ }
+ if err := f.Close(); err != nil {
+ return "", func() {}, err
+ }
+ overlays[k] = f.Name()
+ }
+ b, err := json.Marshal(OverlayJSON{Replace: overlays})
+ if err != nil {
+ return "", func() {}, err
+ }
+ // Write out the overlay file that contains the filepath mappings.
+ filename = filepath.Join(dir, "overlay.json")
+ if err := ioutil.WriteFile(filename, b, 0665); err != nil {
+ return "", func() {}, err
+ }
+ return filename, cleanup, nil
+}
+
func containsGoFile(s []string) bool {
for _, f := range s {
if strings.HasSuffix(f, ".go") {
@@ -985,17 +1078,22 @@ func containsGoFile(s []string) bool {
return false
}
-func cmdDebugStr(cmd *exec.Cmd, args ...string) string {
+func cmdDebugStr(cmd *exec.Cmd) string {
env := make(map[string]string)
for _, kv := range cmd.Env {
- split := strings.Split(kv, "=")
+ split := strings.SplitN(kv, "=", 2)
k, v := split[0], split[1]
env[k] = v
}
- var quotedArgs []string
- for _, arg := range args {
- quotedArgs = append(quotedArgs, strconv.Quote(arg))
- }
- return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v PWD=%v go %s", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["PWD"], strings.Join(quotedArgs, " "))
+ var args []string
+ for _, arg := range cmd.Args {
+ quoted := strconv.Quote(arg)
+ if quoted[1:len(quoted)-1] != arg || strings.Contains(arg, " ") {
+ args = append(args, quoted)
+ } else {
+ args = append(args, arg)
+ }
+ }
+ return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
}
diff --git a/vendor/golang.org/x/tools/go/packages/golist_overlay.go b/vendor/golang.org/x/tools/go/packages/golist_overlay.go
index de2c1dc5793..9576b472f9c 100644
--- a/vendor/golang.org/x/tools/go/packages/golist_overlay.go
+++ b/vendor/golang.org/x/tools/go/packages/golist_overlay.go
@@ -9,7 +9,6 @@ import (
"fmt"
"go/parser"
"go/token"
- "log"
"os"
"path/filepath"
"regexp"
@@ -35,9 +34,12 @@ func (state *golistState) processGolistOverlay(response *responseDeduper) (modif
// This is an approximation of import path to id. This can be
// wrong for tests, vendored packages, and a number of other cases.
havePkgs[pkg.PkgPath] = pkg.ID
- x := commonDir(pkg.GoFiles)
- if x != "" {
- pkgOfDir[x] = append(pkgOfDir[x], pkg)
+ dir, err := commonDir(pkg.GoFiles)
+ if err != nil {
+ return nil, nil, err
+ }
+ if dir != "" {
+ pkgOfDir[dir] = append(pkgOfDir[dir], pkg)
}
}
@@ -441,20 +443,21 @@ func extractPackageName(filename string, contents []byte) (string, bool) {
return f.Name.Name, true
}
-func commonDir(a []string) string {
+// commonDir returns the directory that all files are in, "" if files is empty,
+// or an error if they aren't in the same directory.
+func commonDir(files []string) (string, error) {
seen := make(map[string]bool)
- x := append([]string{}, a...)
- for _, f := range x {
+ for _, f := range files {
seen[filepath.Dir(f)] = true
}
if len(seen) > 1 {
- log.Fatalf("commonDir saw %v for %v", seen, x)
+ return "", fmt.Errorf("files (%v) are in more than one directory: %v", files, seen)
}
for k := range seen {
- // len(seen) == 1
- return k
+ // seen has only one element; return it.
+ return k, nil
}
- return "" // no files
+ return "", nil // no files
}
// It is possible that the files in the disk directory dir have a different package
diff --git a/vendor/golang.org/x/tools/go/packages/packages.go b/vendor/golang.org/x/tools/go/packages/packages.go
index 38475e8712a..8a1a2d68100 100644
--- a/vendor/golang.org/x/tools/go/packages/packages.go
+++ b/vendor/golang.org/x/tools/go/packages/packages.go
@@ -339,6 +339,9 @@ type Package struct {
// forTest is the package under test, if any.
forTest string
+ // depsErrors is the DepsErrors field from the go list response, if any.
+ depsErrors []*packagesinternal.PackageError
+
// module is the module information for the package if it exists.
Module *Module
}
@@ -366,6 +369,9 @@ func init() {
packagesinternal.GetForTest = func(p interface{}) string {
return p.(*Package).forTest
}
+ packagesinternal.GetDepsErrors = func(p interface{}) []*packagesinternal.PackageError {
+ return p.(*Package).depsErrors
+ }
packagesinternal.GetGoCmdRunner = func(config interface{}) *gocommand.Runner {
return config.(*Config).gocmdRunner
}
diff --git a/vendor/golang.org/x/tools/go/packages/visit.go b/vendor/golang.org/x/tools/go/packages/visit.go
index b13cb081fcb..a1dcc40b727 100644
--- a/vendor/golang.org/x/tools/go/packages/visit.go
+++ b/vendor/golang.org/x/tools/go/packages/visit.go
@@ -1,3 +1,7 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
package packages
import (
diff --git a/vendor/golang.org/x/tools/internal/event/core/event.go b/vendor/golang.org/x/tools/internal/event/core/event.go
index e37b4949150..a6cf0e64a4b 100644
--- a/vendor/golang.org/x/tools/internal/event/core/event.go
+++ b/vendor/golang.org/x/tools/internal/event/core/event.go
@@ -12,7 +12,7 @@ import (
"golang.org/x/tools/internal/event/label"
)
-// Event holds the information about an event of note that ocurred.
+// Event holds the information about an event of note that occurred.
type Event struct {
at time.Time
diff --git a/vendor/golang.org/x/tools/internal/event/label/label.go b/vendor/golang.org/x/tools/internal/event/label/label.go
index b55c12eb250..0f526e1f9ab 100644
--- a/vendor/golang.org/x/tools/internal/event/label/label.go
+++ b/vendor/golang.org/x/tools/internal/event/label/label.go
@@ -96,6 +96,8 @@ func Of64(k Key, v uint64) Label { return Label{key: k, packed: v} }
// access should be done with the From method of the key.
func (t Label) Unpack64() uint64 { return t.packed }
+type stringptr unsafe.Pointer
+
// OfString creates a new label from a key and a string.
// This method is for implementing new key types, label creation should
// normally be done with the Of method of the key.
@@ -104,7 +106,7 @@ func OfString(k Key, v string) Label {
return Label{
key: k,
packed: uint64(hdr.Len),
- untyped: unsafe.Pointer(hdr.Data),
+ untyped: stringptr(hdr.Data),
}
}
@@ -115,9 +117,9 @@ func OfString(k Key, v string) Label {
func (t Label) UnpackString() string {
var v string
hdr := (*reflect.StringHeader)(unsafe.Pointer(&v))
- hdr.Data = uintptr(t.untyped.(unsafe.Pointer))
+ hdr.Data = uintptr(t.untyped.(stringptr))
hdr.Len = int(t.packed)
- return *(*string)(unsafe.Pointer(hdr))
+ return v
}
// Valid returns true if the Label is a valid one (it has a key).
diff --git a/vendor/golang.org/x/tools/internal/gocommand/invoke.go b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
index b5c061b0125..8659a0c5da6 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/invoke.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/invoke.go
@@ -9,10 +9,11 @@ import (
"bytes"
"context"
"fmt"
+ exec "golang.org/x/sys/execabs"
"io"
"os"
- "os/exec"
"regexp"
+ "strconv"
"strings"
"sync"
"time"
@@ -132,6 +133,10 @@ type Invocation struct {
BuildFlags []string
ModFlag string
ModFile string
+ Overlay string
+ // If CleanEnv is set, the invocation will run only with the environment
+ // in Env, not starting with os.Environ.
+ CleanEnv bool
Env []string
WorkingDir string
Logf func(format string, args ...interface{})
@@ -171,6 +176,11 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
goArgs = append(goArgs, "-mod="+i.ModFlag)
}
}
+ appendOverlayFlag := func() {
+ if i.Overlay != "" {
+ goArgs = append(goArgs, "-overlay="+i.Overlay)
+ }
+ }
switch i.Verb {
case "env", "version":
@@ -189,6 +199,7 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
goArgs = append(goArgs, i.BuildFlags...)
appendModFile()
appendModFlag()
+ appendOverlayFlag()
goArgs = append(goArgs, i.Args...)
}
cmd := exec.Command("go", goArgs...)
@@ -200,7 +211,10 @@ func (i *Invocation) run(ctx context.Context, stdout, stderr io.Writer) error {
// The Go stdlib has a special feature where if the cwd and the PWD are the
// same node then it trusts the PWD, so by setting it in the env for the child
// process we fix up all the paths returned by the go command.
- cmd.Env = append(os.Environ(), i.Env...)
+ if !i.CleanEnv {
+ cmd.Env = os.Environ()
+ }
+ cmd.Env = append(cmd.Env, i.Env...)
if i.WorkingDir != "" {
cmd.Env = append(cmd.Env, "PWD="+i.WorkingDir)
cmd.Dir = i.WorkingDir
@@ -241,10 +255,19 @@ func runCmdContext(ctx context.Context, cmd *exec.Cmd) error {
func cmdDebugStr(cmd *exec.Cmd) string {
env := make(map[string]string)
for _, kv := range cmd.Env {
- split := strings.Split(kv, "=")
+ split := strings.SplitN(kv, "=", 2)
k, v := split[0], split[1]
env[k] = v
}
- return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v go %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], cmd.Args)
+ var args []string
+ for _, arg := range cmd.Args {
+ quoted := strconv.Quote(arg)
+ if quoted[1:len(quoted)-1] != arg || strings.Contains(arg, " ") {
+ args = append(args, quoted)
+ } else {
+ args = append(args, arg)
+ }
+ }
+ return fmt.Sprintf("GOROOT=%v GOPATH=%v GO111MODULE=%v GOPROXY=%v PWD=%v %v", env["GOROOT"], env["GOPATH"], env["GO111MODULE"], env["GOPROXY"], env["PWD"], strings.Join(args, " "))
}
diff --git a/vendor/golang.org/x/tools/internal/gocommand/vendor.go b/vendor/golang.org/x/tools/internal/gocommand/vendor.go
index 1cd8d8473e9..5e75bd6d8fa 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/vendor.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/vendor.go
@@ -12,6 +12,7 @@ import (
"path/filepath"
"regexp"
"strings"
+ "time"
"golang.org/x/mod/semver"
)
@@ -19,11 +20,15 @@ import (
// ModuleJSON holds information about a module.
type ModuleJSON struct {
Path string // module path
+ Version string // module version
+ Versions []string // available module versions (with -versions)
Replace *ModuleJSON // replaced by this module
+ Time *time.Time // time version was created
+ Update *ModuleJSON // available update, if any (with -u)
Main bool // is this the main module?
Indirect bool // is this module only an indirect dependency of main module?
Dir string // directory holding files for this module, if any
- GoMod string // path to go.mod file for this module, if any
+ GoMod string // path to go.mod file used when loading this module, if any
GoVersion string // go version used in module
}
diff --git a/vendor/golang.org/x/tools/internal/gocommand/version.go b/vendor/golang.org/x/tools/internal/gocommand/version.go
index 60d45ac0e64..71304368020 100644
--- a/vendor/golang.org/x/tools/internal/gocommand/version.go
+++ b/vendor/golang.org/x/tools/internal/gocommand/version.go
@@ -14,11 +14,22 @@ import (
// It returns the X in Go 1.X.
func GoVersion(ctx context.Context, inv Invocation, r *Runner) (int, error) {
inv.Verb = "list"
- inv.Args = []string{"-e", "-f", `{{context.ReleaseTags}}`}
+ inv.Args = []string{"-e", "-f", `{{context.ReleaseTags}}`, `--`, `unsafe`}
inv.Env = append(append([]string{}, inv.Env...), "GO111MODULE=off")
- // Unset any unneeded flags.
+ // Unset any unneeded flags, and remove them from BuildFlags, if they're
+ // present.
inv.ModFile = ""
inv.ModFlag = ""
+ var buildFlags []string
+ for _, flag := range inv.BuildFlags {
+ // Flags can be prefixed by one or two dashes.
+ f := strings.TrimPrefix(strings.TrimPrefix(flag, "-"), "-")
+ if strings.HasPrefix(f, "mod=") || strings.HasPrefix(f, "modfile=") {
+ continue
+ }
+ buildFlags = append(buildFlags, flag)
+ }
+ inv.BuildFlags = buildFlags
stdoutBytes, err := r.Run(ctx, inv)
if err != nil {
return 0, err
diff --git a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
index 1335a5eed8a..9702094c59e 100644
--- a/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
+++ b/vendor/golang.org/x/tools/internal/packagesinternal/packages.go
@@ -1,3 +1,7 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
// Package packagesinternal exposes internal-only fields from go/packages.
package packagesinternal
@@ -6,6 +10,13 @@ import (
)
var GetForTest = func(p interface{}) string { return "" }
+var GetDepsErrors = func(p interface{}) []*PackageError { return nil }
+
+type PackageError struct {
+ ImportStack []string // shortest path from package named on command line to this one
+ Pos string // position of error (if present, file:line:col)
+ Err string // the error itself
+}
var GetGoCmdRunner = func(config interface{}) *gocommand.Runner { return nil }
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
new file mode 100644
index 00000000000..fa2834e2ab8
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/errorcode.go
@@ -0,0 +1,1368 @@
+// Copyright 2020 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package typesinternal
+
+//go:generate stringer -type=ErrorCode
+
+type ErrorCode int
+
+// This file defines the error codes that can be produced during type-checking.
+// Collectively, these codes provide an identifier that may be used to
+// implement special handling for certain types of errors.
+//
+// Error codes should be fine-grained enough that the exact nature of the error
+// can be easily determined, but coarse enough that they are not an
+// implementation detail of the type checking algorithm. As a rule-of-thumb,
+// errors should be considered equivalent if there is a theoretical refactoring
+// of the type checker in which they are emitted in exactly one place. For
+// example, the type checker emits different error messages for "too many
+// arguments" and "too few arguments", but one can imagine an alternative type
+// checker where this check instead just emits a single "wrong number of
+// arguments", so these errors should have the same code.
+//
+// Error code names should be as brief as possible while retaining accuracy and
+// distinctiveness. In most cases names should start with an adjective
+// describing the nature of the error (e.g. "invalid", "unused", "misplaced"),
+// and end with a noun identifying the relevant language object. For example,
+// "DuplicateDecl" or "InvalidSliceExpr". For brevity, naming follows the
+// convention that "bad" implies a problem with syntax, and "invalid" implies a
+// problem with types.
+
+const (
+ _ ErrorCode = iota
+
+ // Test is reserved for errors that only apply while in self-test mode.
+ Test
+
+ /* package names */
+
+ // BlankPkgName occurs when a package name is the blank identifier "_".
+ //
+ // Per the spec:
+ // "The PackageName must not be the blank identifier."
+ BlankPkgName
+
+ // MismatchedPkgName occurs when a file's package name doesn't match the
+ // package name already established by other files.
+ MismatchedPkgName
+
+ // InvalidPkgUse occurs when a package identifier is used outside of a
+ // selector expression.
+ //
+ // Example:
+ // import "fmt"
+ //
+ // var _ = fmt
+ InvalidPkgUse
+
+ /* imports */
+
+ // BadImportPath occurs when an import path is not valid.
+ BadImportPath
+
+ // BrokenImport occurs when importing a package fails.
+ //
+ // Example:
+ // import "amissingpackage"
+ BrokenImport
+
+ // ImportCRenamed occurs when the special import "C" is renamed. "C" is a
+ // pseudo-package, and must not be renamed.
+ //
+ // Example:
+ // import _ "C"
+ ImportCRenamed
+
+ // UnusedImport occurs when an import is unused.
+ //
+ // Example:
+ // import "fmt"
+ //
+ // func main() {}
+ UnusedImport
+
+ /* initialization */
+
+ // InvalidInitCycle occurs when an invalid cycle is detected within the
+ // initialization graph.
+ //
+ // Example:
+ // var x int = f()
+ //
+ // func f() int { return x }
+ InvalidInitCycle
+
+ /* decls */
+
+ // DuplicateDecl occurs when an identifier is declared multiple times.
+ //
+ // Example:
+ // var x = 1
+ // var x = 2
+ DuplicateDecl
+
+ // InvalidDeclCycle occurs when a declaration cycle is not valid.
+ //
+ // Example:
+ // import "unsafe"
+ //
+ // type T struct {
+ // a [n]int
+ // }
+ //
+ // var n = unsafe.Sizeof(T{})
+ InvalidDeclCycle
+
+ // InvalidTypeCycle occurs when a cycle in type definitions results in a
+ // type that is not well-defined.
+ //
+ // Example:
+ // import "unsafe"
+ //
+ // type T [unsafe.Sizeof(T{})]int
+ InvalidTypeCycle
+
+ /* decls > const */
+
+ // InvalidConstInit occurs when a const declaration has a non-constant
+ // initializer.
+ //
+ // Example:
+ // var x int
+ // const _ = x
+ InvalidConstInit
+
+ // InvalidConstVal occurs when a const value cannot be converted to its
+ // target type.
+ //
+ // TODO(findleyr): this error code and example are not very clear. Consider
+ // removing it.
+ //
+ // Example:
+ // const _ = 1 << "hello"
+ InvalidConstVal
+
+ // InvalidConstType occurs when the underlying type in a const declaration
+ // is not a valid constant type.
+ //
+ // Example:
+ // const c *int = 4
+ InvalidConstType
+
+ /* decls > var (+ other variable assignment codes) */
+
+ // UntypedNil occurs when the predeclared (untyped) value nil is used to
+ // initialize a variable declared without an explicit type.
+ //
+ // Example:
+ // var x = nil
+ UntypedNil
+
+ // WrongAssignCount occurs when the number of values on the right-hand side
+ // of an assignment or or initialization expression does not match the number
+ // of variables on the left-hand side.
+ //
+ // Example:
+ // var x = 1, 2
+ WrongAssignCount
+
+ // UnassignableOperand occurs when the left-hand side of an assignment is
+ // not assignable.
+ //
+ // Example:
+ // func f() {
+ // const c = 1
+ // c = 2
+ // }
+ UnassignableOperand
+
+ // NoNewVar occurs when a short variable declaration (':=') does not declare
+ // new variables.
+ //
+ // Example:
+ // func f() {
+ // x := 1
+ // x := 2
+ // }
+ NoNewVar
+
+ // MultiValAssignOp occurs when an assignment operation (+=, *=, etc) does
+ // not have single-valued left-hand or right-hand side.
+ //
+ // Per the spec:
+ // "In assignment operations, both the left- and right-hand expression lists
+ // must contain exactly one single-valued expression"
+ //
+ // Example:
+ // func f() int {
+ // x, y := 1, 2
+ // x, y += 1
+ // return x + y
+ // }
+ MultiValAssignOp
+
+ // InvalidIfaceAssign occurs when a value of type T is used as an
+ // interface, but T does not implement a method of the expected interface.
+ //
+ // Example:
+ // type I interface {
+ // f()
+ // }
+ //
+ // type T int
+ //
+ // var x I = T(1)
+ InvalidIfaceAssign
+
+ // InvalidChanAssign occurs when a chan assignment is invalid.
+ //
+ // Per the spec, a value x is assignable to a channel type T if:
+ // "x is a bidirectional channel value, T is a channel type, x's type V and
+ // T have identical element types, and at least one of V or T is not a
+ // defined type."
+ //
+ // Example:
+ // type T1 chan int
+ // type T2 chan int
+ //
+ // var x T1
+ // // Invalid assignment because both types are named
+ // var _ T2 = x
+ InvalidChanAssign
+
+ // IncompatibleAssign occurs when the type of the right-hand side expression
+ // in an assignment cannot be assigned to the type of the variable being
+ // assigned.
+ //
+ // Example:
+ // var x []int
+ // var _ int = x
+ IncompatibleAssign
+
+ // UnaddressableFieldAssign occurs when trying to assign to a struct field
+ // in a map value.
+ //
+ // Example:
+ // func f() {
+ // m := make(map[string]struct{i int})
+ // m["foo"].i = 42
+ // }
+ UnaddressableFieldAssign
+
+ /* decls > type (+ other type expression codes) */
+
+ // NotAType occurs when the identifier used as the underlying type in a type
+ // declaration or the right-hand side of a type alias does not denote a type.
+ //
+ // Example:
+ // var S = 2
+ //
+ // type T S
+ NotAType
+
+ // InvalidArrayLen occurs when an array length is not a constant value.
+ //
+ // Example:
+ // var n = 3
+ // var _ = [n]int{}
+ InvalidArrayLen
+
+ // BlankIfaceMethod occurs when a method name is '_'.
+ //
+ // Per the spec:
+ // "The name of each explicitly specified method must be unique and not
+ // blank."
+ //
+ // Example:
+ // type T interface {
+ // _(int)
+ // }
+ BlankIfaceMethod
+
+ // IncomparableMapKey occurs when a map key type does not support the == and
+ // != operators.
+ //
+ // Per the spec:
+ // "The comparison operators == and != must be fully defined for operands of
+ // the key type; thus the key type must not be a function, map, or slice."
+ //
+ // Example:
+ // var x map[T]int
+ //
+ // type T []int
+ IncomparableMapKey
+
+ // InvalidIfaceEmbed occurs when a non-interface type is embedded in an
+ // interface.
+ //
+ // Example:
+ // type T struct {}
+ //
+ // func (T) m()
+ //
+ // type I interface {
+ // T
+ // }
+ InvalidIfaceEmbed
+
+ // InvalidPtrEmbed occurs when an embedded field is of the pointer form *T,
+ // and T itself is itself a pointer, an unsafe.Pointer, or an interface.
+ //
+ // Per the spec:
+ // "An embedded field must be specified as a type name T or as a pointer to
+ // a non-interface type name *T, and T itself may not be a pointer type."
+ //
+ // Example:
+ // type T *int
+ //
+ // type S struct {
+ // *T
+ // }
+ InvalidPtrEmbed
+
+ /* decls > func and method */
+
+ // BadRecv occurs when a method declaration does not have exactly one
+ // receiver parameter.
+ //
+ // Example:
+ // func () _() {}
+ BadRecv
+
+ // InvalidRecv occurs when a receiver type expression is not of the form T
+ // or *T, or T is a pointer type.
+ //
+ // Example:
+ // type T struct {}
+ //
+ // func (**T) m() {}
+ InvalidRecv
+
+ // DuplicateFieldAndMethod occurs when an identifier appears as both a field
+ // and method name.
+ //
+ // Example:
+ // type T struct {
+ // m int
+ // }
+ //
+ // func (T) m() {}
+ DuplicateFieldAndMethod
+
+ // DuplicateMethod occurs when two methods on the same receiver type have
+ // the same name.
+ //
+ // Example:
+ // type T struct {}
+ // func (T) m() {}
+ // func (T) m(i int) int { return i }
+ DuplicateMethod
+
+ /* decls > special */
+
+ // InvalidBlank occurs when a blank identifier is used as a value or type.
+ //
+ // Per the spec:
+ // "The blank identifier may appear as an operand only on the left-hand side
+ // of an assignment."
+ //
+ // Example:
+ // var x = _
+ InvalidBlank
+
+ // InvalidIota occurs when the predeclared identifier iota is used outside
+ // of a constant declaration.
+ //
+ // Example:
+ // var x = iota
+ InvalidIota
+
+ // MissingInitBody occurs when an init function is missing its body.
+ //
+ // Example:
+ // func init()
+ MissingInitBody
+
+ // InvalidInitSig occurs when an init function declares parameters or
+ // results.
+ //
+ // Example:
+ // func init() int { return 1 }
+ InvalidInitSig
+
+ // InvalidInitDecl occurs when init is declared as anything other than a
+ // function.
+ //
+ // Example:
+ // var init = 1
+ InvalidInitDecl
+
+ // InvalidMainDecl occurs when main is declared as anything other than a
+ // function, in a main package.
+ InvalidMainDecl
+
+ /* exprs */
+
+ // TooManyValues occurs when a function returns too many values for the
+ // expression context in which it is used.
+ //
+ // Example:
+ // func ReturnTwo() (int, int) {
+ // return 1, 2
+ // }
+ //
+ // var x = ReturnTwo()
+ TooManyValues
+
+ // NotAnExpr occurs when a type expression is used where a value expression
+ // is expected.
+ //
+ // Example:
+ // type T struct {}
+ //
+ // func f() {
+ // T
+ // }
+ NotAnExpr
+
+ /* exprs > const */
+
+ // TruncatedFloat occurs when a float constant is truncated to an integer
+ // value.
+ //
+ // Example:
+ // var _ int = 98.6
+ TruncatedFloat
+
+ // NumericOverflow occurs when a numeric constant overflows its target type.
+ //
+ // Example:
+ // var x int8 = 1000
+ NumericOverflow
+
+ /* exprs > operation */
+
+ // UndefinedOp occurs when an operator is not defined for the type(s) used
+ // in an operation.
+ //
+ // Example:
+ // var c = "a" - "b"
+ UndefinedOp
+
+ // MismatchedTypes occurs when operand types are incompatible in a binary
+ // operation.
+ //
+ // Example:
+ // var a = "hello"
+ // var b = 1
+ // var c = a - b
+ MismatchedTypes
+
+ // DivByZero occurs when a division operation is provable at compile
+ // time to be a division by zero.
+ //
+ // Example:
+ // const divisor = 0
+ // var x int = 1/divisor
+ DivByZero
+
+ // NonNumericIncDec occurs when an increment or decrement operator is
+ // applied to a non-numeric value.
+ //
+ // Example:
+ // func f() {
+ // var c = "c"
+ // c++
+ // }
+ NonNumericIncDec
+
+ /* exprs > ptr */
+
+ // UnaddressableOperand occurs when the & operator is applied to an
+ // unaddressable expression.
+ //
+ // Example:
+ // var x = &1
+ UnaddressableOperand
+
+ // InvalidIndirection occurs when a non-pointer value is indirected via the
+ // '*' operator.
+ //
+ // Example:
+ // var x int
+ // var y = *x
+ InvalidIndirection
+
+ /* exprs > [] */
+
+ // NonIndexableOperand occurs when an index operation is applied to a value
+ // that cannot be indexed.
+ //
+ // Example:
+ // var x = 1
+ // var y = x[1]
+ NonIndexableOperand
+
+ // InvalidIndex occurs when an index argument is not of integer type,
+ // negative, or out-of-bounds.
+ //
+ // Example:
+ // var s = [...]int{1,2,3}
+ // var x = s[5]
+ //
+ // Example:
+ // var s = []int{1,2,3}
+ // var _ = s[-1]
+ //
+ // Example:
+ // var s = []int{1,2,3}
+ // var i string
+ // var _ = s[i]
+ InvalidIndex
+
+ // SwappedSliceIndices occurs when constant indices in a slice expression
+ // are decreasing in value.
+ //
+ // Example:
+ // var _ = []int{1,2,3}[2:1]
+ SwappedSliceIndices
+
+ /* operators > slice */
+
+ // NonSliceableOperand occurs when a slice operation is applied to a value
+ // whose type is not sliceable, or is unaddressable.
+ //
+ // Example:
+ // var x = [...]int{1, 2, 3}[:1]
+ //
+ // Example:
+ // var x = 1
+ // var y = 1[:1]
+ NonSliceableOperand
+
+ // InvalidSliceExpr occurs when a three-index slice expression (a[x:y:z]) is
+ // applied to a string.
+ //
+ // Example:
+ // var s = "hello"
+ // var x = s[1:2:3]
+ InvalidSliceExpr
+
+ /* exprs > shift */
+
+ // InvalidShiftCount occurs when the right-hand side of a shift operation is
+ // either non-integer, negative, or too large.
+ //
+ // Example:
+ // var (
+ // x string
+ // y int = 1 << x
+ // )
+ InvalidShiftCount
+
+ // InvalidShiftOperand occurs when the shifted operand is not an integer.
+ //
+ // Example:
+ // var s = "hello"
+ // var x = s << 2
+ InvalidShiftOperand
+
+ /* exprs > chan */
+
+ // InvalidReceive occurs when there is a channel receive from a value that
+ // is either not a channel, or is a send-only channel.
+ //
+ // Example:
+ // func f() {
+ // var x = 1
+ // <-x
+ // }
+ InvalidReceive
+
+ // InvalidSend occurs when there is a channel send to a value that is not a
+ // channel, or is a receive-only channel.
+ //
+ // Example:
+ // func f() {
+ // var x = 1
+ // x <- "hello!"
+ // }
+ InvalidSend
+
+ /* exprs > literal */
+
+ // DuplicateLitKey occurs when an index is duplicated in a slice, array, or
+ // map literal.
+ //
+ // Example:
+ // var _ = []int{0:1, 0:2}
+ //
+ // Example:
+ // var _ = map[string]int{"a": 1, "a": 2}
+ DuplicateLitKey
+
+ // MissingLitKey occurs when a map literal is missing a key expression.
+ //
+ // Example:
+ // var _ = map[string]int{1}
+ MissingLitKey
+
+ // InvalidLitIndex occurs when the key in a key-value element of a slice or
+ // array literal is not an integer constant.
+ //
+ // Example:
+ // var i = 0
+ // var x = []string{i: "world"}
+ InvalidLitIndex
+
+ // OversizeArrayLit occurs when an array literal exceeds its length.
+ //
+ // Example:
+ // var _ = [2]int{1,2,3}
+ OversizeArrayLit
+
+ // MixedStructLit occurs when a struct literal contains a mix of positional
+ // and named elements.
+ //
+ // Example:
+ // var _ = struct{i, j int}{i: 1, 2}
+ MixedStructLit
+
+ // InvalidStructLit occurs when a positional struct literal has an incorrect
+ // number of values.
+ //
+ // Example:
+ // var _ = struct{i, j int}{1,2,3}
+ InvalidStructLit
+
+ // MissingLitField occurs when a struct literal refers to a field that does
+ // not exist on the struct type.
+ //
+ // Example:
+ // var _ = struct{i int}{j: 2}
+ MissingLitField
+
+ // DuplicateLitField occurs when a struct literal contains duplicated
+ // fields.
+ //
+ // Example:
+ // var _ = struct{i int}{i: 1, i: 2}
+ DuplicateLitField
+
+ // UnexportedLitField occurs when a positional struct literal implicitly
+ // assigns an unexported field of an imported type.
+ UnexportedLitField
+
+ // InvalidLitField occurs when a field name is not a valid identifier.
+ //
+ // Example:
+ // var _ = struct{i int}{1: 1}
+ InvalidLitField
+
+ // UntypedLit occurs when a composite literal omits a required type
+ // identifier.
+ //
+ // Example:
+ // type outer struct{
+ // inner struct { i int }
+ // }
+ //
+ // var _ = outer{inner: {1}}
+ UntypedLit
+
+ // InvalidLit occurs when a composite literal expression does not match its
+ // type.
+ //
+ // Example:
+ // type P *struct{
+ // x int
+ // }
+ // var _ = P {}
+ InvalidLit
+
+ /* exprs > selector */
+
+ // AmbiguousSelector occurs when a selector is ambiguous.
+ //
+ // Example:
+ // type E1 struct { i int }
+ // type E2 struct { i int }
+ // type T struct { E1; E2 }
+ //
+ // var x T
+ // var _ = x.i
+ AmbiguousSelector
+
+ // UndeclaredImportedName occurs when a package-qualified identifier is
+ // undeclared by the imported package.
+ //
+ // Example:
+ // import "go/types"
+ //
+ // var _ = types.NotAnActualIdentifier
+ UndeclaredImportedName
+
+ // UnexportedName occurs when a selector refers to an unexported identifier
+ // of an imported package.
+ //
+ // Example:
+ // import "reflect"
+ //
+ // type _ reflect.flag
+ UnexportedName
+
+ // UndeclaredName occurs when an identifier is not declared in the current
+ // scope.
+ //
+ // Example:
+ // var x T
+ UndeclaredName
+
+ // MissingFieldOrMethod occurs when a selector references a field or method
+ // that does not exist.
+ //
+ // Example:
+ // type T struct {}
+ //
+ // var x = T{}.f
+ MissingFieldOrMethod
+
+ /* exprs > ... */
+
+ // BadDotDotDotSyntax occurs when a "..." occurs in a context where it is
+ // not valid.
+ //
+ // Example:
+ // var _ = map[int][...]int{0: {}}
+ BadDotDotDotSyntax
+
+ // NonVariadicDotDotDot occurs when a "..." is used on the final argument to
+ // a non-variadic function.
+ //
+ // Example:
+ // func printArgs(s []string) {
+ // for _, a := range s {
+ // println(a)
+ // }
+ // }
+ //
+ // func f() {
+ // s := []string{"a", "b", "c"}
+ // printArgs(s...)
+ // }
+ NonVariadicDotDotDot
+
+ // MisplacedDotDotDot occurs when a "..." is used somewhere other than the
+ // final argument to a function call.
+ //
+ // Example:
+ // func printArgs(args ...int) {
+ // for _, a := range args {
+ // println(a)
+ // }
+ // }
+ //
+ // func f() {
+ // a := []int{1,2,3}
+ // printArgs(0, a...)
+ // }
+ MisplacedDotDotDot
+
+ // InvalidDotDotDotOperand occurs when a "..." operator is applied to a
+ // single-valued operand.
+ //
+ // Example:
+ // func printArgs(args ...int) {
+ // for _, a := range args {
+ // println(a)
+ // }
+ // }
+ //
+ // func f() {
+ // a := 1
+ // printArgs(a...)
+ // }
+ //
+ // Example:
+ // func args() (int, int) {
+ // return 1, 2
+ // }
+ //
+ // func printArgs(args ...int) {
+ // for _, a := range args {
+ // println(a)
+ // }
+ // }
+ //
+ // func g() {
+ // printArgs(args()...)
+ // }
+ InvalidDotDotDotOperand
+
+ // InvalidDotDotDot occurs when a "..." is used in a non-variadic built-in
+ // function.
+ //
+ // Example:
+ // var s = []int{1, 2, 3}
+ // var l = len(s...)
+ InvalidDotDotDot
+
+ /* exprs > built-in */
+
+ // UncalledBuiltin occurs when a built-in function is used as a
+ // function-valued expression, instead of being called.
+ //
+ // Per the spec:
+ // "The built-in functions do not have standard Go types, so they can only
+ // appear in call expressions; they cannot be used as function values."
+ //
+ // Example:
+ // var _ = copy
+ UncalledBuiltin
+
+ // InvalidAppend occurs when append is called with a first argument that is
+ // not a slice.
+ //
+ // Example:
+ // var _ = append(1, 2)
+ InvalidAppend
+
+ // InvalidCap occurs when an argument to the cap built-in function is not of
+ // supported type.
+ //
+ // See https://golang.org/ref/spec#Lengthand_capacity for information on
+ // which underlying types are supported as arguments to cap and len.
+ //
+ // Example:
+ // var s = 2
+ // var x = cap(s)
+ InvalidCap
+
+ // InvalidClose occurs when close(...) is called with an argument that is
+ // not of channel type, or that is a receive-only channel.
+ //
+ // Example:
+ // func f() {
+ // var x int
+ // close(x)
+ // }
+ InvalidClose
+
+ // InvalidCopy occurs when the arguments are not of slice type or do not
+ // have compatible type.
+ //
+ // See https://golang.org/ref/spec#Appendingand_copying_slices for more
+ // information on the type requirements for the copy built-in.
+ //
+ // Example:
+ // func f() {
+ // var x []int
+ // y := []int64{1,2,3}
+ // copy(x, y)
+ // }
+ InvalidCopy
+
+ // InvalidComplex occurs when the complex built-in function is called with
+ // arguments with incompatible types.
+ //
+ // Example:
+ // var _ = complex(float32(1), float64(2))
+ InvalidComplex
+
+ // InvalidDelete occurs when the delete built-in function is called with a
+ // first argument that is not a map.
+ //
+ // Example:
+ // func f() {
+ // m := "hello"
+ // delete(m, "e")
+ // }
+ InvalidDelete
+
+ // InvalidImag occurs when the imag built-in function is called with an
+ // argument that does not have complex type.
+ //
+ // Example:
+ // var _ = imag(int(1))
+ InvalidImag
+
+ // InvalidLen occurs when an argument to the len built-in function is not of
+ // supported type.
+ //
+ // See https://golang.org/ref/spec#Lengthand_capacity for information on
+ // which underlying types are supported as arguments to cap and len.
+ //
+ // Example:
+ // var s = 2
+ // var x = len(s)
+ InvalidLen
+
+ // SwappedMakeArgs occurs when make is called with three arguments, and its
+ // length argument is larger than its capacity argument.
+ //
+ // Example:
+ // var x = make([]int, 3, 2)
+ SwappedMakeArgs
+
+ // InvalidMake occurs when make is called with an unsupported type argument.
+ //
+ // See https://golang.org/ref/spec#Makingslices_maps_and_channels for
+ // information on the types that may be created using make.
+ //
+ // Example:
+ // var x = make(int)
+ InvalidMake
+
+ // InvalidReal occurs when the real built-in function is called with an
+ // argument that does not have complex type.
+ //
+ // Example:
+ // var _ = real(int(1))
+ InvalidReal
+
+ /* exprs > assertion */
+
+ // InvalidAssert occurs when a type assertion is applied to a
+ // value that is not of interface type.
+ //
+ // Example:
+ // var x = 1
+ // var _ = x.(float64)
+ InvalidAssert
+
+ // ImpossibleAssert occurs for a type assertion x.(T) when the value x of
+ // interface cannot have dynamic type T, due to a missing or mismatching
+ // method on T.
+ //
+ // Example:
+ // type T int
+ //
+ // func (t *T) m() int { return int(*t) }
+ //
+ // type I interface { m() int }
+ //
+ // var x I
+ // var _ = x.(T)
+ ImpossibleAssert
+
+ /* exprs > conversion */
+
+ // InvalidConversion occurs when the argument type cannot be converted to the
+ // target.
+ //
+ // See https://golang.org/ref/spec#Conversions for the rules of
+ // convertibility.
+ //
+ // Example:
+ // var x float64
+ // var _ = string(x)
+ InvalidConversion
+
+ // InvalidUntypedConversion occurs when an there is no valid implicit
+ // conversion from an untyped value satisfying the type constraints of the
+ // context in which it is used.
+ //
+ // Example:
+ // var _ = 1 + ""
+ InvalidUntypedConversion
+
+ /* offsetof */
+
+ // BadOffsetofSyntax occurs when unsafe.Offsetof is called with an argument
+ // that is not a selector expression.
+ //
+ // Example:
+ // import "unsafe"
+ //
+ // var x int
+ // var _ = unsafe.Offsetof(x)
+ BadOffsetofSyntax
+
+ // InvalidOffsetof occurs when unsafe.Offsetof is called with a method
+ // selector, rather than a field selector, or when the field is embedded via
+ // a pointer.
+ //
+ // Per the spec:
+ //
+ // "If f is an embedded field, it must be reachable without pointer
+ // indirections through fields of the struct. "
+ //
+ // Example:
+ // import "unsafe"
+ //
+ // type T struct { f int }
+ // type S struct { *T }
+ // var s S
+ // var _ = unsafe.Offsetof(s.f)
+ //
+ // Example:
+ // import "unsafe"
+ //
+ // type S struct{}
+ //
+ // func (S) m() {}
+ //
+ // var s S
+ // var _ = unsafe.Offsetof(s.m)
+ InvalidOffsetof
+
+ /* control flow > scope */
+
+ // UnusedExpr occurs when a side-effect free expression is used as a
+ // statement. Such a statement has no effect.
+ //
+ // Example:
+ // func f(i int) {
+ // i*i
+ // }
+ UnusedExpr
+
+ // UnusedVar occurs when a variable is declared but unused.
+ //
+ // Example:
+ // func f() {
+ // x := 1
+ // }
+ UnusedVar
+
+ // MissingReturn occurs when a function with results is missing a return
+ // statement.
+ //
+ // Example:
+ // func f() int {}
+ MissingReturn
+
+ // WrongResultCount occurs when a return statement returns an incorrect
+ // number of values.
+ //
+ // Example:
+ // func ReturnOne() int {
+ // return 1, 2
+ // }
+ WrongResultCount
+
+ // OutOfScopeResult occurs when the name of a value implicitly returned by
+ // an empty return statement is shadowed in a nested scope.
+ //
+ // Example:
+ // func factor(n int) (i int) {
+ // for i := 2; i < n; i++ {
+ // if n%i == 0 {
+ // return
+ // }
+ // }
+ // return 0
+ // }
+ OutOfScopeResult
+
+ /* control flow > if */
+
+ // InvalidCond occurs when an if condition is not a boolean expression.
+ //
+ // Example:
+ // func checkReturn(i int) {
+ // if i {
+ // panic("non-zero return")
+ // }
+ // }
+ InvalidCond
+
+ /* control flow > for */
+
+ // InvalidPostDecl occurs when there is a declaration in a for-loop post
+ // statement.
+ //
+ // Example:
+ // func f() {
+ // for i := 0; i < 10; j := 0 {}
+ // }
+ InvalidPostDecl
+
+ // InvalidChanRange occurs when a send-only channel used in a range
+ // expression.
+ //
+ // Example:
+ // func sum(c chan<- int) {
+ // s := 0
+ // for i := range c {
+ // s += i
+ // }
+ // }
+ InvalidChanRange
+
+ // InvalidIterVar occurs when two iteration variables are used while ranging
+ // over a channel.
+ //
+ // Example:
+ // func f(c chan int) {
+ // for k, v := range c {
+ // println(k, v)
+ // }
+ // }
+ InvalidIterVar
+
+ // InvalidRangeExpr occurs when the type of a range expression is not array,
+ // slice, string, map, or channel.
+ //
+ // Example:
+ // func f(i int) {
+ // for j := range i {
+ // println(j)
+ // }
+ // }
+ InvalidRangeExpr
+
+ /* control flow > switch */
+
+ // MisplacedBreak occurs when a break statement is not within a for, switch,
+ // or select statement of the innermost function definition.
+ //
+ // Example:
+ // func f() {
+ // break
+ // }
+ MisplacedBreak
+
+ // MisplacedContinue occurs when a continue statement is not within a for
+ // loop of the innermost function definition.
+ //
+ // Example:
+ // func sumeven(n int) int {
+ // proceed := func() {
+ // continue
+ // }
+ // sum := 0
+ // for i := 1; i <= n; i++ {
+ // if i % 2 != 0 {
+ // proceed()
+ // }
+ // sum += i
+ // }
+ // return sum
+ // }
+ MisplacedContinue
+
+ // MisplacedFallthrough occurs when a fallthrough statement is not within an
+ // expression switch.
+ //
+ // Example:
+ // func typename(i interface{}) string {
+ // switch i.(type) {
+ // case int64:
+ // fallthrough
+ // case int:
+ // return "int"
+ // }
+ // return "unsupported"
+ // }
+ MisplacedFallthrough
+
+ // DuplicateCase occurs when a type or expression switch has duplicate
+ // cases.
+ //
+ // Example:
+ // func printInt(i int) {
+ // switch i {
+ // case 1:
+ // println("one")
+ // case 1:
+ // println("One")
+ // }
+ // }
+ DuplicateCase
+
+ // DuplicateDefault occurs when a type or expression switch has multiple
+ // default clauses.
+ //
+ // Example:
+ // func printInt(i int) {
+ // switch i {
+ // case 1:
+ // println("one")
+ // default:
+ // println("One")
+ // default:
+ // println("1")
+ // }
+ // }
+ DuplicateDefault
+
+ // BadTypeKeyword occurs when a .(type) expression is used anywhere other
+ // than a type switch.
+ //
+ // Example:
+ // type I interface {
+ // m()
+ // }
+ // var t I
+ // var _ = t.(type)
+ BadTypeKeyword
+
+ // InvalidTypeSwitch occurs when .(type) is used on an expression that is
+ // not of interface type.
+ //
+ // Example:
+ // func f(i int) {
+ // switch x := i.(type) {}
+ // }
+ InvalidTypeSwitch
+
+ // InvalidExprSwitch occurs when a switch expression is not comparable.
+ //
+ // Example:
+ // func _() {
+ // var a struct{ _ func() }
+ // switch a /* ERROR cannot switch on a */ {
+ // }
+ // }
+ InvalidExprSwitch
+
+ /* control flow > select */
+
+ // InvalidSelectCase occurs when a select case is not a channel send or
+ // receive.
+ //
+ // Example:
+ // func checkChan(c <-chan int) bool {
+ // select {
+ // case c:
+ // return true
+ // default:
+ // return false
+ // }
+ // }
+ InvalidSelectCase
+
+ /* control flow > labels and jumps */
+
+ // UndeclaredLabel occurs when an undeclared label is jumped to.
+ //
+ // Example:
+ // func f() {
+ // goto L
+ // }
+ UndeclaredLabel
+
+ // DuplicateLabel occurs when a label is declared more than once.
+ //
+ // Example:
+ // func f() int {
+ // L:
+ // L:
+ // return 1
+ // }
+ DuplicateLabel
+
+ // MisplacedLabel occurs when a break or continue label is not on a for,
+ // switch, or select statement.
+ //
+ // Example:
+ // func f() {
+ // L:
+ // a := []int{1,2,3}
+ // for _, e := range a {
+ // if e > 10 {
+ // break L
+ // }
+ // println(a)
+ // }
+ // }
+ MisplacedLabel
+
+ // UnusedLabel occurs when a label is declared but not used.
+ //
+ // Example:
+ // func f() {
+ // L:
+ // }
+ UnusedLabel
+
+ // JumpOverDecl occurs when a label jumps over a variable declaration.
+ //
+ // Example:
+ // func f() int {
+ // goto L
+ // x := 2
+ // L:
+ // x++
+ // return x
+ // }
+ JumpOverDecl
+
+ // JumpIntoBlock occurs when a forward jump goes to a label inside a nested
+ // block.
+ //
+ // Example:
+ // func f(x int) {
+ // goto L
+ // if x > 0 {
+ // L:
+ // print("inside block")
+ // }
+ // }
+ JumpIntoBlock
+
+ /* control flow > calls */
+
+ // InvalidMethodExpr occurs when a pointer method is called but the argument
+ // is not addressable.
+ //
+ // Example:
+ // type T struct {}
+ //
+ // func (*T) m() int { return 1 }
+ //
+ // var _ = T.m(T{})
+ InvalidMethodExpr
+
+ // WrongArgCount occurs when too few or too many arguments are passed by a
+ // function call.
+ //
+ // Example:
+ // func f(i int) {}
+ // var x = f()
+ WrongArgCount
+
+ // InvalidCall occurs when an expression is called that is not of function
+ // type.
+ //
+ // Example:
+ // var x = "x"
+ // var y = x()
+ InvalidCall
+
+ /* control flow > suspended */
+
+ // UnusedResults occurs when a restricted expression-only built-in function
+ // is suspended via go or defer. Such a suspension discards the results of
+ // these side-effect free built-in functions, and therefore is ineffectual.
+ //
+ // Example:
+ // func f(a []int) int {
+ // defer len(a)
+ // return i
+ // }
+ UnusedResults
+
+ // InvalidDefer occurs when a deferred expression is not a function call,
+ // for example if the expression is a type conversion.
+ //
+ // Example:
+ // func f(i int) int {
+ // defer int32(i)
+ // return i
+ // }
+ InvalidDefer
+
+ // InvalidGo occurs when a go expression is not a function call, for example
+ // if the expression is a type conversion.
+ //
+ // Example:
+ // func f(i int) int {
+ // go int32(i)
+ // return i
+ // }
+ InvalidGo
+)
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go b/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go
new file mode 100644
index 00000000000..3e5842a5f0f
--- /dev/null
+++ b/vendor/golang.org/x/tools/internal/typesinternal/errorcode_string.go
@@ -0,0 +1,153 @@
+// Code generated by "stringer -type=ErrorCode"; DO NOT EDIT.
+
+package typesinternal
+
+import "strconv"
+
+func _() {
+ // An "invalid array index" compiler error signifies that the constant values have changed.
+ // Re-run the stringer command to generate them again.
+ var x [1]struct{}
+ _ = x[Test-1]
+ _ = x[BlankPkgName-2]
+ _ = x[MismatchedPkgName-3]
+ _ = x[InvalidPkgUse-4]
+ _ = x[BadImportPath-5]
+ _ = x[BrokenImport-6]
+ _ = x[ImportCRenamed-7]
+ _ = x[UnusedImport-8]
+ _ = x[InvalidInitCycle-9]
+ _ = x[DuplicateDecl-10]
+ _ = x[InvalidDeclCycle-11]
+ _ = x[InvalidTypeCycle-12]
+ _ = x[InvalidConstInit-13]
+ _ = x[InvalidConstVal-14]
+ _ = x[InvalidConstType-15]
+ _ = x[UntypedNil-16]
+ _ = x[WrongAssignCount-17]
+ _ = x[UnassignableOperand-18]
+ _ = x[NoNewVar-19]
+ _ = x[MultiValAssignOp-20]
+ _ = x[InvalidIfaceAssign-21]
+ _ = x[InvalidChanAssign-22]
+ _ = x[IncompatibleAssign-23]
+ _ = x[UnaddressableFieldAssign-24]
+ _ = x[NotAType-25]
+ _ = x[InvalidArrayLen-26]
+ _ = x[BlankIfaceMethod-27]
+ _ = x[IncomparableMapKey-28]
+ _ = x[InvalidIfaceEmbed-29]
+ _ = x[InvalidPtrEmbed-30]
+ _ = x[BadRecv-31]
+ _ = x[InvalidRecv-32]
+ _ = x[DuplicateFieldAndMethod-33]
+ _ = x[DuplicateMethod-34]
+ _ = x[InvalidBlank-35]
+ _ = x[InvalidIota-36]
+ _ = x[MissingInitBody-37]
+ _ = x[InvalidInitSig-38]
+ _ = x[InvalidInitDecl-39]
+ _ = x[InvalidMainDecl-40]
+ _ = x[TooManyValues-41]
+ _ = x[NotAnExpr-42]
+ _ = x[TruncatedFloat-43]
+ _ = x[NumericOverflow-44]
+ _ = x[UndefinedOp-45]
+ _ = x[MismatchedTypes-46]
+ _ = x[DivByZero-47]
+ _ = x[NonNumericIncDec-48]
+ _ = x[UnaddressableOperand-49]
+ _ = x[InvalidIndirection-50]
+ _ = x[NonIndexableOperand-51]
+ _ = x[InvalidIndex-52]
+ _ = x[SwappedSliceIndices-53]
+ _ = x[NonSliceableOperand-54]
+ _ = x[InvalidSliceExpr-55]
+ _ = x[InvalidShiftCount-56]
+ _ = x[InvalidShiftOperand-57]
+ _ = x[InvalidReceive-58]
+ _ = x[InvalidSend-59]
+ _ = x[DuplicateLitKey-60]
+ _ = x[MissingLitKey-61]
+ _ = x[InvalidLitIndex-62]
+ _ = x[OversizeArrayLit-63]
+ _ = x[MixedStructLit-64]
+ _ = x[InvalidStructLit-65]
+ _ = x[MissingLitField-66]
+ _ = x[DuplicateLitField-67]
+ _ = x[UnexportedLitField-68]
+ _ = x[InvalidLitField-69]
+ _ = x[UntypedLit-70]
+ _ = x[InvalidLit-71]
+ _ = x[AmbiguousSelector-72]
+ _ = x[UndeclaredImportedName-73]
+ _ = x[UnexportedName-74]
+ _ = x[UndeclaredName-75]
+ _ = x[MissingFieldOrMethod-76]
+ _ = x[BadDotDotDotSyntax-77]
+ _ = x[NonVariadicDotDotDot-78]
+ _ = x[MisplacedDotDotDot-79]
+ _ = x[InvalidDotDotDotOperand-80]
+ _ = x[InvalidDotDotDot-81]
+ _ = x[UncalledBuiltin-82]
+ _ = x[InvalidAppend-83]
+ _ = x[InvalidCap-84]
+ _ = x[InvalidClose-85]
+ _ = x[InvalidCopy-86]
+ _ = x[InvalidComplex-87]
+ _ = x[InvalidDelete-88]
+ _ = x[InvalidImag-89]
+ _ = x[InvalidLen-90]
+ _ = x[SwappedMakeArgs-91]
+ _ = x[InvalidMake-92]
+ _ = x[InvalidReal-93]
+ _ = x[InvalidAssert-94]
+ _ = x[ImpossibleAssert-95]
+ _ = x[InvalidConversion-96]
+ _ = x[InvalidUntypedConversion-97]
+ _ = x[BadOffsetofSyntax-98]
+ _ = x[InvalidOffsetof-99]
+ _ = x[UnusedExpr-100]
+ _ = x[UnusedVar-101]
+ _ = x[MissingReturn-102]
+ _ = x[WrongResultCount-103]
+ _ = x[OutOfScopeResult-104]
+ _ = x[InvalidCond-105]
+ _ = x[InvalidPostDecl-106]
+ _ = x[InvalidChanRange-107]
+ _ = x[InvalidIterVar-108]
+ _ = x[InvalidRangeExpr-109]
+ _ = x[MisplacedBreak-110]
+ _ = x[MisplacedContinue-111]
+ _ = x[MisplacedFallthrough-112]
+ _ = x[DuplicateCase-113]
+ _ = x[DuplicateDefault-114]
+ _ = x[BadTypeKeyword-115]
+ _ = x[InvalidTypeSwitch-116]
+ _ = x[InvalidExprSwitch-117]
+ _ = x[InvalidSelectCase-118]
+ _ = x[UndeclaredLabel-119]
+ _ = x[DuplicateLabel-120]
+ _ = x[MisplacedLabel-121]
+ _ = x[UnusedLabel-122]
+ _ = x[JumpOverDecl-123]
+ _ = x[JumpIntoBlock-124]
+ _ = x[InvalidMethodExpr-125]
+ _ = x[WrongArgCount-126]
+ _ = x[InvalidCall-127]
+ _ = x[UnusedResults-128]
+ _ = x[InvalidDefer-129]
+ _ = x[InvalidGo-130]
+}
+
+const _ErrorCode_name = "TestBlankPkgNameMismatchedPkgNameInvalidPkgUseBadImportPathBrokenImportImportCRenamedUnusedImportInvalidInitCycleDuplicateDeclInvalidDeclCycleInvalidTypeCycleInvalidConstInitInvalidConstValInvalidConstTypeUntypedNilWrongAssignCountUnassignableOperandNoNewVarMultiValAssignOpInvalidIfaceAssignInvalidChanAssignIncompatibleAssignUnaddressableFieldAssignNotATypeInvalidArrayLenBlankIfaceMethodIncomparableMapKeyInvalidIfaceEmbedInvalidPtrEmbedBadRecvInvalidRecvDuplicateFieldAndMethodDuplicateMethodInvalidBlankInvalidIotaMissingInitBodyInvalidInitSigInvalidInitDeclInvalidMainDeclTooManyValuesNotAnExprTruncatedFloatNumericOverflowUndefinedOpMismatchedTypesDivByZeroNonNumericIncDecUnaddressableOperandInvalidIndirectionNonIndexableOperandInvalidIndexSwappedSliceIndicesNonSliceableOperandInvalidSliceExprInvalidShiftCountInvalidShiftOperandInvalidReceiveInvalidSendDuplicateLitKeyMissingLitKeyInvalidLitIndexOversizeArrayLitMixedStructLitInvalidStructLitMissingLitFieldDuplicateLitFieldUnexportedLitFieldInvalidLitFieldUntypedLitInvalidLitAmbiguousSelectorUndeclaredImportedNameUnexportedNameUndeclaredNameMissingFieldOrMethodBadDotDotDotSyntaxNonVariadicDotDotDotMisplacedDotDotDotInvalidDotDotDotOperandInvalidDotDotDotUncalledBuiltinInvalidAppendInvalidCapInvalidCloseInvalidCopyInvalidComplexInvalidDeleteInvalidImagInvalidLenSwappedMakeArgsInvalidMakeInvalidRealInvalidAssertImpossibleAssertInvalidConversionInvalidUntypedConversionBadOffsetofSyntaxInvalidOffsetofUnusedExprUnusedVarMissingReturnWrongResultCountOutOfScopeResultInvalidCondInvalidPostDeclInvalidChanRangeInvalidIterVarInvalidRangeExprMisplacedBreakMisplacedContinueMisplacedFallthroughDuplicateCaseDuplicateDefaultBadTypeKeywordInvalidTypeSwitchInvalidExprSwitchInvalidSelectCaseUndeclaredLabelDuplicateLabelMisplacedLabelUnusedLabelJumpOverDeclJumpIntoBlockInvalidMethodExprWrongArgCountInvalidCallUnusedResultsInvalidDeferInvalidGo"
+
+var _ErrorCode_index = [...]uint16{0, 4, 16, 33, 46, 59, 71, 85, 97, 113, 126, 142, 158, 174, 189, 205, 215, 231, 250, 258, 274, 292, 309, 327, 351, 359, 374, 390, 408, 425, 440, 447, 458, 481, 496, 508, 519, 534, 548, 563, 578, 591, 600, 614, 629, 640, 655, 664, 680, 700, 718, 737, 749, 768, 787, 803, 820, 839, 853, 864, 879, 892, 907, 923, 937, 953, 968, 985, 1003, 1018, 1028, 1038, 1055, 1077, 1091, 1105, 1125, 1143, 1163, 1181, 1204, 1220, 1235, 1248, 1258, 1270, 1281, 1295, 1308, 1319, 1329, 1344, 1355, 1366, 1379, 1395, 1412, 1436, 1453, 1468, 1478, 1487, 1500, 1516, 1532, 1543, 1558, 1574, 1588, 1604, 1618, 1635, 1655, 1668, 1684, 1698, 1715, 1732, 1749, 1764, 1778, 1792, 1803, 1815, 1828, 1845, 1858, 1869, 1882, 1894, 1903}
+
+func (i ErrorCode) String() string {
+ i -= 1
+ if i < 0 || i >= ErrorCode(len(_ErrorCode_index)-1) {
+ return "ErrorCode(" + strconv.FormatInt(int64(i+1), 10) + ")"
+ }
+ return _ErrorCode_name[_ErrorCode_index[i]:_ErrorCode_index[i+1]]
+}
diff --git a/vendor/golang.org/x/tools/internal/typesinternal/types.go b/vendor/golang.org/x/tools/internal/typesinternal/types.go
index a5bb408e2f1..c3e1a397dbf 100644
--- a/vendor/golang.org/x/tools/internal/typesinternal/types.go
+++ b/vendor/golang.org/x/tools/internal/typesinternal/types.go
@@ -2,9 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
+// Package typesinternal provides access to internal go/types APIs that are not
+// yet exported.
package typesinternal
import (
+ "go/token"
"go/types"
"reflect"
"unsafe"
@@ -26,3 +29,17 @@ func SetUsesCgo(conf *types.Config) bool {
return true
}
+
+func ReadGo116ErrorData(terr types.Error) (ErrorCode, token.Pos, token.Pos, bool) {
+ var data [3]int
+ // By coincidence all of these fields are ints, which simplifies things.
+ v := reflect.ValueOf(terr)
+ for i, name := range []string{"go116code", "go116start", "go116end"} {
+ f := v.FieldByName(name)
+ if !f.IsValid() {
+ return 0, 0, 0, false
+ }
+ data[i] = int(f.Int())
+ }
+ return ErrorCode(data[0]), token.Pos(data[1]), token.Pos(data[2]), true
+}
diff --git a/vendor/golang.org/x/xerrors/go.mod b/vendor/golang.org/x/xerrors/go.mod
deleted file mode 100644
index 870d4f612db..00000000000
--- a/vendor/golang.org/x/xerrors/go.mod
+++ /dev/null
@@ -1,3 +0,0 @@
-module golang.org/x/xerrors
-
-go 1.11
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0a7c6f0bb4a..4b567fe9635 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -1,11 +1,14 @@
-# golang.org/x/mod v0.3.0
-## explicit
+# golang.org/x/mod v0.5.0
+## explicit; go 1.17
golang.org/x/mod/internal/lazyregexp
golang.org/x/mod/modfile
golang.org/x/mod/module
golang.org/x/mod/semver
-# golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9
-## explicit
+# golang.org/x/sys v0.0.0-20210510120138-977fb7262007
+## explicit; go 1.17
+golang.org/x/sys/execabs
+# golang.org/x/tools v0.1.5
+## explicit; go 1.17
golang.org/x/tools/go/gcexportdata
golang.org/x/tools/go/internal/gcimporter
golang.org/x/tools/go/internal/packagesdriver
@@ -18,5 +21,6 @@ golang.org/x/tools/internal/gocommand
golang.org/x/tools/internal/packagesinternal
golang.org/x/tools/internal/typesinternal
# golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1
+## explicit; go 1.11
golang.org/x/xerrors
golang.org/x/xerrors/internal