diff --git a/.bazelrc b/.bazelrc
index 0a49f682da3..3cabad0b8ca 100644
--- a/.bazelrc
+++ b/.bazelrc
@@ -11,10 +11,17 @@ common --override_module=semmle_code=%workspace%/misc/bazel/semmle_code_stub
build --repo_env=CC=clang --repo_env=CXX=clang++
build:linux --cxxopt=-std=c++20
-build:macos --cxxopt=-std=c++20 --cpu=darwin_x86_64
+# we currently cannot built the swift extractor for ARM
+build:macos --cxxopt=-std=c++20 --copt=-arch --copt=x86_64 --linkopt=-arch --linkopt=x86_64
build:windows --cxxopt=/std:c++20 --cxxopt=/Zc:preprocessor
+# this requires developer mode, but is required to have pack installer functioning
+startup --windows_enable_symlinks
+common --enable_runfiles
+
common --registry=file:///%workspace%/misc/bazel/registry
common --registry=https://bcr.bazel.build
+common --@rules_dotnet//dotnet/settings:strict_deps=false
+
try-import %workspace%/local.bazelrc
diff --git a/.bazelrc.internal b/.bazelrc.internal
index cdffa9ccdea..f7718959c9d 100644
--- a/.bazelrc.internal
+++ b/.bazelrc.internal
@@ -2,3 +2,9 @@
common --registry=file:///%workspace%/ql/misc/bazel/registry
common --registry=https://bcr.bazel.build
+
+# See bazelbuild/rules_dotnet#413: strict_deps in C# also appliy to 3rd-party deps, and when we pull
+# in (for example) the xunit package, there's no code in this at all, it just depends transitively on
+# its implementation packages without providing any code itself.
+# We either can depend on internal implementation details, or turn of strict deps.
+common --@rules_dotnet//dotnet/settings:strict_deps=false
diff --git a/.bazelversion b/.bazelversion
index a3fcc7121bb..a8a18875682 100644
--- a/.bazelversion
+++ b/.bazelversion
@@ -1 +1 @@
-7.1.0
+7.1.2
diff --git a/.gitattributes b/.gitattributes
index 3cd44090159..c58cda655f3 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -73,3 +73,10 @@ python/ql/lib/semmle/python/frameworks/data/internal/subclass-capture/*.yml ling
# auto-generated bazel lock file
ruby/extractor/cargo-bazel-lock.json linguist-generated=true
ruby/extractor/cargo-bazel-lock.json -merge
+
+# auto-generated files for the C# build
+csharp/paket.lock linguist-generated=true
+# needs eol=crlf, as `paket` touches this file and saves it als crlf
+csharp/.paket/Paket.Restore.targets linguist-generated=true eol=crlf
+csharp/paket.main.bzl linguist-generated=true
+csharp/paket.main_extension.bzl linguist-generated=true
diff --git a/.github/workflows/build-ripunzip.yml b/.github/workflows/build-ripunzip.yml
new file mode 100644
index 00000000000..aed80bac669
--- /dev/null
+++ b/.github/workflows/build-ripunzip.yml
@@ -0,0 +1,74 @@
+name: Build runzip
+
+on:
+ workflow_dispatch:
+ inputs:
+ ripunzip-version:
+ description: "what reference to checktout from google/runzip"
+ required: false
+ default: v1.2.1
+ openssl-version:
+ description: "what reference to checkout from openssl/openssl for Linux"
+ required: false
+ default: openssl-3.3.0
+
+jobs:
+ build:
+ strategy:
+ fail-fast: false
+ matrix:
+ os: [ubuntu-20.04, macos-12, windows-2019]
+ runs-on: ${{ matrix.os }}
+ steps:
+ - uses: actions/checkout@v4
+ with:
+ repository: google/ripunzip
+ ref: ${{ inputs.ripunzip-version }}
+ # we need to avoid ripunzip dynamically linking into libssl
+ # see https://github.com/sfackler/rust-openssl/issues/183
+ - if: runner.os == 'Linux'
+ name: checkout openssl
+ uses: actions/checkout@v4
+ with:
+ repository: openssl/openssl
+ path: openssl
+ ref: ${{ inputs.openssl-version }}
+ - if: runner.os == 'Linux'
+ name: build and install openssl with fPIC
+ shell: bash
+ working-directory: openssl
+ run: |
+ ./config -fPIC --prefix=$HOME/.local --openssldir=$HOME/.local/ssl
+ make -j $(nproc)
+ make install_sw -j $(nproc)
+ - if: runner.os == 'Linux'
+ name: build (linux)
+ shell: bash
+ run: |
+ env OPENSSL_LIB_DIR=$HOME/.local/lib64 OPENSSL_INCLUDE_DIR=$HOME/.local/include OPENSSL_STATIC=yes cargo build --release
+ mv target/release/ripunzip ripunzip-linux
+ - if: runner.os == 'Windows'
+ name: build (windows)
+ shell: bash
+ run: |
+ cargo build --release
+ mv target/release/ripunzip ripunzip-windows
+ - name: build (macOS)
+ if: runner.os == 'macOS'
+ shell: bash
+ run: |
+ rustup target install x86_64-apple-darwin
+ rustup target install aarch64-apple-darwin
+ cargo build --target x86_64-apple-darwin --release
+ cargo build --target aarch64-apple-darwin --release
+ lipo -create -output ripunzip-macos \
+ -arch x86_64 target/x86_64-apple-darwin/release/ripunzip \
+ -arch arm64 target/aarch64-apple-darwin/release/ripunzip
+ - uses: actions/upload-artifact@v4
+ with:
+ name: ripunzip-${{ runner.os }}
+ path: ripunzip-*
+ - name: Check built binary
+ shell: bash
+ run: |
+ ./ripunzip-* --version
diff --git a/.github/workflows/buildifier.yml b/.github/workflows/buildifier.yml
index 82444d0440a..b5d1e2244d5 100644
--- a/.github/workflows/buildifier.yml
+++ b/.github/workflows/buildifier.yml
@@ -24,5 +24,5 @@ jobs:
extra_args: >
buildifier --all-files 2>&1 ||
(
- echo -e "In order to format all bazel files, please run:\n bazel run //:buildifier"; exit 1
+ echo -e "In order to format all bazel files, please run:\n bazel run //misc/bazel:buildifier"; exit 1
)
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index d34d40dd8fa..fbe5338e4ca 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -56,7 +56,9 @@ jobs:
# uses a compiled language
- run: |
- dotnet build csharp
+ cd csharp
+ dotnet tool restore
+ dotnet build .
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@main
diff --git a/.github/workflows/csharp-qltest.yml b/.github/workflows/csharp-qltest.yml
index 557354e96de..2075e10a77a 100644
--- a/.github/workflows/csharp-qltest.yml
+++ b/.github/workflows/csharp-qltest.yml
@@ -81,10 +81,11 @@ jobs:
dotnet-version: 8.0.101
- name: Extractor unit tests
run: |
+ dotnet tool restore
dotnet test -p:RuntimeFrameworkVersion=8.0.1 extractor/Semmle.Util.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.1 extractor/Semmle.Extraction.Tests
dotnet test -p:RuntimeFrameworkVersion=8.0.1 autobuilder/Semmle.Autobuild.CSharp.Tests
- dotnet test -p:RuntimeFrameworkVersion=8.0.1 "${{ github.workspace }}/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests"
+ dotnet test -p:RuntimeFrameworkVersion=8.0.1 autobuilder/Semmle.Autobuild.Cpp.Tests
shell: bash
stubgentest:
runs-on: ubuntu-latest
diff --git a/.github/workflows/go-tests-other-os.yml b/.github/workflows/go-tests-other-os.yml
index ded53f868b7..9915b0869db 100644
--- a/.github/workflows/go-tests-other-os.yml
+++ b/.github/workflows/go-tests-other-os.yml
@@ -7,8 +7,6 @@ on:
- .github/workflows/go-tests-other-os.yml
- .github/actions/**
- codeql-workspace.yml
-env:
- GO_VERSION: '~1.22.0'
permissions:
contents: read
@@ -18,72 +16,17 @@ jobs:
name: Test MacOS
runs-on: macos-latest
steps:
- - name: Set up Go ${{ env.GO_VERSION }}
- uses: actions/setup-go@v5
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: false
- id: go
-
- name: Check out code
uses: actions/checkout@v4
-
- - name: Set up CodeQL CLI
- uses: ./.github/actions/fetch-codeql
-
- - name: Enable problem matchers in repository
- shell: bash
- run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
-
- - name: Build
- run: |
- cd go
- make
-
- - name: Cache compilation cache
- id: query-cache
- uses: ./.github/actions/cache-query-compilation
- with:
- key: go-qltest
- - name: Test
- run: |
- cd go
- make test cache="${{ steps.query-cache.outputs.cache-dir }}"
+ - name: Run tests
+ uses: ./go/actions/test
test-win:
if: github.repository_owner == 'github'
name: Test Windows
runs-on: windows-latest-xl
steps:
- - name: Set up Go ${{ env.GO_VERSION }}
- uses: actions/setup-go@v5
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: false
- id: go
-
- name: Check out code
uses: actions/checkout@v4
-
- - name: Set up CodeQL CLI
- uses: ./.github/actions/fetch-codeql
-
- - name: Enable problem matchers in repository
- shell: bash
- run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
-
- - name: Build
- run: |
- cd go
- make
-
- - name: Cache compilation cache
- id: query-cache
- uses: ./.github/actions/cache-query-compilation
- with:
- key: go-qltest
-
- - name: Test
- run: |
- cd go
- make test cache="${{ steps.query-cache.outputs.cache-dir }}"
+ - name: Run tests
+ uses: ./go/actions/test
diff --git a/.github/workflows/go-tests.yml b/.github/workflows/go-tests.yml
index 6d9cac5dae9..63e2b7c4974 100644
--- a/.github/workflows/go-tests.yml
+++ b/.github/workflows/go-tests.yml
@@ -16,9 +16,6 @@ on:
- .github/actions/**
- codeql-workspace.yml
-env:
- GO_VERSION: '~1.22.0'
-
permissions:
contents: read
@@ -28,51 +25,9 @@ jobs:
name: Test Linux (Ubuntu)
runs-on: ubuntu-latest-xl
steps:
- - name: Set up Go ${{ env.GO_VERSION }}
- uses: actions/setup-go@v5
- with:
- go-version: ${{ env.GO_VERSION }}
- cache: false
- id: go
-
- name: Check out code
uses: actions/checkout@v4
-
- - name: Set up CodeQL CLI
- uses: ./.github/actions/fetch-codeql
-
- - name: Enable problem matchers in repository
- shell: bash
- run: 'find .github/problem-matchers -name \*.json -exec echo "::add-matcher::{}" \;'
-
- - name: Build
- run: |
- cd go
- make
-
- - name: Check that all Go code is autoformatted
- run: |
- cd go
- make check-formatting
-
- - name: Compile qhelp files to markdown
- run: |
- cd go
- env QHELP_OUT_DIR=qhelp-out make qhelp-to-markdown
-
- - name: Upload qhelp markdown
- uses: actions/upload-artifact@v3
+ - name: Run tests
+ uses: ./go/actions/test
with:
- name: qhelp-markdown
- path: go/qhelp-out/**/*.md
-
- - name: Cache compilation cache
- id: query-cache
- uses: ./.github/actions/cache-query-compilation
- with:
- key: go-qltest
-
- - name: Test
- run: |
- cd go
- make test cache="${{ steps.query-cache.outputs.cache-dir }}"
+ run-code-checks: true
diff --git a/.lfsconfig b/.lfsconfig
new file mode 100644
index 00000000000..cb0a8e352e8
--- /dev/null
+++ b/.lfsconfig
@@ -0,0 +1,5 @@
+[lfs]
+# codeql is publicly forked by many users, and we don't want any LFS file polluting their working
+# copies. We therefore exclude everything by default.
+# For files required by bazel builds, use rules in `misc/bazel/lfs.bzl` to download them on demand.
+fetchinclude = /nothing
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 7fddd1929d4..62ac0d95779 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -26,9 +26,17 @@ repos:
name: Format bazel files
files: \.(bazel|bzl)
language: system
- entry: bazel run //:buildifier
+ entry: bazel run //misc/bazel:buildifier
pass_filenames: false
+# DISABLED: can be enabled by copying this config and installing `pre-commit` with `--config` on the copy
+# - id: go-gen
+# name: Check checked in generated files in go
+# files: ^go/.*
+# language: system
+# entry: bazel run //go:gen
+# pass_filenames: false
+
- id: codeql-format
name: Fix QL file formatting
files: \.qll?$
diff --git a/BUILD.bazel b/BUILD.bazel
index 3ccdcda5f12..8ef196cd85a 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,9 +1 @@
-load("@buildifier_prebuilt//:rules.bzl", "buildifier")
-
-buildifier(
- name = "buildifier",
- exclude_patterns = [
- "./.git/*",
- ],
- lint_mode = "fix",
-)
+exports_files(["LICENSE"])
diff --git a/CODEOWNERS b/CODEOWNERS
index d8539332467..992acbda4ff 100644
--- a/CODEOWNERS
+++ b/CODEOWNERS
@@ -1,6 +1,7 @@
/cpp/ @github/codeql-c-analysis
-/cpp/autobuilder/ @github/codeql-c-extractor
/csharp/ @github/codeql-csharp
+/csharp/autobuilder/Semmle.Autobuild.Cpp @github/codeql-c-extractor
+/csharp/autobuilder/Semmle.Autobuild.Cpp.Tests @github/codeql-c-extractor
/go/ @github/codeql-go
/java/ @github/codeql-java
/javascript/ @github/codeql-javascript
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5324ac8f301..a0efca6dec9 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,6 +4,8 @@ We welcome contributions to our CodeQL libraries and queries. Got an idea for a
There is lots of useful documentation to help you write queries, ranging from information about query file structure to tutorials for specific target languages. For more information on the documentation available, see [CodeQL queries](https://codeql.github.com/docs/writing-codeql-queries/codeql-queries) on [codeql.github.com](https://codeql.github.com).
+Note that the CodeQL for Visual Studio Code documentation has been migrated to https://docs.github.com/en/code-security/codeql-for-vs-code/, but you can still contribute to it via a different repository. For more information, see [Contributing to GitHub Docs documentation](https://docs.github.com/en/contributing)."
+
## Change notes
Any nontrivial user-visible change to a query pack or library pack should have a change note. For details on how to add a change note for your change, see [this guide](docs/change-notes.md).
@@ -43,7 +45,7 @@ If you have an idea for a query that you would like to share with other CodeQL u
3. **Formatting**
- - The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/about-codeql-for-visual-studio-code).
+ - The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://docs.github.com/en/code-security/codeql-for-vs-code/).
If you prefer, you can either:
1. install the [pre-commit framework](https://pre-commit.com/) and install the configured hooks on this repo via `pre-commit install`, or
diff --git a/MODULE.bazel b/MODULE.bazel
index c834acab7ae..424312f828e 100644
--- a/MODULE.bazel
+++ b/MODULE.bazel
@@ -13,7 +13,8 @@ local_path_override(
# see https://registry.bazel.build/ for a list of available packages
-bazel_dep(name = "platforms", version = "0.0.8")
+bazel_dep(name = "platforms", version = "0.0.9")
+bazel_dep(name = "rules_go", version = "0.47.0")
bazel_dep(name = "rules_pkg", version = "0.10.1")
bazel_dep(name = "rules_nodejs", version = "6.0.3")
bazel_dep(name = "rules_python", version = "0.31.0")
@@ -21,9 +22,20 @@ bazel_dep(name = "bazel_skylib", version = "1.5.0")
bazel_dep(name = "abseil-cpp", version = "20240116.0", repo_name = "absl")
bazel_dep(name = "nlohmann_json", version = "3.11.3", repo_name = "json")
bazel_dep(name = "fmt", version = "10.0.0")
+bazel_dep(name = "gazelle", version = "0.36.0")
+bazel_dep(name = "rules_dotnet", version = "0.15.1")
bazel_dep(name = "buildifier_prebuilt", version = "6.4.0", dev_dependency = True)
+dotnet = use_extension("@rules_dotnet//dotnet:extensions.bzl", "dotnet")
+dotnet.toolchain(dotnet_version = "8.0.101")
+use_repo(dotnet, "dotnet_toolchains")
+
+register_toolchains("@dotnet_toolchains//:all")
+
+csharp_main_extension = use_extension("//csharp:paket.main_extension.bzl", "main_extension")
+use_repo(csharp_main_extension, "paket.main")
+
pip = use_extension("@rules_python//python/extensions:pip.bzl", "pip")
pip.parse(
hub_name = "codegen_deps",
@@ -52,6 +64,9 @@ node.toolchain(
)
use_repo(node, "nodejs", "nodejs_toolchains")
+go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
+go_sdk.download(version = "1.22.2")
+
register_toolchains(
"@nodejs_toolchains//:all",
)
diff --git a/README.md b/README.md
index 407efadd5ee..b0f6c52bbdc 100644
--- a/README.md
+++ b/README.md
@@ -4,7 +4,7 @@ This open source repository contains the standard CodeQL libraries and queries t
## How do I learn CodeQL and run queries?
-There is [extensive documentation](https://codeql.github.com/docs/) on getting started with writing CodeQL using the [CodeQL extension for Visual Studio Code](https://codeql.github.com/docs/codeql-for-visual-studio-code/) and the [CodeQL CLI](https://codeql.github.com/docs/codeql-cli/).
+There is extensive documentation about the [CodeQL language](https://codeql.github.com/docs/), writing CodeQL using the [CodeQL extension for Visual Studio Code](https://docs.github.com/en/code-security/codeql-for-vs-code/) and using the [CodeQL CLI](https://docs.github.com/en/code-security/codeql-cli).
## Contributing
diff --git a/config/dbscheme-fragments.json b/config/dbscheme-fragments.json
index 2a56ed57bae..c56289ff171 100644
--- a/config/dbscheme-fragments.json
+++ b/config/dbscheme-fragments.json
@@ -28,6 +28,7 @@
"/*- Yaml dbscheme -*/",
"/*- Blame dbscheme -*/",
"/*- JSON dbscheme -*/",
- "/*- Python dbscheme -*/"
+ "/*- Python dbscheme -*/",
+ "/*- Empty location -*/"
]
}
\ No newline at end of file
diff --git a/config/identical-files.json b/config/identical-files.json
index d810e30c0c8..172f9b1ea66 100644
--- a/config/identical-files.json
+++ b/config/identical-files.json
@@ -364,5 +364,9 @@
"Python model summaries test extension": [
"python/ql/test/library-tests/dataflow/model-summaries/InlineTaintTest.ext.yml",
"python/ql/test/library-tests/dataflow/model-summaries/NormalDataflowTest.ext.yml"
+ ],
+ "shared tree-sitter extractor cargo.toml": [
+ "shared/tree-sitter-extractor/Cargo.toml",
+ "ruby/extractor/codeql-extractor-fake-crate/Cargo.toml"
]
}
diff --git a/cpp/autobuilder/.gitignore b/cpp/autobuilder/.gitignore
deleted file mode 100644
index f81ecc73dff..00000000000
--- a/cpp/autobuilder/.gitignore
+++ /dev/null
@@ -1,13 +0,0 @@
-obj/
-TestResults/
-*.manifest
-*.pdb
-*.suo
-*.mdb
-*.vsmdi
-csharp.log
-**/bin/Debug
-**/bin/Release
-*.tlog
-.vs
-*.user
\ No newline at end of file
diff --git a/cpp/autobuilder/README.md b/cpp/autobuilder/README.md
new file mode 100644
index 00000000000..a6f213e2bd5
--- /dev/null
+++ b/cpp/autobuilder/README.md
@@ -0,0 +1 @@
+The Windows autobuilder that used to live in this directory moved to `csharp/autobuilder/Semmle.Autobuild.Cpp`.
\ No newline at end of file
diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj
deleted file mode 100644
index 1fe010dc3fc..00000000000
--- a/cpp/autobuilder/Semmle.Autobuild.Cpp.Tests/Semmle.Autobuild.Cpp.Tests.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
- Exe
- net8.0
- false
- win-x64;linux-x64;osx-x64
- enable
-
-
-
-
-
-
-
- all
- runtime; build; native; contentfiles; analyzers
-
-
-
-
-
-
-
-
-
diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp/Properties/AssemblyInfo.cs b/cpp/autobuilder/Semmle.Autobuild.Cpp/Properties/AssemblyInfo.cs
deleted file mode 100644
index 2d14b0e909d..00000000000
--- a/cpp/autobuilder/Semmle.Autobuild.Cpp/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,32 +0,0 @@
-using System.Reflection;
-using System.Runtime.InteropServices;
-
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Semmle.Autobuild.Cpp")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("GitHub")]
-[assembly: AssemblyProduct("CodeQL autobuilder for C++")]
-[assembly: AssemblyCopyright("Copyright © GitHub 2020")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible
-// to COM components. If you need to access a type in this assembly from
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.0.0.0")]
-[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj b/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj
deleted file mode 100644
index 99e49a2f0a7..00000000000
--- a/cpp/autobuilder/Semmle.Autobuild.Cpp/Semmle.Autobuild.Cpp.csproj
+++ /dev/null
@@ -1,28 +0,0 @@
-
-
-
- net8.0
- Semmle.Autobuild.Cpp
- Semmle.Autobuild.Cpp
-
- Exe
-
- false
- win-x64;linux-x64;osx-x64
- enable
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties
index eab51f4d94d..f93f9fc8d04 100644
--- a/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties
+++ b/cpp/downgrades/19887dbd33327fb07d54251786e0cb2578539775/upgrade.properties
@@ -1,4 +1,4 @@
description: Revert support for repeated initializers, which are allowed in C with designated initializers.
compatibility: full
-aggregate_field_init.rel: reorder aggregate_field_init.rel (int aggregate, int initializer, int field, int position) aggregate initializer field
-aggregate_array_init.rel: reorder aggregate_array_init.rel (int aggregate, int initializer, int element_index, int position) aggregate initializer element_index
+aggregate_field_init.rel: reorder aggregate_field_init.rel (@aggregateliteral aggregate, @expr initializer, @membervariable field, int position) aggregate initializer field
+aggregate_array_init.rel: reorder aggregate_array_init.rel (@aggregateliteral aggregate, @expr initializer, int element_index, int position) aggregate initializer element_index
diff --git a/cpp/ql/lib/CHANGELOG.md b/cpp/ql/lib/CHANGELOG.md
index bcb7d30a2ed..da66014df8e 100644
--- a/cpp/ql/lib/CHANGELOG.md
+++ b/cpp/ql/lib/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 1.0.0
+
+### Breaking Changes
+
+* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.
+
+## 0.13.1
+
+No user-facing changes.
+
## 0.13.0
### Breaking Changes
diff --git a/cpp/ql/lib/change-notes/released/0.13.1.md b/cpp/ql/lib/change-notes/released/0.13.1.md
new file mode 100644
index 00000000000..ec58ef441c1
--- /dev/null
+++ b/cpp/ql/lib/change-notes/released/0.13.1.md
@@ -0,0 +1,3 @@
+## 0.13.1
+
+No user-facing changes.
diff --git a/cpp/ql/lib/change-notes/released/1.0.0.md b/cpp/ql/lib/change-notes/released/1.0.0.md
new file mode 100644
index 00000000000..7c7dd01f405
--- /dev/null
+++ b/cpp/ql/lib/change-notes/released/1.0.0.md
@@ -0,0 +1,5 @@
+## 1.0.0
+
+### Breaking Changes
+
+* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.
diff --git a/cpp/ql/lib/codeql-pack.release.yml b/cpp/ql/lib/codeql-pack.release.yml
index 5a1b274ee58..b7eeb5b9736 100644
--- a/cpp/ql/lib/codeql-pack.release.yml
+++ b/cpp/ql/lib/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 0.13.0
+lastReleaseVersion: 1.0.0
diff --git a/cpp/ql/lib/qlpack.yml b/cpp/ql/lib/qlpack.yml
index f6f48625357..653304cedf3 100644
--- a/cpp/ql/lib/qlpack.yml
+++ b/cpp/ql/lib/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-all
-version: 0.13.0
+version: 1.0.0
groups: cpp
dbscheme: semmlecode.cpp.dbscheme
extractor: cpp
diff --git a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll
index bcd214ec000..f06db98e91b 100644
--- a/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll
+++ b/cpp/ql/lib/semmle/code/cpp/controlflow/IRGuards.qll
@@ -565,7 +565,7 @@ class IRGuardCondition extends Instruction {
/** Holds if (determined by this guard) `op == k` evaluates to `areEqual` if this expression evaluates to `value`. */
cached
predicate comparesEq(Operand op, int k, boolean areEqual, AbstractValue value) {
- compares_eq(this, op, k, areEqual, value)
+ unary_compares_eq(this, op, k, areEqual, false, value)
}
/**
@@ -586,7 +586,7 @@ class IRGuardCondition extends Instruction {
cached
predicate ensuresEq(Operand op, int k, IRBlock block, boolean areEqual) {
exists(AbstractValue value |
- compares_eq(this, op, k, areEqual, value) and this.valueControls(block, value)
+ unary_compares_eq(this, op, k, areEqual, false, value) and this.valueControls(block, value)
)
}
@@ -611,7 +611,7 @@ class IRGuardCondition extends Instruction {
cached
predicate ensuresEqEdge(Operand op, int k, IRBlock pred, IRBlock succ, boolean areEqual) {
exists(AbstractValue value |
- compares_eq(this, op, k, areEqual, value) and
+ unary_compares_eq(this, op, k, areEqual, false, value) and
this.valueControlsEdge(pred, succ, value)
)
}
@@ -737,26 +737,66 @@ private predicate compares_eq(
)
}
-/** Holds if `op == k` is `areEqual` given that `test` is equal to `value`. */
-private predicate compares_eq(
- Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
+/**
+ * Holds if `op == k` is `areEqual` given that `test` is equal to `value`.
+ *
+ * Many internal predicates in this file have a `inNonZeroCase` column.
+ * Ideally, the `k` column would be a type such as `Option::Option`, to
+ * represent whether we have a concrete value `k` such that `op == k`, or whether
+ * we only know that `op != 0`.
+ * However, cannot instantiate `Option` with an infinite type. Thus the boolean
+ * `inNonZeroCase` is used to distinquish the `Some` (where we have a concrete
+ * value `k`) and `None` cases (where we only know that `op != 0`).
+ *
+ * Thus, if `inNonZeroCase = true` then `op != 0` and the value of `k` is
+ * meaningless.
+ *
+ * To see why `inNonZeroCase` is needed consider the following C program:
+ * ```c
+ * char* p = ...;
+ * if(p) {
+ * use(p);
+ * }
+ * ```
+ * in C++ there would be an int-to-bool conversion on `p`. However, since C
+ * does not have booleans there is no conversion. We want to be able to
+ * conclude that `p` is non-zero in the true branch, so we need to give `k`
+ * some value. However, simply setting `k = 1` would make the rest of the
+ * analysis think that `k == 1` holds inside the branch. So we distinquish
+ * between the above case and
+ * ```c
+ * if(p == 1) {
+ * use(p)
+ * }
+ * ```
+ * by setting `inNonZeroCase` to `true` in the former case, but not in the
+ * latter.
+ */
+private predicate unary_compares_eq(
+ Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
) {
/* The simple case where the test *is* the comparison so areEqual = testIsTrue xor eq. */
- exists(AbstractValue v | simple_comparison_eq(test, op, k, v) |
+ exists(AbstractValue v | unary_simple_comparison_eq(test, op, k, inNonZeroCase, v) |
areEqual = true and value = v
or
areEqual = false and value = v.getDualValue()
)
or
- complex_eq(test, op, k, areEqual, value)
+ unary_complex_eq(test, op, k, areEqual, inNonZeroCase, value)
or
/* (x is true => (op == k)) => (!x is false => (op == k)) */
- exists(AbstractValue dual | value = dual.getDualValue() |
- compares_eq(test.(LogicalNotInstruction).getUnary(), op, k, areEqual, dual)
+ exists(AbstractValue dual, boolean inNonZeroCase0 |
+ value = dual.getDualValue() and
+ unary_compares_eq(test.(LogicalNotInstruction).getUnary(), op, k, inNonZeroCase0, areEqual, dual)
+ |
+ k = 0 and inNonZeroCase = inNonZeroCase0
+ or
+ k != 0 and inNonZeroCase = true
)
or
// ((test is `areEqual` => op == const + k2) and const == `k1`) =>
// test is `areEqual` => op == k1 + k2
+ inNonZeroCase = false and
exists(int k1, int k2, ConstantInstruction const |
compares_eq(test, op, const.getAUse(), k2, areEqual, value) and
int_value(const) = k1 and
@@ -781,14 +821,53 @@ private predicate simple_comparison_eq(
value.(BooleanValue).getValue() = false
}
-/** Rearrange various simple comparisons into `op == k` form. */
-private predicate simple_comparison_eq(Instruction test, Operand op, int k, AbstractValue value) {
+/**
+ * Holds if `test` is an instruction that is part of test that eventually is
+ * used in a conditional branch.
+ */
+private predicate relevantUnaryComparison(Instruction test) {
+ not test instanceof CompareInstruction and
+ exists(IRType type, ConditionalBranchInstruction branch |
+ type instanceof IRAddressType or type instanceof IRIntegerType
+ |
+ type = test.getResultIRType() and
+ branch.getCondition() = test
+ )
+ or
+ exists(LogicalNotInstruction logicalNot |
+ relevantUnaryComparison(logicalNot) and
+ test = logicalNot.getUnary()
+ )
+}
+
+/**
+ * Rearrange various simple comparisons into `op == k` form.
+ */
+private predicate unary_simple_comparison_eq(
+ Instruction test, Operand op, int k, boolean inNonZeroCase, AbstractValue value
+) {
exists(SwitchInstruction switch, CaseEdge case |
test = switch.getExpression() and
op.getDef() = test and
case = value.(MatchValue).getCase() and
exists(switch.getSuccessor(case)) and
- case.getValue().toInt() = k
+ case.getValue().toInt() = k and
+ inNonZeroCase = false
+ )
+ or
+ // There's no implicit CompareInstruction in files compiled as C since C
+ // doesn't have implicit boolean conversions. So instead we check whether
+ // there's a branch on a value of pointer or integer type.
+ relevantUnaryComparison(test) and
+ op.getDef() = test and
+ (
+ k = 1 and
+ value.(BooleanValue).getValue() = true and
+ inNonZeroCase = true
+ or
+ k = 0 and
+ value.(BooleanValue).getValue() = false and
+ inNonZeroCase = false
)
}
@@ -800,12 +879,12 @@ private predicate complex_eq(
add_eq(cmp, left, right, k, areEqual, value)
}
-private predicate complex_eq(
- Instruction test, Operand op, int k, boolean areEqual, AbstractValue value
+private predicate unary_complex_eq(
+ Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
) {
- sub_eq(test, op, k, areEqual, value)
+ unary_sub_eq(test, op, k, areEqual, inNonZeroCase, value)
or
- add_eq(test, op, k, areEqual, value)
+ unary_add_eq(test, op, k, areEqual, inNonZeroCase, value)
}
/*
@@ -1069,16 +1148,20 @@ private predicate sub_eq(
}
// op - x == c => op == (c+x)
-private predicate sub_eq(Instruction test, Operand op, int k, boolean areEqual, AbstractValue value) {
+private predicate unary_sub_eq(
+ Instruction test, Operand op, int k, boolean areEqual, boolean inNonZeroCase, AbstractValue value
+) {
+ inNonZeroCase = false and
exists(SubInstruction sub, int c, int x |
- compares_eq(test, sub.getAUse(), c, areEqual, value) and
+ unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
op = sub.getLeftOperand() and
x = int_value(sub.getRight()) and
k = c + x
)
or
+ inNonZeroCase = false and
exists(PointerSubInstruction sub, int c, int x |
- compares_eq(test, sub.getAUse(), c, areEqual, value) and
+ unary_compares_eq(test, sub.getAUse(), c, areEqual, inNonZeroCase, value) and
op = sub.getLeftOperand() and
x = int_value(sub.getRight()) and
k = c + x
@@ -1132,11 +1215,13 @@ private predicate add_eq(
}
// left + x == right + c => left == right + (c-x)
-private predicate add_eq(
- Instruction test, Operand left, int k, boolean areEqual, AbstractValue value
+private predicate unary_add_eq(
+ Instruction test, Operand left, int k, boolean areEqual, boolean inNonZeroCase,
+ AbstractValue value
) {
+ inNonZeroCase = false and
exists(AddInstruction lhs, int c, int x |
- compares_eq(test, lhs.getAUse(), c, areEqual, value) and
+ unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
@@ -1145,8 +1230,9 @@ private predicate add_eq(
k = c - x
)
or
+ inNonZeroCase = false and
exists(PointerAddInstruction lhs, int c, int x |
- compares_eq(test, lhs.getAUse(), c, areEqual, value) and
+ unary_compares_eq(test, lhs.getAUse(), c, areEqual, inNonZeroCase, value) and
(
left = lhs.getLeftOperand() and x = int_value(lhs.getRight())
or
diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll
index 895cc09a048..320b5c01f2b 100644
--- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll
+++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowDispatch.qll
@@ -9,7 +9,7 @@ private import DataFlowUtil
/**
* Gets a function that might be called by `call`.
*/
-Function viableCallable(DataFlowCall call) {
+DataFlowCallable viableCallable(DataFlowCall call) {
result = call.(Call).getTarget()
or
// If the target of the call does not have a body in the snapshot, it might
diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll
index 8cbecb5bcbb..afbc5f0e141 100644
--- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll
+++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowPrivate.qll
@@ -242,7 +242,17 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
-class DataFlowCallable = Function;
+class DataFlowCallable extends Function {
+ /** Gets a best-effort total ordering. */
+ int totalorder() {
+ this =
+ rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
+ c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
+ |
+ c order by file, startline, startcolumn
+ )
+ }
+}
class DataFlowExpr = Expr;
@@ -269,9 +279,6 @@ class DataFlowCall extends Expr instanceof Call {
/** Gets the data flow node corresponding to this call. (Alias of `getNode()`) */
ExprNode getDataFlowNode() { result = this.getNode() }
- /** Gets the enclosing callable of this call. */
- Function getEnclosingCallable() { result = this.getEnclosingFunction() }
-
/** Gets the target of the call, as best as makes sense for this kind of call.
*
* The precise meaning depends on the kind of call it is:
@@ -281,9 +288,29 @@ class DataFlowCall extends Expr instanceof Call {
* - For a variable call, it never exists.
*/
DataFlowCallable getARuntimeTarget(){ result = super.getTarget() }
+ /** Gets the enclosing callable of this call. */
+ DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
+
+ /** Gets a best-effort total ordering. */
+ int totalorder() {
+ this =
+ rank[result](DataFlowCall c, int startline, int startcolumn |
+ c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
+ |
+ c order by startline, startcolumn
+ )
+ }
}
-predicate isUnreachableInCall(Node n, DataFlowCall call) { none() } // stub implementation
+class NodeRegion instanceof Unit {
+ string toString() { result = "NodeRegion" }
+
+ predicate contains(Node n) { none() }
+
+ int totalOrder() { result = 1 }
+}
+
+predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation
/**
* Holds if access paths with `c` at their head always should be tracked at high
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
index 3c0e8e0644c..7c5354aa13c 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowPrivate.qll
@@ -1062,6 +1062,16 @@ class DataFlowCallable extends TDataFlowCallable {
result = this.asSummarizedCallable() or // SummarizedCallable = Function (in CPP)
result = this.asSourceCallable()
}
+
+ /** Gets a best-effort total ordering. */
+ int totalorder() {
+ this =
+ rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
+ c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
+ |
+ c order by file, startline, startcolumn
+ )
+ }
}
/**
@@ -1167,6 +1177,15 @@ class DataFlowCall extends TDataFlowCall {
// #43: Stub Implementation
/** Gets the target of the call, as a DataFlowCallable. */
DataFlowCallable getARuntimeTarget(){ none() } // TODO getCallTarget() returns `Instruction`
+ /** Gets a best-effort total ordering. */
+ int totalorder() {
+ this =
+ rank[result](DataFlowCall c, int startline, int startcolumn |
+ c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
+ |
+ c order by startline, startcolumn
+ )
+ }
}
/**
@@ -1255,43 +1274,53 @@ module IsUnreachableInCall {
any(G::IRGuardCondition guard).ensuresLt(left, right, k, block, areEqual)
}
- predicate isUnreachableInCall(Node n, DataFlowCall call) {
+ class NodeRegion instanceof IRBlock {
+ string toString() { result = "NodeRegion" }
+
+ predicate contains(Node n) { this = n.getBasicBlock() }
+
+ int totalOrder() {
+ this =
+ rank[result](IRBlock b, int startline, int startcolumn |
+ b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
+ |
+ b order by startline, startcolumn
+ )
+ }
+ }
+
+ predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
exists(
InstructionDirectParameterNode paramNode, ConstantIntegralTypeArgumentNode arg,
- IntegerConstantInstruction constant, int k, Operand left, Operand right, IRBlock block
+ IntegerConstantInstruction constant, int k, Operand left, Operand right, int argval
|
// arg flows into `paramNode`
- DataFlowImplCommon::viableParamArg(call, paramNode, arg) and
+ DataFlowImplCommon::viableParamArg(call, pragma[only_bind_into](paramNode),
+ pragma[only_bind_into](arg)) and
left = constant.getAUse() and
right = valueNumber(paramNode.getInstruction()).getAUse() and
- block = n.getBasicBlock()
+ argval = arg.getValue()
|
// and there's a guard condition which ensures that the result of `left == right + k` is `areEqual`
- exists(boolean areEqual |
- ensuresEq(pragma[only_bind_into](left), pragma[only_bind_into](right),
- pragma[only_bind_into](k), pragma[only_bind_into](block), areEqual)
- |
+ exists(boolean areEqual | ensuresEq(left, right, k, block, areEqual) |
// this block ensures that left = right + k, but it holds that `left != right + k`
areEqual = true and
- constant.getValue().toInt() != arg.getValue() + k
+ constant.getValue().toInt() != argval + k
or
// this block ensures that or `left != right + k`, but it holds that `left = right + k`
areEqual = false and
- constant.getValue().toInt() = arg.getValue() + k
+ constant.getValue().toInt() = argval + k
)
or
// or there's a guard condition which ensures that the result of `left < right + k` is `isLessThan`
- exists(boolean isLessThan |
- ensuresLt(pragma[only_bind_into](left), pragma[only_bind_into](right),
- pragma[only_bind_into](k), pragma[only_bind_into](block), isLessThan)
- |
+ exists(boolean isLessThan | ensuresLt(left, right, k, block, isLessThan) |
isLessThan = true and
// this block ensures that `left < right + k`, but it holds that `left >= right + k`
- constant.getValue().toInt() >= arg.getValue() + k
+ constant.getValue().toInt() >= argval + k
or
// this block ensures that `left >= right + k`, but it holds that `left < right + k`
isLessThan = false and
- constant.getValue().toInt() < arg.getValue() + k
+ constant.getValue().toInt() < argval + k
)
)
}
@@ -1673,3 +1702,311 @@ class DataFlowSecondLevelScope extends TDataFlowSecondLevelScope {
/** Gets the second-level scope containing the node `n`, if any. */
DataFlowSecondLevelScope getSecondLevelScope(Node n) { result.getANode() = n }
+
+/**
+ * Module that defines flow through iterators.
+ * For example,
+ * ```cpp
+ * auto it = v.begin();
+ * *it = source();
+ * ...
+ * sink(v[0]);
+ * ```
+ */
+module IteratorFlow {
+ private import codeql.ssa.Ssa as SsaImpl
+ private import semmle.code.cpp.models.interfaces.Iterator as Interface
+ private import semmle.code.cpp.models.implementations.Iterator as Impl
+
+ /**
+ * A variable of some type that can produce an iterator.
+ */
+ class SourceVariable extends Ssa::SourceVariable {
+ SourceVariable() {
+ exists(Interface::GetIteratorFunction gets, Cpp::FunctionInput input, int i |
+ input.isParameterDerefOrQualifierObject(i) and
+ gets.getsIterator(input, _)
+ |
+ this.getType().stripType() = gets.getParameter(i).getType().stripType()
+ or
+ i = -1 and
+ this.getType().stripType() = gets.getDeclaringType()
+ )
+ }
+ }
+
+ private module SsaInput implements SsaImpl::InputSig {
+ import Ssa::InputSigCommon
+
+ class SourceVariable = IteratorFlow::SourceVariable;
+
+ /** A call to function that dereferences an iterator. */
+ private class IteratorPointerDereferenceCall extends CallInstruction {
+ IteratorPointerDereferenceCall() {
+ this.getStaticCallTarget() instanceof Impl::IteratorPointerDereferenceOperator
+ }
+ }
+
+ /** A call to a function that obtains an iterator. */
+ private class GetsIteratorCall extends CallInstruction {
+ GetsIteratorCall() { this.getStaticCallTarget() instanceof Impl::GetIteratorFunction }
+ }
+
+ /** A call to `operator++` or `operator--` on an iterator. */
+ private class IteratorCrementCall extends CallInstruction {
+ IteratorCrementCall() { this.getStaticCallTarget() instanceof Impl::IteratorCrementOperator }
+ }
+
+ /**
+ * Gets an ultimate definition of `def`.
+ *
+ * Note: Unlike `def.getAnUltimateDefinition()` this predicate also
+ * traverses back through iterator increment and decrement operations.
+ */
+ private Ssa::Def getAnUltimateDefinition(Ssa::Def def) {
+ result = def.getAnUltimateDefinition()
+ or
+ exists(IRBlock bb, int i, IteratorCrementCall crementCall, Ssa::SourceVariable sv |
+ crementCall = def.getValue().asInstruction().(StoreInstruction).getSourceValue() and
+ sv = def.getSourceVariable() and
+ bb.getInstruction(i) = crementCall and
+ Ssa::ssaDefReachesRead(sv, result.asDef(), bb, i)
+ )
+ }
+
+ /**
+ * Holds if `write` is an instruction that writes to address `address`
+ */
+ private predicate isIteratorWrite(Instruction write, Operand address) {
+ exists(Ssa::DefImpl writeDef, IRBlock bb, int i |
+ writeDef.hasIndexInBlock(bb, i, _) and
+ bb.getInstruction(i) = write and
+ address = writeDef.getAddressOperand()
+ )
+ }
+
+ /**
+ * Holds if `writeToDeref` is a write to an iterator that was obtained
+ * by `beginCall`. That is, the following instruction sequence holds:
+ * ```cpp
+ * it = container.begin(); // or a similar iterator-obtaining function call
+ * ...
+ * *it = value;
+ * ```
+ */
+ private predicate isIteratorStoreInstruction(
+ GetsIteratorCall beginCall, Instruction writeToDeref
+ ) {
+ exists(
+ StoreInstruction beginStore, IRBlock bbStar, int iStar, Ssa::Def def,
+ IteratorPointerDereferenceCall starCall, Ssa::Def ultimate, Operand address
+ |
+ isIteratorWrite(writeToDeref, address) and
+ operandForFullyConvertedCall(address, starCall) and
+ bbStar.getInstruction(iStar) = starCall and
+ Ssa::ssaDefReachesRead(_, def.asDef(), bbStar, iStar) and
+ ultimate = getAnUltimateDefinition*(def) and
+ beginStore = ultimate.getValue().asInstruction() and
+ operandForFullyConvertedCall(beginStore.getSourceValueOperand(), beginCall)
+ )
+ }
+
+ /**
+ * Holds if `(bb, i)` contains a write to an iterator that may have been obtained
+ * by calling `begin` (or related functions) on the variable `v`.
+ */
+ predicate variableWrite(IRBlock bb, int i, SourceVariable v, boolean certain) {
+ certain = false and
+ exists(GetsIteratorCall beginCall, Instruction writeToDeref, IRBlock bbQual, int iQual |
+ isIteratorStoreInstruction(beginCall, writeToDeref) and
+ bb.getInstruction(i) = writeToDeref and
+ bbQual.getInstruction(iQual) = beginCall and
+ Ssa::variableRead(bbQual, iQual, v, _)
+ )
+ }
+
+ /** Holds if `(bb, i)` reads the container variable `v`. */
+ predicate variableRead(IRBlock bb, int i, SourceVariable v, boolean certain) {
+ Ssa::variableRead(bb, i, v, certain)
+ }
+ }
+
+ private module IteratorSsa = SsaImpl::Make;
+
+ cached
+ private newtype TSsaDef =
+ TDef(IteratorSsa::DefinitionExt def) or
+ TPhi(PhiNode phi)
+
+ abstract private class SsaDef extends TSsaDef {
+ /** Gets a textual representation of this element. */
+ string toString() { none() }
+
+ /** Gets the underlying non-phi definition or use. */
+ IteratorSsa::DefinitionExt asDef() { none() }
+
+ /** Gets the underlying phi node. */
+ PhiNode asPhi() { none() }
+
+ /** Gets the location of this element. */
+ abstract Location getLocation();
+ }
+
+ private class Def extends TDef, SsaDef {
+ IteratorSsa::DefinitionExt def;
+
+ Def() { this = TDef(def) }
+
+ final override IteratorSsa::DefinitionExt asDef() { result = def }
+
+ final override Location getLocation() { result = this.getImpl().getLocation() }
+
+ /** Gets the variable written to by this definition. */
+ final SourceVariable getSourceVariable() { result = def.getSourceVariable() }
+
+ override string toString() { result = def.toString() }
+
+ /**
+ * Holds if this definition (or use) has index `index` in block `block`,
+ * and is a definition (or use) of the variable `sv`.
+ */
+ predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
+ def.definesAt(sv, block, index, _)
+ }
+
+ private Ssa::DefImpl getImpl() {
+ exists(IRBlock bb, int i |
+ this.hasIndexInBlock(bb, i, _) and
+ result.hasIndexInBlock(bb, i)
+ )
+ }
+
+ /** Gets the value written by this definition (i.e., the "right-hand side"). */
+ Node0Impl getValue() { result = this.getImpl().getValue() }
+
+ /** Gets the indirection index of this definition. */
+ int getIndirectionIndex() { result = this.getImpl().getIndirectionIndex() }
+ }
+
+ private class Phi extends TPhi, SsaDef {
+ PhiNode phi;
+
+ Phi() { this = TPhi(phi) }
+
+ final override PhiNode asPhi() { result = phi }
+
+ final override Location getLocation() { result = phi.getBasicBlock().getLocation() }
+
+ override string toString() { result = phi.toString() }
+
+ SsaIteratorNode getNode() { result.getIteratorFlowNode() = phi }
+ }
+
+ private class PhiNode extends IteratorSsa::DefinitionExt {
+ PhiNode() {
+ this instanceof IteratorSsa::PhiNode or
+ this instanceof IteratorSsa::PhiReadNode
+ }
+
+ SsaIteratorNode getNode() { result.getIteratorFlowNode() = this }
+ }
+
+ cached
+ private module IteratorSsaCached {
+ cached
+ predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
+ IteratorSsa::adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
+ or
+ exists(PhiNode phi |
+ IteratorSsa::lastRefRedefExt(_, sv, bb1, i1, phi) and
+ phi.definesAt(sv, bb2, i2, _)
+ )
+ }
+
+ cached
+ Node getAPriorDefinition(IteratorSsa::DefinitionExt next) {
+ exists(IRBlock bb, int i, SourceVariable sv, IteratorSsa::DefinitionExt def |
+ IteratorSsa::lastRefRedefExt(pragma[only_bind_into](def), pragma[only_bind_into](sv),
+ pragma[only_bind_into](bb), pragma[only_bind_into](i), next) and
+ nodeToDefOrUse(result, sv, bb, i, _)
+ )
+ }
+ }
+
+ /** The set of nodes necessary for iterator flow. */
+ class IteratorFlowNode instanceof PhiNode {
+ /** Gets a textual representation of this node. */
+ string toString() { result = super.toString() }
+
+ /** Gets the type of this node. */
+ DataFlowType getType() {
+ exists(Ssa::SourceVariable sv |
+ super.definesAt(sv, _, _, _) and
+ result = sv.getType()
+ )
+ }
+
+ /** Gets the `Declaration` that contains this block. */
+ Declaration getFunction() { result = super.getBasicBlock().getEnclosingFunction() }
+
+ /** Gets the locatino of this node. */
+ Location getLocation() { result = super.getBasicBlock().getLocation() }
+ }
+
+ private import IteratorSsaCached
+
+ private predicate defToNode(Node node, Def def, boolean uncertain) {
+ (
+ nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
+ or
+ nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
+ ) and
+ uncertain = false
+ }
+
+ private predicate nodeToDefOrUse(
+ Node node, SourceVariable sv, IRBlock bb, int i, boolean uncertain
+ ) {
+ exists(Def def |
+ def.hasIndexInBlock(bb, i, sv) and
+ defToNode(node, def, uncertain)
+ )
+ or
+ useToNode(bb, i, sv, node) and
+ uncertain = false
+ }
+
+ private predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
+ exists(PhiNode phi |
+ phi.definesAt(sv, bb, i, _) and
+ nodeTo = phi.getNode()
+ )
+ or
+ exists(Ssa::UseImpl use |
+ use.hasIndexInBlock(bb, i, sv) and
+ nodeTo = use.getNode()
+ )
+ }
+
+ /**
+ * Holds if `nodeFrom` flows to `nodeTo` in a single step.
+ */
+ predicate localFlowStep(Node nodeFrom, Node nodeTo) {
+ exists(
+ Node nFrom, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2, boolean uncertain
+ |
+ adjacentDefRead(bb1, i1, sv, bb2, i2) and
+ nodeToDefOrUse(nFrom, sv, bb1, i1, uncertain) and
+ useToNode(bb2, i2, sv, nodeTo)
+ |
+ if uncertain = true
+ then
+ nodeFrom =
+ [
+ nFrom,
+ getAPriorDefinition(any(IteratorSsa::DefinitionExt next | next.definesAt(sv, bb1, i1, _)))
+ ]
+ else nFrom = nodeFrom
+ )
+ }
+}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
index 94729c47fcb..dc591dccbb9 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll
@@ -46,6 +46,7 @@ private newtype TIRDataFlowNode =
Ssa::isModifiableByCall(operand, indirectionIndex)
} or
TSsaPhiNode(Ssa::PhiNode phi) or
+ TSsaIteratorNode(IteratorFlow::IteratorFlowNode n) or
TRawIndirectOperand0(Node0Impl node, int indirectionIndex) {
Ssa::hasRawIndirectOperand(node.asOperand(), indirectionIndex)
} or
@@ -653,6 +654,30 @@ class SsaPhiNode extends Node, TSsaPhiNode {
predicate isPhiRead() { phi.isPhiRead() }
}
+/**
+ * INTERNAL: do not use.
+ *
+ * Dataflow nodes necessary for iterator flow
+ */
+class SsaIteratorNode extends Node, TSsaIteratorNode {
+ IteratorFlow::IteratorFlowNode node;
+
+ SsaIteratorNode() { this = TSsaIteratorNode(node) }
+
+ /** Gets the phi node associated with this node. */
+ IteratorFlow::IteratorFlowNode getIteratorFlowNode() { result = node }
+
+ override Declaration getEnclosingCallable() { result = this.getFunction() }
+
+ override Declaration getFunction() { result = node.getFunction() }
+
+ override DataFlowType getType() { result = node.getType() }
+
+ final override Location getLocationImpl() { result = node.getLocation() }
+
+ override string toStringImpl() { result = node.toString() }
+}
+
/**
* INTERNAL: do not use.
*
@@ -1190,11 +1215,11 @@ class UninitializedNode extends Node {
LocalVariable v;
UninitializedNode() {
- exists(Ssa::Def def |
+ exists(Ssa::Def def, Ssa::SourceVariable sv |
def.getIndirectionIndex() = 0 and
def.getValue().asInstruction() instanceof UninitializedInstruction and
- Ssa::nodeToDefOrUse(this, def, _) and
- v = def.getSourceVariable().getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
+ Ssa::defToNode(this, def, sv, _, _, _) and
+ v = sv.getBaseVariable().(Ssa::BaseIRVariable).getIRVariable().getAst()
)
}
@@ -2151,6 +2176,8 @@ private module Cached {
// Def-use/Use-use flow
Ssa::ssaFlow(nodeFrom, nodeTo)
or
+ IteratorFlow::localFlowStep(nodeFrom, nodeTo)
+ or
// Operand -> Instruction flow
simpleInstructionLocalFlowStep(nodeFrom.asOperand(), nodeTo.asInstruction())
or
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll
index e64f2285821..c2325593df2 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/ProductFlow.qll
@@ -546,7 +546,7 @@ module ProductFlow {
Flow1::PathGraph::edges(pred1, succ1, _, _) and
exists(ReturnKindExt returnKind |
succ1.getNode() = returnKind.getAnOutNode(call) and
- pred1.getNode().(ReturnNodeExt).getKind() = returnKind
+ paramReturnNode(_, pred1.asParameterReturnNode(), _, returnKind)
)
}
@@ -574,7 +574,7 @@ module ProductFlow {
Flow2::PathGraph::edges(pred2, succ2, _, _) and
exists(ReturnKindExt returnKind |
succ2.getNode() = returnKind.getAnOutNode(call) and
- pred2.getNode().(ReturnNodeExt).getKind() = returnKind
+ paramReturnNode(_, pred2.asParameterReturnNode(), _, returnKind)
)
}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
index 7eb84aefe3f..30511ba1285 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternals.qll
@@ -9,6 +9,7 @@ private import semmle.code.cpp.models.interfaces.PartialFlow as PartialFlow
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as FIO
private import semmle.code.cpp.ir.internal.IRCppLanguage
private import semmle.code.cpp.ir.dataflow.internal.ModelUtil
+private import semmle.code.cpp.ir.implementation.raw.internal.TranslatedInitialization
private import DataFlowPrivate
import SsaInternalsCommon
@@ -102,13 +103,21 @@ predicate hasRawIndirectInstruction(Instruction instr, int indirectionIndex) {
}
cached
-private newtype TDefOrUseImpl =
+private newtype TDefImpl =
TDefAddressImpl(BaseIRVariable v) or
- TDefImpl(BaseSourceVariableInstruction base, Operand address, int indirectionIndex) {
- isDef(_, _, address, base, _, indirectionIndex)
+ TDirectDefImpl(Operand address, int indirectionIndex) {
+ isDef(_, _, address, _, _, indirectionIndex)
} or
- TUseImpl(BaseSourceVariableInstruction base, Operand operand, int indirectionIndex) {
- isUse(_, operand, base, _, indirectionIndex) and
+ TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
+ // Represents the initial "definition" of a global variable when entering
+ // a function body.
+ isGlobalDefImpl(v, f, _, indirectionIndex)
+ }
+
+cached
+private newtype TUseImpl =
+ TDirectUseImpl(Operand operand, int indirectionIndex) {
+ isUse(_, operand, _, _, indirectionIndex) and
not isDef(true, _, operand, _, _, _)
} or
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
@@ -116,21 +125,6 @@ private newtype TDefOrUseImpl =
// the assignment to a global variable isn't ruled out as dead.
isGlobalUse(v, f, _, indirectionIndex)
} or
- TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
- // Represents the initial "definition" of a global variable when entering
- // a function body.
- isGlobalDefImpl(v, f, _, indirectionIndex)
- } or
- TIteratorDef(
- Operand iteratorDerefAddress, BaseSourceVariableInstruction container, int indirectionIndex
- ) {
- isIteratorDef(container, iteratorDerefAddress, _, _, indirectionIndex)
- } or
- TIteratorUse(
- Operand iteratorAddress, BaseSourceVariableInstruction container, int indirectionIndex
- ) {
- isIteratorUse(container, iteratorAddress, _, indirectionIndex)
- } or
TFinalParameterUse(Parameter p, int indirectionIndex) {
underlyingTypeIsModifiableAt(p.getUnderlyingType(), indirectionIndex) and
// Only create an SSA read for the final use of a parameter if there's
@@ -177,7 +171,76 @@ private predicate underlyingTypeIsModifiableAt(Type underlying, int indirectionI
private Indirection getIndirectionForUnspecifiedType(Type t) { result.getType() = t }
-abstract private class DefOrUseImpl extends TDefOrUseImpl {
+abstract class DefImpl extends TDefImpl {
+ int indirectionIndex;
+
+ bindingset[indirectionIndex]
+ DefImpl() { any() }
+
+ /** Gets a textual representation of this element. */
+ abstract string toString();
+
+ /** Gets the block of this definition or use. */
+ final IRBlock getBlock() { this.hasIndexInBlock(result, _) }
+
+ /** Holds if this definition or use has index `index` in block `block`. */
+ abstract predicate hasIndexInBlock(IRBlock block, int index);
+
+ /**
+ * Holds if this definition (or use) has index `index` in block `block`,
+ * and is a definition (or use) of the variable `sv`
+ */
+ final predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
+ this.hasIndexInBlock(block, index) and
+ sv = this.getSourceVariable()
+ }
+
+ /** Gets the location of this element. */
+ abstract Cpp::Location getLocation();
+
+ /** Gets the indirection index of this definition. */
+ final int getIndirectionIndex() { result = indirectionIndex }
+
+ /**
+ * Gets the index (i.e., the number of loads required) of this
+ * definition or use.
+ *
+ * Note that this is _not_ the definition's (or use's) index in
+ * the enclosing basic block. To obtain this index, use
+ * `DefOrUseImpl::hasIndexInBlock/2` or `DefOrUseImpl::hasIndexInBlock/3`.
+ */
+ abstract int getIndirection();
+
+ /**
+ * Gets the base source variable (i.e., the variable without
+ * any indirection) of this definition or use.
+ */
+ abstract BaseSourceVariable getBaseSourceVariable();
+
+ /** Gets the variable that is defined or used. */
+ SourceVariable getSourceVariable() {
+ exists(BaseSourceVariable v, int indirection |
+ sourceVariableHasBaseAndIndex(result, v, indirection) and
+ defHasSourceVariable(this, v, indirection)
+ )
+ }
+
+ abstract predicate isCertain();
+
+ abstract Node0Impl getValue();
+
+ Operand getAddressOperand() { none() }
+}
+
+abstract class UseImpl extends TUseImpl {
+ int indirectionIndex;
+
+ bindingset[indirectionIndex]
+ UseImpl() { any() }
+
+ /** Gets the node associated with this use. */
+ abstract Node getNode();
+
/** Gets a textual representation of this element. */
abstract string toString();
@@ -207,35 +270,30 @@ abstract private class DefOrUseImpl extends TDefOrUseImpl {
* the enclosing basic block. To obtain this index, use
* `DefOrUseImpl::hasIndexInBlock/2` or `DefOrUseImpl::hasIndexInBlock/3`.
*/
- abstract int getIndirectionIndex();
+ abstract int getIndirection();
- /**
- * Gets the instruction that computes the base of this definition or use.
- * This is always a `VariableAddressInstruction` or an `CallInstruction`.
- */
- abstract BaseSourceVariableInstruction getBase();
+ /** Gets the indirection index of this use. */
+ final int getIndirectionIndex() { result = indirectionIndex }
/**
* Gets the base source variable (i.e., the variable without
* any indirection) of this definition or use.
*/
- final BaseSourceVariable getBaseSourceVariable() {
- this.getBase().getBaseSourceVariable() = result
- }
+ abstract BaseSourceVariable getBaseSourceVariable();
/** Gets the variable that is defined or used. */
SourceVariable getSourceVariable() {
- exists(BaseSourceVariable v, int ind |
- sourceVariableHasBaseAndIndex(result, v, ind) and
- defOrUseHasSourceVariable(this, v, ind)
+ exists(BaseSourceVariable v, int indirection |
+ sourceVariableHasBaseAndIndex(result, v, indirection) and
+ useHasSourceVariable(this, v, indirection)
)
}
-}
-private predicate defOrUseHasSourceVariable(DefOrUseImpl defOrUse, BaseSourceVariable bv, int ind) {
- defHasSourceVariable(defOrUse, bv, ind)
- or
- useHasSourceVariable(defOrUse, bv, ind)
+ /**
+ * Holds if this use is guaranteed to read the
+ * associated variable.
+ */
+ abstract predicate isCertain();
}
pragma[noinline]
@@ -256,21 +314,15 @@ private predicate sourceVariableHasBaseAndIndex(SourceVariable v, BaseSourceVari
v.getIndirection() = ind
}
-abstract class DefImpl extends DefOrUseImpl {
- int ind;
-
- bindingset[ind]
- DefImpl() { any() }
-
- override int getIndirectionIndex() { result = ind }
-
- override string toString() { result = "Def of " + this.getSourceVariable() }
-
- abstract int getIndirection();
-
- abstract predicate isCertain();
-
- abstract Node0Impl getValue();
+/**
+ * Gets the instruction that computes the address that's used to
+ * initialize `v`.
+ */
+private Instruction getInitializationTargetAddress(IRVariable v) {
+ exists(TranslatedVariableInitialization init |
+ init.getIRVariable() = v and
+ result = init.getTargetAddress()
+ )
}
/** An initial definition of an `IRVariable`'s address. */
@@ -279,9 +331,11 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
DefAddressImpl() {
this = TDefAddressImpl(v) and
- ind = 0
+ indirectionIndex = 0
}
+ override string toString() { result = "Def of &" + v.toString() }
+
final override int getIndirection() { result = 0 }
final override predicate isCertain() { any() }
@@ -289,8 +343,15 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
final override Node0Impl getValue() { none() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
- block = v.getIRVariable().getEnclosingIRFunction().getEntryBlock() and
- index = 0
+ exists(IRVariable var | var = v.getIRVariable() |
+ block.getInstruction(index) = getInitializationTargetAddress(var)
+ or
+ // If there is no translatated element that does initialization of the
+ // variable we place the SSA definition at the entry block of the function.
+ not exists(getInitializationTargetAddress(var)) and
+ block = var.getEnclosingIRFunction().getEntryBlock() and
+ index = 0
+ )
}
override Cpp::Location getLocation() { result = v.getIRVariable().getLocation() }
@@ -300,95 +361,54 @@ private class DefAddressImpl extends DefImpl, TDefAddressImpl {
result.getIndirection() = 0
}
- final override BaseSourceVariableInstruction getBase() { none() }
+ final override BaseSourceVariable getBaseSourceVariable() { result = v }
}
-/**
- * An SSA definition that has an associated `Operand` representing the address
- * that is being written to.
- */
-abstract private class OperandBasedDef extends DefImpl {
+private class DirectDef extends DefImpl, TDirectDefImpl {
Operand address;
- bindingset[ind]
- OperandBasedDef() { any() }
-
- Operand getAddressOperand() { result = address }
+ DirectDef() { this = TDirectDefImpl(address, indirectionIndex) }
override Cpp::Location getLocation() { result = this.getAddressOperand().getUse().getLocation() }
final override predicate hasIndexInBlock(IRBlock block, int index) {
this.getAddressOperand().getUse() = block.getInstruction(index)
}
+
+ override string toString() { result = "Def of " + this.getSourceVariable() }
+
+ override Operand getAddressOperand() { result = address }
+
+ private BaseSourceVariableInstruction getBase() {
+ isDef(_, _, address, result, _, indirectionIndex)
+ }
+
+ override BaseSourceVariable getBaseSourceVariable() {
+ result = this.getBase().getBaseSourceVariable()
+ }
+
+ override int getIndirection() { isDef(_, _, address, _, result, indirectionIndex) }
+
+ override Node0Impl getValue() { isDef(_, result, address, _, _, _) }
+
+ override predicate isCertain() { isDef(true, _, address, _, _, indirectionIndex) }
}
-private class DirectDef extends OperandBasedDef, TDefImpl {
- BaseSourceVariableInstruction base;
+private class DirectUseImpl extends UseImpl, TDirectUseImpl {
+ Operand operand;
- DirectDef() { this = TDefImpl(base, address, ind) }
-
- override BaseSourceVariableInstruction getBase() { result = base }
-
- override int getIndirection() { isDef(_, _, address, base, result, ind) }
-
- override Node0Impl getValue() { isDef(_, result, address, base, _, _) }
-
- override predicate isCertain() { isDef(true, _, address, base, _, ind) }
-}
-
-private class IteratorDef extends OperandBasedDef, TIteratorDef {
- BaseSourceVariableInstruction container;
-
- IteratorDef() { this = TIteratorDef(address, container, ind) }
-
- override BaseSourceVariableInstruction getBase() { result = container }
-
- override int getIndirection() { isIteratorDef(container, address, _, result, ind) }
-
- override Node0Impl getValue() { isIteratorDef(container, address, result, _, _) }
-
- override predicate isCertain() { none() }
-}
-
-abstract class UseImpl extends DefOrUseImpl {
- int ind;
-
- bindingset[ind]
- UseImpl() { any() }
-
- /** Gets the node associated with this use. */
- abstract Node getNode();
+ DirectUseImpl() { this = TDirectUseImpl(operand, indirectionIndex) }
override string toString() { result = "Use of " + this.getSourceVariable() }
- /** Gets the indirection index of this use. */
- final override int getIndirectionIndex() { result = ind }
-
- /** Gets the number of loads that precedence this use. */
- abstract int getIndirection();
-
- /**
- * Holds if this use is guaranteed to read the
- * associated variable.
- */
- abstract predicate isCertain();
-}
-
-abstract private class OperandBasedUse extends UseImpl {
- Operand operand;
- BaseSourceVariableInstruction base;
-
- bindingset[ind]
- OperandBasedUse() { any() }
-
final override predicate hasIndexInBlock(IRBlock block, int index) {
// See the comment in `ssa0`'s `OperandBasedUse` for an explanation of this
// predicate's implementation.
- if base.getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
+ if this.getBase().getAst() = any(Cpp::PostfixCrementOperation c).getOperand()
then
- exists(Operand op, int indirectionIndex, int indirection |
- indirectionIndex = this.getIndirectionIndex() and
+ exists(Operand op, int indirection, Instruction base |
indirection = this.getIndirection() and
+ base = this.getBase() and
op =
min(Operand cand, int i |
isUse(_, cand, base, indirection, indirectionIndex) and
@@ -401,31 +421,21 @@ abstract private class OperandBasedUse extends UseImpl {
else operand.getUse() = block.getInstruction(index)
}
- final override BaseSourceVariableInstruction getBase() { result = base }
+ private BaseSourceVariableInstruction getBase() { isUse(_, operand, result, _, indirectionIndex) }
+
+ override BaseSourceVariable getBaseSourceVariable() {
+ result = this.getBase().getBaseSourceVariable()
+ }
final Operand getOperand() { result = operand }
final override Cpp::Location getLocation() { result = operand.getLocation() }
-}
-private class DirectUse extends OperandBasedUse, TUseImpl {
- DirectUse() { this = TUseImpl(base, operand, ind) }
+ override int getIndirection() { isUse(_, operand, _, result, indirectionIndex) }
- override int getIndirection() { isUse(_, operand, base, result, ind) }
+ override predicate isCertain() { isUse(true, operand, _, _, indirectionIndex) }
- override predicate isCertain() { isUse(true, operand, base, _, ind) }
-
- override Node getNode() { nodeHasOperand(result, operand, ind) }
-}
-
-private class IteratorUse extends OperandBasedUse, TIteratorUse {
- IteratorUse() { this = TIteratorUse(operand, base, ind) }
-
- override int getIndirection() { isIteratorUse(base, operand, result, ind) }
-
- override predicate isCertain() { none() }
-
- override Node getNode() { nodeHasOperand(result, operand, ind) }
+ override Node getNode() { nodeHasOperand(result, operand, indirectionIndex) }
}
pragma[nomagic]
@@ -439,15 +449,17 @@ private predicate finalParameterNodeHasParameterAndIndex(
class FinalParameterUse extends UseImpl, TFinalParameterUse {
Parameter p;
- FinalParameterUse() { this = TFinalParameterUse(p, ind) }
+ FinalParameterUse() { this = TFinalParameterUse(p, indirectionIndex) }
+
+ override string toString() { result = "Use of " + p.toString() }
Parameter getParameter() { result = p }
int getArgumentIndex() { result = p.getIndex() }
- override Node getNode() { finalParameterNodeHasParameterAndIndex(result, p, ind) }
+ override Node getNode() { finalParameterNodeHasParameterAndIndex(result, p, indirectionIndex) }
- override int getIndirection() { result = ind + 1 }
+ override int getIndirection() { result = indirectionIndex + 1 }
override predicate isCertain() { any() }
@@ -480,13 +492,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
result instanceof UnknownDefaultLocation
}
- override BaseSourceVariableInstruction getBase() {
- exists(InitializeParameterInstruction init |
- init.getParameter() = p and
- // This is always a `VariableAddressInstruction`
- result = init.getAnOperand().getDef()
- )
- }
+ override BaseIRVariable getBaseSourceVariable() { result.getIRVariable().getAst() = p }
}
/**
@@ -544,11 +550,13 @@ class GlobalUse extends UseImpl, TGlobalUse {
GlobalLikeVariable global;
IRFunction f;
- GlobalUse() { this = TGlobalUse(global, f, ind) }
+ GlobalUse() { this = TGlobalUse(global, f, indirectionIndex) }
+
+ override string toString() { result = "Use of " + global }
override FinalGlobalValue getNode() { result.getGlobalUse() = this }
- override int getIndirection() { isGlobalUse(global, f, result, ind) }
+ override int getIndirection() { isGlobalUse(global, f, result, indirectionIndex) }
/** Gets the global variable associated with this use. */
GlobalLikeVariable getVariable() { result = global }
@@ -570,8 +578,8 @@ class GlobalUse extends UseImpl, TGlobalUse {
)
}
- override SourceVariable getSourceVariable() {
- sourceVariableIsGlobal(result, global, f, this.getIndirection())
+ override BaseSourceVariable getBaseSourceVariable() {
+ baseSourceVariableIsGlobal(result, global, f)
}
final override Cpp::Location getLocation() { result = f.getLocation() }
@@ -588,8 +596,6 @@ class GlobalUse extends UseImpl, TGlobalUse {
Type getUnderlyingType() { result = global.getUnderlyingType() }
override predicate isCertain() { any() }
-
- override BaseSourceVariableInstruction getBase() { none() }
}
/**
@@ -598,10 +604,9 @@ class GlobalUse extends UseImpl, TGlobalUse {
*
* See the QLDoc for `GlobalUse` for how this is used.
*/
-class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
+class GlobalDefImpl extends DefImpl, TGlobalDefImpl {
GlobalLikeVariable global;
IRFunction f;
- int indirectionIndex;
GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) }
@@ -611,9 +616,6 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
/** Gets the `IRFunction` whose body is evaluated after this definition. */
IRFunction getIRFunction() { result = f }
- /** Gets the global variable associated with this definition. */
- override int getIndirectionIndex() { result = indirectionIndex }
-
/** Holds if this definition or use has index `index` in block `block`. */
final override predicate hasIndexInBlock(IRBlock block, int index) {
exists(EnterFunctionInstruction enter |
@@ -623,11 +625,15 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
}
/** Gets the global variable associated with this definition. */
- override SourceVariable getSourceVariable() {
- sourceVariableIsGlobal(result, global, f, this.getIndirection())
+ override BaseSourceVariable getBaseSourceVariable() {
+ baseSourceVariableIsGlobal(result, global, f)
}
- int getIndirection() { result = indirectionIndex }
+ override int getIndirection() { result = indirectionIndex }
+
+ override Node0Impl getValue() { none() }
+
+ override predicate isCertain() { any() }
/**
* Gets the type of this definition after specifiers have been deeply
@@ -643,65 +649,33 @@ class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
override string toString() { result = "Def of " + this.getSourceVariable() }
override Location getLocation() { result = f.getLocation() }
-
- override BaseSourceVariableInstruction getBase() { none() }
}
/**
- * Holds if `defOrUse1` is a definition which is first read by `use`,
- * or if `defOrUse1` is a use and `use` is a next subsequent use.
- *
- * In both cases, `use` can either be an explicit use written in the
- * source file, or it can be a phi node as computed by the SSA library.
+ * Holds if there is a definition or access at index `i1` in basic block `bb1`
+ * and the next subsequent read is at index `i2` in basic block `bb2`.
*/
-predicate adjacentDefRead(DefOrUse defOrUse1, UseOrPhi use) {
- exists(IRBlock bb1, int i1, SourceVariable v |
- defOrUse1
- .asDefOrUse()
- .hasIndexInBlock(pragma[only_bind_out](bb1), pragma[only_bind_out](i1),
- pragma[only_bind_out](v))
- |
- exists(IRBlock bb2, int i2, DefinitionExt def |
- adjacentDefReadExt(pragma[only_bind_into](def), pragma[only_bind_into](bb1),
- pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
- def.getSourceVariable() = v and
- use.asDefOrUse().(UseImpl).hasIndexInBlock(bb2, i2, v)
- )
- or
- exists(PhiNode phi |
- lastRefRedefExt(_, bb1, i1, phi) and
- use.asPhi() = phi and
- phi.getSourceVariable() = pragma[only_bind_into](v)
- )
+predicate adjacentDefRead(IRBlock bb1, int i1, SourceVariable sv, IRBlock bb2, int i2) {
+ adjacentDefReadExt(_, sv, bb1, i1, bb2, i2)
+ or
+ exists(PhiNode phi |
+ lastRefRedefExt(_, sv, bb1, i1, phi) and
+ phi.definesAt(sv, bb2, i2, _)
)
}
-/**
- * Holds if `globalDef` represents the initial definition of a global variable that
- * flows to `useOrPhi`.
- */
-private predicate globalDefToUse(GlobalDef globalDef, UseOrPhi useOrPhi) {
- exists(IRBlock bb1, int i1, SourceVariable v |
- globalDef
- .hasIndexInBlock(pragma[only_bind_out](bb1), pragma[only_bind_out](i1),
- pragma[only_bind_out](v))
- |
- exists(IRBlock bb2, int i2 |
- adjacentDefReadExt(_, pragma[only_bind_into](bb1), pragma[only_bind_into](i1),
- pragma[only_bind_into](bb2), pragma[only_bind_into](i2)) and
- useOrPhi.asDefOrUse().hasIndexInBlock(bb2, i2, v)
- )
- or
- exists(PhiNode phi |
- lastRefRedefExt(_, bb1, i1, phi) and
- useOrPhi.asPhi() = phi and
- phi.getSourceVariable() = pragma[only_bind_into](v)
- )
+predicate useToNode(IRBlock bb, int i, SourceVariable sv, Node nodeTo) {
+ exists(Phi phi |
+ phi.asPhi().definesAt(sv, bb, i, _) and
+ nodeTo = phi.getNode()
+ )
+ or
+ exists(UseImpl use |
+ use.hasIndexInBlock(bb, i, sv) and
+ nodeTo = use.getNode()
)
}
-private predicate useToNode(UseOrPhi use, Node nodeTo) { use.getNode() = nodeTo }
-
pragma[noinline]
predicate outNodeHasAddressAndIndex(
IndirectArgumentOutNode out, Operand address, int indirectionIndex
@@ -710,11 +684,19 @@ predicate outNodeHasAddressAndIndex(
out.getIndirectionIndex() = indirectionIndex
}
-private predicate defToNode(Node nodeFrom, Def def, boolean uncertain) {
+/**
+ * INTERNAL: Do not use.
+ *
+ * Holds if `node` is the node that corresponds to the definition of `def`.
+ */
+predicate defToNode(Node node, Def def, SourceVariable sv, IRBlock bb, int i, boolean uncertain) {
+ def.hasIndexInBlock(bb, i, sv) and
(
- nodeHasOperand(nodeFrom, def.getValue().asOperand(), def.getIndirectionIndex())
+ nodeHasOperand(node, def.getValue().asOperand(), def.getIndirectionIndex())
or
- nodeHasInstruction(nodeFrom, def.getValue().asInstruction(), def.getIndirectionIndex())
+ nodeHasInstruction(node, def.getValue().asInstruction(), def.getIndirectionIndex())
+ or
+ node.(InitialGlobalValue).getGlobalDef() = def
) and
if def.isCertain() then uncertain = false else uncertain = true
}
@@ -722,14 +704,16 @@ private predicate defToNode(Node nodeFrom, Def def, boolean uncertain) {
/**
* INTERNAL: Do not use.
*
- * Holds if `nodeFrom` is the node that correspond to the definition or use `defOrUse`.
+ * Holds if `node` is the node that corresponds to the definition or use at
+ * index `i` in block `bb` of `sv`.
+ *
+ * `uncertain` is `true` if this is an uncertain definition.
*/
-predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse, boolean uncertain) {
- // Node -> Def
- defToNode(nodeFrom, defOrUse, uncertain)
+predicate nodeToDefOrUse(Node node, SourceVariable sv, IRBlock bb, int i, boolean uncertain) {
+ defToNode(node, _, sv, bb, i, uncertain)
or
// Node -> Use
- useToNode(defOrUse, nodeFrom) and
+ useToNode(bb, i, sv, node) and
uncertain = false
}
@@ -738,9 +722,9 @@ predicate nodeToDefOrUse(Node nodeFrom, SsaDefOrUse defOrUse, boolean uncertain)
* only holds when there is no use-use relation out of `nTo`.
*/
private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
- not exists(UseOrPhi defOrUse |
- nodeToDefOrUse(nTo, defOrUse, _) and
- adjacentDefRead(defOrUse, _)
+ not exists(SourceVariable sv, IRBlock bb2, int i2 |
+ nodeToDefOrUse(nTo, sv, bb2, i2, _) and
+ adjacentDefRead(bb2, i2, sv, _, _)
) and
(
exists(Operand op1, Operand op2, int indirectionIndex, Instruction instr |
@@ -774,60 +758,39 @@ private predicate indirectConversionFlowStep(Node nFrom, Node nTo) {
* So this predicate recurses back along conversions and `PointerArithmeticInstruction`s to find the
* first use that has provides use-use flow, and uses that target as the target of the `nodeFrom`.
*/
-private predicate adjustForPointerArith(PostUpdateNode pun, UseOrPhi use) {
- exists(DefOrUse defOrUse, Node adjusted |
+private predicate adjustForPointerArith(PostUpdateNode pun, SourceVariable sv, IRBlock bb2, int i2) {
+ exists(IRBlock bb1, int i1, Node adjusted |
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
- nodeToDefOrUse(adjusted, defOrUse, _) and
- adjacentDefRead(defOrUse, use)
+ nodeToDefOrUse(adjusted, sv, bb1, i1, _) and
+ adjacentDefRead(bb1, i1, sv, bb2, i2)
)
}
/**
- * Holds if `nodeFrom` flows to `nodeTo` because there is `def-use` or
- * `use-use` flow from `defOrUse` to `use`.
+ * Holds if there should be flow from `nodeFrom` to `nodeTo` because
+ * `nodeFrom` is a definition or use of `sv` at index `i1` at basic
+ * block `bb1`.
*
- * `uncertain` is `true` if the `defOrUse` is an uncertain definition.
+ * `uncertain` is `true` if `(bb1, i1)` is a definition, and that definition
+ * is _not_ guaranteed to overwrite the entire allocation.
*/
-private predicate localSsaFlow(
- SsaDefOrUse defOrUse, Node nodeFrom, UseOrPhi use, Node nodeTo, boolean uncertain
+private predicate ssaFlowImpl(
+ IRBlock bb1, int i1, SourceVariable sv, Node nodeFrom, Node nodeTo, boolean uncertain
) {
- nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and
- adjacentDefRead(defOrUse, use) and
- useToNode(use, nodeTo) and
+ exists(IRBlock bb2, int i2 |
+ nodeToDefOrUse(nodeFrom, sv, bb1, i1, uncertain) and
+ adjacentDefRead(bb1, i1, sv, bb2, i2) and
+ useToNode(bb2, i2, sv, nodeTo)
+ ) and
nodeFrom != nodeTo
}
-private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) {
- exists(UseOrPhi use |
- localSsaFlow(defOrUse, nodeFrom, use, nodeTo, uncertain)
- or
- // Initial global variable value to a first use
- nodeFrom.(InitialGlobalValue).getGlobalDef() = defOrUse and
- globalDefToUse(defOrUse, use) and
- useToNode(use, nodeTo) and
- uncertain = false
- )
-}
-
-/**
- * Holds if `def` is the corresponding definition of
- * the SSA library's `definition`.
- */
-private DefinitionExt ssaDefinition(Def def) {
- exists(IRBlock block, int i, SourceVariable sv |
- def.hasIndexInBlock(block, i, sv) and
- result.definesAt(sv, block, i, _)
- )
-}
-
/** Gets a node that represents the prior definition of `node`. */
-private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
- exists(IRBlock bb, int i, SourceVariable sv, DefinitionExt def, DefOrUse defOrUse0 |
- lastRefRedefExt(pragma[only_bind_into](def), pragma[only_bind_into](bb),
- pragma[only_bind_into](i), ssaDefinition(defOrUse)) and
- def.getSourceVariable() = sv and
- defOrUse0.hasIndexInBlock(bb, i, sv) and
- nodeToDefOrUse(result, defOrUse0, _)
+private Node getAPriorDefinition(DefinitionExt next) {
+ exists(IRBlock bb, int i, SourceVariable sv |
+ lastRefRedefExt(_, pragma[only_bind_into](sv), pragma[only_bind_into](bb),
+ pragma[only_bind_into](i), next) and
+ nodeToDefOrUse(result, sv, bb, i, _)
)
}
@@ -879,12 +842,16 @@ private predicate modeledFlowBarrier(Node n) {
/** Holds if there is def-use or use-use flow from `nodeFrom` to `nodeTo`. */
predicate ssaFlow(Node nodeFrom, Node nodeTo) {
- exists(Node nFrom, boolean uncertain, SsaDefOrUse defOrUse |
- ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
+ exists(Node nFrom, boolean uncertain, IRBlock bb, int i, SourceVariable sv |
+ ssaFlowImpl(bb, i, sv, nFrom, nodeTo, uncertain) and
not modeledFlowBarrier(nFrom) and
nodeFrom != nodeTo
|
- if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
+ if uncertain = true
+ then
+ nodeFrom =
+ [nFrom, getAPriorDefinition(any(DefinitionExt next | next.definesAt(sv, bb, i, _)))]
+ else nodeFrom = nFrom
)
}
@@ -929,15 +896,15 @@ private predicate isArgumentOfCallable(DataFlowCall call, Node n) {
* Holds if there is use-use flow from `pun`'s pre-update node to `n`.
*/
private predicate postUpdateNodeToFirstUse(PostUpdateNode pun, Node n) {
- exists(UseOrPhi use |
- adjustForPointerArith(pun, use) and
- useToNode(use, n)
+ exists(SourceVariable sv, IRBlock bb2, int i2 |
+ adjustForPointerArith(pun, sv, bb2, i2) and
+ useToNode(bb2, i2, sv, n)
)
}
private predicate stepUntilNotInCall(DataFlowCall call, Node n1, Node n2) {
isArgumentOfCallable(call, n1) and
- exists(Node mid | localSsaFlow(_, n1, _, mid, _) |
+ exists(Node mid | ssaFlowImpl(_, _, _, n1, mid, _) |
isArgumentOfCallable(call, mid) and
stepUntilNotInCall(call, mid, n2)
or
@@ -984,43 +951,20 @@ predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
)
}
-/**
- * Holds if `use` is a use of `sv` and is a next adjacent use of `phi` in
- * index `i1` in basic block `bb1`.
- *
- * This predicate exists to prevent an early join of `adjacentDefRead` with `definesAt`.
- */
-pragma[nomagic]
-private predicate fromPhiNodeToUse(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use) {
- exists(IRBlock bb2, int i2 |
- use.asDefOrUse().hasIndexInBlock(bb2, i2, sv) and
- adjacentDefReadExt(pragma[only_bind_into](phi), pragma[only_bind_into](bb1),
- pragma[only_bind_into](i1), pragma[only_bind_into](bb2), pragma[only_bind_into](i2))
- )
-}
-
/** Holds if `nodeTo` receives flow from the phi node `nodeFrom`. */
predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
- exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, UseOrPhi use |
+ exists(PhiNode phi, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2 |
phi = nodeFrom.getPhiNode() and
phi.definesAt(sv, bb1, i1, _) and
- useToNode(use, nodeTo)
- |
- fromPhiNodeToUse(phi, sv, bb1, i1, use)
- or
- exists(PhiNode phiTo |
- phi != phiTo and
- lastRefRedefExt(phi, bb1, i1, phiTo) and
- nodeTo.(SsaPhiNode).getPhiNode() = phiTo
- )
+ adjacentDefRead(bb1, i1, sv, bb2, i2) and
+ useToNode(bb2, i2, sv, nodeTo)
)
}
-private predicate sourceVariableIsGlobal(
- SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
+private predicate baseSourceVariableIsGlobal(
+ BaseIRVariable base, GlobalLikeVariable global, IRFunction func
) {
- exists(IRVariable irVar, BaseIRVariable base |
- sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and
+ exists(IRVariable irVar |
irVar = base.getIRVariable() and
irVar.getEnclosingIRFunction() = func and
global = irVar.getAst() and
@@ -1077,8 +1021,10 @@ module SsaCached {
* path between them without any read of `def`.
*/
cached
- predicate adjacentDefReadExt(DefinitionExt def, IRBlock bb1, int i1, IRBlock bb2, int i2) {
- SsaImpl::adjacentDefReadExt(def, _, bb1, i1, bb2, i2)
+ predicate adjacentDefReadExt(
+ DefinitionExt def, SourceVariable sv, IRBlock bb1, int i1, IRBlock bb2, int i2
+ ) {
+ SsaImpl::adjacentDefReadExt(def, sv, bb1, i1, bb2, i2)
}
/**
@@ -1087,32 +1033,38 @@ module SsaCached {
* without passing through another read or write.
*/
cached
- predicate lastRefRedefExt(DefinitionExt def, IRBlock bb, int i, DefinitionExt next) {
- SsaImpl::lastRefRedefExt(def, _, bb, i, next)
+ predicate lastRefRedefExt(
+ DefinitionExt def, SourceVariable sv, IRBlock bb, int i, DefinitionExt next
+ ) {
+ SsaImpl::lastRefRedefExt(def, sv, bb, i, next)
}
+
+ cached
+ Definition phiHasInputFromBlock(PhiNode phi, IRBlock bb) {
+ SsaImpl::phiHasInputFromBlock(phi, result, bb)
+ }
+
+ cached
+ predicate ssaDefReachesRead(SourceVariable v, Definition def, IRBlock bb, int i) {
+ SsaImpl::ssaDefReachesRead(v, def, bb, i)
+ }
+
+ predicate variableRead = SsaInput::variableRead/4;
+
+ predicate variableWrite = SsaInput::variableWrite/4;
}
cached
-private newtype TSsaDefOrUse =
- TDefOrUse(DefOrUseImpl defOrUse) {
- defOrUse instanceof UseImpl
- or
- // Like in the pruning stage, we only include definition that's live after the
- // write as the final definitions computed by SSA.
- exists(DefinitionExt def, SourceVariable sv, IRBlock bb, int i |
- def.definesAt(sv, bb, i, _) and
- defOrUse.(DefImpl).hasIndexInBlock(bb, i, sv)
- )
- } or
- TPhi(PhiNode phi) or
- TGlobalDef(GlobalDefImpl global)
+private newtype TSsaDef =
+ TDef(DefinitionExt def) or
+ TPhi(PhiNode phi)
-abstract private class SsaDefOrUse extends TSsaDefOrUse {
+abstract private class SsaDef extends TSsaDef {
/** Gets a textual representation of this element. */
string toString() { none() }
/** Gets the underlying non-phi definition or use. */
- DefOrUseImpl asDefOrUse() { none() }
+ DefinitionExt asDef() { none() }
/** Gets the underlying phi node. */
PhiNode asPhi() { none() }
@@ -1121,52 +1073,97 @@ abstract private class SsaDefOrUse extends TSsaDefOrUse {
abstract Location getLocation();
}
-class DefOrUse extends TDefOrUse, SsaDefOrUse {
- DefOrUseImpl defOrUse;
+abstract class Def extends SsaDef, TDef {
+ DefinitionExt def;
- DefOrUse() { this = TDefOrUse(defOrUse) }
+ Def() { this = TDef(def) }
- final override DefOrUseImpl asDefOrUse() { result = defOrUse }
+ final override DefinitionExt asDef() { result = def }
- final override Location getLocation() { result = defOrUse.getLocation() }
+ /** Gets the source variable underlying this SSA definition. */
+ final SourceVariable getSourceVariable() { result = def.getSourceVariable() }
- final SourceVariable getSourceVariable() { result = defOrUse.getSourceVariable() }
-
- override string toString() { result = defOrUse.toString() }
+ override string toString() { result = def.toString() }
/**
* Holds if this definition (or use) has index `index` in block `block`,
* and is a definition (or use) of the variable `sv`.
*/
predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
- defOrUse.hasIndexInBlock(block, index, sv)
+ def.definesAt(sv, block, index, _)
}
+
+ /** Gets the value written by this definition, if any. */
+ Node0Impl getValue() { none() }
+
+ /**
+ * Holds if this definition is guaranteed to overwrite the entire
+ * destination's allocation.
+ */
+ abstract predicate isCertain();
+
+ /** Gets the address operand written to by this definition. */
+ Operand getAddressOperand() { none() }
+
+ /** Gets the address written to by this definition. */
+ final Instruction getAddress() { result = this.getAddressOperand().getDef() }
+
+ /** Gets the indirection index of this definition. */
+ abstract int getIndirectionIndex();
+
+ /**
+ * Gets the indirection level that this definition is writing to.
+ * For instance, `x = y` is a definition of `x` at indirection level 1 and
+ * `*x = y` is a definition of `x` at indirection level 2.
+ */
+ abstract int getIndirection();
+
+ /**
+ * Gets a definition that ultimately defines this SSA definition and is not
+ * itself a phi node.
+ */
+ Def getAnUltimateDefinition() { result.asDef() = def.getAnUltimateDefinition() }
}
-class GlobalDef extends TGlobalDef, SsaDefOrUse {
+private predicate isGlobal(DefinitionExt def, GlobalDefImpl global) {
+ exists(SourceVariable sv, IRBlock bb, int i |
+ def.definesAt(sv, bb, i, _) and
+ global.hasIndexInBlock(bb, i, sv)
+ )
+}
+
+private class NonGlobalDef extends Def {
+ NonGlobalDef() { not isGlobal(def, _) }
+
+ final override Location getLocation() { result = this.getImpl().getLocation() }
+
+ private DefImpl getImpl() {
+ exists(SourceVariable sv, IRBlock bb, int i |
+ this.hasIndexInBlock(bb, i, sv) and
+ result.hasIndexInBlock(bb, i, sv)
+ )
+ }
+
+ override Node0Impl getValue() { result = this.getImpl().getValue() }
+
+ override predicate isCertain() { this.getImpl().isCertain() }
+
+ override Operand getAddressOperand() { result = this.getImpl().getAddressOperand() }
+
+ override int getIndirectionIndex() { result = this.getImpl().getIndirectionIndex() }
+
+ override int getIndirection() { result = this.getImpl().getIndirection() }
+}
+
+class GlobalDef extends Def {
GlobalDefImpl global;
- GlobalDef() { this = TGlobalDef(global) }
-
- /** Gets the location of this definition. */
- final override Location getLocation() { result = global.getLocation() }
+ GlobalDef() { isGlobal(def, global) }
/** Gets a textual representation of this definition. */
override string toString() { result = global.toString() }
- /**
- * Holds if this definition has index `index` in block `block`, and
- * is a definition of the variable `sv`.
- */
- predicate hasIndexInBlock(IRBlock block, int index, SourceVariable sv) {
- global.hasIndexInBlock(block, index, sv)
- }
-
- /** Gets the indirection index of this definition. */
- int getIndirection() { result = global.getIndirection() }
-
- /** Gets the indirection index of this definition. */
- int getIndirectionIndex() { result = global.getIndirectionIndex() }
+ final override Location getLocation() { result = global.getLocation() }
/**
* Gets the type of this definition after specifiers have been deeply stripped
@@ -1184,9 +1181,15 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
/** Gets the global variable associated with this definition. */
GlobalLikeVariable getVariable() { result = global.getVariable() }
+
+ override predicate isCertain() { any() }
+
+ final override int getIndirectionIndex() { result = global.getIndirectionIndex() }
+
+ final override int getIndirection() { result = global.getIndirection() }
}
-class Phi extends TPhi, SsaDefOrUse {
+class Phi extends TPhi, SsaDef {
PhiNode phi;
Phi() { this = TPhi(phi) }
@@ -1198,64 +1201,19 @@ class Phi extends TPhi, SsaDefOrUse {
override string toString() { result = "Phi" }
SsaPhiNode getNode() { result.getPhiNode() = phi }
-}
-class UseOrPhi extends SsaDefOrUse {
- UseOrPhi() {
- this.asDefOrUse() instanceof UseImpl
- or
- this instanceof Phi
- }
+ predicate hasInputFromBlock(Definition inp, IRBlock bb) { inp = phiHasInputFromBlock(phi, bb) }
- final override Location getLocation() {
- result = this.asDefOrUse().getLocation() or result = this.(Phi).getLocation()
- }
-
- final Node getNode() {
- result = this.(Phi).getNode()
- or
- result = this.asDefOrUse().(UseImpl).getNode()
- }
-}
-
-class Def extends DefOrUse {
- override DefImpl defOrUse;
-
- Operand getAddressOperand() { result = defOrUse.(OperandBasedDef).getAddressOperand() }
-
- Instruction getAddress() { result = this.getAddressOperand().getDef() }
-
- /**
- * Gets the indirection index of this definition.
- *
- * This predicate ensures that joins go from `defOrUse` to the result
- * instead of the other way around.
- */
- pragma[inline]
- int getIndirectionIndex() {
- pragma[only_bind_into](result) = pragma[only_bind_out](defOrUse).getIndirectionIndex()
- }
-
- /**
- * Gets the indirection level that this definition is writing to.
- * For instance, `x = y` is a definition of `x` at indirection level 1 and
- * `*x = y` is a definition of `x` at indirection level 2.
- *
- * This predicate ensures that joins go from `defOrUse` to the result
- * instead of the other way around.
- */
- pragma[inline]
- int getIndirection() {
- pragma[only_bind_into](result) = pragma[only_bind_out](defOrUse).getIndirection()
- }
-
- Node0Impl getValue() { result = defOrUse.getValue() }
-
- predicate isCertain() { defOrUse.isCertain() }
+ final Definition getAnInput() { this.hasInputFromBlock(result, _) }
}
private module SsaImpl = SsaImplCommon::Make;
+/**
+ * An static single assignment (SSA) phi node.
+ *
+ * This is either a normal phi node or a phi-read node.
+ */
class PhiNode extends SsaImpl::DefinitionExt {
PhiNode() {
this instanceof SsaImpl::PhiNode or
@@ -1269,10 +1227,30 @@ class PhiNode extends SsaImpl::DefinitionExt {
* on reads instead of writes.
*/
predicate isPhiRead() { this instanceof SsaImpl::PhiReadNode }
+
+ /** Holds if `inp` is an input to this phi node along the edge originating in `bb`. */
+ predicate hasInputFromBlock(Definition inp, IRBlock bb) {
+ inp = SsaCached::phiHasInputFromBlock(this, bb)
+ }
+
+ /** Gets a definition that is an input to this phi node. */
+ final Definition getAnInput() { this.hasInputFromBlock(result, _) }
}
-class DefinitionExt = SsaImpl::DefinitionExt;
+/** An static single assignment (SSA) definition. */
+class DefinitionExt extends SsaImpl::DefinitionExt {
+ private Definition getAPhiInputOrPriorDefinition() { result = this.(PhiNode).getAnInput() }
-class UncertainWriteDefinition = SsaImpl::UncertainWriteDefinition;
+ /**
+ * Gets a definition that ultimately defines this SSA definition and is
+ * not itself a phi node.
+ */
+ final DefinitionExt getAnUltimateDefinition() {
+ result = this.getAPhiInputOrPriorDefinition*() and
+ not result instanceof PhiNode
+ }
+}
+
+class Definition = SsaImpl::Definition;
import SsaCached
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll
index 7e5b4de8122..0920e5a3865 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/SsaInternalsCommon.qll
@@ -246,14 +246,6 @@ private module IteratorIndirections {
baseType = super.getValueType()
}
- override predicate isAdditionalDereference(Instruction deref, Operand address) {
- exists(CallInstruction call |
- operandForFullyConvertedCall(getAUse(deref), call) and
- this = call.getStaticCallTarget().getClassAndName("operator*") and
- address = call.getThisArgumentOperand()
- )
- }
-
override predicate isAdditionalWrite(Node0Impl value, Operand address, boolean certain) {
exists(CallInstruction call | call.getArgumentOperand(0) = value.asOperand() |
this = call.getStaticCallTarget().getClassAndName("operator=") and
@@ -262,16 +254,6 @@ private module IteratorIndirections {
)
}
- override predicate isAdditionalTaintStep(Node node1, Node node2) {
- exists(CallInstruction call |
- // Taint through `operator+=` and `operator-=` on iterators.
- call.getStaticCallTarget() instanceof Iterator::IteratorAssignArithmeticOperator and
- node2.(IndirectArgumentOutNode).getPreUpdateNode() = node1 and
- node1.(IndirectOperand).hasOperandAndIndirectionIndex(call.getArgumentOperand(0), _) and
- node1.getType().getUnspecifiedType() = this
- )
- }
-
override predicate isAdditionalConversionFlow(Operand opFrom, Instruction instrTo) {
// This is a bit annoying: Consider the following snippet:
// ```
@@ -589,230 +571,6 @@ private class BaseCallInstruction extends BaseSourceVariableInstruction, CallIns
cached
private module Cached {
- private import semmle.code.cpp.models.interfaces.Iterator as Interfaces
- private import semmle.code.cpp.models.implementations.Iterator as Iterator
- private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
-
- /**
- * Holds if `next` is a instruction with a memory result that potentially
- * updates the memory produced by `prev`.
- */
- private predicate memorySucc(Instruction prev, Instruction next) {
- prev = next.(ChiInstruction).getTotal()
- or
- // Phi inputs can be inexact.
- prev = next.(PhiInstruction).getAnInputOperand().getAnyDef()
- or
- prev = next.(CopyInstruction).getSourceValue()
- or
- exists(ReadSideEffectInstruction read |
- next = read.getPrimaryInstruction() and
- isAdditionalConversionFlow(_, next) and
- prev = read.getSideEffectOperand().getAnyDef()
- )
- }
-
- /**
- * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
- * that is used for a write operation that writes the value `value`. The `memory` instruction
- * represents the memory that the IR's SSA analysis determined was read by the call to `operator*`.
- *
- * The `numberOfLoads` integer represents the number of dereferences this write corresponds to
- * on the underlying container that produced the iterator.
- */
- private predicate isChiAfterIteratorDef(
- Instruction memory, Operand iteratorDerefAddress, Node0Impl value, int numberOfLoads
- ) {
- exists(
- BaseSourceVariableInstruction iteratorBase, ReadSideEffectInstruction read,
- Operand iteratorAddress
- |
- numberOfLoads >= 0 and
- isDef(_, value, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
- isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
- iteratorBase.getResultType() instanceof Interfaces::Iterator and
- isDereference(iteratorAddress.getDef(), read.getArgumentDef().getAUse(), _) and
- memory = read.getSideEffectOperand().getAnyDef()
- )
- }
-
- private predicate isSource(Instruction instr, Operand iteratorAddress, int numberOfLoads) {
- getAUse(instr) = iteratorAddress and
- exists(BaseSourceVariableInstruction iteratorBase |
- iteratorBase.getResultType() instanceof Interfaces::Iterator and
- not iteratorBase.getResultType() instanceof Cpp::PointerType and
- isUse(_, iteratorAddress, iteratorBase, numberOfLoads - 1, 0)
- )
- }
-
- private predicate isSink(Instruction instr, CallInstruction call) {
- getAUse(instr).(ArgumentOperand).getCall() = call and
- // Only include operations that may modify the object that the iterator points to.
- // The following is a non-exhaustive list of things that may modify the value of the
- // iterator, but never the value of what the iterator points to.
- // The more things we can exclude here, the faster the small dataflow-like analysis
- // done by `convertsIntoArgument` will converge.
- not exists(Function f | f = call.getStaticCallTarget() |
- f instanceof Iterator::IteratorCrementOperator or
- f instanceof Iterator::IteratorBinaryArithmeticOperator or
- f instanceof Iterator::IteratorAssignArithmeticOperator or
- f instanceof Iterator::IteratorCrementMemberOperator or
- f instanceof Iterator::IteratorBinaryArithmeticMemberOperator or
- f instanceof Iterator::IteratorAssignArithmeticMemberOperator or
- f instanceof Iterator::IteratorAssignmentMemberOperator
- )
- }
-
- private predicate convertsIntoArgumentFwd(Instruction instr) {
- isSource(instr, _, _)
- or
- exists(Instruction prev | convertsIntoArgumentFwd(prev) |
- conversionFlow(unique( | | getAUse(prev)), instr, false, _)
- )
- }
-
- private predicate convertsIntoArgumentRev(Instruction instr) {
- convertsIntoArgumentFwd(instr) and
- (
- isSink(instr, _)
- or
- exists(Instruction next | convertsIntoArgumentRev(next) |
- conversionFlow(unique( | | getAUse(instr)), next, false, _)
- )
- )
- }
-
- private predicate convertsIntoArgument(
- Operand iteratorAddress, CallInstruction call, int numberOfLoads
- ) {
- exists(Instruction iteratorAddressDef |
- isSource(iteratorAddressDef, iteratorAddress, numberOfLoads) and
- isSink(iteratorAddressDef, call) and
- convertsIntoArgumentRev(pragma[only_bind_into](iteratorAddressDef))
- )
- }
-
- private predicate isChiAfterIteratorArgument(
- Instruction memory, Operand iteratorAddress, int numberOfLoads
- ) {
- // Ideally, `iteratorAddress` would be an `ArgumentOperand`, but there might be
- // various conversions applied to it before it becomes an argument.
- // So we do a small amount of flow to find the call that the iterator is passed to.
- exists(CallInstruction call | convertsIntoArgument(iteratorAddress, call, numberOfLoads) |
- exists(ReadSideEffectInstruction read |
- read.getPrimaryInstruction() = call and
- read.getSideEffectOperand().getAnyDef() = memory
- )
- or
- exists(LoadInstruction load |
- iteratorAddress.getDef() = load and
- memory = load.getSourceValueOperand().getAnyDef()
- )
- )
- }
-
- /**
- * Holds if `iterator` is a `StoreInstruction` that stores the result of some function
- * returning an iterator into an address computed started at `containerBase`.
- *
- * For example, given a declaration like `std::vector::iterator it = v.begin()`,
- * the `iterator` will be the `StoreInstruction` generated by the write to `it`, and
- * `containerBase` will be the address of `v`.
- */
- private predicate isChiAfterBegin(
- BaseSourceVariableInstruction containerBase, StoreInstruction iterator
- ) {
- exists(
- CallInstruction getIterator, Iterator::GetIteratorFunction getIteratorFunction,
- IO::FunctionInput input, int i
- |
- getIterator = iterator.getSourceValue() and
- getIteratorFunction = getIterator.getStaticCallTarget() and
- getIteratorFunction.getsIterator(input, _) and
- isDef(_, any(Node0Impl n | n.asInstruction() = iterator), _, _, 1, 0) and
- input.isParameterDerefOrQualifierObject(i) and
- isUse(_, getIterator.getArgumentOperand(i), containerBase, 0, 0)
- )
- }
-
- /**
- * Holds if `iteratorAddress` is an address of an iterator that is used for
- * a read operation. The `memory` instruction represents the memory that
- * the IR's SSA analysis determined was read by the call to `operator*`.
- *
- * Finally, the `numberOfLoads` integer represents the number of dereferences
- * this read corresponds to on the underlying container that produced the iterator.
- */
- private predicate isChiBeforeIteratorUse(
- Operand iteratorAddress, Instruction memory, int numberOfLoads
- ) {
- exists(
- BaseSourceVariableInstruction iteratorBase, LoadInstruction load,
- ReadSideEffectInstruction read, Operand iteratorDerefAddress
- |
- numberOfLoads >= 0 and
- isUse(_, iteratorAddress, iteratorBase, numberOfLoads + 1, 0) and
- isUse(_, iteratorDerefAddress, iteratorBase, numberOfLoads + 2, 0) and
- iteratorBase.getResultType() instanceof Interfaces::Iterator and
- load.getSourceAddressOperand() = iteratorDerefAddress and
- read.getPrimaryInstruction() = load.getSourceAddress() and
- memory = read.getSideEffectOperand().getAnyDef()
- )
- }
-
- /**
- * Holds if `iteratorDerefAddress` is an address of an iterator dereference (i.e., `*it`)
- * that is used for a write operation that writes the value `value` to a container that
- * created the iterator. `container` represents the base of the address of the container
- * that was used to create the iterator.
- */
- cached
- predicate isIteratorDef(
- BaseSourceVariableInstruction container, Operand iteratorDerefAddress, Node0Impl value,
- int numberOfLoads, int indirectionIndex
- ) {
- exists(Instruction memory, Instruction begin, int upper, int ind |
- isChiAfterIteratorDef(memory, iteratorDerefAddress, value, numberOfLoads) and
- memorySucc*(begin, memory) and
- isChiAfterBegin(container, begin) and
- upper = countIndirectionsForCppType(getResultLanguageType(container)) and
- ind = numberOfLoads + [1 .. upper] and
- indirectionIndex = ind - (numberOfLoads + 1)
- )
- }
-
- /**
- * Holds if `iteratorAddress` is an address of an iterator that is used for a
- * read operation to read a value from a container that created the iterator.
- * `container` represents the base of the address of the container that was used
- * to create the iterator.
- */
- cached
- predicate isIteratorUse(
- BaseSourceVariableInstruction container, Operand iteratorAddress, int numberOfLoads,
- int indirectionIndex
- ) {
- // Direct use
- exists(Instruction begin, Instruction memory, int upper, int ind |
- isChiBeforeIteratorUse(iteratorAddress, memory, numberOfLoads) and
- memorySucc*(begin, memory) and
- isChiAfterBegin(container, begin) and
- upper = countIndirectionsForCppType(getResultLanguageType(container)) and
- ind = numberOfLoads + [1 .. upper] and
- indirectionIndex = ind - (numberOfLoads + 1)
- )
- or
- // Use through function output
- exists(Instruction memory, Instruction begin, int upper, int ind |
- isChiAfterIteratorArgument(memory, iteratorAddress, numberOfLoads) and
- memorySucc*(begin, memory) and
- isChiAfterBegin(container, begin) and
- upper = countIndirectionsForCppType(getResultLanguageType(container)) and
- ind = numberOfLoads + [1 .. upper] and
- indirectionIndex = ind - (numberOfLoads - 1)
- )
- }
-
/** Holds if `op` is the only use of its defining instruction, and that op is used in a conversation */
private predicate isConversion(Operand op) {
exists(Instruction def, Operand use |
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll
index b31c7898ba7..24135820ab8 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll
@@ -17,18 +17,11 @@ private import Imports::IRType
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
-class IRVariable extends TIRVariable {
+abstract private class AbstractIRVariable extends TIRVariable {
Language::Declaration func;
- IRVariable() {
- this = TIRUserVariable(_, _, func) or
- this = TIRTempVariable(func, _, _, _) or
- this = TIRStringLiteral(func, _, _, _) or
- this = TIRDynamicInitializationFlag(func, _, _)
- }
-
/** Gets a textual representation of this element. */
- string toString() { none() }
+ abstract string toString();
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -49,13 +42,13 @@ class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
- Language::LanguageType getLanguageType() { none() }
+ abstract Language::LanguageType getLanguageType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
- Language::AST getAst() { none() }
+ abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
@@ -64,7 +57,7 @@ class IRVariable extends TIRVariable {
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
- string getUniqueId() { none() }
+ abstract string getUniqueId();
/**
* Gets the source location of this variable.
@@ -74,7 +67,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the IR for the function that references this variable.
*/
- final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
+ final IRFunction getEnclosingIRFunction() { result.getFunction() = this.getEnclosingFunction() }
/**
* Gets the function that references this variable.
@@ -82,10 +75,18 @@ class IRVariable extends TIRVariable {
final Language::Declaration getEnclosingFunction() { result = func }
}
+/**
+ * A variable referenced by the IR for a function.
+ *
+ * The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
+ * by the AST-to-IR translation (`IRTempVariable`).
+ */
+final class IRVariable = AbstractIRVariable;
+
/**
* A user-declared variable referenced by the IR for a function.
*/
-class IRUserVariable extends IRVariable, TIRUserVariable {
+class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
Language::Variable var;
Language::LanguageType type;
@@ -114,26 +115,29 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
-class IRAutomaticVariable extends IRVariable {
- IRAutomaticVariable() {
- exists(Language::Variable var |
- this = TIRUserVariable(var, _, func) and
- Language::isVariableAutomatic(var)
- )
- or
- this = TIRTempVariable(func, _, _, _)
- }
+abstract private class AbstractIRAutomaticVariable extends AbstractIRVariable { }
+
+/**
+ * A variable (user-declared or temporary) that is allocated on the stack. This includes all
+ * parameters, non-static local variables, and temporary variables.
+ */
+final class IRAutomaticVariable = AbstractIRAutomaticVariable;
+
+/**
+ * A user-declared variable that is allocated on the stack. This includes all parameters and
+ * non-static local variables.
+ */
+private class AbstractIRAutomaticUserVariable extends IRUserVariable, AbstractIRAutomaticVariable {
+ override Language::AutomaticVariable var;
+
+ final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
-class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
- override Language::AutomaticVariable var;
-
- final override Language::AutomaticVariable getVariable() { result = var }
-}
+final class IRAutomaticUserVariable = AbstractIRAutomaticUserVariable;
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
@@ -151,16 +155,10 @@ class IRStaticUserVariable extends IRUserVariable {
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
-class IRGeneratedVariable extends IRVariable {
+abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
Language::AST ast;
Language::LanguageType type;
- IRGeneratedVariable() {
- this = TIRTempVariable(func, ast, _, type) or
- this = TIRStringLiteral(func, ast, type, _) or
- this = TIRDynamicInitializationFlag(func, ast, type)
- }
-
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
@@ -196,12 +194,20 @@ class IRGeneratedVariable extends IRVariable {
string getBaseString() { none() }
}
+/**
+ * A variable that is not user-declared. This includes temporary variables generated as part of IR
+ * construction, as well as string literals.
+ */
+final class IRGeneratedVariable = AbstractIRGeneratedVariable;
+
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of a function, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
-class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
+class IRTempVariable extends AbstractIRGeneratedVariable, AbstractIRAutomaticVariable,
+ TIRTempVariable
+{
TempVariableTag tag;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
@@ -241,7 +247,7 @@ class IRThrowVariable extends IRTempVariable {
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
* function that accepts a variable number of arguments.
*/
-class IREllipsisVariable extends IRTempVariable, IRParameter {
+class IREllipsisVariable extends IRTempVariable, AbstractIRParameter {
IREllipsisVariable() { tag = EllipsisTempVar() }
final override string toString() { result = "#ellipsis" }
@@ -252,7 +258,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
/**
* A temporary variable generated to hold the `this` pointer.
*/
-class IRThisVariable extends IRTempVariable, IRParameter {
+class IRThisVariable extends IRTempVariable, AbstractIRParameter {
IRThisVariable() { tag = ThisTempVar() }
final override string toString() { result = "#this" }
@@ -264,7 +270,7 @@ class IRThisVariable extends IRTempVariable, IRParameter {
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
-class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
+class IRStringLiteral extends AbstractIRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
@@ -288,7 +294,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
* used to model the runtime initialization of static local variables in C++, as well as static
* fields in C#.
*/
-class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
+class IRDynamicInitializationFlag extends AbstractIRGeneratedVariable, TIRDynamicInitializationFlag {
Language::Variable var;
IRDynamicInitializationFlag() {
@@ -314,24 +320,24 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
-class IRParameter extends IRAutomaticVariable {
- IRParameter() {
- this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
- or
- this = TIRTempVariable(_, _, ThisTempVar(), _)
- or
- this = TIRTempVariable(_, _, EllipsisTempVar(), _)
- }
-
+abstract private class AbstractIRParameter extends AbstractIRAutomaticVariable {
/**
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
*/
int getIndex() { none() }
}
+/**
+ * An IR variable which acts like a function parameter, including positional parameters and the
+ * temporary variables generated for `this` and ellipsis parameters.
+ */
+final class IRParameter = AbstractIRParameter;
+
/**
* An IR variable representing a positional parameter.
*/
-class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
+class IRPositionalParameter extends AbstractIRParameter, AbstractIRAutomaticUserVariable {
+ IRPositionalParameter() { this.getVariable() instanceof Language::Parameter }
+
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll
index b31c7898ba7..24135820ab8 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/IRVariable.qll
@@ -17,18 +17,11 @@ private import Imports::IRType
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
-class IRVariable extends TIRVariable {
+abstract private class AbstractIRVariable extends TIRVariable {
Language::Declaration func;
- IRVariable() {
- this = TIRUserVariable(_, _, func) or
- this = TIRTempVariable(func, _, _, _) or
- this = TIRStringLiteral(func, _, _, _) or
- this = TIRDynamicInitializationFlag(func, _, _)
- }
-
/** Gets a textual representation of this element. */
- string toString() { none() }
+ abstract string toString();
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -49,13 +42,13 @@ class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
- Language::LanguageType getLanguageType() { none() }
+ abstract Language::LanguageType getLanguageType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
- Language::AST getAst() { none() }
+ abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
@@ -64,7 +57,7 @@ class IRVariable extends TIRVariable {
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
- string getUniqueId() { none() }
+ abstract string getUniqueId();
/**
* Gets the source location of this variable.
@@ -74,7 +67,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the IR for the function that references this variable.
*/
- final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
+ final IRFunction getEnclosingIRFunction() { result.getFunction() = this.getEnclosingFunction() }
/**
* Gets the function that references this variable.
@@ -82,10 +75,18 @@ class IRVariable extends TIRVariable {
final Language::Declaration getEnclosingFunction() { result = func }
}
+/**
+ * A variable referenced by the IR for a function.
+ *
+ * The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
+ * by the AST-to-IR translation (`IRTempVariable`).
+ */
+final class IRVariable = AbstractIRVariable;
+
/**
* A user-declared variable referenced by the IR for a function.
*/
-class IRUserVariable extends IRVariable, TIRUserVariable {
+class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
Language::Variable var;
Language::LanguageType type;
@@ -114,26 +115,29 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
-class IRAutomaticVariable extends IRVariable {
- IRAutomaticVariable() {
- exists(Language::Variable var |
- this = TIRUserVariable(var, _, func) and
- Language::isVariableAutomatic(var)
- )
- or
- this = TIRTempVariable(func, _, _, _)
- }
+abstract private class AbstractIRAutomaticVariable extends AbstractIRVariable { }
+
+/**
+ * A variable (user-declared or temporary) that is allocated on the stack. This includes all
+ * parameters, non-static local variables, and temporary variables.
+ */
+final class IRAutomaticVariable = AbstractIRAutomaticVariable;
+
+/**
+ * A user-declared variable that is allocated on the stack. This includes all parameters and
+ * non-static local variables.
+ */
+private class AbstractIRAutomaticUserVariable extends IRUserVariable, AbstractIRAutomaticVariable {
+ override Language::AutomaticVariable var;
+
+ final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
-class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
- override Language::AutomaticVariable var;
-
- final override Language::AutomaticVariable getVariable() { result = var }
-}
+final class IRAutomaticUserVariable = AbstractIRAutomaticUserVariable;
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
@@ -151,16 +155,10 @@ class IRStaticUserVariable extends IRUserVariable {
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
-class IRGeneratedVariable extends IRVariable {
+abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
Language::AST ast;
Language::LanguageType type;
- IRGeneratedVariable() {
- this = TIRTempVariable(func, ast, _, type) or
- this = TIRStringLiteral(func, ast, type, _) or
- this = TIRDynamicInitializationFlag(func, ast, type)
- }
-
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
@@ -196,12 +194,20 @@ class IRGeneratedVariable extends IRVariable {
string getBaseString() { none() }
}
+/**
+ * A variable that is not user-declared. This includes temporary variables generated as part of IR
+ * construction, as well as string literals.
+ */
+final class IRGeneratedVariable = AbstractIRGeneratedVariable;
+
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of a function, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
-class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
+class IRTempVariable extends AbstractIRGeneratedVariable, AbstractIRAutomaticVariable,
+ TIRTempVariable
+{
TempVariableTag tag;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
@@ -241,7 +247,7 @@ class IRThrowVariable extends IRTempVariable {
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
* function that accepts a variable number of arguments.
*/
-class IREllipsisVariable extends IRTempVariable, IRParameter {
+class IREllipsisVariable extends IRTempVariable, AbstractIRParameter {
IREllipsisVariable() { tag = EllipsisTempVar() }
final override string toString() { result = "#ellipsis" }
@@ -252,7 +258,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
/**
* A temporary variable generated to hold the `this` pointer.
*/
-class IRThisVariable extends IRTempVariable, IRParameter {
+class IRThisVariable extends IRTempVariable, AbstractIRParameter {
IRThisVariable() { tag = ThisTempVar() }
final override string toString() { result = "#this" }
@@ -264,7 +270,7 @@ class IRThisVariable extends IRTempVariable, IRParameter {
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
-class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
+class IRStringLiteral extends AbstractIRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
@@ -288,7 +294,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
* used to model the runtime initialization of static local variables in C++, as well as static
* fields in C#.
*/
-class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
+class IRDynamicInitializationFlag extends AbstractIRGeneratedVariable, TIRDynamicInitializationFlag {
Language::Variable var;
IRDynamicInitializationFlag() {
@@ -314,24 +320,24 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
-class IRParameter extends IRAutomaticVariable {
- IRParameter() {
- this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
- or
- this = TIRTempVariable(_, _, ThisTempVar(), _)
- or
- this = TIRTempVariable(_, _, EllipsisTempVar(), _)
- }
-
+abstract private class AbstractIRParameter extends AbstractIRAutomaticVariable {
/**
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
*/
int getIndex() { none() }
}
+/**
+ * An IR variable which acts like a function parameter, including positional parameters and the
+ * temporary variables generated for `this` and ellipsis parameters.
+ */
+final class IRParameter = AbstractIRParameter;
+
/**
* An IR variable representing a positional parameter.
*/
-class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
+class IRPositionalParameter extends AbstractIRParameter, AbstractIRAutomaticUserVariable {
+ IRPositionalParameter() { this.getVariable() instanceof Language::Parameter }
+
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll
index 7024911a420..4d2b1a95d31 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedElement.qll
@@ -830,6 +830,12 @@ newtype TTranslatedElement =
not ignoreExpr(dc)
)
} or
+ // The set of destructors to invoke after a handler for a `try` statement. These
+ // need to be special cased because the destructors need to run following an
+ // `ExceptionEdge`, but not following a `GotoEdge` edge.
+ TTranslatedDestructorsAfterHandler(Handler handler) {
+ exists(handler.getAnImplicitDestructorCall())
+ } or
// A precise side effect of an argument to a `Call`
TTranslatedArgumentExprSideEffect(Call call, Expr expr, int n, SideEffectOpcode opcode) {
not ignoreExpr(expr) and
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll
index a43595b08e0..ef7251e8e8a 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedExpr.qll
@@ -1844,9 +1844,6 @@ class TranslatedAssignExpr extends TranslatedNonConstantExpr {
child = this.getRightOperand() and
result = this.getLeftOperand().getFirstInstruction(kind)
or
- child = this.getRightOperand() and
- result = this.getLeftOperand().getFirstInstruction(kind)
- or
kind instanceof GotoEdge and
child = this.getLeftOperand() and
result = this.getInstruction(AssignmentStoreTag())
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
index fab2dacc8a7..ad17722477f 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/raw/internal/TranslatedStmt.qll
@@ -777,6 +777,72 @@ abstract class TranslatedHandler extends TranslatedStmt {
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
}
+/**
+ * The IR translation of the destructor calls of the parent `TranslatedCatchByTypeHandler`.
+ *
+ * This object does not itself generate the destructor calls. Instead, its
+ * children provide the actual calls.
+ */
+class TranslatedDestructorsAfterHandler extends TranslatedElement,
+ TTranslatedDestructorsAfterHandler
+{
+ Handler handler;
+
+ TranslatedDestructorsAfterHandler() { this = TTranslatedDestructorsAfterHandler(handler) }
+
+ override string toString() { result = "Destructor calls after handler: " + handler }
+
+ private TranslatedCall getTranslatedImplicitDestructorCall(int id) {
+ result.getExpr() = handler.getImplicitDestructorCall(id)
+ }
+
+ override Instruction getFirstInstruction(EdgeKind kind) {
+ result = this.getChild(0).getFirstInstruction(kind)
+ }
+
+ override Handler getAst() { result = handler }
+
+ override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
+
+ override TranslatedElement getChild(int id) {
+ result = this.getTranslatedImplicitDestructorCall(id)
+ }
+
+ override predicate handlesDestructorsExplicitly() { any() }
+
+ override Declaration getFunction() { result = handler.getEnclosingFunction() }
+
+ override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
+ exists(int id | child = this.getChild(id) |
+ // Transition to the next child, if any.
+ result = this.getChild(id + 1).getFirstInstruction(kind)
+ or
+ // And otherwise go to the next handler, if any.
+ not exists(this.getChild(id + 1)) and
+ result =
+ getTranslatedStmt(handler)
+ .getParent()
+ .(TranslatedTryStmt)
+ .getNextHandler(getTranslatedStmt(handler), kind)
+ )
+ }
+
+ override TranslatedElement getLastChild() {
+ result =
+ this.getTranslatedImplicitDestructorCall(max(int id |
+ exists(handler.getImplicitDestructorCall(id))
+ ))
+ }
+
+ override Instruction getALastInstructionInternal() {
+ result = this.getLastChild().getALastInstruction()
+ }
+
+ override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
+ none()
+ }
+}
+
/**
* The IR translation of a C++ `catch` block that catches an exception with a
* specific type (e.g. `catch (const std::exception&)`).
@@ -790,10 +856,14 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
resultType = getVoidType()
}
+ override predicate handlesDestructorsExplicitly() { any() }
+
override TranslatedElement getChildInternal(int id) {
result = super.getChildInternal(id)
or
id = 0 and result = this.getParameter()
+ or
+ id = 1 and result = this.getDestructors()
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -810,7 +880,9 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
result = this.getParameter().getFirstInstruction(kind)
or
kind instanceof ExceptionEdge and
- result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
+ if exists(this.getDestructors())
+ then result = this.getDestructors().getFirstInstruction(any(GotoEdge edge))
+ else result = this.getParent().(TranslatedTryStmt).getNextHandler(this, any(GotoEdge edge))
)
}
@@ -822,6 +894,8 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
private TranslatedParameter getParameter() {
result = getTranslatedParameter(stmt.getParameter())
}
+
+ private TranslatedDestructorsAfterHandler getDestructors() { result.getAst() = stmt }
}
/**
@@ -842,9 +916,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
}
}
-class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
- override IfStmt stmt;
-
+abstract class TranslatedIfLikeStmt extends TranslatedStmt, ConditionContext {
override Instruction getFirstInstruction(EdgeKind kind) {
if this.hasInitialization()
then result = this.getInitialization().getFirstInstruction(kind)
@@ -857,6 +929,8 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
override TranslatedElement getLastChild() { result = this.getElse() or result = this.getThen() }
+ override predicate handlesDestructorsExplicitly() { any() }
+
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
@@ -867,25 +941,21 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
id = 3 and result = this.getElse()
}
- private predicate hasInitialization() { exists(stmt.getInitialization()) }
+ abstract predicate hasInitialization();
- private TranslatedStmt getInitialization() {
- result = getTranslatedStmt(stmt.getInitialization())
- }
+ abstract TranslatedStmt getInitialization();
- private TranslatedCondition getCondition() {
- result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
- }
+ abstract TranslatedCondition getCondition();
private Instruction getFirstConditionInstruction(EdgeKind kind) {
result = this.getCondition().getFirstInstruction(kind)
}
- private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
+ abstract TranslatedStmt getThen();
- private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
+ abstract TranslatedStmt getElse();
- private predicate hasElse() { exists(stmt.getElse()) }
+ abstract predicate hasElse();
override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
@@ -898,7 +968,11 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
child = this.getCondition() and
if this.hasElse()
then result = this.getElse().getFirstInstruction(kind)
- else result = this.getParent().getChildSuccessor(this, kind)
+ else (
+ if this.hasAnImplicitDestructorCall()
+ then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
+ else result = this.getParent().getChildSuccessor(this, kind)
+ )
}
override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
@@ -906,7 +980,24 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
result = this.getFirstConditionInstruction(kind)
or
(child = this.getThen() or child = this.getElse()) and
- result = this.getParent().getChildSuccessor(this, kind)
+ (
+ if this.hasAnImplicitDestructorCall()
+ then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
+ else result = this.getParent().getChildSuccessor(this, kind)
+ )
+ or
+ exists(int destructorId |
+ destructorId >= this.getFirstDestructorCallIndex() and
+ child = this.getChild(destructorId) and
+ result = this.getChild(destructorId + 1).getFirstInstruction(kind)
+ )
+ or
+ exists(int lastDestructorIndex |
+ lastDestructorIndex =
+ max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
+ child = this.getChild(lastDestructorIndex) and
+ result = this.getParent().getChildSuccessor(this, kind)
+ )
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -914,76 +1005,44 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
}
}
-class TranslatedConstExprIfStmt extends TranslatedStmt, ConditionContext {
- override ConstexprIfStmt stmt;
+class TranslatedIfStmt extends TranslatedIfLikeStmt {
+ override IfStmt stmt;
- override Instruction getFirstInstruction(EdgeKind kind) {
- if this.hasInitialization()
- then result = this.getInitialization().getFirstInstruction(kind)
- else result = this.getFirstConditionInstruction(kind)
- }
+ override predicate hasInitialization() { exists(stmt.getInitialization()) }
- override TranslatedElement getChildInternal(int id) {
- id = 0 and result = this.getInitialization()
- or
- id = 1 and result = this.getCondition()
- or
- id = 2 and result = this.getThen()
- or
- id = 3 and result = this.getElse()
- }
-
- private predicate hasInitialization() { exists(stmt.getInitialization()) }
-
- private TranslatedStmt getInitialization() {
+ override TranslatedStmt getInitialization() {
result = getTranslatedStmt(stmt.getInitialization())
}
- private TranslatedCondition getCondition() {
+ override TranslatedCondition getCondition() {
result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
- private Instruction getFirstConditionInstruction(EdgeKind kind) {
- result = this.getCondition().getFirstInstruction(kind)
+ override TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
+
+ override TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
+
+ override predicate hasElse() { exists(stmt.getElse()) }
+}
+
+class TranslatedConstExprIfStmt extends TranslatedIfLikeStmt {
+ override ConstexprIfStmt stmt;
+
+ override predicate hasInitialization() { exists(stmt.getInitialization()) }
+
+ override TranslatedStmt getInitialization() {
+ result = getTranslatedStmt(stmt.getInitialization())
}
- private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
-
- private TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
-
- private predicate hasElse() { exists(stmt.getElse()) }
-
- override Instruction getInstructionSuccessorInternal(InstructionTag tag, EdgeKind kind) { none() }
-
- override Instruction getChildTrueSuccessor(TranslatedCondition child, EdgeKind kind) {
- child = this.getCondition() and
- result = this.getThen().getFirstInstruction(kind)
+ override TranslatedCondition getCondition() {
+ result = getTranslatedCondition(stmt.getCondition().getFullyConverted())
}
- override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
- child = this.getCondition() and
- if this.hasElse()
- then result = this.getElse().getFirstInstruction(kind)
- else result = this.getParent().getChildSuccessor(this, kind)
- }
+ override TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
- override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
- child = this.getInitialization() and
- result = this.getFirstConditionInstruction(kind)
- or
- (child = this.getThen() or child = this.getElse()) and
- result = this.getParent().getChildSuccessor(this, kind)
- }
+ override TranslatedStmt getElse() { result = getTranslatedStmt(stmt.getElse()) }
- override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
- none()
- }
-
- override Instruction getALastInstructionInternal() {
- result = this.getThen().getALastInstruction()
- or
- result = this.getElse().getALastInstruction()
- }
+ override predicate hasElse() { exists(stmt.getElse()) }
}
abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
@@ -1163,6 +1222,8 @@ class TranslatedForStmt extends TranslatedLoop {
class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override RangeBasedForStmt stmt;
+ override predicate handlesDestructorsExplicitly() { any() }
+
override TranslatedElement getChildInternal(int id) {
id = 0 and result = this.getInitialization()
or
@@ -1216,6 +1277,19 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
or
child = this.getUpdate() and
result = this.getCondition().getFirstInstruction(kind)
+ or
+ exists(int destructorId |
+ destructorId >= this.getFirstDestructorCallIndex() and
+ child = this.getChild(destructorId) and
+ result = this.getChild(destructorId + 1).getFirstInstruction(kind)
+ )
+ or
+ exists(int lastDestructorIndex |
+ lastDestructorIndex =
+ max(int n | exists(this.getChild(n)) and n >= this.getFirstDestructorCallIndex()) and
+ child = this.getChild(lastDestructorIndex) and
+ result = this.getParent().getChildSuccessor(this, kind)
+ )
}
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
@@ -1231,7 +1305,9 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
override Instruction getChildFalseSuccessor(TranslatedCondition child, EdgeKind kind) {
child = this.getCondition() and
- result = this.getParent().getChildSuccessor(this, kind)
+ if this.hasAnImplicitDestructorCall()
+ then result = this.getChild(this.getFirstDestructorCallIndex()).getFirstInstruction(kind)
+ else result = this.getParent().getChildSuccessor(this, kind)
}
private TranslatedDeclStmt getRangeVariableDeclStmt() {
@@ -1276,6 +1352,11 @@ class TranslatedJumpStmt extends TranslatedStmt {
override JumpStmt stmt;
override Instruction getFirstInstruction(EdgeKind kind) {
+ // The first instruction is a destructor call, if any.
+ result = this.getChildInternal(0).getFirstInstruction(kind)
+ or
+ // Otherwise, the first (and only) instruction is a `NoOp`
+ not exists(this.getChildInternal(0)) and
result = this.getInstruction(OnlyInstructionTag()) and
kind instanceof GotoEdge
}
@@ -1284,7 +1365,20 @@ class TranslatedJumpStmt extends TranslatedStmt {
result = this.getInstruction(OnlyInstructionTag())
}
- override TranslatedElement getChildInternal(int id) { none() }
+ private TranslatedCall getTranslatedImplicitDestructorCall(int id) {
+ result.getExpr() = stmt.getImplicitDestructorCall(id)
+ }
+
+ override TranslatedElement getLastChild() {
+ result =
+ this.getTranslatedImplicitDestructorCall(max(int id |
+ exists(stmt.getImplicitDestructorCall(id))
+ ))
+ }
+
+ override TranslatedElement getChildInternal(int id) {
+ result = this.getTranslatedImplicitDestructorCall(id)
+ }
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
tag = OnlyInstructionTag() and
@@ -1297,7 +1391,19 @@ class TranslatedJumpStmt extends TranslatedStmt {
result = getTranslatedStmt(stmt.getTarget()).getFirstInstruction(kind)
}
- override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) { none() }
+ final override predicate handlesDestructorsExplicitly() { any() }
+
+ override Instruction getChildSuccessorInternal(TranslatedElement child, EdgeKind kind) {
+ exists(int id | child = this.getChildInternal(id) |
+ // Transition to the next destructor call, if any.
+ result = this.getChildInternal(id + 1).getFirstInstruction(kind)
+ or
+ // And otherwise, exit this element by flowing to the target of the jump.
+ not exists(this.getChildInternal(id + 1)) and
+ kind instanceof GotoEdge and
+ result = this.getInstruction(OnlyInstructionTag())
+ )
+ }
}
private EdgeKind getCaseEdge(SwitchCase switchCase) {
diff --git a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll
index b31c7898ba7..24135820ab8 100644
--- a/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll
+++ b/cpp/ql/lib/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll
@@ -17,18 +17,11 @@ private import Imports::IRType
* The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
* by the AST-to-IR translation (`IRTempVariable`).
*/
-class IRVariable extends TIRVariable {
+abstract private class AbstractIRVariable extends TIRVariable {
Language::Declaration func;
- IRVariable() {
- this = TIRUserVariable(_, _, func) or
- this = TIRTempVariable(func, _, _, _) or
- this = TIRStringLiteral(func, _, _, _) or
- this = TIRDynamicInitializationFlag(func, _, _)
- }
-
/** Gets a textual representation of this element. */
- string toString() { none() }
+ abstract string toString();
/**
* Holds if this variable's value cannot be changed within a function. Currently used for string
@@ -49,13 +42,13 @@ class IRVariable extends TIRVariable {
/**
* Gets the type of the variable.
*/
- Language::LanguageType getLanguageType() { none() }
+ abstract Language::LanguageType getLanguageType();
/**
* Gets the AST node that declared this variable, or that introduced this
* variable as part of the AST-to-IR translation.
*/
- Language::AST getAst() { none() }
+ abstract Language::AST getAst();
/** DEPRECATED: Alias for getAst */
deprecated Language::AST getAST() { result = this.getAst() }
@@ -64,7 +57,7 @@ class IRVariable extends TIRVariable {
* Gets an identifier string for the variable. This identifier is unique
* within the function.
*/
- string getUniqueId() { none() }
+ abstract string getUniqueId();
/**
* Gets the source location of this variable.
@@ -74,7 +67,7 @@ class IRVariable extends TIRVariable {
/**
* Gets the IR for the function that references this variable.
*/
- final IRFunction getEnclosingIRFunction() { result.getFunction() = func }
+ final IRFunction getEnclosingIRFunction() { result.getFunction() = this.getEnclosingFunction() }
/**
* Gets the function that references this variable.
@@ -82,10 +75,18 @@ class IRVariable extends TIRVariable {
final Language::Declaration getEnclosingFunction() { result = func }
}
+/**
+ * A variable referenced by the IR for a function.
+ *
+ * The variable may be a user-declared variable (`IRUserVariable`) or a temporary variable generated
+ * by the AST-to-IR translation (`IRTempVariable`).
+ */
+final class IRVariable = AbstractIRVariable;
+
/**
* A user-declared variable referenced by the IR for a function.
*/
-class IRUserVariable extends IRVariable, TIRUserVariable {
+class IRUserVariable extends AbstractIRVariable, TIRUserVariable {
Language::Variable var;
Language::LanguageType type;
@@ -114,26 +115,29 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
* A variable (user-declared or temporary) that is allocated on the stack. This includes all
* parameters, non-static local variables, and temporary variables.
*/
-class IRAutomaticVariable extends IRVariable {
- IRAutomaticVariable() {
- exists(Language::Variable var |
- this = TIRUserVariable(var, _, func) and
- Language::isVariableAutomatic(var)
- )
- or
- this = TIRTempVariable(func, _, _, _)
- }
+abstract private class AbstractIRAutomaticVariable extends AbstractIRVariable { }
+
+/**
+ * A variable (user-declared or temporary) that is allocated on the stack. This includes all
+ * parameters, non-static local variables, and temporary variables.
+ */
+final class IRAutomaticVariable = AbstractIRAutomaticVariable;
+
+/**
+ * A user-declared variable that is allocated on the stack. This includes all parameters and
+ * non-static local variables.
+ */
+private class AbstractIRAutomaticUserVariable extends IRUserVariable, AbstractIRAutomaticVariable {
+ override Language::AutomaticVariable var;
+
+ final override Language::AutomaticVariable getVariable() { result = var }
}
/**
* A user-declared variable that is allocated on the stack. This includes all parameters and
* non-static local variables.
*/
-class IRAutomaticUserVariable extends IRUserVariable, IRAutomaticVariable {
- override Language::AutomaticVariable var;
-
- final override Language::AutomaticVariable getVariable() { result = var }
-}
+final class IRAutomaticUserVariable = AbstractIRAutomaticUserVariable;
/**
* A user-declared variable that is not allocated on the stack. This includes all global variables,
@@ -151,16 +155,10 @@ class IRStaticUserVariable extends IRUserVariable {
* A variable that is not user-declared. This includes temporary variables generated as part of IR
* construction, as well as string literals.
*/
-class IRGeneratedVariable extends IRVariable {
+abstract private class AbstractIRGeneratedVariable extends AbstractIRVariable {
Language::AST ast;
Language::LanguageType type;
- IRGeneratedVariable() {
- this = TIRTempVariable(func, ast, _, type) or
- this = TIRStringLiteral(func, ast, type, _) or
- this = TIRDynamicInitializationFlag(func, ast, type)
- }
-
final override Language::LanguageType getLanguageType() { result = type }
final override Language::AST getAst() { result = ast }
@@ -196,12 +194,20 @@ class IRGeneratedVariable extends IRVariable {
string getBaseString() { none() }
}
+/**
+ * A variable that is not user-declared. This includes temporary variables generated as part of IR
+ * construction, as well as string literals.
+ */
+final class IRGeneratedVariable = AbstractIRGeneratedVariable;
+
/**
* A temporary variable introduced by IR construction. The most common examples are the variable
* generated to hold the return value of a function, or the variable generated to hold the result of
* a condition operator (`a ? b : c`).
*/
-class IRTempVariable extends IRGeneratedVariable, IRAutomaticVariable, TIRTempVariable {
+class IRTempVariable extends AbstractIRGeneratedVariable, AbstractIRAutomaticVariable,
+ TIRTempVariable
+{
TempVariableTag tag;
IRTempVariable() { this = TIRTempVariable(func, ast, tag, type) }
@@ -241,7 +247,7 @@ class IRThrowVariable extends IRTempVariable {
* A temporary variable generated to hold the contents of all arguments passed to the `...` of a
* function that accepts a variable number of arguments.
*/
-class IREllipsisVariable extends IRTempVariable, IRParameter {
+class IREllipsisVariable extends IRTempVariable, AbstractIRParameter {
IREllipsisVariable() { tag = EllipsisTempVar() }
final override string toString() { result = "#ellipsis" }
@@ -252,7 +258,7 @@ class IREllipsisVariable extends IRTempVariable, IRParameter {
/**
* A temporary variable generated to hold the `this` pointer.
*/
-class IRThisVariable extends IRTempVariable, IRParameter {
+class IRThisVariable extends IRTempVariable, AbstractIRParameter {
IRThisVariable() { tag = ThisTempVar() }
final override string toString() { result = "#this" }
@@ -264,7 +270,7 @@ class IRThisVariable extends IRTempVariable, IRParameter {
* A variable generated to represent the contents of a string literal. This variable acts much like
* a read-only global variable.
*/
-class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
+class IRStringLiteral extends AbstractIRGeneratedVariable, TIRStringLiteral {
Language::StringLiteral literal;
IRStringLiteral() { this = TIRStringLiteral(func, ast, type, literal) }
@@ -288,7 +294,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
* used to model the runtime initialization of static local variables in C++, as well as static
* fields in C#.
*/
-class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitializationFlag {
+class IRDynamicInitializationFlag extends AbstractIRGeneratedVariable, TIRDynamicInitializationFlag {
Language::Variable var;
IRDynamicInitializationFlag() {
@@ -314,24 +320,24 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
* An IR variable which acts like a function parameter, including positional parameters and the
* temporary variables generated for `this` and ellipsis parameters.
*/
-class IRParameter extends IRAutomaticVariable {
- IRParameter() {
- this.(IRAutomaticUserVariable).getVariable() instanceof Language::Parameter
- or
- this = TIRTempVariable(_, _, ThisTempVar(), _)
- or
- this = TIRTempVariable(_, _, EllipsisTempVar(), _)
- }
-
+abstract private class AbstractIRParameter extends AbstractIRAutomaticVariable {
/**
* Gets the zero-based index of this parameter. The `this` parameter has index -1.
*/
int getIndex() { none() }
}
+/**
+ * An IR variable which acts like a function parameter, including positional parameters and the
+ * temporary variables generated for `this` and ellipsis parameters.
+ */
+final class IRParameter = AbstractIRParameter;
+
/**
* An IR variable representing a positional parameter.
*/
-class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
+class IRPositionalParameter extends AbstractIRParameter, AbstractIRAutomaticUserVariable {
+ IRPositionalParameter() { this.getVariable() instanceof Language::Parameter }
+
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
}
diff --git a/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll b/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
index 4dd53134830..94e3a3efc9b 100644
--- a/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
+++ b/cpp/ql/lib/semmle/code/cpp/models/implementations/Iterator.qll
@@ -565,7 +565,7 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
TaintFunction, SideEffectFunction, AliasFunction
{
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
- input.isParameterDeref(0) and
+ (input.isParameterDeref(0) or input.isParameter(0)) and
output.isQualifierObject()
}
@@ -584,17 +584,34 @@ private class IteratorAssignmentMemberOperatorModel extends IteratorAssignmentMe
override predicate parameterEscapesOnlyViaReturn(int index) { index = -1 }
}
+/**
+ * A `begin` member function, or a related function, that returns an iterator.
+ */
+class BeginFunction extends MemberFunction {
+ BeginFunction() {
+ this.hasName(["begin", "cbegin", "rbegin", "crbegin", "before_begin", "cbefore_begin"]) and
+ this.getType().getUnspecifiedType() instanceof Iterator
+ }
+}
+
+/**
+ * An `end` member function, or a related function, that returns an iterator.
+ */
+class EndFunction extends MemberFunction {
+ EndFunction() {
+ this.hasName(["end", "cend", "rend", "crend"]) and
+ this.getType().getUnspecifiedType() instanceof Iterator
+ }
+}
+
/**
* A `begin` or `end` member function, or a related member function, that
* returns an iterator.
*/
class BeginOrEndFunction extends MemberFunction {
BeginOrEndFunction() {
- this.hasName([
- "begin", "cbegin", "rbegin", "crbegin", "end", "cend", "rend", "crend", "before_begin",
- "cbefore_begin"
- ]) and
- this.getType().getUnspecifiedType() instanceof Iterator
+ this instanceof BeginFunction or
+ this instanceof EndFunction
}
}
diff --git a/cpp/ql/lib/upgrades/ddd31fd02e51ad270bc9e6712708e5a5b6881518/upgrade.properties b/cpp/ql/lib/upgrades/ddd31fd02e51ad270bc9e6712708e5a5b6881518/upgrade.properties
index a0c4ba602a1..3e361d800fb 100644
--- a/cpp/ql/lib/upgrades/ddd31fd02e51ad270bc9e6712708e5a5b6881518/upgrade.properties
+++ b/cpp/ql/lib/upgrades/ddd31fd02e51ad270bc9e6712708e5a5b6881518/upgrade.properties
@@ -1,4 +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
\ No newline at end of file
+files.rel: reorder files.rel (@file id, string name, string simple, string ext, int fromSource) id name
+folders.rel: reorder folders.rel (@folder id, string name, string simple) id name
\ No newline at end of file
diff --git a/cpp/ql/src/CHANGELOG.md b/cpp/ql/src/CHANGELOG.md
index 52ce33161a7..b530e148482 100644
--- a/cpp/ql/src/CHANGELOG.md
+++ b/cpp/ql/src/CHANGELOG.md
@@ -1,3 +1,20 @@
+## 1.0.0
+
+### Breaking Changes
+
+* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.
+
+### Minor Analysis Improvements
+
+* The "Use of unique pointer after lifetime ends" query (`cpp/use-of-unique-pointer-after-lifetime-ends`) no longer reports an alert when the pointer is converted to a boolean
+* The "Variable not initialized before use" query (`cpp/not-initialised`) no longer reports an alert on static variables.
+
+## 0.9.12
+
+### New Queries
+
+* Added a new query, `cpp/iterator-to-expired-container`, to detect the creation of iterators owned by a temporary objects that are about to be destroyed.
+
## 0.9.11
### Minor Analysis Improvements
diff --git a/cpp/ql/src/Critical/DoubleFree.qhelp b/cpp/ql/src/Critical/DoubleFree.qhelp
index 0b38858eae4..b8c817617f7 100644
--- a/cpp/ql/src/Critical/DoubleFree.qhelp
+++ b/cpp/ql/src/Critical/DoubleFree.qhelp
@@ -14,13 +14,32 @@ the program, or security vulnerabilities, by allowing an attacker to overwrite a
-Ensure that all execution paths deallocate the allocated memory at most once. If possible, reassign
-the pointer to a null value after deallocating it. This will prevent double-free vulnerabilities since
-most deallocation functions will perform a null-pointer check before attempting to deallocate the memory.
+Ensure that all execution paths deallocate the allocated memory at most once. In complex cases it may
+help to reassign a pointer to a null value after deallocating it. This will prevent double-free vulnerabilities
+since most deallocation functions will perform a null-pointer check before attempting to deallocate memory.
-
+
+
+In the following example, buff is allocated and then freed twice:
+
+
+
+Reviewing the code above, the issue can be fixed by simply deleting the additional call to
+free(buff).
+
+
+
+In the next example, task may be deleted twice, if an exception occurs inside the try
+block after the first delete:
+
+
+
+The problem can be solved by assigning a null value to the pointer after the first delete, as
+calling delete a second time on the null pointer is harmless.
+
+
diff --git a/cpp/ql/src/Critical/DoubleFree.cpp b/cpp/ql/src/Critical/DoubleFreeBad.cpp
similarity index 100%
rename from cpp/ql/src/Critical/DoubleFree.cpp
rename to cpp/ql/src/Critical/DoubleFreeBad.cpp
diff --git a/cpp/ql/src/Critical/DoubleFreeBad2.cpp b/cpp/ql/src/Critical/DoubleFreeBad2.cpp
new file mode 100644
index 00000000000..b63e100434d
--- /dev/null
+++ b/cpp/ql/src/Critical/DoubleFreeBad2.cpp
@@ -0,0 +1,16 @@
+void g() {
+ MyTask *task = nullptr;
+
+ try
+ {
+ task = new MyTask;
+
+ ...
+
+ delete task;
+
+ ...
+ } catch (...) {
+ delete task; // BAD: potential double-free
+ }
+}
diff --git a/cpp/ql/src/Critical/DoubleFreeGood.cpp b/cpp/ql/src/Critical/DoubleFreeGood.cpp
new file mode 100644
index 00000000000..024c7aea493
--- /dev/null
+++ b/cpp/ql/src/Critical/DoubleFreeGood.cpp
@@ -0,0 +1,7 @@
+int* f() {
+ int *buff = malloc(SIZE*sizeof(int));
+ do_stuff(buff);
+ free(buff); // GOOD: buff is only freed once.
+ int *new_buffer = malloc(SIZE*sizeof(int));
+ return new_buffer;
+}
diff --git a/cpp/ql/src/Critical/DoubleFreeGood2.cpp b/cpp/ql/src/Critical/DoubleFreeGood2.cpp
new file mode 100644
index 00000000000..f1abdd01688
--- /dev/null
+++ b/cpp/ql/src/Critical/DoubleFreeGood2.cpp
@@ -0,0 +1,17 @@
+void g() {
+ MyTask *task = nullptr;
+
+ try
+ {
+ task = new MyTask;
+
+ ...
+
+ delete task;
+ task = nullptr;
+
+ ...
+ } catch (...) {
+ delete task; // GOOD: harmless if task is NULL
+ }
+}
diff --git a/cpp/ql/src/Critical/NotInitialised.ql b/cpp/ql/src/Critical/NotInitialised.ql
index 14cc757457a..8e8e67740ac 100644
--- a/cpp/ql/src/Critical/NotInitialised.ql
+++ b/cpp/ql/src/Critical/NotInitialised.ql
@@ -54,6 +54,7 @@ predicate undefinedLocalUse(VariableAccess va) {
// it is hard to tell when a struct or array has been initialized, so we
// ignore them
not isAggregateType(lv.getUnderlyingType()) and
+ not lv.isStatic() and // static variables are initialized to zero or null by default
not lv.getType().hasName("va_list") and
va = lv.getAnAccess() and
noDefPath(lv, va) and
@@ -70,7 +71,8 @@ predicate uninitialisedGlobal(GlobalVariable gv) {
va = gv.getAnAccess() and
va.isRValue() and
not gv.hasInitializer() and
- not gv.hasSpecifier("extern")
+ not gv.hasSpecifier("extern") and
+ not gv.isStatic() // static variables are initialized to zero or null by default
)
}
diff --git a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.qhelp b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.qhelp
index 1df186def0a..6994e49943f 100644
--- a/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.qhelp
+++ b/cpp/ql/src/Likely Bugs/Format/NonConstantFormat.qhelp
@@ -42,7 +42,7 @@ in the previous example, one solution is to make the log message a trailing argu
An alternative solution is to allow log_with_timestamp to accept format arguments:
In this formulation, the non-constant format string to printf has been replaced with
-a non-constant format string to vprintf. Semmle will no longer consider the body of
+a non-constant format string to vprintf. The analysis will no longer consider the body of
log_with_timestamp to be a problem, and will instead check that every call to
log_with_timestamp passes a constant format string.
diff --git a/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.qhelp b/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.qhelp
index bbd64254d54..b4df60cbac7 100644
--- a/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.qhelp
+++ b/cpp/ql/src/Likely Bugs/Format/TooManyFormatArguments.qhelp
@@ -22,10 +22,8 @@ function.
-cplusplus.com: C++ Functions.
+CERT C Coding Standard: FIO47-C. Use valid format strings.
Microsoft C Runtime Library Reference: printf, wprintf.
-
-
diff --git a/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.qhelp b/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.qhelp
index 66344e93f22..bb4687b2d9a 100644
--- a/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.qhelp
+++ b/cpp/ql/src/Likely Bugs/Format/WrongNumberOfFormatArguments.qhelp
@@ -19,8 +19,8 @@ contents.
-Review the format and arguments expected by the highlighted function calls. Update either
-the format or the arguments so that the expected number of arguments are passed to the
+
Review the format and arguments expected by the highlighted function calls. Update either
+the format or the arguments so that the expected number of arguments are passed to the
function.
@@ -30,11 +30,8 @@ function.
-CERT C Coding
-Standard: FIO30-C. Exclude user input from format strings.
-cplusplus.com: C++ Functions.
+CERT C Coding Standard: FIO47-C. Use valid format strings.
Microsoft C Runtime Library Reference: printf, wprintf.
-
diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.cpp b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.cpp
deleted file mode 100644
index c3dd09c3071..00000000000
--- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.cpp
+++ /dev/null
@@ -1,4 +0,0 @@
-int main() {
- printf("%s\n", 42); //printf will treat 42 as a char*, will most likely segfault
- return 0;
-}
diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.qhelp b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.qhelp
index 02bfd391a33..055adeb741f 100644
--- a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.qhelp
+++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArguments.qhelp
@@ -4,29 +4,33 @@
Each call to the printf function or a related function should include
-the type and sequence of arguments defined by the format. If the function is passed arguments
+the type and sequence of arguments defined by the format. If the function is passed arguments
of a different type or in a different sequence then the arguments are reinterpreted to fit the type and sequence expected, resulting in unpredictable behavior.
-Review the format and arguments expected by the highlighted function calls. Update either
-the format or the arguments so that the expected type and sequence of arguments are passed to
+
Review the format and arguments expected by the highlighted function calls. Update either
+the format or the arguments so that the expected type and sequence of arguments are passed to
the function.
-
+
+
+In the following example, the wrong format specifier is given for an integer format argument:
+
+
+
+The corrected version uses %i as the format specifier for the integer format argument:
+
+
-CERT C Coding
-Standard: FIO30-C. Exclude user input from format strings.
-cplusplus.com: C++ Functions.
-CRT Alphabetical Function Reference: printf, _printf_l, wprintf, _wprintf_l.
-
-
-
+Microsoft Learn: Format specification syntax: printf and wprintf functions.
+cplusplus.com:printf
+CERT C Coding Standard: FIO47-C. Use valid format strings.
diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArgumentsBad.cpp b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArgumentsBad.cpp
new file mode 100644
index 00000000000..046233af1b0
--- /dev/null
+++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArgumentsBad.cpp
@@ -0,0 +1,4 @@
+int main() {
+ printf("%s\n", 42); // BAD: printf will treat 42 as a char*, will most likely segfault
+ return 0;
+}
diff --git a/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArgumentsGood.cpp b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArgumentsGood.cpp
new file mode 100644
index 00000000000..0bd3fb5c439
--- /dev/null
+++ b/cpp/ql/src/Likely Bugs/Format/WrongTypeFormatArgumentsGood.cpp
@@ -0,0 +1,4 @@
+int main() {
+ printf("%i\n", 42); // GOOD: printf will treat 42 as an int
+ return 0;
+}
diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.cpp b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.cpp
index c3640a66ab6..29eef7c2b1f 100644
--- a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.cpp
+++ b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.cpp
@@ -2,19 +2,18 @@
void f_warning(int i)
{
- // The usage of the logical not operator in this case is unlikely to be correct
+ // BAD: the usage of the logical not operator in this case is unlikely to be correct
// as the output is being used as an operator for a bit-wise and operation
- if (i & !FLAGS)
+ if (i & !FLAGS)
{
// code
}
}
-
void f_fixed(int i)
{
- if (i & ~FLAGS) // Changing the logical not operator for the bit-wise not operator would fix this logic
+ if (i & ~FLAGS) // GOOD: Changing the logical not operator for the bit-wise not operator would fix this logic
{
// code
}
-}
\ No newline at end of file
+}
diff --git a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp
index bac09fe9cf1..3b5824c314a 100644
--- a/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp
+++ b/cpp/ql/src/Likely Bugs/Likely Typos/IncorrectNotOperatorUsage.qhelp
@@ -16,7 +16,13 @@
Carefully inspect the flagged expressions. Consider the intent in the code logic, and decide whether it is necessary to change the not operator.
-
+
+Here is an example of this issue and how it can be fixed:
+
+
+
+In other cases, particularly when the expressions have bool type, the fix may instead be of the form a && !b.
+
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql
index e08f2a2a4c1..267d0b9bd88 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql
+++ b/cpp/ql/src/Likely Bugs/Memory Management/AllocaInLoop.ql
@@ -37,6 +37,19 @@ class AllocaCall extends FunctionCall {
}
}
+/**
+ * Gets an expression associated with a dataflow node.
+ */
+private Expr getExpr(DataFlow::Node node) {
+ result = node.asInstruction().getAst()
+ or
+ result = node.asOperand().getUse().getAst()
+ or
+ result = node.(DataFlow::RawIndirectInstruction).getInstruction().getAst()
+ or
+ result = node.(DataFlow::RawIndirectOperand).getOperand().getUse().getAst()
+}
+
/**
* A loop that contains an `alloca` call.
*/
@@ -185,19 +198,6 @@ class LoopWithAlloca extends Stmt {
not this.conditionReachesWithoutUpdate(var, this.(Loop).getCondition())
}
- /**
- * Gets an expression associated with a dataflow node.
- */
- private Expr getExpr(DataFlow::Node node) {
- result = node.asInstruction().getAst()
- or
- result = node.asOperand().getUse().getAst()
- or
- result = node.(DataFlow::RawIndirectInstruction).getInstruction().getAst()
- or
- result = node.(DataFlow::RawIndirectOperand).getOperand().getUse().getAst()
- }
-
/**
* Gets a definition that may be the most recent definition of the
* controlling variable `var` before this loop.
@@ -210,7 +210,7 @@ class LoopWithAlloca extends Stmt {
// Phi nodes will be preceded by nodes that represent actual definitions
not result instanceof DataFlow::SsaPhiNode and
// A source is outside the loop if it's not inside the loop
- not exists(Expr e | e = this.getExpr(result) | this = getAnEnclosingLoopOfExpr(e))
+ not exists(Expr e | e = getExpr(result) | this = getAnEnclosingLoopOfExpr(e))
)
}
@@ -221,9 +221,9 @@ class LoopWithAlloca extends Stmt {
private int getAControllingVarInitialValue(Variable var, DataFlow::Node source) {
source = this.getAPrecedingDef(var) and
(
- result = this.getExpr(source).getValue().toInt()
+ result = getExpr(source).getValue().toInt()
or
- result = this.getExpr(source).(Assignment).getRValue().getValue().toInt()
+ result = getExpr(source).(Assignment).getRValue().getValue().toInt()
)
}
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll
index 1bd90084c67..53ab3b4df93 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll
+++ b/cpp/ql/src/Likely Bugs/Memory Management/NtohlArrayNoBound.qll
@@ -107,7 +107,7 @@ class SnprintfSizeExpr extends BufferAccess, FunctionCall {
}
class MemcmpSizeExpr extends BufferAccess, FunctionCall {
- MemcmpSizeExpr() { this.getTarget().hasName("Memcmp") }
+ MemcmpSizeExpr() { this.getTarget().hasName("memcmp") }
override Expr getPointer() {
result = this.getArgument(0) or
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.cpp b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.cpp
deleted file mode 100644
index 07acc91cd5a..00000000000
--- a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.cpp
+++ /dev/null
@@ -1,2 +0,0 @@
-strncpy(dest, src, sizeof(src)); //wrong: size of dest should be used
-strncpy(dest, src, strlen(src)); //wrong: size of dest should be used
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.qhelp b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.qhelp
index 2e297116710..201b9057499 100644
--- a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.qhelp
+++ b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgs.qhelp
@@ -3,7 +3,7 @@
"qhelp.dtd">
-The standard library function strncpy copies a source string to a destination buffer. The third argument defines the maximum number of characters to copy and should be less than
+
The standard library function strncpy copies a source string to a destination buffer. The third argument defines the maximum number of characters to copy and should be less than
or equal to the size of the destination buffer. Calls of the form strncpy(dest, src, strlen(src)) or strncpy(dest, src, sizeof(src)) incorrectly set the third argument to the size of the source buffer. Executing a call of this type may cause a buffer overflow. Buffer overflows can lead to anything from a segmentation fault to a security vulnerability.
@@ -12,14 +12,20 @@ or equal to the size of the destination buffer. Calls of the form strncpy(
not the source buffer.
-
+
+In the following examples, the size of the source buffer is incorrectly used as a parameter to strncpy:
+
+The corrected version uses the size of the destination buffer, or a variable containing the size of the destination buffer as the size parameter to strncpy:
+
+
+
-cplusplus.com: strncpy.
+cplusplus.com: strncpy.
I. Gerg. An Overview and Example of the Buffer-Overflow Exploit. IANewsletter vol 7 no 4. 2005.
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgsBad.cpp b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgsBad.cpp
new file mode 100644
index 00000000000..952550b2638
--- /dev/null
+++ b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgsBad.cpp
@@ -0,0 +1,9 @@
+char src[256];
+char dest1[128];
+
+...
+
+strncpy(dest1, src, sizeof(src)); // wrong: size of dest should be used
+
+char *dest2 = (char *)malloc(sz1 + sz2 + sz3);
+strncpy(dest2, src, strlen(src)); // wrong: size of dest should be used
diff --git a/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgsGood.cpp b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgsGood.cpp
new file mode 100644
index 00000000000..22fc4ebd222
--- /dev/null
+++ b/cpp/ql/src/Likely Bugs/Memory Management/StrncpyFlippedArgsGood.cpp
@@ -0,0 +1,10 @@
+char src[256];
+char dest1[128];
+
+...
+
+strncpy(dest1, src, sizeof(dest1)); // correct
+
+size_t destSize = sz1 + sz2 + sz3;
+char *dest2 = (char *)malloc(destSize);
+strncpy(dest2, src, destSize); // correct
diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.c b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.c
deleted file mode 100644
index 63856888ebb..00000000000
--- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.c
+++ /dev/null
@@ -1,22 +0,0 @@
-int main(int argc, char** argv) {
- char *userAndFile = argv[2];
-
- {
- char fileBuffer[FILENAME_MAX] = "/home/";
- char *fileName = fileBuffer;
- size_t len = strlen(fileName);
- strncat(fileName+len, userAndFile, FILENAME_MAX-len-1);
- // BAD: a string from the user is used in a filename
- fopen(fileName, "wb+");
- }
-
- {
- char fileBuffer[FILENAME_MAX] = "/home/";
- char *fileName = fileBuffer;
- size_t len = strlen(fileName);
- // GOOD: use a fixed file
- char* fixed = "jim/file.txt";
- strncat(fileName+len, fixed, FILENAME_MAX-len-1);
- fopen(fileName, "wb+");
- }
-}
diff --git a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp
index eba2ede58f5..4d6238ac335 100644
--- a/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-022/TaintedPath.qhelp
@@ -3,36 +3,57 @@
"qhelp.dtd">
-Accessing paths controlled by users can allow an attacker to access unexpected resources. This
+
Accessing paths controlled by users can allow an attacker to access unexpected resources. This
can result in sensitive information being revealed or deleted, or an attacker being able to influence
behavior by modifying unexpected files.
-Paths that are naively constructed from data controlled by a user may contain unexpected special characters,
-such as "..". Such a path may potentially point to any directory on the filesystem.
+Paths that are naively constructed from data controlled by a user may be absolute paths, or may contain
+unexpected special characters such as "..". Such a path could point anywhere on the file system.
-Validate user input before using it to construct a filepath. Ideally, follow these rules:
+Validate user input before using it to construct a file path.
-
-- Do not allow more than a single "." character.
-- Do not allow directory separators such as "/" or "\" (depending on the filesystem).
-- Do not rely on simply replacing problematic sequences such as "../". For example, after applying this filter to
-".../...//" the resulting string would still be "../".
-- Ideally use a whitelist of known good patterns.
-
+Common validation methods include checking that the normalized path is relative and does not contain
+any ".." components, or checking that the path is contained within a safe folder. The method you should use depends
+on how the path is used in the application, and whether the path should be a single path component.
+
+
+If the path should be a single path component (such as a file name), you can check for the existence
+of any path separators ("/" or "\"), or ".." sequences in the input, and reject the input if any are found.
+
+
+
+Note that removing "../" sequences is not sufficient, since the input could still contain a path separator
+followed by "..". For example, the input ".../...//" would still result in the string "../" if only "../" sequences
+are removed.
+
+
+Finally, the simplest (but most restrictive) option is to use an allow list of safe patterns and make sure that
+the user input matches one of these patterns.
-In this example, a username and file are read from the arguments to main and then used to access a file in the
-user's home directory. However, a malicious user could enter a filename which contains special
-characters. For example, the string "../../etc/passwd" will result in the code reading the file located at
-"/home/[user]/../../etc/passwd", which is the system's password file. This could potentially allow them to
-access all the system's passwords.
+In this example, a file name is read from a user and then used to access a file.
+However, a malicious user could enter a file name anywhere on the file system,
+such as "/etc/passwd" or "../../../etc/passwd".
-
+
+
+
+If the input should only be a file name, you can check that it doesn't contain any path separators or ".." sequences.
+
+
+
+
+
+If the input should be within a specific directory, you can check that the resolved path
+is still contained within that directory.
+
+
+
@@ -41,6 +62,7 @@ access all the system's passwords.
OWASP:
Path Traversal.
+Linux man pages: realpath(3).
diff --git a/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPath.c b/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPath.c
new file mode 100644
index 00000000000..ff309d7d9d8
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPath.c
@@ -0,0 +1,10 @@
+int main(int argc, char** argv) {
+ char *userAndFile = argv[2];
+
+ {
+ char fileBuffer[PATH_MAX];
+ snprintf(fileBuffer, sizeof(fileBuffer), "/home/%s", userAndFile);
+ // BAD: a string from the user is used in a filename
+ fopen(fileBuffer, "wb+");
+ }
+}
diff --git a/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPathFolder.c b/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPathFolder.c
new file mode 100644
index 00000000000..1970e515d02
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPathFolder.c
@@ -0,0 +1,28 @@
+#include
+#include
+
+int main(int argc, char** argv) {
+ char *userAndFile = argv[2];
+ const char *baseDir = "/home/user/public/";
+ char fullPath[PATH_MAX];
+
+ // Attempt to concatenate the base directory and the user-supplied path
+ snprintf(fullPath, sizeof(fullPath), "%s%s", baseDir, userAndFile);
+
+ // Resolve the absolute path, normalizing any ".." or "."
+ char *resolvedPath = realpath(fullPath, NULL);
+ if (resolvedPath == NULL) {
+ perror("Error resolving path");
+ return 1;
+ }
+
+ // Check if the resolved path starts with the base directory
+ if (strncmp(baseDir, resolvedPath, strlen(baseDir)) != 0) {
+ free(resolvedPath);
+ return 1;
+ }
+
+ // GOOD: Path is within the intended directory
+ FILE *file = fopen(resolvedPath, "wb+");
+ free(resolvedPath);
+}
\ No newline at end of file
diff --git a/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPathNormalize.c b/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPathNormalize.c
new file mode 100644
index 00000000000..ab7607cdd3d
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-022/examples/TaintedPathNormalize.c
@@ -0,0 +1,16 @@
+#include
+#include
+
+int main(int argc, char** argv) {
+ char *fileName = argv[2];
+ // Check for invalid sequences in the user input
+ if (strstr(fileName , "..") || strchr(fileName , '/') || strchr(fileName , '\\')) {
+ printf("Invalid filename.\n");
+ return 1;
+ }
+
+ char fileBuffer[PATH_MAX];
+ snprintf(fileBuffer, sizeof(fileBuffer), "/home/user/files/%s", fileName);
+ // GOOD: We know that the filename is safe and stays within the public folder
+ FILE *file = fopen(fileBuffer, "wb+");
+}
\ No newline at end of file
diff --git a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.qhelp b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.qhelp
index 1bed6a59f52..fdf552ba766 100644
--- a/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-131/NoSpaceForZeroTerminator.qhelp
@@ -12,8 +12,8 @@ the required buffer size, but do not allocate space for the zero terminator.
-The expression highlighted by this rule creates a buffer that is of insufficient size to contain
-the data being copied. This makes the code vulnerable to buffer overflow which can result in anything from a segmentation fault to a security vulnerability (particularly if the array is on stack-allocated memory).
+The highlighted code segment creates a buffer without ensuring it's large enough to accommodate the copied data.
+This leaves the code susceptible to a buffer overflow attack, which could lead to anything from program crashes to malicious code execution.
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
similarity index 84%
rename from cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
rename to cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
index 19975b17493..87cc75c5f01 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.qhelp
@@ -30,6 +30,12 @@ This is because the temporary container is not bound to a rvalue reference.
+
+To fix lifetime_of_temp_not_extended, consider rewriting the code so that the lifetime of the temporary object is extended.
+In fixed_lifetime_of_temp_not_extended, the lifetime of the temporary object has been extended by storing it in an rvalue reference.
+
+
+
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
similarity index 72%
rename from cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
rename to cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
index a36e54070bb..139555cfa1d 100644
--- a/cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
+++ b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
@@ -2,9 +2,10 @@
* @name Iterator to expired container
* @description Using an iterator owned by a container whose lifetime has expired may lead to unexpected behavior.
* @kind problem
- * @precision high
+ * @precision medium
* @id cpp/iterator-to-expired-container
* @problem.severity warning
+ * @security-severity 8.8
* @tags reliability
* security
* external/cwe/cwe-416
@@ -61,14 +62,38 @@ DataFlow::Node getADestroyedNode(DataFlow::Node n) {
)
}
-predicate destroyedToBeginSink(DataFlow::Node sink, FunctionCall fc) {
+predicate destroyedToBeginSink(DataFlow::Node sink) {
exists(CallInstruction call |
call = sink.asOperand().(ThisArgumentOperand).getCall() and
- fc = call.getUnconvertedResultExpression() and
call.getStaticCallTarget() instanceof BeginOrEndFunction
)
}
+/**
+ * Holds if `node1` is the node corresponding to a qualifier of a destructor
+ * call and `node2` is a node that is destroyed as a result of `node1` being
+ * destroyed.
+ */
+private predicate qualifierToDestroyed(DataFlow::Node node1, DataFlow::Node node2) {
+ tempToDestructorSink(node1, _) and
+ node2 = getADestroyedNode(node1)
+}
+
+/**
+ * A configuration to track flow from a destroyed node to a qualifier of
+ * a `begin` or `end` function call.
+ *
+ * This configuration exists to prevent a cartesian product between all sinks and
+ * all states in `Config::isSink`.
+ */
+module Config0 implements DataFlow::ConfigSig {
+ predicate isSource(DataFlow::Node source) { qualifierToDestroyed(_, source) }
+
+ predicate isSink(DataFlow::Node sink) { destroyedToBeginSink(sink) }
+}
+
+module Flow0 = DataFlow::Global;
+
/**
* A configuration to track flow from a temporary variable to the qualifier of
* a destructor call, and subsequently to a qualifier of a call to `begin` or
@@ -78,12 +103,15 @@ module Config implements DataFlow::StateConfigSig {
newtype FlowState =
additional TempToDestructor() or
additional DestroyedToBegin(DataFlow::Node n) {
- exists(DataFlow::Node thisOperand |
- tempToDestructorSink(thisOperand, _) and
- n = getADestroyedNode(thisOperand)
- )
+ any(Flow0::PathNode pn | pn.isSource()).getNode() = n
}
+ /**
+ * Holds if `sink` is a qualifier to a call to `begin`, and `mid` is an
+ * object that is destroyed.
+ */
+ private predicate relevant(DataFlow::Node mid, DataFlow::Node sink) { Flow0::flow(mid, sink) }
+
predicate isSource(DataFlow::Node source, FlowState state) {
source.asInstruction().(VariableAddressInstruction).getIRVariable() instanceof IRTempVariable and
state = TempToDestructor()
@@ -92,16 +120,16 @@ module Config implements DataFlow::StateConfigSig {
predicate isAdditionalFlowStep(
DataFlow::Node node1, FlowState state1, DataFlow::Node node2, FlowState state2
) {
- tempToDestructorSink(node1, _) and
state1 = TempToDestructor() and
state2 = DestroyedToBegin(node2) and
- node2 = getADestroyedNode(node1)
+ qualifierToDestroyed(node1, node2)
}
predicate isSink(DataFlow::Node sink, FlowState state) {
- // Note: This is a non-trivial cartesian product!
- // Hopefully, both of these sets are quite small in practice
- destroyedToBeginSink(sink, _) and state instanceof DestroyedToBegin
+ exists(DataFlow::Node mid |
+ relevant(mid, sink) and
+ state = DestroyedToBegin(mid)
+ )
}
DataFlow::FlowFeature getAFeature() {
@@ -121,9 +149,9 @@ module Config implements DataFlow::StateConfigSig {
module Flow = DataFlow::GlobalWithState;
-from Flow::PathNode source, Flow::PathNode sink, FunctionCall beginOrEnd, DataFlow::Node mid
+from Flow::PathNode source, Flow::PathNode sink, DataFlow::Node mid
where
Flow::flowPath(source, sink) and
- destroyedToBeginSink(sink.getNode(), beginOrEnd) and
+ destroyedToBeginSink(sink.getNode()) and
sink.getState() = Config::DestroyedToBegin(mid)
-select mid, "This object is destroyed before $@ is called.", beginOrEnd, beginOrEnd.toString()
+select mid, "This object is destroyed at the end of the full-expression."
diff --git a/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime-fixed.cpp b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime-fixed.cpp
new file mode 100644
index 00000000000..d113b4165ff
--- /dev/null
+++ b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime-fixed.cpp
@@ -0,0 +1,6 @@
+void fixed_lifetime_of_temp_not_extended() {
+ auto&& v = get_vector();
+ for(auto x : log_and_return_argument(v)) {
+ use(x); // GOOD: The lifetime of the container returned by `get_vector()` has been extended to the lifetime of `v`.
+ }
+}
diff --git a/cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime.cpp b/cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime.cpp
similarity index 100%
rename from cpp/ql/src/experimental/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime.cpp
rename to cpp/ql/src/Security/CWE/CWE-416/IteratorToExpiredContainerExtendedLifetime.cpp
diff --git a/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.qhelp b/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.qhelp
index e0678c0beff..3a449b4c38c 100644
--- a/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.qhelp
+++ b/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.qhelp
@@ -8,6 +8,12 @@
When the std::string object is destroyed, the pointer returned by c_str is no
longer valid. If the pointer is used after the std::string object is destroyed, then the behavior is undefined.
+
+Typically, this problem occurs when a std::string is returned by a function call (or overloaded operator)
+by value, and the result is not immediately stored in a variable by value or reference in a way that extends the lifetime of
+the temporary object. The resulting temporary std::string object is destroyed at the end of the containing expression
+statement, along with any memory returned by a call to c_str.
+
@@ -39,6 +45,8 @@ points to valid memory.
MEM50-CPP. Do not access freed memory.
+Microsoft Learn: Temporary objects.
+cppreference.com: Lifetime of a temporary.
diff --git a/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql b/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql
index 7d776280f91..98248675908 100644
--- a/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql
+++ b/cpp/ql/src/Security/CWE/CWE-416/UseOfStringAfterLifetimeEnds.ql
@@ -23,4 +23,5 @@ where
(c.getTarget() instanceof StdStringCStr or c.getTarget() instanceof StdStringData) and
isTemporary(c.getQualifier().getFullyConverted())
select c,
- "The underlying string object is destroyed after the call to '" + c.getTarget() + "' returns."
+ "The underlying temporary string object is destroyed after the call to '" + c.getTarget() +
+ "' returns."
diff --git a/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql b/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql
index 84ef99ce955..8e99d6163d8 100644
--- a/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql
+++ b/cpp/ql/src/Security/CWE/CWE-416/UseOfUniquePointerAfterLifetimeEnds.ql
@@ -30,6 +30,8 @@ where
outlivesFullExpr(c) and
not c.isFromUninstantiatedTemplate(_) and
isUniquePointerDerefFunction(c.getTarget()) and
+ // Exclude cases where the pointer is implicitly converted to a non-pointer type
+ not c.getActualType() instanceof IntegralType and
isTemporary(c.getQualifier().getFullyConverted())
select c,
"The underlying unique pointer object is destroyed after the call to '" + c.getTarget() +
diff --git a/cpp/ql/src/change-notes/released/0.9.12.md b/cpp/ql/src/change-notes/released/0.9.12.md
new file mode 100644
index 00000000000..0a66e72ed44
--- /dev/null
+++ b/cpp/ql/src/change-notes/released/0.9.12.md
@@ -0,0 +1,5 @@
+## 0.9.12
+
+### New Queries
+
+* Added a new query, `cpp/iterator-to-expired-container`, to detect the creation of iterators owned by a temporary objects that are about to be destroyed.
diff --git a/cpp/ql/src/change-notes/released/1.0.0.md b/cpp/ql/src/change-notes/released/1.0.0.md
new file mode 100644
index 00000000000..6f9b4e6e6b1
--- /dev/null
+++ b/cpp/ql/src/change-notes/released/1.0.0.md
@@ -0,0 +1,10 @@
+## 1.0.0
+
+### Breaking Changes
+
+* CodeQL package management is now generally available, and all GitHub-produced CodeQL packages have had their version numbers increased to 1.0.0.
+
+### Minor Analysis Improvements
+
+* The "Use of unique pointer after lifetime ends" query (`cpp/use-of-unique-pointer-after-lifetime-ends`) no longer reports an alert when the pointer is converted to a boolean
+* The "Variable not initialized before use" query (`cpp/not-initialised`) no longer reports an alert on static variables.
diff --git a/cpp/ql/src/codeql-pack.release.yml b/cpp/ql/src/codeql-pack.release.yml
index 47eb8b55bab..b7eeb5b9736 100644
--- a/cpp/ql/src/codeql-pack.release.yml
+++ b/cpp/ql/src/codeql-pack.release.yml
@@ -1,2 +1,2 @@
---
-lastReleaseVersion: 0.9.11
+lastReleaseVersion: 1.0.0
diff --git a/cpp/ql/src/experimental/Best Practices/GuardedFree.cpp b/cpp/ql/src/experimental/Best Practices/GuardedFree.cpp
new file mode 100644
index 00000000000..5242e3da8f5
--- /dev/null
+++ b/cpp/ql/src/experimental/Best Practices/GuardedFree.cpp
@@ -0,0 +1,11 @@
+void test()
+{
+ char *foo = malloc(100);
+
+ // BAD
+ if (foo)
+ free(foo);
+
+ // GOOD
+ free(foo);
+}
\ No newline at end of file
diff --git a/cpp/ql/src/experimental/Best Practices/GuardedFree.qhelp b/cpp/ql/src/experimental/Best Practices/GuardedFree.qhelp
new file mode 100644
index 00000000000..77fdd467000
--- /dev/null
+++ b/cpp/ql/src/experimental/Best Practices/GuardedFree.qhelp
@@ -0,0 +1,18 @@
+
+
+
+The free function, which deallocates heap memory, may accept a NULL pointer and take no action. Therefore, it is unnecessary to check its argument for the value of NULL before a function call to free. As such, these guards may hinder performance and readability.
+
+
+A function call to free should not depend upon the value of its argument. Delete the if condition preceeding a function call to free when its only purpose is to check the value of the pointer to be freed.
+
+
+
+
+
+
+ The Open Group Base Specifications Issue 7, 2018 Edition:
+ free - free allocated memory
+
+
+
\ No newline at end of file
diff --git a/cpp/ql/src/experimental/Best Practices/GuardedFree.ql b/cpp/ql/src/experimental/Best Practices/GuardedFree.ql
new file mode 100644
index 00000000000..2d504d9bc05
--- /dev/null
+++ b/cpp/ql/src/experimental/Best Practices/GuardedFree.ql
@@ -0,0 +1,26 @@
+/**
+ * @name Guarded Free
+ * @description NULL-condition guards before function calls to the memory-deallocation
+ * function free(3) are unnecessary, because passing NULL to free(3) is a no-op.
+ * @kind problem
+ * @problem.severity recommendation
+ * @precision very-high
+ * @id cpp/guarded-free
+ * @tags maintainability
+ * readability
+ * experimental
+ */
+
+import cpp
+import semmle.code.cpp.controlflow.Guards
+
+class FreeCall extends FunctionCall {
+ FreeCall() { this.getTarget().hasGlobalName("free") }
+}
+
+from GuardCondition gc, FreeCall fc, Variable v, BasicBlock bb
+where
+ gc.ensuresEq(v.getAnAccess(), 0, bb, false) and
+ fc.getArgument(0) = v.getAnAccess() and
+ bb = fc.getEnclosingStmt()
+select gc, "unnecessary NULL check before call to $@", fc, "free"
diff --git a/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.cpp b/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.cpp
new file mode 100644
index 00000000000..f96d67517b7
--- /dev/null
+++ b/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.cpp
@@ -0,0 +1,23 @@
+char * create (int arg) {
+ if (arg > 42) {
+ // this function may return NULL
+ return NULL;
+ }
+ char * r = malloc(arg);
+ snprintf(r, arg -1, "Hello");
+ return r;
+}
+
+void process(char *str) {
+ // str is dereferenced
+ if (str[0] == 'H') {
+ printf("Hello H\n");
+ }
+}
+
+void test(int arg) {
+ // first function returns a pointer that may be NULL
+ char *str = create(arg);
+ // str is not checked for nullness before being passed to process function
+ process(str);
+}
diff --git a/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.qhelp b/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.qhelp
new file mode 100644
index 00000000000..6c802a9b60b
--- /dev/null
+++ b/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.qhelp
@@ -0,0 +1,26 @@
+
+
+
+
+This rule finds a dereference of a function parameter, whose value comes from another function call that may return NULL, without checks in the meantime.
+
+
+
+A check should be added between the return of the function which may return NULL, and its use by the function dereferencing ths pointer.
+
+
+
+
+
+
+
+
+
+ Null Dereference
+
+
+
+
+
diff --git a/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.ql b/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.ql
new file mode 100644
index 00000000000..875c4f1dd96
--- /dev/null
+++ b/cpp/ql/src/experimental/Likely Bugs/DerefNullResult.ql
@@ -0,0 +1,34 @@
+/**
+ * @name Null dereference from a function result
+ * @description A function parameter is dereferenced,
+ * while it comes from a function that may return NULL,
+ * and is not checked for nullness by the caller.
+ * @kind problem
+ * @id cpp/deref-null-result
+ * @problem.severity recommendation
+ * @tags reliability
+ * security
+ * external/cwe/cwe-476
+ */
+
+import cpp
+import semmle.code.cpp.dataflow.new.DataFlow
+
+from Function nuller, Parameter pd, FunctionCall fc, Variable v
+where
+ mayReturnNull(nuller) and
+ functionDereferences(pd.getFunction(), pd.getIndex()) and
+ // there is a function call which will deref parameter pd
+ fc.getTarget() = pd.getFunction() and
+ // the parameter pd comes from a variable v
+ DataFlow::localFlow(DataFlow::exprNode(v.getAnAccess()),
+ DataFlow::exprNode(fc.getArgument(pd.getIndex()))) and
+ // this variable v was assigned by a call to the nuller function
+ unique( | | v.getAnAssignedValue()) = nuller.getACallToThisFunction() and
+ // this variable v is not accessed for an operation (check for NULLness)
+ not exists(VariableAccess vc |
+ vc.getTarget() = v and
+ (vc.getParent() instanceof Operation or vc.getParent() instanceof IfStmt)
+ )
+select fc, "This function call may deref $@ when it can be NULL from $@", v, v.getName(), nuller,
+ nuller.getName()
diff --git a/cpp/ql/src/qlpack.yml b/cpp/ql/src/qlpack.yml
index 7eb3d91c602..9e45007445b 100644
--- a/cpp/ql/src/qlpack.yml
+++ b/cpp/ql/src/qlpack.yml
@@ -1,5 +1,5 @@
name: codeql/cpp-queries
-version: 0.9.11
+version: 1.0.0
groups:
- cpp
- queries
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected
index 805d87c9645..fa7f625210d 100644
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected
+++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/constant-size/ConstantSizeArrayOffByOne.expected
@@ -1,55 +1,55 @@
edges
-| test.cpp:34:10:34:12 | buf | test.cpp:34:5:34:24 | access to array | provenance | |
-| test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | provenance | |
-| test.cpp:36:10:36:12 | buf | test.cpp:36:5:36:24 | access to array | provenance | |
-| test.cpp:39:14:39:16 | buf | test.cpp:39:9:39:19 | access to array | provenance | |
-| test.cpp:43:14:43:16 | buf | test.cpp:43:9:43:19 | access to array | provenance | |
-| test.cpp:48:10:48:12 | buf | test.cpp:48:5:48:24 | access to array | provenance | |
-| test.cpp:49:10:49:12 | buf | test.cpp:49:5:49:22 | access to array | provenance | |
-| test.cpp:50:10:50:12 | buf | test.cpp:50:5:50:24 | access to array | provenance | |
-| test.cpp:53:14:53:16 | buf | test.cpp:53:9:53:19 | access to array | provenance | |
-| test.cpp:57:14:57:16 | buf | test.cpp:57:9:57:19 | access to array | provenance | |
-| test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array | provenance | |
-| test.cpp:70:33:70:33 | p | test.cpp:71:5:71:17 | access to array | provenance | |
-| test.cpp:70:33:70:33 | p | test.cpp:72:5:72:15 | access to array | provenance | |
+| test.cpp:34:10:34:12 | buf | test.cpp:34:5:34:24 | access to array | provenance | Config |
+| test.cpp:35:10:35:12 | buf | test.cpp:35:5:35:22 | access to array | provenance | Config |
+| test.cpp:36:10:36:12 | buf | test.cpp:36:5:36:24 | access to array | provenance | Config |
+| test.cpp:39:14:39:16 | buf | test.cpp:39:9:39:19 | access to array | provenance | Config |
+| test.cpp:43:14:43:16 | buf | test.cpp:43:9:43:19 | access to array | provenance | Config |
+| test.cpp:48:10:48:12 | buf | test.cpp:48:5:48:24 | access to array | provenance | Config |
+| test.cpp:49:10:49:12 | buf | test.cpp:49:5:49:22 | access to array | provenance | Config |
+| test.cpp:50:10:50:12 | buf | test.cpp:50:5:50:24 | access to array | provenance | Config |
+| test.cpp:53:14:53:16 | buf | test.cpp:53:9:53:19 | access to array | provenance | Config |
+| test.cpp:57:14:57:16 | buf | test.cpp:57:9:57:19 | access to array | provenance | Config |
+| test.cpp:61:14:61:16 | buf | test.cpp:61:9:61:19 | access to array | provenance | Config |
+| test.cpp:70:33:70:33 | p | test.cpp:71:5:71:17 | access to array | provenance | Config |
+| test.cpp:70:33:70:33 | p | test.cpp:72:5:72:15 | access to array | provenance | Config |
| test.cpp:76:26:76:46 | & ... | test.cpp:66:32:66:32 | p | provenance | |
-| test.cpp:76:32:76:34 | buf | test.cpp:76:26:76:46 | & ... | provenance | |
+| test.cpp:76:32:76:34 | buf | test.cpp:76:26:76:46 | & ... | provenance | Config |
| test.cpp:77:26:77:44 | & ... | test.cpp:66:32:66:32 | p | provenance | |
-| test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... | provenance | |
+| test.cpp:77:32:77:34 | buf | test.cpp:77:26:77:44 | & ... | provenance | Config |
| test.cpp:79:27:79:34 | buf | test.cpp:70:33:70:33 | p | provenance | |
| test.cpp:79:32:79:34 | buf | test.cpp:79:27:79:34 | buf | provenance | |
-| test.cpp:85:21:85:36 | buf | test.cpp:87:5:87:31 | access to array | provenance | |
-| test.cpp:85:21:85:36 | buf | test.cpp:88:5:88:27 | access to array | provenance | |
+| test.cpp:85:21:85:36 | buf | test.cpp:87:5:87:31 | access to array | provenance | Config |
+| test.cpp:85:21:85:36 | buf | test.cpp:88:5:88:27 | access to array | provenance | Config |
| test.cpp:85:34:85:36 | buf | test.cpp:85:21:85:36 | buf | provenance | |
-| test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array | provenance | |
-| test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | |
-| test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | |
-| test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | |
-| test.cpp:115:35:115:37 | arr | test.cpp:111:17:111:22 | access to array | provenance | |
-| test.cpp:115:35:115:37 | arr | test.cpp:115:35:115:40 | access to array | provenance | |
-| test.cpp:115:35:115:37 | arr | test.cpp:119:17:119:22 | access to array | provenance | |
-| test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | |
-| test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | |
-| test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | |
-| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | provenance | |
-| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... | provenance | |
+| test.cpp:96:13:96:15 | arr | test.cpp:96:13:96:18 | access to array | provenance | Config |
+| test.cpp:111:17:111:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | Config |
+| test.cpp:111:17:111:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | Config |
+| test.cpp:111:17:111:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | Config |
+| test.cpp:115:35:115:37 | arr | test.cpp:111:17:111:22 | access to array | provenance | Config |
+| test.cpp:115:35:115:37 | arr | test.cpp:115:35:115:40 | access to array | provenance | Config |
+| test.cpp:115:35:115:37 | arr | test.cpp:119:17:119:22 | access to array | provenance | Config |
+| test.cpp:119:17:119:19 | arr | test.cpp:111:17:111:22 | access to array | provenance | Config |
+| test.cpp:119:17:119:19 | arr | test.cpp:115:35:115:40 | access to array | provenance | Config |
+| test.cpp:119:17:119:19 | arr | test.cpp:119:17:119:22 | access to array | provenance | Config |
+| test.cpp:128:9:128:11 | arr | test.cpp:128:9:128:14 | access to array | provenance | Config |
+| test.cpp:134:25:134:27 | arr | test.cpp:136:9:136:16 | ... += ... | provenance | Config |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:136:9:136:16 | ... += ... | provenance | |
| test.cpp:136:9:136:16 | ... += ... | test.cpp:138:13:138:15 | arr | provenance | |
| test.cpp:143:18:143:21 | asdf | test.cpp:134:25:134:27 | arr | provenance | |
| test.cpp:143:18:143:21 | asdf | test.cpp:143:18:143:21 | asdf | provenance | |
| test.cpp:146:26:146:26 | *p | test.cpp:147:4:147:9 | -- ... | provenance | |
-| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... | provenance | |
+| test.cpp:156:12:156:14 | buf | test.cpp:156:12:156:18 | ... + ... | provenance | Config |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:156:12:156:18 | ... + ... | provenance | |
| test.cpp:156:12:156:18 | ... + ... | test.cpp:158:17:158:18 | *& ... | provenance | |
| test.cpp:158:17:158:18 | *& ... | test.cpp:146:26:146:26 | *p | provenance | |
-| test.cpp:218:16:218:28 | buffer | test.cpp:220:5:220:11 | access to array | provenance | |
-| test.cpp:218:16:218:28 | buffer | test.cpp:221:5:221:11 | access to array | provenance | |
+| test.cpp:218:16:218:28 | buffer | test.cpp:220:5:220:11 | access to array | provenance | Config |
+| test.cpp:218:16:218:28 | buffer | test.cpp:221:5:221:11 | access to array | provenance | Config |
| test.cpp:218:23:218:28 | buffer | test.cpp:218:16:218:28 | buffer | provenance | |
-| test.cpp:229:17:229:29 | array | test.cpp:231:5:231:10 | access to array | provenance | |
-| test.cpp:229:17:229:29 | array | test.cpp:232:5:232:10 | access to array | provenance | |
+| test.cpp:229:17:229:29 | array | test.cpp:231:5:231:10 | access to array | provenance | Config |
+| test.cpp:229:17:229:29 | array | test.cpp:232:5:232:10 | access to array | provenance | Config |
| test.cpp:229:25:229:29 | array | test.cpp:229:17:229:29 | array | provenance | |
-| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | |
-| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | |
+| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | Config |
+| test.cpp:245:30:245:30 | p | test.cpp:261:27:261:30 | access to array | provenance | Config |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:245:30:245:30 | p | provenance | |
| test.cpp:274:14:274:20 | buffer3 | test.cpp:274:14:274:20 | buffer3 | provenance | |
| test.cpp:277:35:277:35 | p | test.cpp:278:14:278:14 | p | provenance | |
@@ -60,21 +60,20 @@ edges
| test.cpp:286:19:286:25 | buffer2 | test.cpp:286:19:286:25 | buffer2 | provenance | |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:277:35:277:35 | p | provenance | |
| test.cpp:289:19:289:25 | buffer3 | test.cpp:289:19:289:25 | buffer3 | provenance | |
-| test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | provenance | |
-| test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | provenance | |
+| test.cpp:292:25:292:27 | arr | test.cpp:299:16:299:21 | access to array | provenance | Config |
| test.cpp:306:20:306:23 | arr1 | test.cpp:292:25:292:27 | arr | provenance | |
| test.cpp:306:20:306:23 | arr1 | test.cpp:306:20:306:23 | arr1 | provenance | |
| test.cpp:309:20:309:23 | arr2 | test.cpp:292:25:292:27 | arr | provenance | |
| test.cpp:309:20:309:23 | arr2 | test.cpp:309:20:309:23 | arr2 | provenance | |
| test.cpp:319:13:319:27 | ... = ... | test.cpp:325:24:325:26 | end | provenance | |
-| test.cpp:319:19:319:22 | temp | test.cpp:319:19:319:27 | ... + ... | provenance | |
-| test.cpp:319:19:319:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | |
+| test.cpp:319:19:319:22 | temp | test.cpp:319:19:319:27 | ... + ... | provenance | Config |
+| test.cpp:319:19:319:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | Config |
| test.cpp:319:19:319:27 | ... + ... | test.cpp:319:13:319:27 | ... = ... | provenance | |
| test.cpp:322:13:322:27 | ... = ... | test.cpp:325:24:325:26 | end | provenance | |
-| test.cpp:322:19:322:22 | temp | test.cpp:322:19:322:27 | ... + ... | provenance | |
-| test.cpp:322:19:322:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | |
+| test.cpp:322:19:322:22 | temp | test.cpp:322:19:322:27 | ... + ... | provenance | Config |
+| test.cpp:322:19:322:22 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | Config |
| test.cpp:322:19:322:27 | ... + ... | test.cpp:322:13:322:27 | ... = ... | provenance | |
-| test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | |
+| test.cpp:324:23:324:26 | temp | test.cpp:324:23:324:32 | ... + ... | provenance | Config |
| test.cpp:324:23:324:32 | ... + ... | test.cpp:324:23:324:32 | ... + ... | provenance | |
| test.cpp:324:23:324:32 | ... + ... | test.cpp:325:15:325:19 | temp2 | provenance | |
nodes
@@ -159,7 +158,6 @@ nodes
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
| test.cpp:289:19:289:25 | buffer3 | semmle.label | buffer3 |
| test.cpp:292:25:292:27 | arr | semmle.label | arr |
-| test.cpp:292:25:292:27 | arr | semmle.label | arr |
| test.cpp:299:16:299:21 | access to array | semmle.label | access to array |
| test.cpp:306:20:306:23 | arr1 | semmle.label | arr1 |
| test.cpp:306:20:306:23 | arr1 | semmle.label | arr1 |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.expected
deleted file mode 100644
index c29e7953ea6..00000000000
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.expected
+++ /dev/null
@@ -1,11 +0,0 @@
-| test.cpp:680:30:680:30 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:680:17:680:17 | call to begin | call to begin |
-| test.cpp:680:30:680:30 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:680:17:680:17 | call to end | call to end |
-| test.cpp:683:31:683:32 | call to at | This object is destroyed before $@ is called. | test.cpp:683:17:683:17 | call to begin | call to begin |
-| test.cpp:683:31:683:32 | call to at | This object is destroyed before $@ is called. | test.cpp:683:17:683:17 | call to end | call to end |
-| test.cpp:689:46:689:58 | pointer to ~vector output argument | This object is destroyed before $@ is called. | test.cpp:689:60:689:62 | call to end | call to end |
-| test.cpp:702:27:702:27 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:703:19:703:23 | call to begin | call to begin |
-| test.cpp:702:27:702:27 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:703:36:703:38 | call to end | call to end |
-| test.cpp:727:23:727:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:750:17:750:17 | call to begin | call to begin |
-| test.cpp:727:23:727:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:750:17:750:17 | call to end | call to end |
-| test.cpp:735:23:735:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:759:17:759:17 | call to begin | call to begin |
-| test.cpp:735:23:735:23 | call to operator[] | This object is destroyed before $@ is called. | test.cpp:759:17:759:17 | call to end | call to end |
diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.qlref b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.qlref
deleted file mode 100644
index 5f86bb26ff0..00000000000
--- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-416/IteratorToExpiredContainer.qlref
+++ /dev/null
@@ -1 +0,0 @@
-experimental/Security/CWE/CWE-416/IteratorToExpiredContainer.ql
diff --git a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected
index 943d7028a5d..6cf7d2b6a95 100644
--- a/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected
+++ b/cpp/ql/test/library-tests/controlflow/guards-ir/tests.expected
@@ -148,6 +148,27 @@ astGuardsCompare
| 109 | y < 0+0 when ... < ... is true |
| 109 | y >= 0+0 when ... < ... is false |
| 109 | y >= 0+0 when ... \|\| ... is false |
+| 126 | 1 != 0 when 1 is true |
+| 126 | 1 != 0 when ... && ... is true |
+| 126 | 1 == 0 when 1 is false |
+| 126 | call to test3_condition != 0 when ... && ... is true |
+| 126 | call to test3_condition != 0 when call to test3_condition is true |
+| 126 | call to test3_condition == 0 when call to test3_condition is false |
+| 131 | b != 0 when b is true |
+| 131 | b == 0 when b is false |
+| 137 | 0 != 0 when 0 is true |
+| 137 | 0 == 0 when 0 is false |
+| 146 | ! ... != 0 when ! ... is true |
+| 146 | ! ... == 0 when ! ... is false |
+| 146 | x != 0 when ! ... is false |
+| 146 | x != 0 when x is true |
+| 146 | x == 0 when x is false |
+| 152 | x != 0 when ... && ... is true |
+| 152 | x != 0 when x is true |
+| 152 | x == 0 when x is false |
+| 152 | y != 0 when ... && ... is true |
+| 152 | y != 0 when y is true |
+| 152 | y == 0 when y is false |
| 156 | ... + ... != x+0 when ... == ... is false |
| 156 | ... + ... == x+0 when ... == ... is true |
| 156 | x != ... + ...+0 when ... == ... is false |
@@ -186,6 +207,8 @@ astGuardsCompare
| 175 | call to foo != 0+0 when ... == ... is false |
| 175 | call to foo == 0 when ... == ... is true |
| 175 | call to foo == 0+0 when ... == ... is true |
+| 181 | x != 0 when x is true |
+| 181 | x == 0 when x is false |
astGuardsControl
| test.c:7:9:7:13 | ... > ... | false | 10 | 11 |
| test.c:7:9:7:13 | ... > ... | true | 7 | 9 |
@@ -487,8 +510,28 @@ astGuardsEnsure_const
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 109 | 109 |
| test.c:109:9:109:14 | ... == ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 126 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
+| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
+| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
+| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
+| test.c:131:7:131:7 | b | test.c:131:7:131:7 | b | != | 0 | 131 | 132 |
+| test.c:137:7:137:7 | 0 | test.c:137:7:137:7 | 0 | == | 0 | 142 | 136 |
+| test.c:146:7:146:8 | ! ... | test.c:146:7:146:8 | ! ... | != | 0 | 146 | 147 |
+| test.c:146:8:146:8 | x | test.c:146:8:146:8 | x | == | 0 | 146 | 147 |
+| test.c:152:10:152:10 | x | test.c:152:10:152:10 | x | != | 0 | 151 | 152 |
+| test.c:152:10:152:10 | x | test.c:152:10:152:10 | x | != | 0 | 152 | 152 |
+| test.c:152:10:152:15 | ... && ... | test.c:152:10:152:10 | x | != | 0 | 151 | 152 |
+| test.c:152:10:152:15 | ... && ... | test.c:152:15:152:15 | y | != | 0 | 151 | 152 |
+| test.c:152:15:152:15 | y | test.c:152:15:152:15 | y | != | 0 | 151 | 152 |
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | != | 0 | 175 | 175 |
| test.c:175:13:175:32 | ... == ... | test.c:175:13:175:15 | call to foo | == | 0 | 175 | 175 |
+| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | != | 0 | 181 | 182 |
+| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | != | 0 | 186 | 180 |
+| test.c:181:9:181:9 | x | test.c:181:9:181:9 | x | == | 0 | 183 | 184 |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
@@ -640,6 +683,23 @@ irGuardsCompare
| 109 | y < 0+0 when CompareLT: ... < ... is true |
| 109 | y >= 0 when CompareLT: ... < ... is false |
| 109 | y >= 0+0 when CompareLT: ... < ... is false |
+| 126 | 1 != 0 when Constant: 1 is true |
+| 126 | 1 == 0 when Constant: 1 is false |
+| 126 | call to test3_condition != 0 when Call: call to test3_condition is true |
+| 126 | call to test3_condition == 0 when Call: call to test3_condition is false |
+| 131 | b != 0 when Load: b is true |
+| 131 | b == 0 when Load: b is false |
+| 137 | 0 != 0 when Constant: 0 is true |
+| 137 | 0 == 0 when Constant: 0 is false |
+| 146 | ! ... != 0 when LogicalNot: ! ... is true |
+| 146 | ! ... == 0 when LogicalNot: ! ... is false |
+| 146 | x != 0 when Load: x is true |
+| 146 | x != 0 when LogicalNot: ! ... is false |
+| 146 | x == 0 when Load: x is false |
+| 152 | x != 0 when Load: x is true |
+| 152 | x == 0 when Load: x is false |
+| 152 | y != 0 when Load: y is true |
+| 152 | y == 0 when Load: y is false |
| 156 | ... + ... != x+0 when CompareEQ: ... == ... is false |
| 156 | ... + ... == x+0 when CompareEQ: ... == ... is true |
| 156 | x != ... + ...+0 when CompareEQ: ... == ... is false |
@@ -678,6 +738,8 @@ irGuardsCompare
| 175 | call to foo != 0+0 when CompareEQ: ... == ... is false |
| 175 | call to foo == 0 when CompareEQ: ... == ... is true |
| 175 | call to foo == 0+0 when CompareEQ: ... == ... is true |
+| 181 | x != 0 when Load: x is true |
+| 181 | x == 0 when Load: x is false |
irGuardsControl
| test.c:7:9:7:13 | CompareGT: ... > ... | false | 11 | 11 |
| test.c:7:9:7:13 | CompareGT: ... > ... | true | 8 | 8 |
@@ -999,8 +1061,22 @@ irGuardsEnsure_const
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | 0 | 109 | 109 |
| test.c:109:9:109:14 | CompareEQ: ... == ... | test.c:109:9:109:9 | Load: x | != | 0 | 113 | 113 |
| test.c:109:19:109:23 | CompareLT: ... < ... | test.c:109:19:109:19 | Load: y | >= | 0 | 113 | 113 |
+| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 126 | 126 |
+| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 127 | 127 |
+| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 131 | 131 |
+| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 132 | 132 |
+| test.c:126:7:126:7 | Constant: 1 | test.c:126:7:126:7 | Constant: 1 | != | 0 | 134 | 134 |
+| test.c:126:12:126:26 | Call: call to test3_condition | test.c:126:12:126:26 | Call: call to test3_condition | != | 0 | 127 | 127 |
+| test.c:131:7:131:7 | Load: b | test.c:131:7:131:7 | Load: b | != | 0 | 132 | 132 |
+| test.c:137:7:137:7 | Constant: 0 | test.c:137:7:137:7 | Constant: 0 | == | 0 | 142 | 142 |
+| test.c:146:7:146:8 | LogicalNot: ! ... | test.c:146:7:146:8 | LogicalNot: ! ... | != | 0 | 147 | 147 |
+| test.c:146:8:146:8 | Load: x | test.c:146:8:146:8 | Load: x | == | 0 | 147 | 147 |
+| test.c:152:10:152:10 | Load: x | test.c:152:10:152:10 | Load: x | != | 0 | 152 | 152 |
+| test.c:152:15:152:15 | Load: y | test.c:152:15:152:15 | Load: y | != | 0 | 152 | 152 |
| test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | != | 0 | 175 | 175 |
| test.c:175:13:175:32 | CompareEQ: ... == ... | test.c:175:13:175:15 | Call: call to foo | == | 0 | 175 | 175 |
+| test.c:181:9:181:9 | Load: x | test.c:181:9:181:9 | Load: x | != | 0 | 182 | 182 |
+| test.c:181:9:181:9 | Load: x | test.c:181:9:181:9 | Load: x | == | 0 | 184 | 184 |
| test.cpp:18:8:18:12 | CompareNE: (bool)... | test.cpp:18:8:18:10 | Call: call to get | != | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | != | -1 | 34 | 34 |
| test.cpp:31:7:31:13 | CompareEQ: ... == ... | test.cpp:31:7:31:7 | Load: x | == | -1 | 30 | 30 |
diff --git a/cpp/ql/test/library-tests/controlflow/guards/Guards.expected b/cpp/ql/test/library-tests/controlflow/guards/Guards.expected
index 08a8a9281bb..13d6c2b654f 100644
--- a/cpp/ql/test/library-tests/controlflow/guards/Guards.expected
+++ b/cpp/ql/test/library-tests/controlflow/guards/Guards.expected
@@ -26,6 +26,12 @@
| test.c:137:7:137:7 | 0 |
| test.c:146:7:146:8 | ! ... |
| test.c:146:8:146:8 | x |
+| test.c:152:8:152:8 | p |
+| test.c:158:8:158:9 | ! ... |
+| test.c:158:9:158:9 | p |
+| test.c:164:8:164:8 | s |
+| test.c:170:8:170:9 | ! ... |
+| test.c:170:9:170:9 | s |
| test.cpp:18:8:18:10 | call to get |
| test.cpp:31:7:31:13 | ... == ... |
| test.cpp:42:13:42:20 | call to getABool |
diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected b/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected
index 756140604e1..3d32ada5f30 100644
--- a/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected
+++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsCompare.expected
@@ -149,3 +149,32 @@
| 111 | 0.0 == i+0 when ... != ... is false |
| 111 | i != 0.0+0 when ... != ... is true |
| 111 | i == 0.0+0 when ... != ... is false |
+| 126 | 1 != 0 when 1 is true |
+| 126 | 1 != 0 when ... && ... is true |
+| 126 | 1 == 0 when 1 is false |
+| 126 | call to test3_condition != 0 when ... && ... is true |
+| 126 | call to test3_condition != 0 when call to test3_condition is true |
+| 126 | call to test3_condition == 0 when call to test3_condition is false |
+| 131 | b != 0 when b is true |
+| 131 | b == 0 when b is false |
+| 137 | 0 != 0 when 0 is true |
+| 137 | 0 == 0 when 0 is false |
+| 146 | ! ... != 0 when ! ... is true |
+| 146 | ! ... == 0 when ! ... is false |
+| 146 | x != 0 when ! ... is false |
+| 146 | x != 0 when x is true |
+| 146 | x == 0 when x is false |
+| 152 | p != 0 when p is true |
+| 152 | p == 0 when p is false |
+| 158 | ! ... != 0 when ! ... is true |
+| 158 | ! ... == 0 when ! ... is false |
+| 158 | p != 0 when ! ... is false |
+| 158 | p != 0 when p is true |
+| 158 | p == 0 when p is false |
+| 164 | s != 0 when s is true |
+| 164 | s == 0 when s is false |
+| 170 | ! ... != 0 when ! ... is true |
+| 170 | ! ... == 0 when ! ... is false |
+| 170 | s != 0 when ! ... is false |
+| 170 | s != 0 when s is true |
+| 170 | s == 0 when s is false |
diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected b/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected
index 62d9b0a1229..cf36a58a515 100644
--- a/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected
+++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsControl.expected
@@ -79,6 +79,12 @@
| test.c:137:7:137:7 | 0 | false | 142 | 136 |
| test.c:146:7:146:8 | ! ... | true | 146 | 147 |
| test.c:146:8:146:8 | x | false | 146 | 147 |
+| test.c:152:8:152:8 | p | true | 152 | 154 |
+| test.c:158:8:158:9 | ! ... | true | 158 | 160 |
+| test.c:158:9:158:9 | p | false | 158 | 160 |
+| test.c:164:8:164:8 | s | true | 164 | 166 |
+| test.c:170:8:170:9 | ! ... | true | 170 | 172 |
+| test.c:170:9:170:9 | s | false | 170 | 172 |
| test.cpp:18:8:18:10 | call to get | true | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | false | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | false | 34 | 34 |
diff --git a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected
index f9eaced1276..84c416445ae 100644
--- a/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected
+++ b/cpp/ql/test/library-tests/controlflow/guards/GuardsEnsure.expected
@@ -234,6 +234,24 @@ unary
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:9:109:9 | x | != | 0 | 113 | 113 |
| test.c:109:9:109:23 | ... \|\| ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 |
| test.c:109:19:109:23 | ... < ... | test.c:109:19:109:19 | y | >= | 0 | 113 | 113 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 126 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 131 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 131 | 132 |
+| test.c:126:7:126:7 | 1 | test.c:126:7:126:7 | 1 | != | 0 | 134 | 123 |
+| test.c:126:7:126:28 | ... && ... | test.c:126:7:126:7 | 1 | != | 0 | 126 | 128 |
+| test.c:126:7:126:28 | ... && ... | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
+| test.c:126:12:126:26 | call to test3_condition | test.c:126:12:126:26 | call to test3_condition | != | 0 | 126 | 128 |
+| test.c:131:7:131:7 | b | test.c:131:7:131:7 | b | != | 0 | 131 | 132 |
+| test.c:137:7:137:7 | 0 | test.c:137:7:137:7 | 0 | == | 0 | 142 | 136 |
+| test.c:146:7:146:8 | ! ... | test.c:146:7:146:8 | ! ... | != | 0 | 146 | 147 |
+| test.c:146:8:146:8 | x | test.c:146:8:146:8 | x | == | 0 | 146 | 147 |
+| test.c:152:8:152:8 | p | test.c:152:8:152:8 | p | != | 0 | 152 | 154 |
+| test.c:158:8:158:9 | ! ... | test.c:158:8:158:9 | ! ... | != | 0 | 158 | 160 |
+| test.c:158:9:158:9 | p | test.c:158:9:158:9 | p | == | 0 | 158 | 160 |
+| test.c:164:8:164:8 | s | test.c:164:8:164:8 | s | != | 0 | 164 | 166 |
+| test.c:170:8:170:9 | ! ... | test.c:170:8:170:9 | ! ... | != | 0 | 170 | 172 |
+| test.c:170:9:170:9 | s | test.c:170:9:170:9 | s | == | 0 | 170 | 172 |
| test.cpp:18:8:18:10 | call to get | test.cpp:18:8:18:10 | call to get | != | 0 | 19 | 19 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 30 | 30 |
| test.cpp:31:7:31:13 | ... == ... | test.cpp:31:7:31:7 | x | != | -1 | 34 | 34 |
diff --git a/cpp/ql/test/library-tests/controlflow/guards/test.c b/cpp/ql/test/library-tests/controlflow/guards/test.c
index 186244d4fca..207e23baa0e 100644
--- a/cpp/ql/test/library-tests/controlflow/guards/test.c
+++ b/cpp/ql/test/library-tests/controlflow/guards/test.c
@@ -147,3 +147,27 @@ void test5(int x) {
test3();
}
}
+
+void test6(char* p) {
+ if(p) {
+
+ }
+}
+
+void test7(char* p) {
+ if(!p) {
+
+ }
+}
+
+void test8(short s) {
+ if(s) {
+
+ }
+}
+
+void test9(short s) {
+ if(!s) {
+
+ }
+}
\ No newline at end of file
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected
index e03ee68b8a3..e8afa785492 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test-source-sink.expected
@@ -228,7 +228,6 @@ irFlow
| test.cpp:333:17:333:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:333:17:333:22 | call to source | test.cpp:343:10:343:18 | globalVar |
-| test.cpp:333:17:333:22 | call to source | test.cpp:349:10:349:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:337:10:337:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:339:10:339:18 | globalVar |
| test.cpp:347:17:347:22 | call to source | test.cpp:343:10:343:18 | globalVar |
@@ -260,7 +259,6 @@ irFlow
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:566:10:566:19 | * ... |
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:568:10:568:19 | * ... |
| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:572:10:572:19 | * ... |
-| test.cpp:562:17:562:31 | *call to indirect_source | test.cpp:578:10:578:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:566:10:566:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:568:10:568:19 | * ... |
| test.cpp:576:17:576:31 | *call to indirect_source | test.cpp:572:10:572:19 | * ... |
diff --git a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
index af9e18034ed..c1c84c71e3b 100644
--- a/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
+++ b/cpp/ql/test/library-tests/dataflow/dataflow-tests/test.cpp
@@ -346,7 +346,7 @@ namespace FlowThroughGlobals {
void taintAndCall() {
globalVar = source();
calledAfterTaint();
- sink(globalVar); // $ ast ir=333:17 ir=347:17
+ sink(globalVar); // $ ast ir
}
}
@@ -575,7 +575,7 @@ namespace IndirectFlowThroughGlobals {
void taintAndCall() {
globalInt = indirect_source();
calledAfterTaint();
- sink(*globalInt); // $ ir=562:17 ir=576:17 MISSING: ast=562:17 ast=576:17
+ sink(*globalInt); // $ ir MISSING: ast=562:17 ast=576:17
}
}
diff --git a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected
index 66439f38754..4f9b5b7b853 100644
--- a/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected
+++ b/cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.expected
@@ -1,7 +1,9 @@
edges
| A.cpp:23:10:23:10 | c | A.cpp:25:7:25:17 | ... = ... | provenance | |
+| A.cpp:25:7:25:10 | *this [post update] [c] | A.cpp:23:5:23:5 | *this [Return] [c] | provenance | |
| A.cpp:25:7:25:17 | ... = ... | A.cpp:25:7:25:10 | *this [post update] [c] | provenance | |
| A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | ... = ... | provenance | |
+| A.cpp:27:22:27:25 | *this [post update] [c] | A.cpp:27:10:27:12 | *this [Return] [c] | provenance | |
| A.cpp:27:22:27:32 | ... = ... | A.cpp:27:22:27:25 | *this [post update] [c] | provenance | |
| A.cpp:28:8:28:10 | *this [c] | A.cpp:28:23:28:26 | *this [c] | provenance | |
| A.cpp:28:23:28:26 | *this [c] | A.cpp:28:29:28:29 | c | provenance | |
@@ -13,7 +15,7 @@ edges
| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | provenance | |
| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | call to B [c] | provenance | |
| A.cpp:41:5:41:6 | insert output argument | A.cpp:43:10:43:12 | *& ... | provenance | |
-| A.cpp:41:15:41:21 | new | A.cpp:41:5:41:6 | insert output argument | provenance | |
+| A.cpp:41:15:41:21 | new | A.cpp:41:5:41:6 | insert output argument | provenance | Config |
| A.cpp:47:12:47:18 | new | A.cpp:47:12:47:18 | new | provenance | |
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c | provenance | |
| A.cpp:48:12:48:18 | *call to make [c] | A.cpp:48:12:48:18 | *call to make [c] | provenance | |
@@ -66,23 +68,28 @@ edges
| A.cpp:112:7:112:13 | *... = ... [a] | A.cpp:118:18:118:39 | *cc [a] | provenance | |
| A.cpp:118:18:118:39 | *cc [a] | A.cpp:120:12:120:13 | *c1 [a] | provenance | |
| A.cpp:120:12:120:13 | *c1 [a] | A.cpp:120:12:120:16 | a | provenance | |
+| A.cpp:124:14:124:14 | *b [Return] [c] | A.cpp:131:8:131:8 | f7 output argument [c] | provenance | |
| A.cpp:124:14:124:14 | *b [c] | A.cpp:131:8:131:8 | f7 output argument [c] | provenance | |
+| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:124:14:124:14 | *b [Return] [c] | provenance | |
| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:124:14:124:14 | *b [c] | provenance | |
-| A.cpp:126:5:126:5 | set output argument [c] | A.cpp:131:8:131:8 | f7 output argument [c] | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | set output argument [c] | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:126:12:126:18 | new | provenance | |
| A.cpp:131:8:131:8 | f7 output argument [c] | A.cpp:132:10:132:10 | *b [c] | provenance | |
| A.cpp:132:10:132:10 | *b [c] | A.cpp:132:10:132:13 | c | provenance | |
+| A.cpp:140:5:140:5 | *this [Return] [*b, c] | A.cpp:151:12:151:24 | call to D [*b, c] | provenance | |
+| A.cpp:140:5:140:5 | *this [Return] [b] | A.cpp:151:12:151:24 | call to D [b] | provenance | |
+| A.cpp:140:13:140:13 | *b [Return] [c] | A.cpp:151:18:151:18 | D output argument [c] | provenance | |
| A.cpp:140:13:140:13 | *b [c] | A.cpp:151:18:151:18 | D output argument [c] | provenance | |
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... | provenance | |
+| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:140:13:140:13 | *b [Return] [c] | provenance | |
| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:140:13:140:13 | *b [c] | provenance | |
| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:143:7:143:31 | *... = ... [c] | provenance | |
-| A.cpp:142:7:142:7 | *b [post update] [c] | A.cpp:151:18:151:18 | D output argument [c] | provenance | |
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | *b [post update] [c] | provenance | |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | ... = ... | provenance | |
-| A.cpp:143:7:143:10 | *this [post update] [*b, c] | A.cpp:151:12:151:24 | call to D [*b, c] | provenance | |
-| A.cpp:143:7:143:10 | *this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] | provenance | |
+| A.cpp:143:7:143:10 | *this [post update] [*b, c] | A.cpp:140:5:140:5 | *this [Return] [*b, c] | provenance | |
+| A.cpp:143:7:143:10 | *this [post update] [b] | A.cpp:140:5:140:5 | *this [Return] [b] | provenance | |
+| A.cpp:143:7:143:10 | *this [post update] [b] | A.cpp:140:5:140:5 | *this [Return] [b] | provenance | |
| A.cpp:143:7:143:31 | *... = ... [c] | A.cpp:143:7:143:10 | *this [post update] [*b, c] | provenance | |
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | *this [post update] [b] | provenance | |
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | *this [post update] [b] | provenance | |
@@ -138,7 +145,10 @@ edges
| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... | provenance | |
| A.cpp:181:32:181:35 | *next [*next, head] | A.cpp:184:7:184:23 | *... = ... [*next, head] | provenance | |
| A.cpp:181:32:181:35 | *next [head] | A.cpp:184:7:184:23 | *... = ... [head] | provenance | |
+| A.cpp:183:7:183:10 | *this [post update] [head] | A.cpp:181:5:181:10 | *this [Return] [head] | provenance | |
| A.cpp:183:7:183:20 | ... = ... | A.cpp:183:7:183:10 | *this [post update] [head] | provenance | |
+| A.cpp:184:7:184:10 | *this [post update] [*next, *next, head] | A.cpp:181:5:181:10 | *this [Return] [*next, *next, head] | provenance | |
+| A.cpp:184:7:184:10 | *this [post update] [*next, head] | A.cpp:181:5:181:10 | *this [Return] [*next, head] | provenance | |
| A.cpp:184:7:184:23 | *... = ... [*next, head] | A.cpp:184:7:184:10 | *this [post update] [*next, *next, head] | provenance | |
| A.cpp:184:7:184:23 | *... = ... [head] | A.cpp:184:7:184:10 | *this [post update] [*next, head] | provenance | |
| B.cpp:6:15:6:24 | new | B.cpp:6:15:6:24 | new | provenance | |
@@ -167,10 +177,14 @@ edges
| B.cpp:19:14:19:17 | *box1 [elem2] | B.cpp:19:10:19:24 | elem2 | provenance | |
| B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:22 | ... = ... | provenance | |
| B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:22 | ... = ... | provenance | |
+| B.cpp:35:7:35:10 | *this [post update] [elem1] | B.cpp:33:5:33:8 | *this [Return] [elem1] | provenance | |
| B.cpp:35:7:35:22 | ... = ... | B.cpp:35:7:35:10 | *this [post update] [elem1] | provenance | |
+| B.cpp:36:7:36:10 | *this [post update] [elem2] | B.cpp:33:5:33:8 | *this [Return] [elem2] | provenance | |
| B.cpp:36:7:36:22 | ... = ... | B.cpp:36:7:36:10 | *this [post update] [elem2] | provenance | |
| B.cpp:44:16:44:17 | *b1 [elem1] | B.cpp:46:7:46:21 | *... = ... [elem1] | provenance | |
| B.cpp:44:16:44:17 | *b1 [elem2] | B.cpp:46:7:46:21 | *... = ... [elem2] | provenance | |
+| B.cpp:46:7:46:10 | *this [post update] [*box1, elem1] | B.cpp:44:5:44:8 | *this [Return] [*box1, elem1] | provenance | |
+| B.cpp:46:7:46:10 | *this [post update] [*box1, elem2] | B.cpp:44:5:44:8 | *this [Return] [*box1, elem2] | provenance | |
| B.cpp:46:7:46:21 | *... = ... [elem1] | B.cpp:46:7:46:10 | *this [post update] [*box1, elem1] | provenance | |
| B.cpp:46:7:46:21 | *... = ... [elem2] | B.cpp:46:7:46:10 | *this [post update] [*box1, elem2] | provenance | |
| C.cpp:18:12:18:18 | *new [s1] | C.cpp:19:5:19:5 | *c [s1] | provenance | |
@@ -179,10 +193,12 @@ edges
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:18:12:18:18 | *new [s3] | provenance | |
| C.cpp:19:5:19:5 | *c [s1] | C.cpp:27:8:27:11 | *this [s1] | provenance | |
| C.cpp:19:5:19:5 | *c [s3] | C.cpp:27:8:27:11 | *this [s3] | provenance | |
-| C.cpp:22:3:22:3 | *this [post update] [s1] | C.cpp:18:12:18:18 | call to C [s1] | provenance | |
+| C.cpp:22:3:22:3 | *this [Return] [s1] | C.cpp:18:12:18:18 | call to C [s1] | provenance | |
+| C.cpp:22:3:22:3 | *this [Return] [s3] | C.cpp:18:12:18:18 | call to C [s3] | provenance | |
+| C.cpp:22:3:22:3 | *this [post update] [s1] | C.cpp:22:3:22:3 | *this [Return] [s1] | provenance | |
| C.cpp:22:12:22:21 | new | C.cpp:22:3:22:3 | *this [post update] [s1] | provenance | |
| C.cpp:22:12:22:21 | new | C.cpp:22:12:22:21 | new | provenance | |
-| C.cpp:24:5:24:8 | *this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] | provenance | |
+| C.cpp:24:5:24:8 | *this [post update] [s3] | C.cpp:22:3:22:3 | *this [Return] [s3] | provenance | |
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | *this [post update] [s3] | provenance | |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... | provenance | |
| C.cpp:27:8:27:11 | *this [s1] | C.cpp:29:10:29:11 | *this [s1] | provenance | |
@@ -194,6 +210,7 @@ edges
| D.cpp:10:30:10:33 | elem | D.cpp:10:11:10:17 | *getElem | provenance | |
| D.cpp:10:30:10:33 | elem | D.cpp:10:30:10:33 | elem | provenance | |
| D.cpp:11:24:11:24 | e | D.cpp:11:29:11:36 | ... = ... | provenance | |
+| D.cpp:11:29:11:32 | *this [post update] [elem] | D.cpp:11:10:11:16 | *this [Return] [elem] | provenance | |
| D.cpp:11:29:11:36 | ... = ... | D.cpp:11:29:11:32 | *this [post update] [elem] | provenance | |
| D.cpp:17:11:17:17 | *this [*box, elem] | D.cpp:17:30:17:32 | *this [*box, elem] | provenance | |
| D.cpp:17:30:17:32 | *box [elem] | D.cpp:17:11:17:17 | **getBox1 [elem] | provenance | |
@@ -252,14 +269,16 @@ edges
| E.cpp:30:23:30:26 | *data [post update] [*buffer] | E.cpp:30:21:30:21 | *p [post update] [data, *buffer] | provenance | |
| E.cpp:32:10:32:10 | *b [*buffer] | E.cpp:32:13:32:18 | *buffer | provenance | |
| E.cpp:33:18:33:19 | *& ... [data, *buffer] | E.cpp:19:27:19:27 | *p [data, *buffer] | provenance | |
+| aliasing.cpp:8:23:8:23 | *s [Return] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | provenance | |
| aliasing.cpp:8:23:8:23 | *s [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | provenance | |
+| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | aliasing.cpp:8:23:8:23 | *s [Return] [m1] | provenance | |
| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | aliasing.cpp:8:23:8:23 | *s [m1] | provenance | |
-| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | provenance | |
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:3:9:3 | *s [post update] [m1] | provenance | |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... | provenance | |
+| aliasing.cpp:12:25:12:25 | *s [Return] [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | provenance | |
| aliasing.cpp:12:25:12:25 | *s [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | provenance | |
+| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | aliasing.cpp:12:25:12:25 | *s [Return] [m1] | provenance | |
| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | aliasing.cpp:12:25:12:25 | *s [m1] | provenance | |
-| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | aliasing.cpp:26:19:26:20 | referenceSetter output argument [m1] | provenance | |
| aliasing.cpp:13:3:13:21 | ... = ... | aliasing.cpp:13:3:13:3 | *s [post update] [m1] | provenance | |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | ... = ... | provenance | |
| aliasing.cpp:25:17:25:19 | pointerSetter output argument [m1] | aliasing.cpp:29:8:29:9 | *s1 [m1] | provenance | |
@@ -376,14 +395,18 @@ edges
| arrays.cpp:50:10:50:17 | *indirect [*ptr, data] | arrays.cpp:50:20:50:22 | *ptr [data] | provenance | |
| arrays.cpp:50:20:50:22 | *ptr [data] | arrays.cpp:50:8:50:25 | *access to array [data] | provenance | |
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... | provenance | |
+| by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:11:39:11:39 | *s [Return] [a] | provenance | |
| by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:11:39:11:39 | *s [a] | provenance | |
| by_reference.cpp:12:5:12:16 | ... = ... | by_reference.cpp:12:5:12:5 | *s [post update] [a] | provenance | |
| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | ... = ... | provenance | |
+| by_reference.cpp:16:5:16:8 | *this [post update] [a] | by_reference.cpp:15:8:15:18 | *this [Return] [a] | provenance | |
| by_reference.cpp:16:5:16:19 | ... = ... | by_reference.cpp:16:5:16:8 | *this [post update] [a] | provenance | |
| by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:23:20:27 | value | provenance | |
+| by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | by_reference.cpp:19:8:19:20 | *this [Return] [a] | provenance | |
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | provenance | |
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | provenance | |
| by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:25:24:29 | value | provenance | |
+| by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | by_reference.cpp:23:8:23:26 | *this [Return] [a] | provenance | |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | provenance | |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | provenance | |
| by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:32:12:32:12 | *s [a] | provenance | |
@@ -424,26 +447,28 @@ edges
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] | provenance | |
| by_reference.cpp:69:22:69:23 | *& ... [a] | by_reference.cpp:31:46:31:46 | *s [a] | provenance | |
| by_reference.cpp:69:22:69:23 | *& ... [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | provenance | |
+| by_reference.cpp:83:31:83:35 | *inner [Return] [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | *inner [Return] [a] | by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | *inner [Return] [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | *inner [Return] [a] | by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:83:31:83:35 | *inner [a] | by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | provenance | |
+| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:83:31:83:35 | *inner [Return] [a] | provenance | |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:83:31:83:35 | *inner [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:102:21:102:39 | taint_inner_a_ptr output argument [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:103:27:103:35 | taint_inner_a_ptr output argument [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:106:21:106:41 | taint_inner_a_ptr output argument [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | by_reference.cpp:107:29:107:37 | taint_inner_a_ptr output argument [a] | provenance | |
| by_reference.cpp:84:3:84:25 | ... = ... | by_reference.cpp:84:3:84:7 | *inner [post update] [a] | provenance | |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | ... = ... | provenance | |
+| by_reference.cpp:87:31:87:35 | *inner [Return] [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | provenance | |
+| by_reference.cpp:87:31:87:35 | *inner [Return] [a] | by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | provenance | |
+| by_reference.cpp:87:31:87:35 | *inner [Return] [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | provenance | |
+| by_reference.cpp:87:31:87:35 | *inner [Return] [a] | by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:87:31:87:35 | *inner [a] | by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | provenance | |
+| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:87:31:87:35 | *inner [Return] [a] | provenance | |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:87:31:87:35 | *inner [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:122:21:122:38 | taint_inner_a_ref output argument [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:123:21:123:36 | taint_inner_a_ref output argument [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:126:21:126:40 | taint_inner_a_ref output argument [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | by_reference.cpp:127:21:127:38 | taint_inner_a_ref output argument [a] | provenance | |
| by_reference.cpp:88:3:88:24 | ... = ... | by_reference.cpp:88:3:88:7 | *inner [post update] [a] | provenance | |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | ... = ... | provenance | |
| by_reference.cpp:91:25:91:26 | *pa | by_reference.cpp:104:15:104:22 | taint_a_ptr output argument | provenance | |
@@ -599,8 +624,10 @@ edges
| complex.cpp:10:20:10:21 | b_ | complex.cpp:10:7:10:7 | *b | provenance | |
| complex.cpp:10:20:10:21 | b_ | complex.cpp:10:20:10:21 | b_ | provenance | |
| complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | ... = ... | provenance | |
+| complex.cpp:11:22:11:23 | *this [post update] [a_] | complex.cpp:11:8:11:11 | *this [Return] [a_] | provenance | |
| complex.cpp:11:22:11:27 | ... = ... | complex.cpp:11:22:11:23 | *this [post update] [a_] | provenance | |
| complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | ... = ... | provenance | |
+| complex.cpp:12:22:12:23 | *this [post update] [b_] | complex.cpp:12:8:12:11 | *this [Return] [b_] | provenance | |
| complex.cpp:12:22:12:27 | ... = ... | complex.cpp:12:22:12:23 | *this [post update] [b_] | provenance | |
| complex.cpp:40:17:40:17 | *b [inner, f, a_] | complex.cpp:42:8:42:8 | *b [inner, f, a_] | provenance | |
| complex.cpp:40:17:40:17 | *b [inner, f, b_] | complex.cpp:43:8:43:8 | *b [inner, f, b_] | provenance | |
@@ -669,6 +696,8 @@ edges
| constructors.cpp:19:22:19:23 | *this [b_] | constructors.cpp:19:22:19:23 | b_ | provenance | |
| constructors.cpp:19:22:19:23 | b_ | constructors.cpp:19:9:19:9 | *b | provenance | |
| constructors.cpp:19:22:19:23 | b_ | constructors.cpp:19:22:19:23 | b_ | provenance | |
+| constructors.cpp:23:5:23:7 | *this [post update] [a_] | constructors.cpp:23:5:23:7 | *this [Return] [a_] | provenance | |
+| constructors.cpp:23:5:23:7 | *this [post update] [b_] | constructors.cpp:23:5:23:7 | *this [Return] [b_] | provenance | |
| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:28:23:28 | a | provenance | |
| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | b | provenance | |
| constructors.cpp:23:28:23:28 | a | constructors.cpp:23:5:23:7 | *this [post update] [a_] | provenance | |
@@ -696,11 +725,14 @@ edges
| constructors.cpp:46:9:46:9 | *h [a_] | constructors.cpp:26:15:26:15 | *f [a_] | provenance | |
| constructors.cpp:46:9:46:9 | *h [b_] | constructors.cpp:26:15:26:15 | *f [b_] | provenance | |
| qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:44 | ... = ... | provenance | |
+| qualifiers.cpp:9:30:9:33 | *this [post update] [a] | qualifiers.cpp:9:10:9:13 | *this [Return] [a] | provenance | |
| qualifiers.cpp:9:30:9:44 | ... = ... | qualifiers.cpp:9:30:9:33 | *this [post update] [a] | provenance | |
| qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:64 | ... = ... | provenance | |
+| qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | qualifiers.cpp:12:27:12:31 | *inner [Return] [a] | provenance | |
| qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | qualifiers.cpp:12:27:12:31 | *inner [a] | provenance | |
| qualifiers.cpp:12:49:12:64 | ... = ... | qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | provenance | |
| qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:65 | ... = ... | provenance | |
+| qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | qualifiers.cpp:13:29:13:33 | *inner [Return] [a] | provenance | |
| qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | qualifiers.cpp:13:29:13:33 | *inner [a] | provenance | |
| qualifiers.cpp:13:51:13:65 | ... = ... | qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | provenance | |
| qualifiers.cpp:22:5:22:9 | getInner output argument [*inner, a] | qualifiers.cpp:23:10:23:14 | *outer [*inner, a] | provenance | |
@@ -758,8 +790,10 @@ edges
| simple.cpp:19:22:19:23 | b_ | simple.cpp:19:9:19:9 | *b | provenance | |
| simple.cpp:19:22:19:23 | b_ | simple.cpp:19:22:19:23 | b_ | provenance | |
| simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | ... = ... | provenance | |
+| simple.cpp:20:24:20:25 | *this [post update] [a_] | simple.cpp:20:10:20:13 | *this [Return] [a_] | provenance | |
| simple.cpp:20:24:20:29 | ... = ... | simple.cpp:20:24:20:25 | *this [post update] [a_] | provenance | |
| simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | ... = ... | provenance | |
+| simple.cpp:21:24:21:25 | *this [post update] [b_] | simple.cpp:21:10:21:13 | *this [Return] [b_] | provenance | |
| simple.cpp:21:24:21:29 | ... = ... | simple.cpp:21:24:21:25 | *this [post update] [b_] | provenance | |
| simple.cpp:26:15:26:15 | *f [a_] | simple.cpp:28:10:28:10 | *f [a_] | provenance | |
| simple.cpp:26:15:26:15 | *f [b_] | simple.cpp:29:10:29:10 | *f [b_] | provenance | |
@@ -844,9 +878,11 @@ edges
| struct_init.c:46:10:46:14 | *outer [*pointerAB, a] | struct_init.c:46:16:46:24 | *pointerAB [a] | provenance | |
| struct_init.c:46:16:46:24 | *pointerAB [a] | struct_init.c:14:24:14:25 | *ab [a] | provenance | |
nodes
+| A.cpp:23:5:23:5 | *this [Return] [c] | semmle.label | *this [Return] [c] |
| A.cpp:23:10:23:10 | c | semmle.label | c |
| A.cpp:25:7:25:10 | *this [post update] [c] | semmle.label | *this [post update] [c] |
| A.cpp:25:7:25:17 | ... = ... | semmle.label | ... = ... |
+| A.cpp:27:10:27:12 | *this [Return] [c] | semmle.label | *this [Return] [c] |
| A.cpp:27:17:27:17 | c | semmle.label | c |
| A.cpp:27:22:27:25 | *this [post update] [c] | semmle.label | *this [post update] [c] |
| A.cpp:27:22:27:32 | ... = ... | semmle.label | ... = ... |
@@ -914,6 +950,7 @@ nodes
| A.cpp:118:18:118:39 | *cc [a] | semmle.label | *cc [a] |
| A.cpp:120:12:120:13 | *c1 [a] | semmle.label | *c1 [a] |
| A.cpp:120:12:120:16 | a | semmle.label | a |
+| A.cpp:124:14:124:14 | *b [Return] [c] | semmle.label | *b [Return] [c] |
| A.cpp:124:14:124:14 | *b [c] | semmle.label | *b [c] |
| A.cpp:126:5:126:5 | set output argument [c] | semmle.label | set output argument [c] |
| A.cpp:126:12:126:18 | new | semmle.label | new |
@@ -921,6 +958,10 @@ nodes
| A.cpp:131:8:131:8 | f7 output argument [c] | semmle.label | f7 output argument [c] |
| A.cpp:132:10:132:10 | *b [c] | semmle.label | *b [c] |
| A.cpp:132:10:132:13 | c | semmle.label | c |
+| A.cpp:140:5:140:5 | *this [Return] [*b, c] | semmle.label | *this [Return] [*b, c] |
+| A.cpp:140:5:140:5 | *this [Return] [b] | semmle.label | *this [Return] [b] |
+| A.cpp:140:5:140:5 | *this [Return] [b] | semmle.label | *this [Return] [b] |
+| A.cpp:140:13:140:13 | *b [Return] [c] | semmle.label | *b [Return] [c] |
| A.cpp:140:13:140:13 | *b [c] | semmle.label | *b [c] |
| A.cpp:140:13:140:13 | b | semmle.label | b |
| A.cpp:142:7:142:7 | *b [post update] [c] | semmle.label | *b [post update] [c] |
@@ -979,6 +1020,9 @@ nodes
| A.cpp:169:12:169:18 | head | semmle.label | head |
| A.cpp:173:26:173:26 | *o [c] | semmle.label | *o [c] |
| A.cpp:173:26:173:26 | *o [c] | semmle.label | *o [c] |
+| A.cpp:181:5:181:10 | *this [Return] [*next, *next, head] | semmle.label | *this [Return] [*next, *next, head] |
+| A.cpp:181:5:181:10 | *this [Return] [*next, head] | semmle.label | *this [Return] [*next, head] |
+| A.cpp:181:5:181:10 | *this [Return] [head] | semmle.label | *this [Return] [head] |
| A.cpp:181:15:181:21 | newHead | semmle.label | newHead |
| A.cpp:181:32:181:35 | *next [*next, head] | semmle.label | *next [*next, head] |
| A.cpp:181:32:181:35 | *next [head] | semmle.label | *next [head] |
@@ -1010,12 +1054,16 @@ nodes
| B.cpp:19:10:19:11 | *b2 [*box1, elem2] | semmle.label | *b2 [*box1, elem2] |
| B.cpp:19:10:19:24 | elem2 | semmle.label | elem2 |
| B.cpp:19:14:19:17 | *box1 [elem2] | semmle.label | *box1 [elem2] |
+| B.cpp:33:5:33:8 | *this [Return] [elem1] | semmle.label | *this [Return] [elem1] |
+| B.cpp:33:5:33:8 | *this [Return] [elem2] | semmle.label | *this [Return] [elem2] |
| B.cpp:33:16:33:17 | e1 | semmle.label | e1 |
| B.cpp:33:26:33:27 | e2 | semmle.label | e2 |
| B.cpp:35:7:35:10 | *this [post update] [elem1] | semmle.label | *this [post update] [elem1] |
| B.cpp:35:7:35:22 | ... = ... | semmle.label | ... = ... |
| B.cpp:36:7:36:10 | *this [post update] [elem2] | semmle.label | *this [post update] [elem2] |
| B.cpp:36:7:36:22 | ... = ... | semmle.label | ... = ... |
+| B.cpp:44:5:44:8 | *this [Return] [*box1, elem1] | semmle.label | *this [Return] [*box1, elem1] |
+| B.cpp:44:5:44:8 | *this [Return] [*box1, elem2] | semmle.label | *this [Return] [*box1, elem2] |
| B.cpp:44:16:44:17 | *b1 [elem1] | semmle.label | *b1 [elem1] |
| B.cpp:44:16:44:17 | *b1 [elem2] | semmle.label | *b1 [elem2] |
| B.cpp:46:7:46:10 | *this [post update] [*box1, elem1] | semmle.label | *this [post update] [*box1, elem1] |
@@ -1028,6 +1076,8 @@ nodes
| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] |
| C.cpp:19:5:19:5 | *c [s1] | semmle.label | *c [s1] |
| C.cpp:19:5:19:5 | *c [s3] | semmle.label | *c [s3] |
+| C.cpp:22:3:22:3 | *this [Return] [s1] | semmle.label | *this [Return] [s1] |
+| C.cpp:22:3:22:3 | *this [Return] [s3] | semmle.label | *this [Return] [s3] |
| C.cpp:22:3:22:3 | *this [post update] [s1] | semmle.label | *this [post update] [s1] |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:22:12:22:21 | new | semmle.label | new |
@@ -1045,6 +1095,7 @@ nodes
| D.cpp:10:30:10:33 | *this [elem] | semmle.label | *this [elem] |
| D.cpp:10:30:10:33 | elem | semmle.label | elem |
| D.cpp:10:30:10:33 | elem | semmle.label | elem |
+| D.cpp:11:10:11:16 | *this [Return] [elem] | semmle.label | *this [Return] [elem] |
| D.cpp:11:24:11:24 | e | semmle.label | e |
| D.cpp:11:29:11:32 | *this [post update] [elem] | semmle.label | *this [post update] [elem] |
| D.cpp:11:29:11:36 | ... = ... | semmle.label | ... = ... |
@@ -1107,10 +1158,12 @@ nodes
| E.cpp:32:10:32:10 | *b [*buffer] | semmle.label | *b [*buffer] |
| E.cpp:32:13:32:18 | *buffer | semmle.label | *buffer |
| E.cpp:33:18:33:19 | *& ... [data, *buffer] | semmle.label | *& ... [data, *buffer] |
+| aliasing.cpp:8:23:8:23 | *s [Return] [m1] | semmle.label | *s [Return] [m1] |
| aliasing.cpp:8:23:8:23 | *s [m1] | semmle.label | *s [m1] |
| aliasing.cpp:9:3:9:3 | *s [post update] [m1] | semmle.label | *s [post update] [m1] |
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
+| aliasing.cpp:12:25:12:25 | *s [Return] [m1] | semmle.label | *s [Return] [m1] |
| aliasing.cpp:12:25:12:25 | *s [m1] | semmle.label | *s [m1] |
| aliasing.cpp:13:3:13:3 | *s [post update] [m1] | semmle.label | *s [post update] [m1] |
| aliasing.cpp:13:3:13:21 | ... = ... | semmle.label | ... = ... |
@@ -1236,16 +1289,20 @@ nodes
| arrays.cpp:50:10:50:17 | *indirect [*ptr, data] | semmle.label | *indirect [*ptr, data] |
| arrays.cpp:50:20:50:22 | *ptr [data] | semmle.label | *ptr [data] |
| arrays.cpp:50:27:50:30 | data | semmle.label | data |
+| by_reference.cpp:11:39:11:39 | *s [Return] [a] | semmle.label | *s [Return] [a] |
| by_reference.cpp:11:39:11:39 | *s [a] | semmle.label | *s [a] |
| by_reference.cpp:11:48:11:52 | value | semmle.label | value |
| by_reference.cpp:12:5:12:5 | *s [post update] [a] | semmle.label | *s [post update] [a] |
| by_reference.cpp:12:5:12:16 | ... = ... | semmle.label | ... = ... |
+| by_reference.cpp:15:8:15:18 | *this [Return] [a] | semmle.label | *this [Return] [a] |
| by_reference.cpp:15:26:15:30 | value | semmle.label | value |
| by_reference.cpp:16:5:16:8 | *this [post update] [a] | semmle.label | *this [post update] [a] |
| by_reference.cpp:16:5:16:19 | ... = ... | semmle.label | ... = ... |
+| by_reference.cpp:19:8:19:20 | *this [Return] [a] | semmle.label | *this [Return] [a] |
| by_reference.cpp:19:28:19:32 | value | semmle.label | value |
| by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | semmle.label | setDirectly output argument [a] |
| by_reference.cpp:20:23:20:27 | value | semmle.label | value |
+| by_reference.cpp:23:8:23:26 | *this [Return] [a] | semmle.label | *this [Return] [a] |
| by_reference.cpp:23:34:23:38 | value | semmle.label | value |
| by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | semmle.label | nonMemberSetA output argument [a] |
| by_reference.cpp:24:25:24:29 | value | semmle.label | value |
@@ -1285,10 +1342,12 @@ nodes
| by_reference.cpp:68:21:68:30 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
| by_reference.cpp:69:22:69:23 | *& ... [a] | semmle.label | *& ... [a] |
+| by_reference.cpp:83:31:83:35 | *inner [Return] [a] | semmle.label | *inner [Return] [a] |
| by_reference.cpp:83:31:83:35 | *inner [a] | semmle.label | *inner [a] |
| by_reference.cpp:84:3:84:7 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| by_reference.cpp:84:3:84:25 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
+| by_reference.cpp:87:31:87:35 | *inner [Return] [a] | semmle.label | *inner [Return] [a] |
| by_reference.cpp:87:31:87:35 | *inner [a] | semmle.label | *inner [a] |
| by_reference.cpp:88:3:88:7 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| by_reference.cpp:88:3:88:24 | ... = ... | semmle.label | ... = ... |
@@ -1454,9 +1513,11 @@ nodes
| complex.cpp:10:20:10:21 | *this [b_] | semmle.label | *this [b_] |
| complex.cpp:10:20:10:21 | b_ | semmle.label | b_ |
| complex.cpp:10:20:10:21 | b_ | semmle.label | b_ |
+| complex.cpp:11:8:11:11 | *this [Return] [a_] | semmle.label | *this [Return] [a_] |
| complex.cpp:11:17:11:17 | a | semmle.label | a |
| complex.cpp:11:22:11:23 | *this [post update] [a_] | semmle.label | *this [post update] [a_] |
| complex.cpp:11:22:11:27 | ... = ... | semmle.label | ... = ... |
+| complex.cpp:12:8:12:11 | *this [Return] [b_] | semmle.label | *this [Return] [b_] |
| complex.cpp:12:17:12:17 | b | semmle.label | b |
| complex.cpp:12:22:12:23 | *this [post update] [b_] | semmle.label | *this [post update] [b_] |
| complex.cpp:12:22:12:27 | ... = ... | semmle.label | ... = ... |
@@ -1531,6 +1592,8 @@ nodes
| constructors.cpp:19:22:19:23 | *this [b_] | semmle.label | *this [b_] |
| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ |
| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ |
+| constructors.cpp:23:5:23:7 | *this [Return] [a_] | semmle.label | *this [Return] [a_] |
+| constructors.cpp:23:5:23:7 | *this [Return] [b_] | semmle.label | *this [Return] [b_] |
| constructors.cpp:23:5:23:7 | *this [post update] [a_] | semmle.label | *this [post update] [a_] |
| constructors.cpp:23:5:23:7 | *this [post update] [b_] | semmle.label | *this [post update] [b_] |
| constructors.cpp:23:13:23:13 | a | semmle.label | a |
@@ -1555,13 +1618,16 @@ nodes
| constructors.cpp:43:9:43:9 | *g [b_] | semmle.label | *g [b_] |
| constructors.cpp:46:9:46:9 | *h [a_] | semmle.label | *h [a_] |
| constructors.cpp:46:9:46:9 | *h [b_] | semmle.label | *h [b_] |
+| qualifiers.cpp:9:10:9:13 | *this [Return] [a] | semmle.label | *this [Return] [a] |
| qualifiers.cpp:9:21:9:25 | value | semmle.label | value |
| qualifiers.cpp:9:30:9:33 | *this [post update] [a] | semmle.label | *this [post update] [a] |
| qualifiers.cpp:9:30:9:44 | ... = ... | semmle.label | ... = ... |
+| qualifiers.cpp:12:27:12:31 | *inner [Return] [a] | semmle.label | *inner [Return] [a] |
| qualifiers.cpp:12:27:12:31 | *inner [a] | semmle.label | *inner [a] |
| qualifiers.cpp:12:40:12:44 | value | semmle.label | value |
| qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
| qualifiers.cpp:12:49:12:64 | ... = ... | semmle.label | ... = ... |
+| qualifiers.cpp:13:29:13:33 | *inner [Return] [a] | semmle.label | *inner [Return] [a] |
| qualifiers.cpp:13:29:13:33 | *inner [a] | semmle.label | *inner [a] |
| qualifiers.cpp:13:42:13:46 | value | semmle.label | value |
| qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | semmle.label | *inner [post update] [a] |
@@ -1626,9 +1692,11 @@ nodes
| simple.cpp:19:22:19:23 | *this [b_] | semmle.label | *this [b_] |
| simple.cpp:19:22:19:23 | b_ | semmle.label | b_ |
| simple.cpp:19:22:19:23 | b_ | semmle.label | b_ |
+| simple.cpp:20:10:20:13 | *this [Return] [a_] | semmle.label | *this [Return] [a_] |
| simple.cpp:20:19:20:19 | a | semmle.label | a |
| simple.cpp:20:24:20:25 | *this [post update] [a_] | semmle.label | *this [post update] [a_] |
| simple.cpp:20:24:20:29 | ... = ... | semmle.label | ... = ... |
+| simple.cpp:21:10:21:13 | *this [Return] [b_] | semmle.label | *this [Return] [b_] |
| simple.cpp:21:19:21:19 | b | semmle.label | b |
| simple.cpp:21:24:21:25 | *this [post update] [b_] | semmle.label | *this [post update] [b_] |
| simple.cpp:21:24:21:29 | ... = ... | semmle.label | ... = ... |
@@ -1715,67 +1783,67 @@ nodes
| struct_init.c:46:10:46:14 | *outer [*pointerAB, a] | semmle.label | *outer [*pointerAB, a] |
| struct_init.c:46:16:46:24 | *pointerAB [a] | semmle.label | *pointerAB [a] |
subpaths
-| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | *this [post update] [c] | A.cpp:31:14:31:21 | call to B [c] |
+| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:23:5:23:5 | *this [Return] [c] | A.cpp:31:14:31:21 | call to B [c] |
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | A.cpp:29:15:29:18 | **make [c] | A.cpp:48:12:48:18 | *call to make [c] |
-| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | *this [post update] [c] | A.cpp:55:5:55:5 | set output argument [c] |
+| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:10:27:12 | *this [Return] [c] | A.cpp:55:5:55:5 | set output argument [c] |
| A.cpp:56:10:56:10 | *b [c] | A.cpp:28:8:28:10 | *this [c] | A.cpp:28:8:28:10 | *get | A.cpp:56:10:56:17 | call to get |
| A.cpp:57:11:57:24 | *new [c] | A.cpp:28:8:28:10 | *this [c] | A.cpp:28:8:28:10 | *get | A.cpp:57:10:57:32 | call to get |
-| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | *this [post update] [c] | A.cpp:57:11:57:24 | call to B [c] |
+| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:23:5:23:5 | *this [Return] [c] | A.cpp:57:11:57:24 | call to B [c] |
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | **setOnB [c] | A.cpp:64:10:64:15 | *call to setOnB [c] |
| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c | A.cpp:78:6:78:15 | **setOnBWrap [c] | A.cpp:73:10:73:19 | *call to setOnBWrap [c] |
| A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c | A.cpp:85:9:85:14 | **setOnB [c] | A.cpp:81:10:81:15 | *call to setOnB [c] |
-| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | *this [post update] [c] | A.cpp:90:7:90:8 | set output argument [c] |
-| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | *this [post update] [c] | A.cpp:126:5:126:5 | set output argument [c] |
-| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:143:7:143:10 | *this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
+| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:10:27:12 | *this [Return] [c] | A.cpp:90:7:90:8 | set output argument [c] |
+| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:10:27:12 | *this [Return] [c] | A.cpp:126:5:126:5 | set output argument [c] |
+| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:140:5:140:5 | *this [Return] [b] | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:152:10:152:13 | *b [c] | A.cpp:173:26:173:26 | *o [c] | A.cpp:173:26:173:26 | *o [c] | A.cpp:152:10:152:13 | sink output argument [c] |
-| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | *this [post update] [head] | A.cpp:160:18:160:60 | call to MyList [head] |
-| A.cpp:161:38:161:39 | *l1 [head] | A.cpp:181:32:181:35 | *next [head] | A.cpp:184:7:184:10 | *this [post update] [*next, head] | A.cpp:161:18:161:40 | call to MyList [*next, head] |
-| A.cpp:162:38:162:39 | *l2 [*next, head] | A.cpp:181:32:181:35 | *next [*next, head] | A.cpp:184:7:184:10 | *this [post update] [*next, *next, head] | A.cpp:162:18:162:40 | call to MyList [*next, *next, head] |
-| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:10 | *this [post update] [elem1] | B.cpp:7:16:7:35 | call to Box1 [elem1] |
-| B.cpp:8:25:8:26 | *b1 [elem1] | B.cpp:44:16:44:17 | *b1 [elem1] | B.cpp:46:7:46:10 | *this [post update] [*box1, elem1] | B.cpp:8:16:8:27 | call to Box2 [*box1, elem1] |
-| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:10 | *this [post update] [elem2] | B.cpp:16:16:16:38 | call to Box1 [elem2] |
-| B.cpp:17:25:17:26 | *b1 [elem2] | B.cpp:44:16:44:17 | *b1 [elem2] | B.cpp:46:7:46:10 | *this [post update] [*box1, elem2] | B.cpp:17:16:17:27 | call to Box2 [*box1, elem2] |
+| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:181:5:181:10 | *this [Return] [head] | A.cpp:160:18:160:60 | call to MyList [head] |
+| A.cpp:161:38:161:39 | *l1 [head] | A.cpp:181:32:181:35 | *next [head] | A.cpp:181:5:181:10 | *this [Return] [*next, head] | A.cpp:161:18:161:40 | call to MyList [*next, head] |
+| A.cpp:162:38:162:39 | *l2 [*next, head] | A.cpp:181:32:181:35 | *next [*next, head] | A.cpp:181:5:181:10 | *this [Return] [*next, *next, head] | A.cpp:162:18:162:40 | call to MyList [*next, *next, head] |
+| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:33:5:33:8 | *this [Return] [elem1] | B.cpp:7:16:7:35 | call to Box1 [elem1] |
+| B.cpp:8:25:8:26 | *b1 [elem1] | B.cpp:44:16:44:17 | *b1 [elem1] | B.cpp:44:5:44:8 | *this [Return] [*box1, elem1] | B.cpp:8:16:8:27 | call to Box2 [*box1, elem1] |
+| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:33:5:33:8 | *this [Return] [elem2] | B.cpp:16:16:16:38 | call to Box1 [elem2] |
+| B.cpp:17:25:17:26 | *b1 [elem2] | B.cpp:44:16:44:17 | *b1 [elem2] | B.cpp:44:5:44:8 | *this [Return] [*box1, elem2] | B.cpp:17:16:17:27 | call to Box2 [*box1, elem2] |
| D.cpp:22:10:22:11 | *b2 [*box, elem] | D.cpp:17:11:17:17 | *this [*box, elem] | D.cpp:17:11:17:17 | **getBox1 [elem] | D.cpp:22:14:22:20 | *call to getBox1 [elem] |
| D.cpp:22:14:22:20 | *call to getBox1 [elem] | D.cpp:10:11:10:17 | *this [elem] | D.cpp:10:11:10:17 | *getElem | D.cpp:22:10:22:33 | call to getElem |
-| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | *this [post update] [elem] | D.cpp:37:8:37:10 | setElem output argument [elem] |
-| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | *this [post update] [elem] | D.cpp:51:8:51:14 | setElem output argument [elem] |
-| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | *this [post update] [a] | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] |
+| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:10:11:16 | *this [Return] [elem] | D.cpp:37:8:37:10 | setElem output argument [elem] |
+| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:10:11:16 | *this [Return] [elem] | D.cpp:51:8:51:14 | setElem output argument [elem] |
+| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:15:8:15:18 | *this [Return] [a] | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] |
+| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | *s [Return] [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | *s [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
-| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] |
| by_reference.cpp:40:12:40:15 | *this [a] | by_reference.cpp:35:9:35:19 | *this [a] | by_reference.cpp:35:9:35:19 | *getDirectly | by_reference.cpp:40:18:40:28 | call to getDirectly |
| by_reference.cpp:44:26:44:29 | *this [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:31:16:31:28 | *nonMemberGetA | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
-| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | *this [post update] [a] | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] |
+| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:15:8:15:18 | *this [Return] [a] | by_reference.cpp:50:3:50:3 | setDirectly output argument [a] |
| by_reference.cpp:51:8:51:8 | *s [a] | by_reference.cpp:35:9:35:19 | *this [a] | by_reference.cpp:35:9:35:19 | *getDirectly | by_reference.cpp:51:10:51:20 | call to getDirectly |
-| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | setDirectly output argument [a] | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] |
+| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:19:8:19:20 | *this [Return] [a] | by_reference.cpp:56:3:56:3 | setIndirectly output argument [a] |
| by_reference.cpp:57:8:57:8 | *s [a] | by_reference.cpp:39:9:39:21 | *this [a] | by_reference.cpp:39:9:39:21 | *getIndirectly | by_reference.cpp:57:10:57:22 | call to getIndirectly |
-| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | nonMemberSetA output argument [a] | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] |
+| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:23:8:23:26 | *this [Return] [a] | by_reference.cpp:62:3:62:3 | setThroughNonMember output argument [a] |
| by_reference.cpp:63:8:63:8 | *s [a] | by_reference.cpp:43:9:43:27 | *this [a] | by_reference.cpp:43:9:43:27 | *getThroughNonMember | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
+| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | *s [Return] [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | *s [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
-| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | *s [post update] [a] | by_reference.cpp:68:17:68:18 | nonMemberSetA output argument [a] |
| by_reference.cpp:69:22:69:23 | *& ... [a] | by_reference.cpp:31:46:31:46 | *s [a] | by_reference.cpp:31:16:31:28 | *nonMemberGetA | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| complex.cpp:42:16:42:16 | *f [a_] | complex.cpp:9:7:9:7 | *this [a_] | complex.cpp:9:7:9:7 | *a | complex.cpp:42:18:42:18 | call to a |
| complex.cpp:43:16:43:16 | *f [b_] | complex.cpp:10:7:10:7 | *this [b_] | complex.cpp:10:7:10:7 | *b | complex.cpp:43:18:43:18 | call to b |
-| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | *this [post update] [a_] | complex.cpp:53:12:53:12 | setA output argument [a_] |
-| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | *this [post update] [b_] | complex.cpp:54:12:54:12 | setB output argument [b_] |
-| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | *this [post update] [a_] | complex.cpp:55:12:55:12 | setA output argument [a_] |
-| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | *this [post update] [b_] | complex.cpp:56:12:56:12 | setB output argument [b_] |
+| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:8:11:11 | *this [Return] [a_] | complex.cpp:53:12:53:12 | setA output argument [a_] |
+| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:8:12:11 | *this [Return] [b_] | complex.cpp:54:12:54:12 | setB output argument [b_] |
+| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:8:11:11 | *this [Return] [a_] | complex.cpp:55:12:55:12 | setA output argument [a_] |
+| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:8:12:11 | *this [Return] [b_] | complex.cpp:56:12:56:12 | setB output argument [b_] |
| constructors.cpp:28:10:28:10 | *f [a_] | constructors.cpp:18:9:18:9 | *this [a_] | constructors.cpp:18:9:18:9 | *a | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:29:10:29:10 | *f [b_] | constructors.cpp:19:9:19:9 | *this [b_] | constructors.cpp:19:9:19:9 | *b | constructors.cpp:29:12:29:12 | call to b |
-| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | *this [post update] [a_] | constructors.cpp:34:9:34:9 | call to Foo [a_] |
-| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | *this [post update] [b_] | constructors.cpp:35:9:35:9 | call to Foo [b_] |
-| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | *this [post update] [a_] | constructors.cpp:36:9:36:9 | call to Foo [a_] |
-| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | *this [post update] [b_] | constructors.cpp:36:9:36:9 | call to Foo [b_] |
-| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:33 | *this [post update] [a] | qualifiers.cpp:27:11:27:18 | setA output argument [a] |
+| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | *this [Return] [a_] | constructors.cpp:34:9:34:9 | call to Foo [a_] |
+| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | *this [Return] [b_] | constructors.cpp:35:9:35:9 | call to Foo [b_] |
+| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | *this [Return] [a_] | constructors.cpp:36:9:36:9 | call to Foo [a_] |
+| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | *this [Return] [b_] | constructors.cpp:36:9:36:9 | call to Foo [b_] |
+| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:10:9:13 | *this [Return] [a] | qualifiers.cpp:27:11:27:18 | setA output argument [a] |
+| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:27:12:31 | *inner [Return] [a] | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] |
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:27:12:31 | *inner [a] | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] |
-| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:53 | *inner [post update] [a] | qualifiers.cpp:32:23:32:30 | pointerSetA output argument [a] |
+| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:29:13:33 | *inner [Return] [a] | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] |
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:29:13:33 | *inner [a] | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] |
-| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:55 | *inner [post update] [a] | qualifiers.cpp:37:19:37:35 | referenceSetA output argument [a] |
| simple.cpp:28:10:28:10 | *f [a_] | simple.cpp:18:9:18:9 | *this [a_] | simple.cpp:18:9:18:9 | *a | simple.cpp:28:12:28:12 | call to a |
| simple.cpp:29:10:29:10 | *f [b_] | simple.cpp:19:9:19:9 | *this [b_] | simple.cpp:19:9:19:9 | *b | simple.cpp:29:12:29:12 | call to b |
-| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | *this [post update] [a_] | simple.cpp:39:5:39:5 | setA output argument [a_] |
-| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | *this [post update] [b_] | simple.cpp:40:5:40:5 | setB output argument [b_] |
-| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | *this [post update] [a_] | simple.cpp:41:5:41:5 | setA output argument [a_] |
-| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | *this [post update] [b_] | simple.cpp:42:5:42:5 | setB output argument [b_] |
+| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:10:20:13 | *this [Return] [a_] | simple.cpp:39:5:39:5 | setA output argument [a_] |
+| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:10:21:13 | *this [Return] [b_] | simple.cpp:40:5:40:5 | setB output argument [b_] |
+| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:10:20:13 | *this [Return] [a_] | simple.cpp:41:5:41:5 | setA output argument [a_] |
+| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:10:21:13 | *this [Return] [b_] | simple.cpp:42:5:42:5 | setB output argument [b_] |
| simple.cpp:84:14:84:20 | *this [f2, f1] | simple.cpp:78:9:78:15 | *this [f2, f1] | simple.cpp:78:9:78:15 | *getf2f1 | simple.cpp:84:14:84:20 | call to getf2f1 |
| struct_init.c:24:10:24:12 | *& ... [a] | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:14:24:14:25 | *ab [a] | struct_init.c:24:10:24:12 | absink output argument [a] |
#select
diff --git a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected
index 3eebd355b14..9def426deb1 100644
--- a/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected
+++ b/cpp/ql/test/library-tests/dataflow/fields/path-flow.expected
@@ -1,7 +1,9 @@
edges
| A.cpp:23:10:23:10 | c | A.cpp:25:7:25:17 | ... = ... | provenance | |
+| A.cpp:25:7:25:10 | this [post update] [c] | A.cpp:23:5:23:5 | this [Return] [c] | provenance | |
| A.cpp:25:7:25:17 | ... = ... | A.cpp:25:7:25:10 | this [post update] [c] | provenance | |
| A.cpp:27:17:27:17 | c | A.cpp:27:22:27:32 | ... = ... | provenance | |
+| A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:27:10:27:12 | this [Return] [c] | provenance | |
| A.cpp:27:22:27:32 | ... = ... | A.cpp:27:22:27:25 | this [post update] [c] | provenance | |
| A.cpp:28:8:28:10 | this [c] | A.cpp:28:23:28:26 | this [c] | provenance | |
| A.cpp:28:23:28:26 | this [c] | A.cpp:28:29:28:29 | c | provenance | |
@@ -10,8 +12,9 @@ edges
| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | provenance | |
| A.cpp:31:20:31:20 | c | A.cpp:31:14:31:21 | call to B [c] | provenance | |
| A.cpp:41:5:41:6 | ref arg ct | A.cpp:43:11:43:12 | ct | provenance | |
-| A.cpp:41:15:41:21 | new | A.cpp:41:5:41:6 | ref arg ct | provenance | |
+| A.cpp:41:15:41:21 | new | A.cpp:41:5:41:6 | ref arg ct | provenance | Config |
| A.cpp:43:11:43:12 | ct | A.cpp:43:10:43:12 | & ... | provenance | |
+| A.cpp:43:11:43:12 | ct | A.cpp:43:10:43:12 | & ... | provenance | Config |
| A.cpp:47:12:47:18 | new | A.cpp:48:20:48:20 | c | provenance | |
| A.cpp:48:12:48:18 | call to make [c] | A.cpp:49:10:49:10 | b [c] | provenance | |
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | provenance | |
@@ -51,22 +54,27 @@ edges
| A.cpp:103:14:103:14 | c [a] | A.cpp:120:12:120:13 | c1 [a] | provenance | |
| A.cpp:107:12:107:13 | c1 [a] | A.cpp:107:16:107:16 | a | provenance | |
| A.cpp:120:12:120:13 | c1 [a] | A.cpp:120:16:120:16 | a | provenance | |
+| A.cpp:124:14:124:14 | b [Return] [c] | A.cpp:131:8:131:8 | ref arg b [c] | provenance | |
| A.cpp:124:14:124:14 | b [c] | A.cpp:131:8:131:8 | ref arg b [c] | provenance | |
+| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:124:14:124:14 | b [Return] [c] | provenance | |
| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:124:14:124:14 | b [c] | provenance | |
-| A.cpp:126:5:126:5 | ref arg b [c] | A.cpp:131:8:131:8 | ref arg b [c] | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | provenance | |
| A.cpp:126:12:126:18 | new | A.cpp:126:5:126:5 | ref arg b [c] | provenance | |
| A.cpp:131:8:131:8 | ref arg b [c] | A.cpp:132:10:132:10 | b [c] | provenance | |
| A.cpp:132:10:132:10 | b [c] | A.cpp:132:13:132:13 | c | provenance | |
+| A.cpp:140:5:140:5 | this [Return] [b, c] | A.cpp:151:12:151:24 | call to D [b, c] | provenance | |
+| A.cpp:140:5:140:5 | this [Return] [b] | A.cpp:151:12:151:24 | call to D [b] | provenance | |
| A.cpp:140:13:140:13 | b | A.cpp:143:7:143:31 | ... = ... | provenance | |
+| A.cpp:140:13:140:13 | b [Return] [c] | A.cpp:151:18:151:18 | ref arg b [c] | provenance | |
| A.cpp:140:13:140:13 | b [c] | A.cpp:151:18:151:18 | ref arg b [c] | provenance | |
+| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:140:13:140:13 | b [Return] [c] | provenance | |
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:140:13:140:13 | b [c] | provenance | |
| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:143:7:143:31 | ... = ... [c] | provenance | |
-| A.cpp:142:7:142:7 | b [post update] [c] | A.cpp:151:18:151:18 | ref arg b [c] | provenance | |
| A.cpp:142:7:142:20 | ... = ... | A.cpp:142:7:142:7 | b [post update] [c] | provenance | |
| A.cpp:142:14:142:20 | new | A.cpp:142:7:142:20 | ... = ... | provenance | |
-| A.cpp:143:7:143:10 | this [post update] [b, c] | A.cpp:151:12:151:24 | call to D [b, c] | provenance | |
-| A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] | provenance | |
+| A.cpp:143:7:143:10 | this [post update] [b, c] | A.cpp:140:5:140:5 | this [Return] [b, c] | provenance | |
+| A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:140:5:140:5 | this [Return] [b] | provenance | |
+| A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:140:5:140:5 | this [Return] [b] | provenance | |
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | this [post update] [b] | provenance | |
| A.cpp:143:7:143:31 | ... = ... | A.cpp:143:7:143:10 | this [post update] [b] | provenance | |
| A.cpp:143:7:143:31 | ... = ... [c] | A.cpp:143:7:143:10 | this [post update] [b, c] | provenance | |
@@ -118,7 +126,10 @@ edges
| A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:20 | ... = ... | provenance | |
| A.cpp:181:32:181:35 | next [head] | A.cpp:184:7:184:23 | ... = ... [head] | provenance | |
| A.cpp:181:32:181:35 | next [next, head] | A.cpp:184:7:184:23 | ... = ... [next, head] | provenance | |
+| A.cpp:183:7:183:10 | this [post update] [head] | A.cpp:181:5:181:10 | this [Return] [head] | provenance | |
| A.cpp:183:7:183:20 | ... = ... | A.cpp:183:7:183:10 | this [post update] [head] | provenance | |
+| A.cpp:184:7:184:10 | this [post update] [next, head] | A.cpp:181:5:181:10 | this [Return] [next, head] | provenance | |
+| A.cpp:184:7:184:10 | this [post update] [next, next, head] | A.cpp:181:5:181:10 | this [Return] [next, next, head] | provenance | |
| A.cpp:184:7:184:23 | ... = ... [head] | A.cpp:184:7:184:10 | this [post update] [next, head] | provenance | |
| A.cpp:184:7:184:23 | ... = ... [next, head] | A.cpp:184:7:184:10 | this [post update] [next, next, head] | provenance | |
| B.cpp:6:15:6:24 | new | B.cpp:7:25:7:25 | e | provenance | |
@@ -141,19 +152,25 @@ edges
| B.cpp:19:14:19:17 | box1 [elem2] | B.cpp:19:20:19:24 | elem2 | provenance | |
| B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:22 | ... = ... | provenance | |
| B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:22 | ... = ... | provenance | |
+| B.cpp:35:7:35:10 | this [post update] [elem1] | B.cpp:33:5:33:8 | this [Return] [elem1] | provenance | |
| B.cpp:35:7:35:22 | ... = ... | B.cpp:35:7:35:10 | this [post update] [elem1] | provenance | |
+| B.cpp:36:7:36:10 | this [post update] [elem2] | B.cpp:33:5:33:8 | this [Return] [elem2] | provenance | |
| B.cpp:36:7:36:22 | ... = ... | B.cpp:36:7:36:10 | this [post update] [elem2] | provenance | |
| B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:46:7:46:21 | ... = ... [elem1] | provenance | |
| B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:7:46:21 | ... = ... [elem2] | provenance | |
+| B.cpp:46:7:46:10 | this [post update] [box1, elem1] | B.cpp:44:5:44:8 | this [Return] [box1, elem1] | provenance | |
+| B.cpp:46:7:46:10 | this [post update] [box1, elem2] | B.cpp:44:5:44:8 | this [Return] [box1, elem2] | provenance | |
| B.cpp:46:7:46:21 | ... = ... [elem1] | B.cpp:46:7:46:10 | this [post update] [box1, elem1] | provenance | |
| B.cpp:46:7:46:21 | ... = ... [elem2] | B.cpp:46:7:46:10 | this [post update] [box1, elem2] | provenance | |
| C.cpp:18:12:18:18 | call to C [s1] | C.cpp:19:5:19:5 | c [s1] | provenance | |
| C.cpp:18:12:18:18 | call to C [s3] | C.cpp:19:5:19:5 | c [s3] | provenance | |
| C.cpp:19:5:19:5 | c [s1] | C.cpp:27:8:27:11 | this [s1] | provenance | |
| C.cpp:19:5:19:5 | c [s3] | C.cpp:27:8:27:11 | this [s3] | provenance | |
-| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:18:12:18:18 | call to C [s1] | provenance | |
+| C.cpp:22:3:22:3 | this [Return] [s1] | C.cpp:18:12:18:18 | call to C [s1] | provenance | |
+| C.cpp:22:3:22:3 | this [Return] [s3] | C.cpp:18:12:18:18 | call to C [s3] | provenance | |
+| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | C.cpp:22:3:22:3 | this [Return] [s1] | provenance | |
| C.cpp:22:12:22:21 | new | C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | provenance | |
-| C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:18:12:18:18 | call to C [s3] | provenance | |
+| C.cpp:24:5:24:8 | this [post update] [s3] | C.cpp:22:3:22:3 | this [Return] [s3] | provenance | |
| C.cpp:24:5:24:25 | ... = ... | C.cpp:24:5:24:8 | this [post update] [s3] | provenance | |
| C.cpp:24:16:24:25 | new | C.cpp:24:5:24:25 | ... = ... | provenance | |
| C.cpp:27:8:27:11 | this [s1] | C.cpp:29:10:29:11 | this [s1] | provenance | |
@@ -163,6 +180,7 @@ edges
| D.cpp:10:11:10:17 | this [elem] | D.cpp:10:30:10:33 | this [elem] | provenance | |
| D.cpp:10:30:10:33 | this [elem] | D.cpp:10:30:10:33 | elem | provenance | |
| D.cpp:11:24:11:24 | e | D.cpp:11:29:11:36 | ... = ... | provenance | |
+| D.cpp:11:29:11:32 | this [post update] [elem] | D.cpp:11:10:11:16 | this [Return] [elem] | provenance | |
| D.cpp:11:29:11:36 | ... = ... | D.cpp:11:29:11:32 | this [post update] [elem] | provenance | |
| D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:30:17:32 | this [box, elem] | provenance | |
| D.cpp:17:30:17:32 | this [box, elem] | D.cpp:17:30:17:32 | box [elem] | provenance | |
@@ -215,14 +233,16 @@ edges
| E.cpp:32:10:32:10 | b [buffer] | E.cpp:32:13:32:18 | buffer | provenance | |
| E.cpp:33:18:33:19 | & ... [data, buffer] | E.cpp:19:27:19:27 | p [data, buffer] | provenance | |
| E.cpp:33:19:33:19 | p [data, buffer] | E.cpp:33:18:33:19 | & ... [data, buffer] | provenance | |
+| aliasing.cpp:8:23:8:23 | s [Return] [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | provenance | |
| aliasing.cpp:8:23:8:23 | s [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | provenance | |
+| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:8:23:8:23 | s [Return] [m1] | provenance | |
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:8:23:8:23 | s [m1] | provenance | |
-| aliasing.cpp:9:3:9:3 | s [post update] [m1] | aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | provenance | |
| aliasing.cpp:9:3:9:22 | ... = ... | aliasing.cpp:9:3:9:3 | s [post update] [m1] | provenance | |
| aliasing.cpp:9:11:9:20 | call to user_input | aliasing.cpp:9:3:9:22 | ... = ... | provenance | |
+| aliasing.cpp:12:25:12:25 | s [Return] [m1] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | provenance | |
| aliasing.cpp:12:25:12:25 | s [m1] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | provenance | |
+| aliasing.cpp:13:3:13:3 | s [post update] [m1] | aliasing.cpp:12:25:12:25 | s [Return] [m1] | provenance | |
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | aliasing.cpp:12:25:12:25 | s [m1] | provenance | |
-| aliasing.cpp:13:3:13:3 | s [post update] [m1] | aliasing.cpp:26:19:26:20 | ref arg s2 [m1] | provenance | |
| aliasing.cpp:13:3:13:21 | ... = ... | aliasing.cpp:13:3:13:3 | s [post update] [m1] | provenance | |
| aliasing.cpp:13:10:13:19 | call to user_input | aliasing.cpp:13:3:13:21 | ... = ... | provenance | |
| aliasing.cpp:25:17:25:19 | ref arg & ... [m1] | aliasing.cpp:29:8:29:9 | s1 [m1] | provenance | |
@@ -244,13 +264,13 @@ edges
| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:175:15:175:22 | ref arg & ... | provenance | |
| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:187:15:187:22 | ref arg & ... | provenance | |
| aliasing.cpp:105:23:105:24 | pa | aliasing.cpp:200:15:200:24 | ref arg & ... | provenance | |
-| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:158:17:158:20 | ref arg data | provenance | |
-| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:164:17:164:20 | ref arg data | provenance | |
-| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:175:15:175:22 | ref arg & ... | provenance | |
-| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:187:15:187:22 | ref arg & ... | provenance | |
-| aliasing.cpp:106:4:106:5 | pa [inner post update] | aliasing.cpp:200:15:200:24 | ref arg & ... | provenance | |
+| aliasing.cpp:105:23:105:24 | pa [Return] | aliasing.cpp:158:17:158:20 | ref arg data | provenance | |
+| aliasing.cpp:105:23:105:24 | pa [Return] | aliasing.cpp:164:17:164:20 | ref arg data | provenance | |
+| aliasing.cpp:105:23:105:24 | pa [Return] | aliasing.cpp:175:15:175:22 | ref arg & ... | provenance | |
+| aliasing.cpp:105:23:105:24 | pa [Return] | aliasing.cpp:187:15:187:22 | ref arg & ... | provenance | |
+| aliasing.cpp:105:23:105:24 | pa [Return] | aliasing.cpp:200:15:200:24 | ref arg & ... | provenance | |
| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:105:23:105:24 | pa | provenance | |
-| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:106:4:106:5 | pa [inner post update] | provenance | |
+| aliasing.cpp:106:9:106:18 | call to user_input | aliasing.cpp:105:23:105:24 | pa [Return] | provenance | |
| aliasing.cpp:158:15:158:15 | s [post update] [data] | aliasing.cpp:159:9:159:9 | s [data] | provenance | |
| aliasing.cpp:158:17:158:20 | ref arg data | aliasing.cpp:158:15:158:15 | s [post update] [data] | provenance | |
| aliasing.cpp:159:9:159:9 | s [data] | aliasing.cpp:159:11:159:14 | data | provenance | |
@@ -330,14 +350,18 @@ edges
| arrays.cpp:44:10:44:17 | indirect [arr, data] | arrays.cpp:44:20:44:22 | arr [data] | provenance | |
| arrays.cpp:44:20:44:22 | arr [data] | arrays.cpp:44:8:44:25 | access to array [data] | provenance | |
| by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:16 | ... = ... | provenance | |
+| by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:11:39:11:39 | s [Return] [a] | provenance | |
| by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:11:39:11:39 | s [a] | provenance | |
| by_reference.cpp:12:5:12:16 | ... = ... | by_reference.cpp:12:5:12:5 | s [post update] [a] | provenance | |
| by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:19 | ... = ... | provenance | |
+| by_reference.cpp:16:5:16:8 | this [post update] [a] | by_reference.cpp:15:8:15:18 | this [Return] [a] | provenance | |
| by_reference.cpp:16:5:16:19 | ... = ... | by_reference.cpp:16:5:16:8 | this [post update] [a] | provenance | |
| by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:23:20:27 | value | provenance | |
+| by_reference.cpp:20:5:20:8 | ref arg this [a] | by_reference.cpp:19:8:19:20 | this [Return] [a] | provenance | |
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | provenance | |
| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:20:5:20:8 | ref arg this [a] | provenance | |
| by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:25:24:29 | value | provenance | |
+| by_reference.cpp:24:19:24:22 | ref arg this [a] | by_reference.cpp:23:8:23:26 | this [Return] [a] | provenance | |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | provenance | |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:24:19:24:22 | ref arg this [a] | provenance | |
| by_reference.cpp:31:46:31:46 | s [a] | by_reference.cpp:32:12:32:12 | s [a] | provenance | |
@@ -371,34 +395,36 @@ edges
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:31:46:31:46 | s [a] | provenance | |
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:69:8:69:20 | call to nonMemberGetA | provenance | |
| by_reference.cpp:69:23:69:23 | s [a] | by_reference.cpp:69:22:69:23 | & ... [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | inner [Return] [a] | by_reference.cpp:102:21:102:39 | ref arg & ... [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | inner [Return] [a] | by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | inner [Return] [a] | by_reference.cpp:106:21:106:41 | ref arg & ... [a] | provenance | |
+| by_reference.cpp:83:31:83:35 | inner [Return] [a] | by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | provenance | |
| by_reference.cpp:83:31:83:35 | inner [a] | by_reference.cpp:102:21:102:39 | ref arg & ... [a] | provenance | |
| by_reference.cpp:83:31:83:35 | inner [a] | by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | provenance | |
| by_reference.cpp:83:31:83:35 | inner [a] | by_reference.cpp:106:21:106:41 | ref arg & ... [a] | provenance | |
| by_reference.cpp:83:31:83:35 | inner [a] | by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | provenance | |
+| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:83:31:83:35 | inner [Return] [a] | provenance | |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:83:31:83:35 | inner [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:102:21:102:39 | ref arg & ... [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:103:27:103:35 | ref arg inner_ptr [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:106:21:106:41 | ref arg & ... [a] | provenance | |
-| by_reference.cpp:84:3:84:7 | inner [post update] [a] | by_reference.cpp:107:29:107:37 | ref arg inner_ptr [a] | provenance | |
| by_reference.cpp:84:3:84:25 | ... = ... | by_reference.cpp:84:3:84:7 | inner [post update] [a] | provenance | |
| by_reference.cpp:84:14:84:23 | call to user_input | by_reference.cpp:84:3:84:25 | ... = ... | provenance | |
+| by_reference.cpp:87:31:87:35 | inner [Return] [a] | by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | provenance | |
+| by_reference.cpp:87:31:87:35 | inner [Return] [a] | by_reference.cpp:123:21:123:36 | ref arg * ... [a] | provenance | |
+| by_reference.cpp:87:31:87:35 | inner [Return] [a] | by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] | provenance | |
+| by_reference.cpp:87:31:87:35 | inner [Return] [a] | by_reference.cpp:127:21:127:38 | ref arg * ... [a] | provenance | |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | provenance | |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:123:21:123:36 | ref arg * ... [a] | provenance | |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] | provenance | |
| by_reference.cpp:87:31:87:35 | inner [a] | by_reference.cpp:127:21:127:38 | ref arg * ... [a] | provenance | |
+| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:87:31:87:35 | inner [Return] [a] | provenance | |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:87:31:87:35 | inner [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:122:27:122:38 | ref arg inner_nested [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:123:21:123:36 | ref arg * ... [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:126:29:126:40 | ref arg inner_nested [a] | provenance | |
-| by_reference.cpp:88:3:88:7 | inner [post update] [a] | by_reference.cpp:127:21:127:38 | ref arg * ... [a] | provenance | |
| by_reference.cpp:88:3:88:24 | ... = ... | by_reference.cpp:88:3:88:7 | inner [post update] [a] | provenance | |
| by_reference.cpp:88:13:88:22 | call to user_input | by_reference.cpp:88:3:88:24 | ... = ... | provenance | |
| by_reference.cpp:91:25:91:26 | pa | by_reference.cpp:104:15:104:22 | ref arg & ... | provenance | |
| by_reference.cpp:91:25:91:26 | pa | by_reference.cpp:108:15:108:24 | ref arg & ... | provenance | |
-| by_reference.cpp:92:4:92:5 | pa [inner post update] | by_reference.cpp:104:15:104:22 | ref arg & ... | provenance | |
-| by_reference.cpp:92:4:92:5 | pa [inner post update] | by_reference.cpp:108:15:108:24 | ref arg & ... | provenance | |
+| by_reference.cpp:91:25:91:26 | pa [Return] | by_reference.cpp:104:15:104:22 | ref arg & ... | provenance | |
+| by_reference.cpp:91:25:91:26 | pa [Return] | by_reference.cpp:108:15:108:24 | ref arg & ... | provenance | |
| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:91:25:91:26 | pa | provenance | |
-| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:92:4:92:5 | pa [inner post update] | provenance | |
+| by_reference.cpp:92:9:92:18 | call to user_input | by_reference.cpp:91:25:91:26 | pa [Return] | provenance | |
| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:124:21:124:21 | ref arg a | provenance | |
| by_reference.cpp:95:25:95:26 | pa | by_reference.cpp:128:23:128:23 | ref arg a | provenance | |
| by_reference.cpp:96:8:96:17 | call to user_input | by_reference.cpp:95:25:95:26 | pa | provenance | |
@@ -493,8 +519,10 @@ edges
| complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | this [b_] | provenance | |
| complex.cpp:10:20:10:21 | this [b_] | complex.cpp:10:20:10:21 | b_ | provenance | |
| complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:27 | ... = ... | provenance | |
+| complex.cpp:11:22:11:23 | this [post update] [a_] | complex.cpp:11:8:11:11 | this [Return] [a_] | provenance | |
| complex.cpp:11:22:11:27 | ... = ... | complex.cpp:11:22:11:23 | this [post update] [a_] | provenance | |
| complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:27 | ... = ... | provenance | |
+| complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:12:8:12:11 | this [Return] [b_] | provenance | |
| complex.cpp:12:22:12:27 | ... = ... | complex.cpp:12:22:12:23 | this [post update] [b_] | provenance | |
| complex.cpp:40:17:40:17 | b [inner, f, a_] | complex.cpp:42:8:42:8 | b [inner, f, a_] | provenance | |
| complex.cpp:40:17:40:17 | b [inner, f, b_] | complex.cpp:43:8:43:8 | b [inner, f, b_] | provenance | |
@@ -557,7 +585,9 @@ edges
| constructors.cpp:19:22:19:23 | this [b_] | constructors.cpp:19:22:19:23 | b_ | provenance | |
| constructors.cpp:23:13:23:13 | a | constructors.cpp:23:28:23:28 | a | provenance | |
| constructors.cpp:23:20:23:20 | b | constructors.cpp:23:35:23:35 | b | provenance | |
+| constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | constructors.cpp:23:5:23:7 | this [Return] [a_] | provenance | |
| constructors.cpp:23:28:23:28 | a | constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | provenance | |
+| constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | constructors.cpp:23:5:23:7 | this [Return] [b_] | provenance | |
| constructors.cpp:23:35:23:35 | b | constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | provenance | |
| constructors.cpp:26:15:26:15 | f [a_] | constructors.cpp:28:10:28:10 | f [a_] | provenance | |
| constructors.cpp:26:15:26:15 | f [b_] | constructors.cpp:29:10:29:10 | f [b_] | provenance | |
@@ -582,11 +612,14 @@ edges
| constructors.cpp:46:9:46:9 | h [a_] | constructors.cpp:26:15:26:15 | f [a_] | provenance | |
| constructors.cpp:46:9:46:9 | h [b_] | constructors.cpp:26:15:26:15 | f [b_] | provenance | |
| qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:44 | ... = ... | provenance | |
+| qualifiers.cpp:9:30:9:33 | this [post update] [a] | qualifiers.cpp:9:10:9:13 | this [Return] [a] | provenance | |
| qualifiers.cpp:9:30:9:44 | ... = ... | qualifiers.cpp:9:30:9:33 | this [post update] [a] | provenance | |
| qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:64 | ... = ... | provenance | |
+| qualifiers.cpp:12:49:12:53 | inner [post update] [a] | qualifiers.cpp:12:27:12:31 | inner [Return] [a] | provenance | |
| qualifiers.cpp:12:49:12:53 | inner [post update] [a] | qualifiers.cpp:12:27:12:31 | inner [a] | provenance | |
| qualifiers.cpp:12:49:12:64 | ... = ... | qualifiers.cpp:12:49:12:53 | inner [post update] [a] | provenance | |
| qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:65 | ... = ... | provenance | |
+| qualifiers.cpp:13:51:13:55 | inner [post update] [a] | qualifiers.cpp:13:29:13:33 | inner [Return] [a] | provenance | |
| qualifiers.cpp:13:51:13:55 | inner [post update] [a] | qualifiers.cpp:13:29:13:33 | inner [a] | provenance | |
| qualifiers.cpp:13:51:13:65 | ... = ... | qualifiers.cpp:13:51:13:55 | inner [post update] [a] | provenance | |
| qualifiers.cpp:22:5:22:9 | ref arg outer [inner, a] | qualifiers.cpp:23:10:23:14 | outer [inner, a] | provenance | |
@@ -654,8 +687,10 @@ edges
| simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:22:19:23 | this [b_] | provenance | |
| simple.cpp:19:22:19:23 | this [b_] | simple.cpp:19:22:19:23 | b_ | provenance | |
| simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:29 | ... = ... | provenance | |
+| simple.cpp:20:24:20:25 | this [post update] [a_] | simple.cpp:20:10:20:13 | this [Return] [a_] | provenance | |
| simple.cpp:20:24:20:29 | ... = ... | simple.cpp:20:24:20:25 | this [post update] [a_] | provenance | |
| simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:29 | ... = ... | provenance | |
+| simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:21:10:21:13 | this [Return] [b_] | provenance | |
| simple.cpp:21:24:21:29 | ... = ... | simple.cpp:21:24:21:25 | this [post update] [b_] | provenance | |
| simple.cpp:26:15:26:15 | f [a_] | simple.cpp:28:10:28:10 | f [a_] | provenance | |
| simple.cpp:26:15:26:15 | f [b_] | simple.cpp:29:10:29:10 | f [b_] | provenance | |
@@ -747,9 +782,11 @@ edges
| struct_init.c:46:10:46:14 | outer [pointerAB, a] | struct_init.c:46:16:46:24 | pointerAB [a] | provenance | |
| struct_init.c:46:16:46:24 | pointerAB [a] | struct_init.c:14:24:14:25 | ab [a] | provenance | |
nodes
+| A.cpp:23:5:23:5 | this [Return] [c] | semmle.label | this [Return] [c] |
| A.cpp:23:10:23:10 | c | semmle.label | c |
| A.cpp:25:7:25:10 | this [post update] [c] | semmle.label | this [post update] [c] |
| A.cpp:25:7:25:17 | ... = ... | semmle.label | ... = ... |
+| A.cpp:27:10:27:12 | this [Return] [c] | semmle.label | this [Return] [c] |
| A.cpp:27:17:27:17 | c | semmle.label | c |
| A.cpp:27:22:27:25 | this [post update] [c] | semmle.label | this [post update] [c] |
| A.cpp:27:22:27:32 | ... = ... | semmle.label | ... = ... |
@@ -802,13 +839,18 @@ nodes
| A.cpp:107:16:107:16 | a | semmle.label | a |
| A.cpp:120:12:120:13 | c1 [a] | semmle.label | c1 [a] |
| A.cpp:120:16:120:16 | a | semmle.label | a |
+| A.cpp:124:14:124:14 | b [Return] [c] | semmle.label | b [Return] [c] |
| A.cpp:124:14:124:14 | b [c] | semmle.label | b [c] |
| A.cpp:126:5:126:5 | ref arg b [c] | semmle.label | ref arg b [c] |
| A.cpp:126:12:126:18 | new | semmle.label | new |
| A.cpp:131:8:131:8 | ref arg b [c] | semmle.label | ref arg b [c] |
| A.cpp:132:10:132:10 | b [c] | semmle.label | b [c] |
| A.cpp:132:13:132:13 | c | semmle.label | c |
+| A.cpp:140:5:140:5 | this [Return] [b, c] | semmle.label | this [Return] [b, c] |
+| A.cpp:140:5:140:5 | this [Return] [b] | semmle.label | this [Return] [b] |
+| A.cpp:140:5:140:5 | this [Return] [b] | semmle.label | this [Return] [b] |
| A.cpp:140:13:140:13 | b | semmle.label | b |
+| A.cpp:140:13:140:13 | b [Return] [c] | semmle.label | b [Return] [c] |
| A.cpp:140:13:140:13 | b [c] | semmle.label | b [c] |
| A.cpp:142:7:142:7 | b [post update] [c] | semmle.label | b [post update] [c] |
| A.cpp:142:7:142:20 | ... = ... | semmle.label | ... = ... |
@@ -862,6 +904,9 @@ nodes
| A.cpp:173:26:173:26 | o | semmle.label | o |
| A.cpp:173:26:173:26 | o [c] | semmle.label | o [c] |
| A.cpp:173:26:173:26 | o [c] | semmle.label | o [c] |
+| A.cpp:181:5:181:10 | this [Return] [head] | semmle.label | this [Return] [head] |
+| A.cpp:181:5:181:10 | this [Return] [next, head] | semmle.label | this [Return] [next, head] |
+| A.cpp:181:5:181:10 | this [Return] [next, next, head] | semmle.label | this [Return] [next, next, head] |
| A.cpp:181:15:181:21 | newHead | semmle.label | newHead |
| A.cpp:181:32:181:35 | next [head] | semmle.label | next [head] |
| A.cpp:181:32:181:35 | next [next, head] | semmle.label | next [next, head] |
@@ -887,12 +932,16 @@ nodes
| B.cpp:19:10:19:11 | b2 [box1, elem2] | semmle.label | b2 [box1, elem2] |
| B.cpp:19:14:19:17 | box1 [elem2] | semmle.label | box1 [elem2] |
| B.cpp:19:20:19:24 | elem2 | semmle.label | elem2 |
+| B.cpp:33:5:33:8 | this [Return] [elem1] | semmle.label | this [Return] [elem1] |
+| B.cpp:33:5:33:8 | this [Return] [elem2] | semmle.label | this [Return] [elem2] |
| B.cpp:33:16:33:17 | e1 | semmle.label | e1 |
| B.cpp:33:26:33:27 | e2 | semmle.label | e2 |
| B.cpp:35:7:35:10 | this [post update] [elem1] | semmle.label | this [post update] [elem1] |
| B.cpp:35:7:35:22 | ... = ... | semmle.label | ... = ... |
| B.cpp:36:7:36:10 | this [post update] [elem2] | semmle.label | this [post update] [elem2] |
| B.cpp:36:7:36:22 | ... = ... | semmle.label | ... = ... |
+| B.cpp:44:5:44:8 | this [Return] [box1, elem1] | semmle.label | this [Return] [box1, elem1] |
+| B.cpp:44:5:44:8 | this [Return] [box1, elem2] | semmle.label | this [Return] [box1, elem2] |
| B.cpp:44:16:44:17 | b1 [elem1] | semmle.label | b1 [elem1] |
| B.cpp:44:16:44:17 | b1 [elem2] | semmle.label | b1 [elem2] |
| B.cpp:46:7:46:10 | this [post update] [box1, elem1] | semmle.label | this [post update] [box1, elem1] |
@@ -903,6 +952,8 @@ nodes
| C.cpp:18:12:18:18 | call to C [s3] | semmle.label | call to C [s3] |
| C.cpp:19:5:19:5 | c [s1] | semmle.label | c [s1] |
| C.cpp:19:5:19:5 | c [s3] | semmle.label | c [s3] |
+| C.cpp:22:3:22:3 | this [Return] [s1] | semmle.label | this [Return] [s1] |
+| C.cpp:22:3:22:3 | this [Return] [s3] | semmle.label | this [Return] [s3] |
| C.cpp:22:9:22:22 | constructor init of field s1 [post-this] [s1] | semmle.label | constructor init of field s1 [post-this] [s1] |
| C.cpp:22:12:22:21 | new | semmle.label | new |
| C.cpp:24:5:24:8 | this [post update] [s3] | semmle.label | this [post update] [s3] |
@@ -917,6 +968,7 @@ nodes
| D.cpp:10:11:10:17 | this [elem] | semmle.label | this [elem] |
| D.cpp:10:30:10:33 | elem | semmle.label | elem |
| D.cpp:10:30:10:33 | this [elem] | semmle.label | this [elem] |
+| D.cpp:11:10:11:16 | this [Return] [elem] | semmle.label | this [Return] [elem] |
| D.cpp:11:24:11:24 | e | semmle.label | e |
| D.cpp:11:29:11:32 | this [post update] [elem] | semmle.label | this [post update] [elem] |
| D.cpp:11:29:11:36 | ... = ... | semmle.label | ... = ... |
@@ -973,10 +1025,12 @@ nodes
| E.cpp:32:13:32:18 | buffer | semmle.label | buffer |
| E.cpp:33:18:33:19 | & ... [data, buffer] | semmle.label | & ... [data, buffer] |
| E.cpp:33:19:33:19 | p [data, buffer] | semmle.label | p [data, buffer] |
+| aliasing.cpp:8:23:8:23 | s [Return] [m1] | semmle.label | s [Return] [m1] |
| aliasing.cpp:8:23:8:23 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:9:3:9:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:9:3:9:22 | ... = ... | semmle.label | ... = ... |
| aliasing.cpp:9:11:9:20 | call to user_input | semmle.label | call to user_input |
+| aliasing.cpp:12:25:12:25 | s [Return] [m1] | semmle.label | s [Return] [m1] |
| aliasing.cpp:12:25:12:25 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:13:3:13:3 | s [post update] [m1] | semmle.label | s [post update] [m1] |
| aliasing.cpp:13:3:13:21 | ... = ... | semmle.label | ... = ... |
@@ -1000,7 +1054,7 @@ nodes
| aliasing.cpp:93:10:93:10 | s [m1] | semmle.label | s [m1] |
| aliasing.cpp:93:12:93:13 | m1 | semmle.label | m1 |
| aliasing.cpp:105:23:105:24 | pa | semmle.label | pa |
-| aliasing.cpp:106:4:106:5 | pa [inner post update] | semmle.label | pa [inner post update] |
+| aliasing.cpp:105:23:105:24 | pa [Return] | semmle.label | pa [Return] |
| aliasing.cpp:106:9:106:18 | call to user_input | semmle.label | call to user_input |
| aliasing.cpp:158:15:158:15 | s [post update] [data] | semmle.label | s [post update] [data] |
| aliasing.cpp:158:17:158:20 | ref arg data | semmle.label | ref arg data |
@@ -1085,16 +1139,20 @@ nodes
| arrays.cpp:44:10:44:17 | indirect [arr, data] | semmle.label | indirect [arr, data] |
| arrays.cpp:44:20:44:22 | arr [data] | semmle.label | arr [data] |
| arrays.cpp:44:27:44:30 | data | semmle.label | data |
+| by_reference.cpp:11:39:11:39 | s [Return] [a] | semmle.label | s [Return] [a] |
| by_reference.cpp:11:39:11:39 | s [a] | semmle.label | s [a] |
| by_reference.cpp:11:48:11:52 | value | semmle.label | value |
| by_reference.cpp:12:5:12:5 | s [post update] [a] | semmle.label | s [post update] [a] |
| by_reference.cpp:12:5:12:16 | ... = ... | semmle.label | ... = ... |
+| by_reference.cpp:15:8:15:18 | this [Return] [a] | semmle.label | this [Return] [a] |
| by_reference.cpp:15:26:15:30 | value | semmle.label | value |
| by_reference.cpp:16:5:16:8 | this [post update] [a] | semmle.label | this [post update] [a] |
| by_reference.cpp:16:5:16:19 | ... = ... | semmle.label | ... = ... |
+| by_reference.cpp:19:8:19:20 | this [Return] [a] | semmle.label | this [Return] [a] |
| by_reference.cpp:19:28:19:32 | value | semmle.label | value |
| by_reference.cpp:20:5:20:8 | ref arg this [a] | semmle.label | ref arg this [a] |
| by_reference.cpp:20:23:20:27 | value | semmle.label | value |
+| by_reference.cpp:23:8:23:26 | this [Return] [a] | semmle.label | this [Return] [a] |
| by_reference.cpp:23:34:23:38 | value | semmle.label | value |
| by_reference.cpp:24:19:24:22 | ref arg this [a] | semmle.label | ref arg this [a] |
| by_reference.cpp:24:25:24:29 | value | semmle.label | value |
@@ -1127,16 +1185,18 @@ nodes
| by_reference.cpp:69:8:69:20 | call to nonMemberGetA | semmle.label | call to nonMemberGetA |
| by_reference.cpp:69:22:69:23 | & ... [a] | semmle.label | & ... [a] |
| by_reference.cpp:69:23:69:23 | s [a] | semmle.label | s [a] |
+| by_reference.cpp:83:31:83:35 | inner [Return] [a] | semmle.label | inner [Return] [a] |
| by_reference.cpp:83:31:83:35 | inner [a] | semmle.label | inner [a] |
| by_reference.cpp:84:3:84:7 | inner [post update] [a] | semmle.label | inner [post update] [a] |
| by_reference.cpp:84:3:84:25 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:84:14:84:23 | call to user_input | semmle.label | call to user_input |
+| by_reference.cpp:87:31:87:35 | inner [Return] [a] | semmle.label | inner [Return] [a] |
| by_reference.cpp:87:31:87:35 | inner [a] | semmle.label | inner [a] |
| by_reference.cpp:88:3:88:7 | inner [post update] [a] | semmle.label | inner [post update] [a] |
| by_reference.cpp:88:3:88:24 | ... = ... | semmle.label | ... = ... |
| by_reference.cpp:88:13:88:22 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:91:25:91:26 | pa | semmle.label | pa |
-| by_reference.cpp:92:4:92:5 | pa [inner post update] | semmle.label | pa [inner post update] |
+| by_reference.cpp:91:25:91:26 | pa [Return] | semmle.label | pa [Return] |
| by_reference.cpp:92:9:92:18 | call to user_input | semmle.label | call to user_input |
| by_reference.cpp:95:25:95:26 | pa | semmle.label | pa |
| by_reference.cpp:96:8:96:17 | call to user_input | semmle.label | call to user_input |
@@ -1253,9 +1313,11 @@ nodes
| complex.cpp:10:7:10:7 | this [b_] | semmle.label | this [b_] |
| complex.cpp:10:20:10:21 | b_ | semmle.label | b_ |
| complex.cpp:10:20:10:21 | this [b_] | semmle.label | this [b_] |
+| complex.cpp:11:8:11:11 | this [Return] [a_] | semmle.label | this [Return] [a_] |
| complex.cpp:11:17:11:17 | a | semmle.label | a |
| complex.cpp:11:22:11:23 | this [post update] [a_] | semmle.label | this [post update] [a_] |
| complex.cpp:11:22:11:27 | ... = ... | semmle.label | ... = ... |
+| complex.cpp:12:8:12:11 | this [Return] [b_] | semmle.label | this [Return] [b_] |
| complex.cpp:12:17:12:17 | b | semmle.label | b |
| complex.cpp:12:22:12:23 | this [post update] [b_] | semmle.label | this [post update] [b_] |
| complex.cpp:12:22:12:27 | ... = ... | semmle.label | ... = ... |
@@ -1321,6 +1383,8 @@ nodes
| constructors.cpp:19:9:19:9 | this [b_] | semmle.label | this [b_] |
| constructors.cpp:19:22:19:23 | b_ | semmle.label | b_ |
| constructors.cpp:19:22:19:23 | this [b_] | semmle.label | this [b_] |
+| constructors.cpp:23:5:23:7 | this [Return] [a_] | semmle.label | this [Return] [a_] |
+| constructors.cpp:23:5:23:7 | this [Return] [b_] | semmle.label | this [Return] [b_] |
| constructors.cpp:23:13:23:13 | a | semmle.label | a |
| constructors.cpp:23:20:23:20 | b | semmle.label | b |
| constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | semmle.label | constructor init of field a_ [post-this] [a_] |
@@ -1345,13 +1409,16 @@ nodes
| constructors.cpp:43:9:43:9 | g [b_] | semmle.label | g [b_] |
| constructors.cpp:46:9:46:9 | h [a_] | semmle.label | h [a_] |
| constructors.cpp:46:9:46:9 | h [b_] | semmle.label | h [b_] |
+| qualifiers.cpp:9:10:9:13 | this [Return] [a] | semmle.label | this [Return] [a] |
| qualifiers.cpp:9:21:9:25 | value | semmle.label | value |
| qualifiers.cpp:9:30:9:33 | this [post update] [a] | semmle.label | this [post update] [a] |
| qualifiers.cpp:9:30:9:44 | ... = ... | semmle.label | ... = ... |
+| qualifiers.cpp:12:27:12:31 | inner [Return] [a] | semmle.label | inner [Return] [a] |
| qualifiers.cpp:12:27:12:31 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:12:40:12:44 | value | semmle.label | value |
| qualifiers.cpp:12:49:12:53 | inner [post update] [a] | semmle.label | inner [post update] [a] |
| qualifiers.cpp:12:49:12:64 | ... = ... | semmle.label | ... = ... |
+| qualifiers.cpp:13:29:13:33 | inner [Return] [a] | semmle.label | inner [Return] [a] |
| qualifiers.cpp:13:29:13:33 | inner [a] | semmle.label | inner [a] |
| qualifiers.cpp:13:42:13:46 | value | semmle.label | value |
| qualifiers.cpp:13:51:13:55 | inner [post update] [a] | semmle.label | inner [post update] [a] |
@@ -1425,9 +1492,11 @@ nodes
| simple.cpp:19:9:19:9 | this [b_] | semmle.label | this [b_] |
| simple.cpp:19:22:19:23 | b_ | semmle.label | b_ |
| simple.cpp:19:22:19:23 | this [b_] | semmle.label | this [b_] |
+| simple.cpp:20:10:20:13 | this [Return] [a_] | semmle.label | this [Return] [a_] |
| simple.cpp:20:19:20:19 | a | semmle.label | a |
| simple.cpp:20:24:20:25 | this [post update] [a_] | semmle.label | this [post update] [a_] |
| simple.cpp:20:24:20:29 | ... = ... | semmle.label | ... = ... |
+| simple.cpp:21:10:21:13 | this [Return] [b_] | semmle.label | this [Return] [b_] |
| simple.cpp:21:19:21:19 | b | semmle.label | b |
| simple.cpp:21:24:21:25 | this [post update] [b_] | semmle.label | this [post update] [b_] |
| simple.cpp:21:24:21:29 | ... = ... | semmle.label | ... = ... |
@@ -1513,71 +1582,71 @@ nodes
| struct_init.c:46:10:46:14 | outer [pointerAB, a] | semmle.label | outer [pointerAB, a] |
| struct_init.c:46:16:46:24 | pointerAB [a] | semmle.label | pointerAB [a] |
subpaths
-| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | this [post update] [c] | A.cpp:31:14:31:21 | call to B [c] |
+| A.cpp:31:20:31:20 | c | A.cpp:23:10:23:10 | c | A.cpp:23:5:23:5 | this [Return] [c] | A.cpp:31:14:31:21 | call to B [c] |
| A.cpp:48:20:48:20 | c | A.cpp:29:23:29:23 | c | A.cpp:31:14:31:21 | new [c] | A.cpp:48:12:48:18 | call to make [c] |
-| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:55:5:55:5 | ref arg b [c] |
+| A.cpp:55:12:55:19 | new | A.cpp:27:17:27:17 | c | A.cpp:27:10:27:12 | this [Return] [c] | A.cpp:55:5:55:5 | ref arg b [c] |
| A.cpp:56:10:56:10 | b [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:29:28:29 | c | A.cpp:56:13:56:15 | call to get |
| A.cpp:57:11:57:24 | new [c] | A.cpp:28:8:28:10 | this [c] | A.cpp:28:29:28:29 | c | A.cpp:57:28:57:30 | call to get |
-| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:25:7:25:10 | this [post update] [c] | A.cpp:57:11:57:24 | call to B [c] |
+| A.cpp:57:17:57:23 | new | A.cpp:23:10:23:10 | c | A.cpp:23:5:23:5 | this [Return] [c] | A.cpp:57:11:57:24 | call to B [c] |
| A.cpp:64:21:64:28 | new | A.cpp:85:26:85:26 | c | A.cpp:91:14:91:15 | b2 [c] | A.cpp:64:10:64:15 | call to setOnB [c] |
| A.cpp:73:25:73:32 | new | A.cpp:78:27:78:27 | c | A.cpp:82:12:82:24 | ... ? ... : ... [c] | A.cpp:73:10:73:19 | call to setOnBWrap [c] |
| A.cpp:81:21:81:21 | c | A.cpp:85:26:85:26 | c | A.cpp:91:14:91:15 | b2 [c] | A.cpp:81:10:81:15 | call to setOnB [c] |
-| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:90:7:90:8 | ref arg b2 [c] |
-| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:22:27:25 | this [post update] [c] | A.cpp:126:5:126:5 | ref arg b [c] |
-| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:143:7:143:10 | this [post update] [b] | A.cpp:151:12:151:24 | call to D [b] |
+| A.cpp:90:15:90:15 | c | A.cpp:27:17:27:17 | c | A.cpp:27:10:27:12 | this [Return] [c] | A.cpp:90:7:90:8 | ref arg b2 [c] |
+| A.cpp:126:12:126:18 | new | A.cpp:27:17:27:17 | c | A.cpp:27:10:27:12 | this [Return] [c] | A.cpp:126:5:126:5 | ref arg b [c] |
+| A.cpp:151:18:151:18 | b | A.cpp:140:13:140:13 | b | A.cpp:140:5:140:5 | this [Return] [b] | A.cpp:151:12:151:24 | call to D [b] |
| A.cpp:152:13:152:13 | b [c] | A.cpp:173:26:173:26 | o [c] | A.cpp:173:26:173:26 | o [c] | A.cpp:152:13:152:13 | ref arg b [c] |
-| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:183:7:183:10 | this [post update] [head] | A.cpp:160:18:160:60 | call to MyList [head] |
-| A.cpp:161:38:161:39 | l1 [head] | A.cpp:181:32:181:35 | next [head] | A.cpp:184:7:184:10 | this [post update] [next, head] | A.cpp:161:18:161:40 | call to MyList [next, head] |
-| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:181:32:181:35 | next [next, head] | A.cpp:184:7:184:10 | this [post update] [next, next, head] | A.cpp:162:18:162:40 | call to MyList [next, next, head] |
+| A.cpp:160:29:160:29 | b | A.cpp:181:15:181:21 | newHead | A.cpp:181:5:181:10 | this [Return] [head] | A.cpp:160:18:160:60 | call to MyList [head] |
+| A.cpp:161:38:161:39 | l1 [head] | A.cpp:181:32:181:35 | next [head] | A.cpp:181:5:181:10 | this [Return] [next, head] | A.cpp:161:18:161:40 | call to MyList [next, head] |
+| A.cpp:162:38:162:39 | l2 [next, head] | A.cpp:181:32:181:35 | next [next, head] | A.cpp:181:5:181:10 | this [Return] [next, next, head] | A.cpp:162:18:162:40 | call to MyList [next, next, head] |
| A.cpp:165:26:165:29 | head | A.cpp:173:26:173:26 | o | A.cpp:173:26:173:26 | o | A.cpp:165:26:165:29 | ref arg head |
-| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:35:7:35:10 | this [post update] [elem1] | B.cpp:7:16:7:35 | call to Box1 [elem1] |
-| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:46:7:46:10 | this [post update] [box1, elem1] | B.cpp:8:16:8:27 | call to Box2 [box1, elem1] |
-| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:36:7:36:10 | this [post update] [elem2] | B.cpp:16:16:16:38 | call to Box1 [elem2] |
-| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:46:7:46:10 | this [post update] [box1, elem2] | B.cpp:17:16:17:27 | call to Box2 [box1, elem2] |
+| B.cpp:7:25:7:25 | e | B.cpp:33:16:33:17 | e1 | B.cpp:33:5:33:8 | this [Return] [elem1] | B.cpp:7:16:7:35 | call to Box1 [elem1] |
+| B.cpp:8:25:8:26 | b1 [elem1] | B.cpp:44:16:44:17 | b1 [elem1] | B.cpp:44:5:44:8 | this [Return] [box1, elem1] | B.cpp:8:16:8:27 | call to Box2 [box1, elem1] |
+| B.cpp:16:37:16:37 | e | B.cpp:33:26:33:27 | e2 | B.cpp:33:5:33:8 | this [Return] [elem2] | B.cpp:16:16:16:38 | call to Box1 [elem2] |
+| B.cpp:17:25:17:26 | b1 [elem2] | B.cpp:44:16:44:17 | b1 [elem2] | B.cpp:44:5:44:8 | this [Return] [box1, elem2] | B.cpp:17:16:17:27 | call to Box2 [box1, elem2] |
| D.cpp:22:10:22:11 | b2 [box, elem] | D.cpp:17:11:17:17 | this [box, elem] | D.cpp:17:30:17:32 | box [elem] | D.cpp:22:14:22:20 | call to getBox1 [elem] |
| D.cpp:22:14:22:20 | call to getBox1 [elem] | D.cpp:10:11:10:17 | this [elem] | D.cpp:10:30:10:33 | elem | D.cpp:22:25:22:31 | call to getElem |
-| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | this [post update] [elem] | D.cpp:37:8:37:10 | ref arg box [elem] |
-| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:29:11:32 | this [post update] [elem] | D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] |
+| D.cpp:37:21:37:21 | e | D.cpp:11:24:11:24 | e | D.cpp:11:10:11:16 | this [Return] [elem] | D.cpp:37:8:37:10 | ref arg box [elem] |
+| D.cpp:51:27:51:27 | e | D.cpp:11:24:11:24 | e | D.cpp:11:10:11:16 | this [Return] [elem] | D.cpp:51:8:51:14 | ref arg call to getBox1 [elem] |
| arrays.cpp:37:24:37:27 | data | realistic.cpp:41:17:41:17 | o | realistic.cpp:41:17:41:17 | o | arrays.cpp:37:24:37:27 | ref arg data |
| arrays.cpp:43:27:43:30 | data | realistic.cpp:41:17:41:17 | o | realistic.cpp:41:17:41:17 | o | arrays.cpp:43:27:43:30 | ref arg data |
-| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | this [post update] [a] | by_reference.cpp:20:5:20:8 | ref arg this [a] |
+| by_reference.cpp:20:23:20:27 | value | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:15:8:15:18 | this [Return] [a] | by_reference.cpp:20:5:20:8 | ref arg this [a] |
+| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | s [Return] [a] | by_reference.cpp:24:19:24:22 | ref arg this [a] |
| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | s [a] | by_reference.cpp:24:19:24:22 | ref arg this [a] |
-| by_reference.cpp:24:25:24:29 | value | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:24:19:24:22 | ref arg this [a] |
| by_reference.cpp:40:12:40:15 | this [a] | by_reference.cpp:35:9:35:19 | this [a] | by_reference.cpp:36:18:36:18 | a | by_reference.cpp:40:18:40:28 | call to getDirectly |
| by_reference.cpp:44:26:44:29 | this [a] | by_reference.cpp:31:46:31:46 | s [a] | by_reference.cpp:32:15:32:15 | a | by_reference.cpp:44:12:44:24 | call to nonMemberGetA |
-| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:16:5:16:8 | this [post update] [a] | by_reference.cpp:50:3:50:3 | ref arg s [a] |
+| by_reference.cpp:50:17:50:26 | call to user_input | by_reference.cpp:15:26:15:30 | value | by_reference.cpp:15:8:15:18 | this [Return] [a] | by_reference.cpp:50:3:50:3 | ref arg s [a] |
| by_reference.cpp:51:8:51:8 | s [a] | by_reference.cpp:35:9:35:19 | this [a] | by_reference.cpp:36:18:36:18 | a | by_reference.cpp:51:10:51:20 | call to getDirectly |
-| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:20:5:20:8 | ref arg this [a] | by_reference.cpp:56:3:56:3 | ref arg s [a] |
+| by_reference.cpp:56:19:56:28 | call to user_input | by_reference.cpp:19:28:19:32 | value | by_reference.cpp:19:8:19:20 | this [Return] [a] | by_reference.cpp:56:3:56:3 | ref arg s [a] |
| by_reference.cpp:57:8:57:8 | s [a] | by_reference.cpp:39:9:39:21 | this [a] | by_reference.cpp:40:18:40:28 | call to getDirectly | by_reference.cpp:57:10:57:22 | call to getIndirectly |
-| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:24:19:24:22 | ref arg this [a] | by_reference.cpp:62:3:62:3 | ref arg s [a] |
+| by_reference.cpp:62:25:62:34 | call to user_input | by_reference.cpp:23:34:23:38 | value | by_reference.cpp:23:8:23:26 | this [Return] [a] | by_reference.cpp:62:3:62:3 | ref arg s [a] |
| by_reference.cpp:63:8:63:8 | s [a] | by_reference.cpp:43:9:43:27 | this [a] | by_reference.cpp:44:12:44:24 | call to nonMemberGetA | by_reference.cpp:63:10:63:28 | call to getThroughNonMember |
+| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | s [Return] [a] | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:11:39:11:39 | s [a] | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
-| by_reference.cpp:68:21:68:30 | call to user_input | by_reference.cpp:11:48:11:52 | value | by_reference.cpp:12:5:12:5 | s [post update] [a] | by_reference.cpp:68:17:68:18 | ref arg & ... [a] |
| by_reference.cpp:69:22:69:23 | & ... [a] | by_reference.cpp:31:46:31:46 | s [a] | by_reference.cpp:32:15:32:15 | a | by_reference.cpp:69:8:69:20 | call to nonMemberGetA |
| complex.cpp:42:16:42:16 | f [a_] | complex.cpp:9:7:9:7 | this [a_] | complex.cpp:9:20:9:21 | a_ | complex.cpp:42:18:42:18 | call to a |
| complex.cpp:43:16:43:16 | f [b_] | complex.cpp:10:7:10:7 | this [b_] | complex.cpp:10:20:10:21 | b_ | complex.cpp:43:18:43:18 | call to b |
-| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this [post update] [a_] | complex.cpp:53:12:53:12 | ref arg f [a_] |
-| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:54:12:54:12 | ref arg f [b_] |
-| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:22:11:23 | this [post update] [a_] | complex.cpp:55:12:55:12 | ref arg f [a_] |
-| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:22:12:23 | this [post update] [b_] | complex.cpp:56:12:56:12 | ref arg f [b_] |
+| complex.cpp:53:19:53:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:8:11:11 | this [Return] [a_] | complex.cpp:53:12:53:12 | ref arg f [a_] |
+| complex.cpp:54:19:54:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:8:12:11 | this [Return] [b_] | complex.cpp:54:12:54:12 | ref arg f [b_] |
+| complex.cpp:55:19:55:28 | call to user_input | complex.cpp:11:17:11:17 | a | complex.cpp:11:8:11:11 | this [Return] [a_] | complex.cpp:55:12:55:12 | ref arg f [a_] |
+| complex.cpp:56:19:56:28 | call to user_input | complex.cpp:12:17:12:17 | b | complex.cpp:12:8:12:11 | this [Return] [b_] | complex.cpp:56:12:56:12 | ref arg f [b_] |
| constructors.cpp:28:10:28:10 | f [a_] | constructors.cpp:18:9:18:9 | this [a_] | constructors.cpp:18:22:18:23 | a_ | constructors.cpp:28:12:28:12 | call to a |
| constructors.cpp:29:10:29:10 | f [b_] | constructors.cpp:19:9:19:9 | this [b_] | constructors.cpp:19:22:19:23 | b_ | constructors.cpp:29:12:29:12 | call to b |
-| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | constructors.cpp:34:11:34:26 | call to Foo [a_] |
-| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | constructors.cpp:35:11:35:26 | call to Foo [b_] |
-| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:25:23:29 | constructor init of field a_ [post-this] [a_] | constructors.cpp:36:11:36:37 | call to Foo [a_] |
-| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:32:23:36 | constructor init of field b_ [post-this] [b_] | constructors.cpp:36:11:36:37 | call to Foo [b_] |
-| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:30:9:33 | this [post update] [a] | qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] |
+| constructors.cpp:34:11:34:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | this [Return] [a_] | constructors.cpp:34:11:34:26 | call to Foo [a_] |
+| constructors.cpp:35:14:35:23 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | this [Return] [b_] | constructors.cpp:35:11:35:26 | call to Foo [b_] |
+| constructors.cpp:36:11:36:20 | call to user_input | constructors.cpp:23:13:23:13 | a | constructors.cpp:23:5:23:7 | this [Return] [a_] | constructors.cpp:36:11:36:37 | call to Foo [a_] |
+| constructors.cpp:36:25:36:34 | call to user_input | constructors.cpp:23:20:23:20 | b | constructors.cpp:23:5:23:7 | this [Return] [b_] | constructors.cpp:36:11:36:37 | call to Foo [b_] |
+| qualifiers.cpp:27:28:27:37 | call to user_input | qualifiers.cpp:9:21:9:25 | value | qualifiers.cpp:9:10:9:13 | this [Return] [a] | qualifiers.cpp:27:11:27:18 | ref arg call to getInner [a] |
+| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:27:12:31 | inner [Return] [a] | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:27:12:31 | inner [a] | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
-| qualifiers.cpp:32:35:32:44 | call to user_input | qualifiers.cpp:12:40:12:44 | value | qualifiers.cpp:12:49:12:53 | inner [post update] [a] | qualifiers.cpp:32:23:32:30 | ref arg call to getInner [a] |
+| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:29:13:33 | inner [Return] [a] | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:29:13:33 | inner [a] | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
-| qualifiers.cpp:37:38:37:47 | call to user_input | qualifiers.cpp:13:42:13:46 | value | qualifiers.cpp:13:51:13:55 | inner [post update] [a] | qualifiers.cpp:37:19:37:35 | ref arg * ... [a] |
| realistic.cpp:61:47:61:55 | bufferLen | realistic.cpp:41:17:41:17 | o | realistic.cpp:41:17:41:17 | o | realistic.cpp:61:47:61:55 | ref arg bufferLen |
| simple.cpp:28:10:28:10 | f [a_] | simple.cpp:18:9:18:9 | this [a_] | simple.cpp:18:22:18:23 | a_ | simple.cpp:28:12:28:12 | call to a |
| simple.cpp:29:10:29:10 | f [b_] | simple.cpp:19:9:19:9 | this [b_] | simple.cpp:19:22:19:23 | b_ | simple.cpp:29:12:29:12 | call to b |
-| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this [post update] [a_] | simple.cpp:39:5:39:5 | ref arg f [a_] |
-| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:40:5:40:5 | ref arg g [b_] |
-| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:24:20:25 | this [post update] [a_] | simple.cpp:41:5:41:5 | ref arg h [a_] |
-| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:24:21:25 | this [post update] [b_] | simple.cpp:42:5:42:5 | ref arg h [b_] |
+| simple.cpp:39:12:39:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:10:20:13 | this [Return] [a_] | simple.cpp:39:5:39:5 | ref arg f [a_] |
+| simple.cpp:40:12:40:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:10:21:13 | this [Return] [b_] | simple.cpp:40:5:40:5 | ref arg g [b_] |
+| simple.cpp:41:12:41:21 | call to user_input | simple.cpp:20:19:20:19 | a | simple.cpp:20:10:20:13 | this [Return] [a_] | simple.cpp:41:5:41:5 | ref arg h [a_] |
+| simple.cpp:42:12:42:21 | call to user_input | simple.cpp:21:19:21:19 | b | simple.cpp:21:10:21:13 | this [Return] [b_] | simple.cpp:42:5:42:5 | ref arg h [b_] |
| simple.cpp:84:14:84:20 | this [f2, f1] | simple.cpp:78:9:78:15 | this [f2, f1] | simple.cpp:79:19:79:20 | f1 | simple.cpp:84:14:84:20 | call to getf2f1 |
| struct_init.c:15:12:15:12 | a | realistic.cpp:41:17:41:17 | o | realistic.cpp:41:17:41:17 | o | struct_init.c:15:12:15:12 | ref arg a |
| struct_init.c:22:11:22:11 | a | realistic.cpp:41:17:41:17 | o | realistic.cpp:41:17:41:17 | o | struct_init.c:22:11:22:11 | ref arg a |
diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp
index 7265cb17542..a39e0698806 100644
--- a/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp
+++ b/cpp/ql/test/library-tests/dataflow/taint-tests/standalone_iterators.cpp
@@ -66,8 +66,8 @@ public:
insert_iterator_by_trait operator++(int);
insert_iterator_by_trait &operator--();
insert_iterator_by_trait operator--(int);
- insert_iterator_by_trait operator*();
- insert_iterator_by_trait operator=(int x);
+ insert_iterator_by_trait& operator*();
+ insert_iterator_by_trait& operator=(int x);
};
template<>
diff --git a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp
index 179c5eb6b19..c26eef5176c 100644
--- a/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp
+++ b/cpp/ql/test/library-tests/dataflow/taint-tests/vector.cpp
@@ -389,7 +389,7 @@ void test_vector_output_iterator(int b) {
*i9 = source();
taint_vector_output_iterator(i9);
- sink(v9); // $ ast=330:10 MISSING: ir SPURIOUS: ast=389:8
+ sink(v9); // $ ast=330:10 ir SPURIOUS: ast=389:8
std::vector::iterator i10 = v10.begin();
vector_iterator_assign_wrapper(i10, 10);
@@ -440,14 +440,14 @@ void test_vector_inserter(char *source_string) {
std::vector out;
auto it = std::back_inserter(out);
*++it = std::string(source_string);
- sink(out); // $ ast MISSING: ir
+ sink(out); // $ ast,ir
}
{
std::vector out;
auto it = std::back_inserter(out);
*++it = source();
- sink(out); // $ ast MISSING: ir
+ sink(out); // $ ast,ir
}
}
diff --git a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
index 28c1398d90b..d7b240c8949 100644
--- a/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
+++ b/cpp/ql/test/library-tests/ir/ir/PrintAST.expected
@@ -12159,8 +12159,12 @@ ir.cpp:
# 1109| Type = [IntType] int
# 1110| [Destructor] void std::vector::~vector()
# 1110| :
+# 1110| [Destructor] void std::vector::~vector()
+# 1110| :
# 1110| [Destructor] void std::vector::~vector()
# 1110| :
+# 1110| [Destructor] void std::vector::~vector()
+# 1110| :
# 1110| [Destructor] void std::vector::~vector()
# 1110| :
# 1115| [ConstMemberFunction] std::vector::iterator std::vector::begin() const
@@ -19307,181 +19311,195 @@ ir.cpp:
# 2193| getQualifier(): [ThisExpr] this
# 2193| Type = [PointerType] ClassWithDestructor *
# 2193| ValueCategory = prvalue(load)
-# 2196| [GlobalVariable] bool initialization_with_destructor_bool
-# 2196| getInitializer(): [Initializer] initializer for initialization_with_destructor_bool
-# 2196| getExpr(): [Literal] 1
-# 2196| Type = [BoolType] bool
-# 2196| Value = [Literal] 1
-# 2196| ValueCategory = prvalue
-# 2198| [TopLevelFunction] void initialization_with_destructor(bool, char)
-# 2198| :
-# 2198| getParameter(0): [Parameter] b
-# 2198| Type = [BoolType] bool
-# 2198| getParameter(1): [Parameter] c
-# 2198| Type = [PlainCharType] char
-# 2198| getEntryPoint(): [BlockStmt] { ... }
-# 2199| getStmt(0): [IfStmt] if (...) ...
-# 2199| getInitialization(): [DeclStmt] declaration
-# 2199| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2199| Type = [Class] ClassWithDestructor
-# 2199| getVariable().getInitializer(): [Initializer] initializer for x
-# 2199| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2199| Type = [VoidType] void
-# 2199| ValueCategory = prvalue
-# 2199| getCondition(): [VariableAccess] b
-# 2199| Type = [BoolType] bool
-# 2199| ValueCategory = prvalue(load)
-# 2200| getThen(): [ExprStmt] ExprStmt
-# 2200| getExpr(): [FunctionCall] call to set_x
-# 2200| Type = [VoidType] void
-# 2200| ValueCategory = prvalue
-# 2200| getQualifier(): [VariableAccess] x
-# 2200| Type = [Class] ClassWithDestructor
-# 2200| ValueCategory = lvalue
-# 2200| getArgument(0): [CharLiteral] 97
-# 2200| Type = [PlainCharType] char
-# 2200| Value = [CharLiteral] 97
-# 2200| ValueCategory = prvalue
-# 2200| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2200| Type = [VoidType] void
-# 2200| ValueCategory = prvalue
-# 2200| getQualifier(): [VariableAccess] x
+# 2194| [ConstMemberFunction,ConversionOperator] bool ClassWithDestructor::operator bool() const
+# 2194| :
+# 2197| [GlobalVariable] bool initialization_with_destructor_bool
+# 2197| getInitializer(): [Initializer] initializer for initialization_with_destructor_bool
+# 2197| getExpr(): [Literal] 1
+# 2197| Type = [BoolType] bool
+# 2197| Value = [Literal] 1
+# 2197| ValueCategory = prvalue
+# 2199| [TopLevelFunction] void initialization_with_destructor(bool, char)
+# 2199| :
+# 2199| getParameter(0): [Parameter] b
+# 2199| Type = [BoolType] bool
+# 2199| getParameter(1): [Parameter] c
+# 2199| Type = [PlainCharType] char
+# 2199| getEntryPoint(): [BlockStmt] { ... }
+# 2200| getStmt(0): [IfStmt] if (...) ...
+# 2200| getInitialization(): [DeclStmt] declaration
+# 2200| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2200| Type = [Class] ClassWithDestructor
-# 2200| ValueCategory = lvalue
-# 2202| getStmt(1): [ConstexprIfStmt] if constexpr (...) ...
-# 2202| getInitialization(): [DeclStmt] declaration
-# 2202| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2202| Type = [Class] ClassWithDestructor
-# 2202| getVariable().getInitializer(): [Initializer] initializer for x
-# 2202| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2202| Type = [VoidType] void
-# 2202| ValueCategory = prvalue
-# 2202| getCondition(): [VariableAccess] initialization_with_destructor_bool
-# 2202| Type = [BoolType] bool
-# 2202| Value = [VariableAccess] 1
-# 2202| ValueCategory = prvalue(load)
-# 2203| getThen(): [ExprStmt] ExprStmt
-# 2203| getExpr(): [FunctionCall] call to set_x
-# 2203| Type = [VoidType] void
-# 2203| ValueCategory = prvalue
-# 2203| getQualifier(): [VariableAccess] x
-# 2203| Type = [Class] ClassWithDestructor
-# 2203| ValueCategory = lvalue
-# 2203| getArgument(0): [CharLiteral] 97
-# 2203| Type = [PlainCharType] char
-# 2203| Value = [CharLiteral] 97
-# 2203| ValueCategory = prvalue
-# 2203| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2203| Type = [VoidType] void
-# 2203| ValueCategory = prvalue
-# 2203| getQualifier(): [VariableAccess] x
+# 2200| getVariable().getInitializer(): [Initializer] initializer for x
+# 2200| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2200| Type = [VoidType] void
+# 2200| ValueCategory = prvalue
+# 2200| getCondition(): [VariableAccess] b
+# 2200| Type = [BoolType] bool
+# 2200| ValueCategory = prvalue(load)
+# 2201| getThen(): [ExprStmt] ExprStmt
+# 2201| getExpr(): [FunctionCall] call to set_x
+# 2201| Type = [VoidType] void
+# 2201| ValueCategory = prvalue
+# 2201| getQualifier(): [VariableAccess] x
+# 2201| Type = [Class] ClassWithDestructor
+# 2201| ValueCategory = lvalue
+# 2201| getArgument(0): [CharLiteral] 97
+# 2201| Type = [PlainCharType] char
+# 2201| Value = [CharLiteral] 97
+# 2201| ValueCategory = prvalue
+# 2201| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2201| Type = [VoidType] void
+# 2201| ValueCategory = prvalue
+# 2201| getQualifier(): [VariableAccess] x
+# 2201| Type = [Class] ClassWithDestructor
+# 2201| ValueCategory = lvalue
+# 2203| getStmt(1): [ConstexprIfStmt] if constexpr (...) ...
+# 2203| getInitialization(): [DeclStmt] declaration
+# 2203| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2203| Type = [Class] ClassWithDestructor
-# 2203| ValueCategory = lvalue
-# 2205| getStmt(2): [SwitchStmt] switch (...) ...
-# 2205| getInitialization(): [DeclStmt] declaration
-# 2205| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2205| Type = [Class] ClassWithDestructor
-# 2205| getVariable().getInitializer(): [Initializer] initializer for x
-# 2205| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2205| Type = [VoidType] void
-# 2205| ValueCategory = prvalue
-# 2205| getExpr(): [VariableAccess] c
-# 2205| Type = [PlainCharType] char
-# 2205| ValueCategory = prvalue(load)
-# 2205| getStmt(): [BlockStmt] { ... }
-# 2206| getStmt(0): [SwitchCase] case ...:
-# 2206| getExpr(): [CharLiteral] 97
-# 2206| Type = [PlainCharType] char
-# 2206| Value = [CharLiteral] 97
-# 2206| ValueCategory = prvalue
-# 2206| getExpr().getFullyConverted(): [CStyleCast] (int)...
-# 2206| Conversion = [IntegralConversion] integral conversion
-# 2206| Type = [IntType] int
-# 2206| Value = [CStyleCast] 97
-# 2206| ValueCategory = prvalue
-# 2207| getStmt(1): [ExprStmt] ExprStmt
-# 2207| getExpr(): [FunctionCall] call to set_x
-# 2207| Type = [VoidType] void
+# 2203| getVariable().getInitializer(): [Initializer] initializer for x
+# 2203| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2203| Type = [VoidType] void
+# 2203| ValueCategory = prvalue
+# 2203| getCondition(): [VariableAccess] initialization_with_destructor_bool
+# 2203| Type = [BoolType] bool
+# 2203| Value = [VariableAccess] 1
+# 2203| ValueCategory = prvalue(load)
+# 2204| getThen(): [ExprStmt] ExprStmt
+# 2204| getExpr(): [FunctionCall] call to set_x
+# 2204| Type = [VoidType] void
+# 2204| ValueCategory = prvalue
+# 2204| getQualifier(): [VariableAccess] x
+# 2204| Type = [Class] ClassWithDestructor
+# 2204| ValueCategory = lvalue
+# 2204| getArgument(0): [CharLiteral] 97
+# 2204| Type = [PlainCharType] char
+# 2204| Value = [CharLiteral] 97
+# 2204| ValueCategory = prvalue
+# 2204| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2204| Type = [VoidType] void
+# 2204| ValueCategory = prvalue
+# 2204| getQualifier(): [VariableAccess] x
+# 2204| Type = [Class] ClassWithDestructor
+# 2204| ValueCategory = lvalue
+# 2206| getStmt(2): [SwitchStmt] switch (...) ...
+# 2206| getInitialization(): [DeclStmt] declaration
+# 2206| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
+# 2206| Type = [Class] ClassWithDestructor
+# 2206| getVariable().getInitializer(): [Initializer] initializer for x
+# 2206| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2206| Type = [VoidType] void
+# 2206| ValueCategory = prvalue
+# 2206| getExpr(): [VariableAccess] c
+# 2206| Type = [PlainCharType] char
+# 2206| ValueCategory = prvalue(load)
+# 2206| getStmt(): [BlockStmt] { ... }
+# 2207| getStmt(0): [SwitchCase] case ...:
+# 2207| getExpr(): [CharLiteral] 97
+# 2207| Type = [PlainCharType] char
+# 2207| Value = [CharLiteral] 97
# 2207| ValueCategory = prvalue
-# 2207| getQualifier(): [VariableAccess] x
-# 2207| Type = [Class] ClassWithDestructor
-# 2207| ValueCategory = lvalue
-# 2207| getArgument(0): [CharLiteral] 97
-# 2207| Type = [PlainCharType] char
-# 2207| Value = [CharLiteral] 97
-# 2207| ValueCategory = prvalue
-# 2208| getStmt(2): [BreakStmt] break;
-# 2209| getStmt(3): [SwitchCase] default:
-# 2210| getStmt(4): [ExprStmt] ExprStmt
-# 2210| getExpr(): [FunctionCall] call to set_x
-# 2210| Type = [VoidType] void
-# 2210| ValueCategory = prvalue
-# 2210| getQualifier(): [VariableAccess] x
-# 2210| Type = [Class] ClassWithDestructor
-# 2210| ValueCategory = lvalue
-# 2210| getArgument(0): [CharLiteral] 98
-# 2210| Type = [PlainCharType] char
-# 2210| Value = [CharLiteral] 98
-# 2210| ValueCategory = prvalue
-# 2211| getStmt(5): [BreakStmt] break;
-# 2212| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2212| Type = [VoidType] void
-# 2212| ValueCategory = prvalue
-# 2212| getQualifier(): [VariableAccess] x
-# 2212| Type = [Class] ClassWithDestructor
-# 2212| ValueCategory = lvalue
-# 2205| getExpr().getFullyConverted(): [CStyleCast] (int)...
-# 2205| Conversion = [IntegralConversion] integral conversion
-# 2205| Type = [IntType] int
-# 2205| ValueCategory = prvalue
-# 2212| getStmt(3): [LabelStmt] label ...:
-# 2214| getStmt(4): [DeclStmt] declaration
-# 2214| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2214| Type = [Class] ClassWithDestructor
-# 2214| getVariable().getInitializer(): [Initializer] initializer for x
-# 2214| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2214| Type = [VoidType] void
-# 2214| ValueCategory = prvalue
-# 2215| getStmt(5): [RangeBasedForStmt] for(...:...) ...
-# 2215| getInitialization(): [DeclStmt] declaration
-# 2215| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
-# 2215| Type = [ClassTemplateInstantiation,Struct] vector
-# 2215| getVariable().getInitializer(): [Initializer] initializer for ys
-# 2215| getExpr(): [ConstructorCall] call to vector
-# 2215| Type = [VoidType] void
-# 2215| ValueCategory = prvalue
-# 2215| getArgument(0): [VariableAccess] x
-# 2215| Type = [Class] ClassWithDestructor
-# 2215| ValueCategory = prvalue(load)
-# 2215| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2215| Type = [VoidType] void
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2215| Type = [Class] ClassWithDestructor
-# 2215| ValueCategory = xvalue
-# 2215| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2215| Type = [Class] ClassWithDestructor
-# 2215| ValueCategory = lvalue
-# 2215| getChild(1): [DeclStmt] declaration
-# 2215| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
-# 2215| Type = [LValueReferenceType] vector &
+# 2207| getExpr().getFullyConverted(): [CStyleCast] (int)...
+# 2207| Conversion = [IntegralConversion] integral conversion
+# 2207| Type = [IntType] int
+# 2207| Value = [CStyleCast] 97
+# 2207| ValueCategory = prvalue
+# 2208| getStmt(1): [ExprStmt] ExprStmt
+# 2208| getExpr(): [FunctionCall] call to set_x
+# 2208| Type = [VoidType] void
+# 2208| ValueCategory = prvalue
+# 2208| getQualifier(): [VariableAccess] x
+# 2208| Type = [Class] ClassWithDestructor
+# 2208| ValueCategory = lvalue
+# 2208| getArgument(0): [CharLiteral] 97
+# 2208| Type = [PlainCharType] char
+# 2208| Value = [CharLiteral] 97
+# 2208| ValueCategory = prvalue
+# 2209| getStmt(2): [BreakStmt] break;
+# 2213| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2213| Type = [VoidType] void
+# 2213| ValueCategory = prvalue
+# 2213| getQualifier(): [VariableAccess] x
+# 2213| Type = [Class] ClassWithDestructor
+# 2213| ValueCategory = lvalue
+# 2210| getStmt(3): [SwitchCase] default:
+# 2211| getStmt(4): [ExprStmt] ExprStmt
+# 2211| getExpr(): [FunctionCall] call to set_x
+# 2211| Type = [VoidType] void
+# 2211| ValueCategory = prvalue
+# 2211| getQualifier(): [VariableAccess] x
+# 2211| Type = [Class] ClassWithDestructor
+# 2211| ValueCategory = lvalue
+# 2211| getArgument(0): [CharLiteral] 98
+# 2211| Type = [PlainCharType] char
+# 2211| Value = [CharLiteral] 98
+# 2211| ValueCategory = prvalue
+# 2212| getStmt(5): [BreakStmt] break;
+# 2213| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2213| Type = [VoidType] void
+# 2213| ValueCategory = prvalue
+# 2213| getQualifier(): [VariableAccess] x
+# 2213| Type = [Class] ClassWithDestructor
+# 2213| ValueCategory = lvalue
+# 2213| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2213| Type = [VoidType] void
+# 2213| ValueCategory = prvalue
+# 2213| getQualifier(): [VariableAccess] x
+# 2213| Type = [Class] ClassWithDestructor
+# 2213| ValueCategory = lvalue
+# 2206| getExpr().getFullyConverted(): [CStyleCast] (int)...
+# 2206| Conversion = [IntegralConversion] integral conversion
+# 2206| Type = [IntType] int
+# 2206| ValueCategory = prvalue
+# 2213| getStmt(3): [LabelStmt] label ...:
+# 2215| getStmt(4): [DeclStmt] declaration
+# 2215| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
+# 2215| Type = [Class] ClassWithDestructor
+# 2215| getVariable().getInitializer(): [Initializer] initializer for x
+# 2215| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2215| Type = [VoidType] void
+# 2215| ValueCategory = prvalue
+# 2216| getStmt(5): [RangeBasedForStmt] for(...:...) ...
+# 2216| getInitialization(): [DeclStmt] declaration
+# 2216| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
+# 2216| Type = [ClassTemplateInstantiation,Struct] vector
+# 2216| getVariable().getInitializer(): [Initializer] initializer for ys
+# 2216| getExpr(): [ConstructorCall] call to vector
+# 2216| Type = [VoidType] void
+# 2216| ValueCategory = prvalue
+# 2216| getArgument(0): [VariableAccess] x
+# 2216| Type = [Class] ClassWithDestructor
+# 2216| ValueCategory = prvalue(load)
+# 2216| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2216| Type = [VoidType] void
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2216| Type = [Class] ClassWithDestructor
+# 2216| ValueCategory = xvalue
+# 2216| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2216| Type = [Class] ClassWithDestructor
+# 2216| ValueCategory = lvalue
+# 2216| getChild(1): [DeclStmt] declaration
+# 2216| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
+# 2216| Type = [LValueReferenceType] vector &
#-----| getVariable().getInitializer(): [Initializer] initializer for (__range)
-# 2215| getExpr(): [VariableAccess] ys
-# 2215| Type = [ClassTemplateInstantiation,Struct] vector
-# 2215| ValueCategory = lvalue
-# 2215| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2215| Type = [LValueReferenceType] vector &
-# 2215| ValueCategory = prvalue
-# 2215| getBeginEndDeclaration(): [DeclStmt] declaration
-# 2215| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| getExpr(): [VariableAccess] ys
+# 2216| Type = [ClassTemplateInstantiation,Struct] vector
+# 2216| ValueCategory = lvalue
+# 2216| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2216| Type = [LValueReferenceType] vector &
+# 2216| ValueCategory = prvalue
+# 2216| getBeginEndDeclaration(): [DeclStmt] declaration
+# 2216| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__begin)
-# 2215| getExpr(): [FunctionCall] call to begin
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] (__range)
-# 2215| Type = [LValueReferenceType] vector &
-# 2215| ValueCategory = prvalue(load)
+# 2216| getExpr(): [FunctionCall] call to begin
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [VariableAccess] (__range)
+# 2216| Type = [LValueReferenceType] vector &
+# 2216| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19489,15 +19507,15 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2215| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__end)
-# 2215| getExpr(): [FunctionCall] call to end
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] (__range)
-# 2215| Type = [LValueReferenceType] vector &
-# 2215| ValueCategory = prvalue(load)
+# 2216| getExpr(): [FunctionCall] call to end
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [VariableAccess] (__range)
+# 2216| Type = [LValueReferenceType] vector &
+# 2216| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19505,18 +19523,18 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2215| getCondition(): [FunctionCall] call to operator!=
-# 2215| Type = [BoolType] bool
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] (__begin)
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2215| ValueCategory = lvalue
-# 2215| getArgument(0): [ConstructorCall] call to iterator
-# 2215| Type = [VoidType] void
-# 2215| ValueCategory = prvalue
-# 2215| getArgument(0): [VariableAccess] (__end)
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2215| ValueCategory = lvalue
+# 2216| getCondition(): [FunctionCall] call to operator!=
+# 2216| Type = [BoolType] bool
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [VariableAccess] (__begin)
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| ValueCategory = lvalue
+# 2216| getArgument(0): [ConstructorCall] call to iterator
+# 2216| Type = [VoidType] void
+# 2216| ValueCategory = prvalue
+# 2216| getArgument(0): [VariableAccess] (__end)
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| ValueCategory = lvalue
#-----| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] const iterator &
#-----| ValueCategory = prvalue
@@ -19531,95 +19549,95 @@ ir.cpp:
#-----| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [ClassTemplateInstantiation,Struct] iterator
#-----| ValueCategory = lvalue
-# 2215| getUpdate(): [FunctionCall] call to operator++
-# 2215| Type = [LValueReferenceType] iterator &
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] (__begin)
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2215| ValueCategory = lvalue
-# 2215| getChild(5): [DeclStmt] declaration
-# 2215| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
-# 2215| Type = [Class] ClassWithDestructor
-# 2215| getVariable().getInitializer(): [Initializer] initializer for y
-# 2215| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
-# 2215| Type = [LValueReferenceType] ClassWithDestructor &
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] (__begin)
-# 2215| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2215| ValueCategory = lvalue
+# 2216| getUpdate(): [FunctionCall] call to operator++
+# 2216| Type = [LValueReferenceType] iterator &
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [VariableAccess] (__begin)
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| ValueCategory = lvalue
+# 2216| getChild(5): [DeclStmt] declaration
+# 2216| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
+# 2216| Type = [Class] ClassWithDestructor
+# 2216| getVariable().getInitializer(): [Initializer] initializer for y
+# 2216| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
+# 2216| Type = [LValueReferenceType] ClassWithDestructor &
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [VariableAccess] (__begin)
+# 2216| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2216| ValueCategory = lvalue
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const iterator)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const iterator
#-----| ValueCategory = lvalue
-# 2215| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2215| Type = [Class] ClassWithDestructor
-# 2215| ValueCategory = prvalue(load)
-# 2216| getStmt(): [ExprStmt] ExprStmt
-# 2216| getExpr(): [FunctionCall] call to set_x
+# 2216| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2216| Type = [Class] ClassWithDestructor
+# 2216| ValueCategory = prvalue(load)
+# 2217| getStmt(): [ExprStmt] ExprStmt
+# 2217| getExpr(): [FunctionCall] call to set_x
+# 2217| Type = [VoidType] void
+# 2217| ValueCategory = prvalue
+# 2217| getQualifier(): [VariableAccess] y
+# 2217| Type = [Class] ClassWithDestructor
+# 2217| ValueCategory = lvalue
+# 2217| getArgument(0): [CharLiteral] 97
+# 2217| Type = [PlainCharType] char
+# 2217| Value = [CharLiteral] 97
+# 2217| ValueCategory = prvalue
+# 2216| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
+# 2216| Type = [VoidType] void
+# 2216| ValueCategory = prvalue
+# 2216| getQualifier(): [VariableAccess] ys
+# 2216| Type = [ClassTemplateInstantiation,Struct] vector
+# 2216| ValueCategory = lvalue
+# 2216| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2216| Type = [ClassTemplateInstantiation,Struct] iterator
+# 2216| ValueCategory = lvalue
+# 2216| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
# 2216| Type = [VoidType] void
# 2216| ValueCategory = prvalue
# 2216| getQualifier(): [VariableAccess] y
# 2216| Type = [Class] ClassWithDestructor
# 2216| ValueCategory = lvalue
-# 2216| getArgument(0): [CharLiteral] 97
-# 2216| Type = [PlainCharType] char
-# 2216| Value = [CharLiteral] 97
-# 2216| ValueCategory = prvalue
-# 2215| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
-# 2215| Type = [VoidType] void
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] ys
-# 2215| Type = [ClassTemplateInstantiation,Struct] vector
-# 2215| ValueCategory = lvalue
-# 2215| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2215| Type = [ClassTemplateInstantiation,Struct] iterator
-# 2215| ValueCategory = lvalue
-# 2215| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2215| Type = [VoidType] void
-# 2215| ValueCategory = prvalue
-# 2215| getQualifier(): [VariableAccess] y
-# 2215| Type = [Class] ClassWithDestructor
-# 2215| ValueCategory = lvalue
-# 2218| getStmt(6): [RangeBasedForStmt] for(...:...) ...
-# 2218| getInitialization(): [DeclStmt] declaration
-# 2218| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
-# 2218| Type = [ClassTemplateInstantiation,Struct] vector
-# 2218| getVariable().getInitializer(): [Initializer] initializer for ys
-# 2218| getExpr(): [ConstructorCall] call to vector
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getArgument(0): [VariableAccess] x
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| ValueCategory = prvalue(load)
-# 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| ValueCategory = xvalue
-# 2218| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| ValueCategory = lvalue
-# 2218| getChild(1): [DeclStmt] declaration
-# 2218| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
-# 2218| Type = [LValueReferenceType] vector &
+# 2219| getStmt(6): [RangeBasedForStmt] for(...:...) ...
+# 2219| getInitialization(): [DeclStmt] declaration
+# 2219| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
+# 2219| Type = [ClassTemplateInstantiation,Struct] vector
+# 2219| getVariable().getInitializer(): [Initializer] initializer for ys
+# 2219| getExpr(): [ConstructorCall] call to vector
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getArgument(0): [VariableAccess] x
+# 2219| Type = [Class] ClassWithDestructor
+# 2219| ValueCategory = prvalue(load)
+# 2219| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2219| Type = [Class] ClassWithDestructor
+# 2219| ValueCategory = xvalue
+# 2219| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2219| Type = [Class] ClassWithDestructor
+# 2219| ValueCategory = lvalue
+# 2219| getChild(1): [DeclStmt] declaration
+# 2219| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
+# 2219| Type = [LValueReferenceType] vector &
#-----| getVariable().getInitializer(): [Initializer] initializer for (__range)
-# 2218| getExpr(): [VariableAccess] ys
-# 2218| Type = [ClassTemplateInstantiation,Struct] vector
-# 2218| ValueCategory = lvalue
-# 2218| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2218| Type = [LValueReferenceType] vector &
-# 2218| ValueCategory = prvalue
-# 2218| getBeginEndDeclaration(): [DeclStmt] declaration
-# 2218| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| getExpr(): [VariableAccess] ys
+# 2219| Type = [ClassTemplateInstantiation,Struct] vector
+# 2219| ValueCategory = lvalue
+# 2219| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2219| Type = [LValueReferenceType] vector &
+# 2219| ValueCategory = prvalue
+# 2219| getBeginEndDeclaration(): [DeclStmt] declaration
+# 2219| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__begin)
-# 2218| getExpr(): [FunctionCall] call to begin
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] (__range)
-# 2218| Type = [LValueReferenceType] vector &
-# 2218| ValueCategory = prvalue(load)
+# 2219| getExpr(): [FunctionCall] call to begin
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] (__range)
+# 2219| Type = [LValueReferenceType] vector &
+# 2219| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19627,15 +19645,15 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2218| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__end)
-# 2218| getExpr(): [FunctionCall] call to end
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] (__range)
-# 2218| Type = [LValueReferenceType] vector &
-# 2218| ValueCategory = prvalue(load)
+# 2219| getExpr(): [FunctionCall] call to end
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] (__range)
+# 2219| Type = [LValueReferenceType] vector &
+# 2219| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19643,18 +19661,18 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2218| getCondition(): [FunctionCall] call to operator!=
-# 2218| Type = [BoolType] bool
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] (__begin)
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2218| ValueCategory = lvalue
-# 2218| getArgument(0): [ConstructorCall] call to iterator
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getArgument(0): [VariableAccess] (__end)
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2218| ValueCategory = lvalue
+# 2219| getCondition(): [FunctionCall] call to operator!=
+# 2219| Type = [BoolType] bool
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] (__begin)
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| ValueCategory = lvalue
+# 2219| getArgument(0): [ConstructorCall] call to iterator
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getArgument(0): [VariableAccess] (__end)
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| ValueCategory = lvalue
#-----| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] const iterator &
#-----| ValueCategory = prvalue
@@ -19669,130 +19687,130 @@ ir.cpp:
#-----| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [ClassTemplateInstantiation,Struct] iterator
#-----| ValueCategory = lvalue
-# 2218| getUpdate(): [FunctionCall] call to operator++
-# 2218| Type = [LValueReferenceType] iterator &
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] (__begin)
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2218| ValueCategory = lvalue
-# 2218| getChild(5): [DeclStmt] declaration
-# 2218| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| getVariable().getInitializer(): [Initializer] initializer for y
-# 2218| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
-# 2218| Type = [LValueReferenceType] ClassWithDestructor &
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] (__begin)
-# 2218| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2218| ValueCategory = lvalue
+# 2219| getUpdate(): [FunctionCall] call to operator++
+# 2219| Type = [LValueReferenceType] iterator &
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] (__begin)
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| ValueCategory = lvalue
+# 2219| getChild(5): [DeclStmt] declaration
+# 2219| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
+# 2219| Type = [Class] ClassWithDestructor
+# 2219| getVariable().getInitializer(): [Initializer] initializer for y
+# 2219| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
+# 2219| Type = [LValueReferenceType] ClassWithDestructor &
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] (__begin)
+# 2219| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2219| ValueCategory = lvalue
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const iterator)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const iterator
#-----| ValueCategory = lvalue
-# 2218| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| ValueCategory = prvalue(load)
-# 2218| getStmt(): [BlockStmt] { ... }
-# 2219| getStmt(0): [ExprStmt] ExprStmt
-# 2219| getExpr(): [FunctionCall] call to set_x
-# 2219| Type = [VoidType] void
-# 2219| ValueCategory = prvalue
-# 2219| getQualifier(): [VariableAccess] y
+# 2219| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 2219| Type = [Class] ClassWithDestructor
-# 2219| ValueCategory = lvalue
-# 2219| getArgument(0): [CharLiteral] 97
-# 2219| Type = [PlainCharType] char
-# 2219| Value = [CharLiteral] 97
-# 2219| ValueCategory = prvalue
-# 2220| getStmt(1): [IfStmt] if (...) ...
-# 2220| getCondition(): [EQExpr] ... == ...
-# 2220| Type = [BoolType] bool
+# 2219| ValueCategory = prvalue(load)
+# 2219| getStmt(): [BlockStmt] { ... }
+# 2220| getStmt(0): [ExprStmt] ExprStmt
+# 2220| getExpr(): [FunctionCall] call to set_x
+# 2220| Type = [VoidType] void
# 2220| ValueCategory = prvalue
-# 2220| getLeftOperand(): [FunctionCall] call to get_x
+# 2220| getQualifier(): [VariableAccess] y
+# 2220| Type = [Class] ClassWithDestructor
+# 2220| ValueCategory = lvalue
+# 2220| getArgument(0): [CharLiteral] 97
# 2220| Type = [PlainCharType] char
+# 2220| Value = [CharLiteral] 97
# 2220| ValueCategory = prvalue
-# 2220| getQualifier(): [VariableAccess] y
-# 2220| Type = [Class] ClassWithDestructor
-# 2220| ValueCategory = lvalue
-# 2220| getRightOperand(): [CharLiteral] 98
-# 2220| Type = [PlainCharType] char
-# 2220| Value = [CharLiteral] 98
-# 2220| ValueCategory = prvalue
-# 2220| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
-# 2220| Conversion = [IntegralConversion] integral conversion
-# 2220| Type = [IntType] int
-# 2220| ValueCategory = prvalue
-# 2220| getRightOperand().getFullyConverted(): [CStyleCast] (int)...
-# 2220| Conversion = [IntegralConversion] integral conversion
-# 2220| Type = [IntType] int
-# 2220| Value = [CStyleCast] 98
-# 2220| ValueCategory = prvalue
-# 2221| getThen(): [ReturnStmt] return ...
-# 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] y
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| ValueCategory = lvalue
-# 2218| getImplicitDestructorCall(1): [DestructorCall] call to ~vector
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] ys
-# 2218| Type = [ClassTemplateInstantiation,Struct] vector
-# 2218| ValueCategory = lvalue
-# 2233| getImplicitDestructorCall(2): [DestructorCall] call to ~ClassWithDestructor
-# 2233| Type = [VoidType] void
-# 2233| ValueCategory = prvalue
-# 2233| getQualifier(): [VariableAccess] x
-# 2233| Type = [Class] ClassWithDestructor
-# 2233| ValueCategory = lvalue
-# 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] ys
-# 2218| Type = [ClassTemplateInstantiation,Struct] vector
-# 2218| ValueCategory = lvalue
-# 2218| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2218| Type = [ClassTemplateInstantiation,Struct] iterator
-# 2218| ValueCategory = lvalue
-# 2218| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2218| Type = [VoidType] void
-# 2218| ValueCategory = prvalue
-# 2218| getQualifier(): [VariableAccess] y
-# 2218| Type = [Class] ClassWithDestructor
-# 2218| ValueCategory = lvalue
-# 2224| getStmt(7): [RangeBasedForStmt] for(...:...) ...
-# 2224| getInitialization(): [DeclStmt] declaration
-# 2224| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
-# 2224| Type = [ClassTemplateInstantiation,Struct] vector
-# 2224| getVariable().getInitializer(): [Initializer] initializer for ys
-# 2224| getExpr(): [ConstructorCall] call to vector
-# 2224| Type = [VoidType] void
-# 2224| ValueCategory = prvalue
-# 2224| getArgument(0): [Literal] 1
-# 2224| Type = [IntType] int
-# 2224| Value = [Literal] 1
-# 2224| ValueCategory = prvalue
-# 2224| getChild(1): [DeclStmt] declaration
-# 2224| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
-# 2224| Type = [LValueReferenceType] vector &
+# 2221| getStmt(1): [IfStmt] if (...) ...
+# 2221| getCondition(): [EQExpr] ... == ...
+# 2221| Type = [BoolType] bool
+# 2221| ValueCategory = prvalue
+# 2221| getLeftOperand(): [FunctionCall] call to get_x
+# 2221| Type = [PlainCharType] char
+# 2221| ValueCategory = prvalue
+# 2221| getQualifier(): [VariableAccess] y
+# 2221| Type = [Class] ClassWithDestructor
+# 2221| ValueCategory = lvalue
+# 2221| getRightOperand(): [CharLiteral] 98
+# 2221| Type = [PlainCharType] char
+# 2221| Value = [CharLiteral] 98
+# 2221| ValueCategory = prvalue
+# 2221| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
+# 2221| Conversion = [IntegralConversion] integral conversion
+# 2221| Type = [IntType] int
+# 2221| ValueCategory = prvalue
+# 2221| getRightOperand().getFullyConverted(): [CStyleCast] (int)...
+# 2221| Conversion = [IntegralConversion] integral conversion
+# 2221| Type = [IntType] int
+# 2221| Value = [CStyleCast] 98
+# 2221| ValueCategory = prvalue
+# 2222| getThen(): [ReturnStmt] return ...
+# 2219| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] y
+# 2219| Type = [Class] ClassWithDestructor
+# 2219| ValueCategory = lvalue
+# 2219| getImplicitDestructorCall(1): [DestructorCall] call to ~vector
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] ys
+# 2219| Type = [ClassTemplateInstantiation,Struct] vector
+# 2219| ValueCategory = lvalue
+# 2234| getImplicitDestructorCall(2): [DestructorCall] call to ~ClassWithDestructor
+# 2234| Type = [VoidType] void
+# 2234| ValueCategory = prvalue
+# 2234| getQualifier(): [VariableAccess] x
+# 2234| Type = [Class] ClassWithDestructor
+# 2234| ValueCategory = lvalue
+# 2219| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] ys
+# 2219| Type = [ClassTemplateInstantiation,Struct] vector
+# 2219| ValueCategory = lvalue
+# 2219| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2219| Type = [ClassTemplateInstantiation,Struct] iterator
+# 2219| ValueCategory = lvalue
+# 2219| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2219| Type = [VoidType] void
+# 2219| ValueCategory = prvalue
+# 2219| getQualifier(): [VariableAccess] y
+# 2219| Type = [Class] ClassWithDestructor
+# 2219| ValueCategory = lvalue
+# 2225| getStmt(7): [RangeBasedForStmt] for(...:...) ...
+# 2225| getInitialization(): [DeclStmt] declaration
+# 2225| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
+# 2225| Type = [ClassTemplateInstantiation,Struct] vector
+# 2225| getVariable().getInitializer(): [Initializer] initializer for ys
+# 2225| getExpr(): [ConstructorCall] call to vector
+# 2225| Type = [VoidType] void
+# 2225| ValueCategory = prvalue
+# 2225| getArgument(0): [Literal] 1
+# 2225| Type = [IntType] int
+# 2225| Value = [Literal] 1
+# 2225| ValueCategory = prvalue
+# 2225| getChild(1): [DeclStmt] declaration
+# 2225| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
+# 2225| Type = [LValueReferenceType] vector &
#-----| getVariable().getInitializer(): [Initializer] initializer for (__range)
-# 2224| getExpr(): [VariableAccess] ys
-# 2224| Type = [ClassTemplateInstantiation,Struct] vector
-# 2224| ValueCategory = lvalue
-# 2224| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2224| Type = [LValueReferenceType] vector &
-# 2224| ValueCategory = prvalue
-# 2224| getBeginEndDeclaration(): [DeclStmt] declaration
-# 2224| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| getExpr(): [VariableAccess] ys
+# 2225| Type = [ClassTemplateInstantiation,Struct] vector
+# 2225| ValueCategory = lvalue
+# 2225| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2225| Type = [LValueReferenceType] vector &
+# 2225| ValueCategory = prvalue
+# 2225| getBeginEndDeclaration(): [DeclStmt] declaration
+# 2225| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__begin)
-# 2224| getExpr(): [FunctionCall] call to begin
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] (__range)
-# 2224| Type = [LValueReferenceType] vector &
-# 2224| ValueCategory = prvalue(load)
+# 2225| getExpr(): [FunctionCall] call to begin
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| ValueCategory = prvalue
+# 2225| getQualifier(): [VariableAccess] (__range)
+# 2225| Type = [LValueReferenceType] vector &
+# 2225| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19800,15 +19818,15 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2224| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__end)
-# 2224| getExpr(): [FunctionCall] call to end
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] (__range)
-# 2224| Type = [LValueReferenceType] vector &
-# 2224| ValueCategory = prvalue(load)
+# 2225| getExpr(): [FunctionCall] call to end
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| ValueCategory = prvalue
+# 2225| getQualifier(): [VariableAccess] (__range)
+# 2225| Type = [LValueReferenceType] vector &
+# 2225| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19816,18 +19834,18 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2224| getCondition(): [FunctionCall] call to operator!=
-# 2224| Type = [BoolType] bool
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] (__begin)
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2224| ValueCategory = lvalue
-# 2224| getArgument(0): [ConstructorCall] call to iterator
-# 2224| Type = [VoidType] void
-# 2224| ValueCategory = prvalue
-# 2224| getArgument(0): [VariableAccess] (__end)
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2224| ValueCategory = lvalue
+# 2225| getCondition(): [FunctionCall] call to operator!=
+# 2225| Type = [BoolType] bool
+# 2225| ValueCategory = prvalue
+# 2225| getQualifier(): [VariableAccess] (__begin)
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| ValueCategory = lvalue
+# 2225| getArgument(0): [ConstructorCall] call to iterator
+# 2225| Type = [VoidType] void
+# 2225| ValueCategory = prvalue
+# 2225| getArgument(0): [VariableAccess] (__end)
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| ValueCategory = lvalue
#-----| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] const iterator &
#-----| ValueCategory = prvalue
@@ -19842,103 +19860,103 @@ ir.cpp:
#-----| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [ClassTemplateInstantiation,Struct] iterator
#-----| ValueCategory = lvalue
-# 2224| getUpdate(): [FunctionCall] call to operator++
-# 2224| Type = [LValueReferenceType] iterator &
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] (__begin)
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2224| ValueCategory = lvalue
-# 2224| getChild(5): [DeclStmt] declaration
-# 2224| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
-# 2224| Type = [IntType] int
-# 2224| getVariable().getInitializer(): [Initializer] initializer for y
-# 2224| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
-# 2224| Type = [LValueReferenceType] int &
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] (__begin)
-# 2224| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2224| ValueCategory = lvalue
+# 2225| getUpdate(): [FunctionCall] call to operator++
+# 2225| Type = [LValueReferenceType] iterator &
+# 2225| ValueCategory = prvalue
+# 2225| getQualifier(): [VariableAccess] (__begin)
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| ValueCategory = lvalue
+# 2225| getChild(5): [DeclStmt] declaration
+# 2225| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
+# 2225| Type = [IntType] int
+# 2225| getVariable().getInitializer(): [Initializer] initializer for y
+# 2225| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
+# 2225| Type = [LValueReferenceType] int &
+# 2225| ValueCategory = prvalue
+# 2225| getQualifier(): [VariableAccess] (__begin)
+# 2225| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2225| ValueCategory = lvalue
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const iterator)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const iterator
#-----| ValueCategory = lvalue
-# 2224| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2224| Type = [IntType] int
-# 2224| ValueCategory = prvalue(load)
-# 2224| getStmt(): [BlockStmt] { ... }
-# 2225| getStmt(0): [IfStmt] if (...) ...
-# 2225| getCondition(): [EQExpr] ... == ...
-# 2225| Type = [BoolType] bool
-# 2225| ValueCategory = prvalue
-# 2225| getLeftOperand(): [VariableAccess] y
+# 2225| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 2225| Type = [IntType] int
# 2225| ValueCategory = prvalue(load)
-# 2225| getRightOperand(): [Literal] 1
-# 2225| Type = [IntType] int
-# 2225| Value = [Literal] 1
+# 2225| getStmt(): [BlockStmt] { ... }
+# 2226| getStmt(0): [IfStmt] if (...) ...
+# 2226| getCondition(): [EQExpr] ... == ...
+# 2226| Type = [BoolType] bool
+# 2226| ValueCategory = prvalue
+# 2226| getLeftOperand(): [VariableAccess] y
+# 2226| Type = [IntType] int
+# 2226| ValueCategory = prvalue(load)
+# 2226| getRightOperand(): [Literal] 1
+# 2226| Type = [IntType] int
+# 2226| Value = [Literal] 1
+# 2226| ValueCategory = prvalue
+# 2227| getThen(): [ReturnStmt] return ...
+# 2225| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
+# 2225| Type = [VoidType] void
# 2225| ValueCategory = prvalue
-# 2226| getThen(): [ReturnStmt] return ...
-# 2224| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
-# 2224| Type = [VoidType] void
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] ys
-# 2224| Type = [ClassTemplateInstantiation,Struct] vector
-# 2224| ValueCategory = lvalue
-# 2233| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor
-# 2233| Type = [VoidType] void
-# 2233| ValueCategory = prvalue
-# 2233| getQualifier(): [VariableAccess] x
-# 2233| Type = [Class] ClassWithDestructor
-# 2233| ValueCategory = lvalue
-# 2224| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
-# 2224| Type = [VoidType] void
-# 2224| ValueCategory = prvalue
-# 2224| getQualifier(): [VariableAccess] ys
-# 2224| Type = [ClassTemplateInstantiation,Struct] vector
-# 2224| ValueCategory = lvalue
-# 2224| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2224| Type = [ClassTemplateInstantiation,Struct] iterator
-# 2224| ValueCategory = lvalue
-# 2229| getStmt(8): [RangeBasedForStmt] for(...:...) ...
-# 2229| getInitialization(): [DeclStmt] declaration
-# 2229| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
-# 2229| Type = [ClassTemplateInstantiation,Struct] vector
-# 2229| getVariable().getInitializer(): [Initializer] initializer for ys
-# 2229| getExpr(): [ConstructorCall] call to vector
-# 2229| Type = [VoidType] void
-# 2229| ValueCategory = prvalue
-# 2229| getArgument(0): [VariableAccess] x
-# 2229| Type = [Class] ClassWithDestructor
-# 2229| ValueCategory = prvalue(load)
-# 2229| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2229| Type = [VoidType] void
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2229| Type = [Class] ClassWithDestructor
-# 2229| ValueCategory = xvalue
-# 2229| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2229| Type = [Class] ClassWithDestructor
-# 2229| ValueCategory = lvalue
-# 2229| getChild(1): [DeclStmt] declaration
-# 2229| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
-# 2229| Type = [LValueReferenceType] vector &
+# 2225| getQualifier(): [VariableAccess] ys
+# 2225| Type = [ClassTemplateInstantiation,Struct] vector
+# 2225| ValueCategory = lvalue
+# 2234| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor
+# 2234| Type = [VoidType] void
+# 2234| ValueCategory = prvalue
+# 2234| getQualifier(): [VariableAccess] x
+# 2234| Type = [Class] ClassWithDestructor
+# 2234| ValueCategory = lvalue
+# 2225| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
+# 2225| Type = [VoidType] void
+# 2225| ValueCategory = prvalue
+# 2225| getQualifier(): [VariableAccess] ys
+# 2225| Type = [ClassTemplateInstantiation,Struct] vector
+# 2225| ValueCategory = lvalue
+# 2225| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2225| Type = [ClassTemplateInstantiation,Struct] iterator
+# 2225| ValueCategory = lvalue
+# 2230| getStmt(8): [RangeBasedForStmt] for(...:...) ...
+# 2230| getInitialization(): [DeclStmt] declaration
+# 2230| getDeclarationEntry(0): [VariableDeclarationEntry] definition of ys
+# 2230| Type = [ClassTemplateInstantiation,Struct] vector
+# 2230| getVariable().getInitializer(): [Initializer] initializer for ys
+# 2230| getExpr(): [ConstructorCall] call to vector
+# 2230| Type = [VoidType] void
+# 2230| ValueCategory = prvalue
+# 2230| getArgument(0): [VariableAccess] x
+# 2230| Type = [Class] ClassWithDestructor
+# 2230| ValueCategory = prvalue(load)
+# 2230| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2230| Type = [VoidType] void
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2230| Type = [Class] ClassWithDestructor
+# 2230| ValueCategory = xvalue
+# 2230| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2230| Type = [Class] ClassWithDestructor
+# 2230| ValueCategory = lvalue
+# 2230| getChild(1): [DeclStmt] declaration
+# 2230| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
+# 2230| Type = [LValueReferenceType] vector &
#-----| getVariable().getInitializer(): [Initializer] initializer for (__range)
-# 2229| getExpr(): [VariableAccess] ys
-# 2229| Type = [ClassTemplateInstantiation,Struct] vector
-# 2229| ValueCategory = lvalue
-# 2229| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2229| Type = [LValueReferenceType] vector &
-# 2229| ValueCategory = prvalue
-# 2229| getBeginEndDeclaration(): [DeclStmt] declaration
-# 2229| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| getExpr(): [VariableAccess] ys
+# 2230| Type = [ClassTemplateInstantiation,Struct] vector
+# 2230| ValueCategory = lvalue
+# 2230| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2230| Type = [LValueReferenceType] vector &
+# 2230| ValueCategory = prvalue
+# 2230| getBeginEndDeclaration(): [DeclStmt] declaration
+# 2230| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__begin)
-# 2229| getExpr(): [FunctionCall] call to begin
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] (__range)
-# 2229| Type = [LValueReferenceType] vector &
-# 2229| ValueCategory = prvalue(load)
+# 2230| getExpr(): [FunctionCall] call to begin
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] (__range)
+# 2230| Type = [LValueReferenceType] vector &
+# 2230| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19946,15 +19964,15 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2229| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__end)
-# 2229| getExpr(): [FunctionCall] call to end
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] (__range)
-# 2229| Type = [LValueReferenceType] vector &
-# 2229| ValueCategory = prvalue(load)
+# 2230| getExpr(): [FunctionCall] call to end
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] (__range)
+# 2230| Type = [LValueReferenceType] vector &
+# 2230| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -19962,18 +19980,18 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2229| getCondition(): [FunctionCall] call to operator!=
-# 2229| Type = [BoolType] bool
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] (__begin)
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2229| ValueCategory = lvalue
-# 2229| getArgument(0): [ConstructorCall] call to iterator
-# 2229| Type = [VoidType] void
-# 2229| ValueCategory = prvalue
-# 2229| getArgument(0): [VariableAccess] (__end)
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2229| ValueCategory = lvalue
+# 2230| getCondition(): [FunctionCall] call to operator!=
+# 2230| Type = [BoolType] bool
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] (__begin)
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| ValueCategory = lvalue
+# 2230| getArgument(0): [ConstructorCall] call to iterator
+# 2230| Type = [VoidType] void
+# 2230| ValueCategory = prvalue
+# 2230| getArgument(0): [VariableAccess] (__end)
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| ValueCategory = lvalue
#-----| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] const iterator &
#-----| ValueCategory = prvalue
@@ -19988,584 +20006,584 @@ ir.cpp:
#-----| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [ClassTemplateInstantiation,Struct] iterator
#-----| ValueCategory = lvalue
-# 2229| getUpdate(): [FunctionCall] call to operator++
-# 2229| Type = [LValueReferenceType] iterator &
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] (__begin)
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2229| ValueCategory = lvalue
-# 2229| getChild(5): [DeclStmt] declaration
-# 2229| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
-# 2229| Type = [Class] ClassWithDestructor
-# 2229| getVariable().getInitializer(): [Initializer] initializer for y
-# 2229| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
-# 2229| Type = [LValueReferenceType] ClassWithDestructor &
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] (__begin)
-# 2229| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2229| ValueCategory = lvalue
+# 2230| getUpdate(): [FunctionCall] call to operator++
+# 2230| Type = [LValueReferenceType] iterator &
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] (__begin)
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| ValueCategory = lvalue
+# 2230| getChild(5): [DeclStmt] declaration
+# 2230| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
+# 2230| Type = [Class] ClassWithDestructor
+# 2230| getVariable().getInitializer(): [Initializer] initializer for y
+# 2230| getExpr(): [OverloadedPointerDereferenceExpr] call to operator*
+# 2230| Type = [LValueReferenceType] ClassWithDestructor &
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] (__begin)
+# 2230| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2230| ValueCategory = lvalue
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const iterator)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const iterator
#-----| ValueCategory = lvalue
-# 2229| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2229| Type = [Class] ClassWithDestructor
-# 2229| ValueCategory = prvalue(load)
-# 2229| getStmt(): [BlockStmt] { ... }
-# 2230| getStmt(0): [DeclStmt] declaration
-# 2230| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z1
-# 2230| Type = [Class] ClassWithDestructor
-# 2230| getVariable().getInitializer(): [Initializer] initializer for z1
-# 2230| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2230| Type = [VoidType] void
-# 2230| ValueCategory = prvalue
-# 2231| getStmt(1): [DeclStmt] declaration
-# 2231| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z2
+# 2230| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2230| Type = [Class] ClassWithDestructor
+# 2230| ValueCategory = prvalue(load)
+# 2230| getStmt(): [BlockStmt] { ... }
+# 2231| getStmt(0): [DeclStmt] declaration
+# 2231| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z1
# 2231| Type = [Class] ClassWithDestructor
-# 2231| getVariable().getInitializer(): [Initializer] initializer for z2
+# 2231| getVariable().getInitializer(): [Initializer] initializer for z1
# 2231| getExpr(): [ConstructorCall] call to ClassWithDestructor
# 2231| Type = [VoidType] void
# 2231| ValueCategory = prvalue
-# 2232| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2232| Type = [VoidType] void
-# 2232| ValueCategory = prvalue
-# 2232| getQualifier(): [VariableAccess] z2
+# 2232| getStmt(1): [DeclStmt] declaration
+# 2232| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z2
# 2232| Type = [Class] ClassWithDestructor
-# 2232| ValueCategory = lvalue
-# 2232| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor
-# 2232| Type = [VoidType] void
-# 2232| ValueCategory = prvalue
-# 2232| getQualifier(): [VariableAccess] z1
-# 2232| Type = [Class] ClassWithDestructor
-# 2232| ValueCategory = lvalue
-# 2229| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
-# 2229| Type = [VoidType] void
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] ys
-# 2229| Type = [ClassTemplateInstantiation,Struct] vector
-# 2229| ValueCategory = lvalue
-# 2229| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2229| Type = [ClassTemplateInstantiation,Struct] iterator
-# 2229| ValueCategory = lvalue
-# 2229| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2229| Type = [VoidType] void
-# 2229| ValueCategory = prvalue
-# 2229| getQualifier(): [VariableAccess] y
-# 2229| Type = [Class] ClassWithDestructor
-# 2229| ValueCategory = lvalue
-# 2233| getStmt(9): [ReturnStmt] return ...
-# 2233| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2233| Type = [VoidType] void
-# 2233| ValueCategory = prvalue
-# 2233| getQualifier(): [VariableAccess] x
-# 2233| Type = [Class] ClassWithDestructor
-# 2233| ValueCategory = lvalue
-# 2235| [TopLevelFunction] void static_variable_with_destructor_1()
-# 2235| :
-# 2235| getEntryPoint(): [BlockStmt] { ... }
-# 2236| getStmt(0): [DeclStmt] declaration
-# 2236| getDeclarationEntry(0): [VariableDeclarationEntry] definition of a
-# 2236| Type = [Class] ClassWithDestructor
-# 2236| getVariable().getInitializer(): [Initializer] initializer for a
-# 2236| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2236| Type = [VoidType] void
-# 2236| ValueCategory = prvalue
-# 2237| getStmt(1): [DeclStmt] declaration
-# 2237| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
+# 2232| getVariable().getInitializer(): [Initializer] initializer for z2
+# 2232| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2232| Type = [VoidType] void
+# 2232| ValueCategory = prvalue
+# 2233| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2233| Type = [VoidType] void
+# 2233| ValueCategory = prvalue
+# 2233| getQualifier(): [VariableAccess] z2
+# 2233| Type = [Class] ClassWithDestructor
+# 2233| ValueCategory = lvalue
+# 2233| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor
+# 2233| Type = [VoidType] void
+# 2233| ValueCategory = prvalue
+# 2233| getQualifier(): [VariableAccess] z1
+# 2233| Type = [Class] ClassWithDestructor
+# 2233| ValueCategory = lvalue
+# 2230| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
+# 2230| Type = [VoidType] void
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] ys
+# 2230| Type = [ClassTemplateInstantiation,Struct] vector
+# 2230| ValueCategory = lvalue
+# 2230| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2230| Type = [ClassTemplateInstantiation,Struct] iterator
+# 2230| ValueCategory = lvalue
+# 2230| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2230| Type = [VoidType] void
+# 2230| ValueCategory = prvalue
+# 2230| getQualifier(): [VariableAccess] y
+# 2230| Type = [Class] ClassWithDestructor
+# 2230| ValueCategory = lvalue
+# 2234| getStmt(9): [ReturnStmt] return ...
+# 2234| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2234| Type = [VoidType] void
+# 2234| ValueCategory = prvalue
+# 2234| getQualifier(): [VariableAccess] x
+# 2234| Type = [Class] ClassWithDestructor
+# 2234| ValueCategory = lvalue
+# 2236| [TopLevelFunction] void static_variable_with_destructor_1()
+# 2236| :
+# 2236| getEntryPoint(): [BlockStmt] { ... }
+# 2237| getStmt(0): [DeclStmt] declaration
+# 2237| getDeclarationEntry(0): [VariableDeclarationEntry] definition of a
# 2237| Type = [Class] ClassWithDestructor
+# 2237| getVariable().getInitializer(): [Initializer] initializer for a
+# 2237| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2237| Type = [VoidType] void
+# 2237| ValueCategory = prvalue
+# 2238| getStmt(1): [DeclStmt] declaration
+# 2238| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
+# 2238| Type = [Class] ClassWithDestructor
#-----| getVariable().getInitializer(): [Initializer] initializer for b
#-----| getExpr(): [ConstructorCall] call to ClassWithDestructor
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
-# 2238| getStmt(2): [ReturnStmt] return ...
-# 2238| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2238| Type = [VoidType] void
-# 2238| ValueCategory = prvalue
-# 2238| getQualifier(): [VariableAccess] a
-# 2238| Type = [Class] ClassWithDestructor
-# 2238| ValueCategory = lvalue
-# 2240| [TopLevelFunction] void static_variable_with_destructor_2()
-# 2240| :
-# 2240| getEntryPoint(): [BlockStmt] { ... }
-# 2241| getStmt(0): [DeclStmt] declaration
-# 2241| getDeclarationEntry(0): [VariableDeclarationEntry] definition of a
-# 2241| Type = [Class] ClassWithDestructor
+# 2239| getStmt(2): [ReturnStmt] return ...
+# 2239| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2239| Type = [VoidType] void
+# 2239| ValueCategory = prvalue
+# 2239| getQualifier(): [VariableAccess] a
+# 2239| Type = [Class] ClassWithDestructor
+# 2239| ValueCategory = lvalue
+# 2241| [TopLevelFunction] void static_variable_with_destructor_2()
+# 2241| :
+# 2241| getEntryPoint(): [BlockStmt] { ... }
+# 2242| getStmt(0): [DeclStmt] declaration
+# 2242| getDeclarationEntry(0): [VariableDeclarationEntry] definition of a
+# 2242| Type = [Class] ClassWithDestructor
#-----| getVariable().getInitializer(): [Initializer] initializer for a
#-----| getExpr(): [ConstructorCall] call to ClassWithDestructor
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
-# 2242| getStmt(1): [DeclStmt] declaration
-# 2242| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
-# 2242| Type = [Class] ClassWithDestructor
-# 2242| getVariable().getInitializer(): [Initializer] initializer for b
-# 2242| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2242| Type = [VoidType] void
-# 2242| ValueCategory = prvalue
-# 2243| getStmt(2): [ReturnStmt] return ...
-# 2243| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2243| Type = [VoidType] void
-# 2243| ValueCategory = prvalue
-# 2243| getQualifier(): [VariableAccess] b
-# 2243| Type = [Class] ClassWithDestructor
-# 2243| ValueCategory = lvalue
-# 2245| [TopLevelFunction] void static_variable_with_destructor_3()
-# 2245| :
-# 2245| getEntryPoint(): [BlockStmt] { ... }
-# 2246| getStmt(0): [DeclStmt] declaration
-# 2246| getDeclarationEntry(0): [VariableDeclarationEntry] definition of a
-# 2246| Type = [Class] ClassWithDestructor
-# 2246| getVariable().getInitializer(): [Initializer] initializer for a
-# 2246| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2246| Type = [VoidType] void
-# 2246| ValueCategory = prvalue
-# 2247| getStmt(1): [DeclStmt] declaration
-# 2247| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
+# 2243| getStmt(1): [DeclStmt] declaration
+# 2243| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
+# 2243| Type = [Class] ClassWithDestructor
+# 2243| getVariable().getInitializer(): [Initializer] initializer for b
+# 2243| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2243| Type = [VoidType] void
+# 2243| ValueCategory = prvalue
+# 2244| getStmt(2): [ReturnStmt] return ...
+# 2244| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2244| Type = [VoidType] void
+# 2244| ValueCategory = prvalue
+# 2244| getQualifier(): [VariableAccess] b
+# 2244| Type = [Class] ClassWithDestructor
+# 2244| ValueCategory = lvalue
+# 2246| [TopLevelFunction] void static_variable_with_destructor_3()
+# 2246| :
+# 2246| getEntryPoint(): [BlockStmt] { ... }
+# 2247| getStmt(0): [DeclStmt] declaration
+# 2247| getDeclarationEntry(0): [VariableDeclarationEntry] definition of a
# 2247| Type = [Class] ClassWithDestructor
-# 2247| getVariable().getInitializer(): [Initializer] initializer for b
+# 2247| getVariable().getInitializer(): [Initializer] initializer for a
# 2247| getExpr(): [ConstructorCall] call to ClassWithDestructor
# 2247| Type = [VoidType] void
# 2247| ValueCategory = prvalue
-# 2248| getStmt(2): [DeclStmt] declaration
-# 2248| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
+# 2248| getStmt(1): [DeclStmt] declaration
+# 2248| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
# 2248| Type = [Class] ClassWithDestructor
+# 2248| getVariable().getInitializer(): [Initializer] initializer for b
+# 2248| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2248| Type = [VoidType] void
+# 2248| ValueCategory = prvalue
+# 2249| getStmt(2): [DeclStmt] declaration
+# 2249| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
+# 2249| Type = [Class] ClassWithDestructor
#-----| getVariable().getInitializer(): [Initializer] initializer for c
#-----| getExpr(): [ConstructorCall] call to ClassWithDestructor
#-----| Type = [VoidType] void
#-----| ValueCategory = prvalue
-# 2249| getStmt(3): [ReturnStmt] return ...
-# 2249| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2249| Type = [VoidType] void
-# 2249| ValueCategory = prvalue
-# 2249| getQualifier(): [VariableAccess] b
-# 2249| Type = [Class] ClassWithDestructor
-# 2249| ValueCategory = lvalue
-# 2249| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor
-# 2249| Type = [VoidType] void
-# 2249| ValueCategory = prvalue
-# 2249| getQualifier(): [VariableAccess] a
-# 2249| Type = [Class] ClassWithDestructor
-# 2249| ValueCategory = lvalue
-# 2251| [GlobalVariable] ClassWithDestructor global_class_with_destructor
-# 2251| getInitializer(): [Initializer] initializer for global_class_with_destructor
-# 2251| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2251| Type = [VoidType] void
-# 2251| ValueCategory = prvalue
-# 2255| [FunctionTemplateInstantiation,TopLevelFunction] ClassWithDestructor& vacuous_destructor_call::get(ClassWithDestructor&)
-# 2255| :
-# 2255| getParameter(0): [Parameter] t
-# 2255| Type = [LValueReferenceType] ClassWithDestructor &
-# 2255| getEntryPoint(): [BlockStmt] { ... }
-# 2255| getStmt(0): [ReturnStmt] return ...
-# 2255| getExpr(): [VariableAccess] t
-# 2255| Type = [LValueReferenceType] ClassWithDestructor &
-# 2255| ValueCategory = prvalue(load)
-# 2255| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2255| Type = [LValueReferenceType] ClassWithDestructor &
-# 2255| ValueCategory = prvalue
-# 2255| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
-# 2255| Type = [Class] ClassWithDestructor
-# 2255| ValueCategory = lvalue
-# 2255| [TemplateFunction,TopLevelFunction] T& vacuous_destructor_call::get(T&)
-# 2255| :
-# 2255| getParameter(0): [Parameter] t
-# 2255| Type = [LValueReferenceType] T &
-# 2255| getEntryPoint(): [BlockStmt] { ... }
-# 2255| getStmt(0): [ReturnStmt] return ...
-# 2255| getExpr(): [VariableAccess] t
-# 2255| Type = [LValueReferenceType] T &
-# 2255| ValueCategory = prvalue(load)
-# 2255| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2255| Type = [TemplateParameter] T
-# 2255| ValueCategory = lvalue
-# 2255| [FunctionTemplateInstantiation,TopLevelFunction] int& vacuous_destructor_call::get(int&)
-# 2255| :
-# 2255| getParameter(0): [Parameter] t
-# 2255| Type = [LValueReferenceType] int &
-# 2255| getEntryPoint(): [BlockStmt] { ... }
-# 2255| getStmt(0): [ReturnStmt] return ...
-# 2255| getExpr(): [VariableAccess] t
-# 2255| Type = [LValueReferenceType] int &
-# 2255| ValueCategory = prvalue(load)
-# 2255| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2255| Type = [LValueReferenceType] int &
-# 2255| ValueCategory = prvalue
-# 2255| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
-# 2255| Type = [IntType] int
-# 2255| ValueCategory = lvalue
-# 2258| [FunctionTemplateInstantiation,TopLevelFunction] void vacuous_destructor_call::call_destructor(ClassWithDestructor&)
-# 2258| :
-# 2258| getParameter(0): [Parameter] t
-# 2258| Type = [LValueReferenceType] ClassWithDestructor &
-# 2258| getEntryPoint(): [BlockStmt] { ... }
-# 2259| getStmt(0): [ExprStmt] ExprStmt
-# 2259| getExpr(): [DestructorCall] call to ~ClassWithDestructor
-# 2259| Type = [VoidType] void
-# 2259| ValueCategory = prvalue
-# 2259| getQualifier(): [FunctionCall] call to get
-# 2259| Type = [LValueReferenceType] ClassWithDestructor &
-# 2259| ValueCategory = prvalue
-# 2259| getArgument(0): [VariableAccess] t
-# 2259| Type = [LValueReferenceType] ClassWithDestructor &
-# 2259| ValueCategory = prvalue(load)
-# 2259| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2259| Type = [LValueReferenceType] ClassWithDestructor &
-# 2259| ValueCategory = prvalue
-# 2259| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
-# 2259| Type = [Class] ClassWithDestructor
-# 2259| ValueCategory = lvalue
-# 2259| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2259| Type = [Class] ClassWithDestructor
-# 2259| ValueCategory = lvalue
-# 2260| getStmt(1): [ReturnStmt] return ...
-# 2258| [TemplateFunction,TopLevelFunction] void vacuous_destructor_call::call_destructor(T&)
-# 2258| :
-# 2258| getParameter(0): [Parameter] t
-# 2258| Type = [LValueReferenceType] T &
-# 2258| getEntryPoint(): [BlockStmt] { ... }
-# 2259| getStmt(0): [ExprStmt] ExprStmt
-# 2259| getExpr(): [ExprCall] call to expression
-# 2259| Type = [UnknownType] unknown
-# 2259| ValueCategory = prvalue
-# 2259| getExpr(): [Literal] Unknown literal
-# 2259| Type = [UnknownType] unknown
-# 2259| ValueCategory = prvalue
-# 2259| getChild(-1): [ExprCall] call to expression
-# 2259| Type = [UnknownType] unknown
-# 2259| ValueCategory = prvalue
-# 2259| getExpr(): [Literal] Unknown literal
-# 2259| Type = [UnknownType] unknown
-# 2259| ValueCategory = prvalue
-# 2259| getArgument(0): [VariableAccess] t
-# 2259| Type = [LValueReferenceType] T &
-# 2259| ValueCategory = prvalue(load)
-# 2259| getArgument(0).getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2259| Type = [TemplateParameter] T
-# 2259| ValueCategory = lvalue
-# 2260| getStmt(1): [ReturnStmt] return ...
-# 2258| [FunctionTemplateInstantiation,TopLevelFunction] void vacuous_destructor_call::call_destructor(int&)
-# 2258| :
-# 2258| getParameter(0): [Parameter] t
-# 2258| Type = [LValueReferenceType] int &
-# 2258| getEntryPoint(): [BlockStmt] { ... }
-# 2259| getStmt(0): [ExprStmt] ExprStmt
-# 2259| getExpr(): [VacuousDestructorCall] (vacuous destructor call)
-# 2259| Type = [VoidType] void
-# 2259| ValueCategory = prvalue
-# 2259| getChild(0): [FunctionCall] call to get
-# 2259| Type = [LValueReferenceType] int &
-# 2259| ValueCategory = prvalue
-# 2259| getArgument(0): [VariableAccess] t
-# 2259| Type = [LValueReferenceType] int &
-# 2259| ValueCategory = prvalue(load)
-# 2259| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2259| Type = [LValueReferenceType] int &
-# 2259| ValueCategory = prvalue
-# 2259| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
-# 2259| Type = [IntType] int
-# 2259| ValueCategory = lvalue
-# 2259| getChild(0).getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2259| Type = [IntType] int
-# 2259| ValueCategory = lvalue
-# 2260| getStmt(1): [ReturnStmt] return ...
-# 2262| [TopLevelFunction] void vacuous_destructor_call::non_vacuous_destructor_call()
-# 2262| :
-# 2262| getEntryPoint(): [BlockStmt] { ... }
-# 2263| getStmt(0): [DeclStmt] declaration
-# 2263| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
-# 2263| Type = [Class] ClassWithDestructor
-# 2263| getVariable().getInitializer(): [Initializer] initializer for c
-# 2263| getExpr(): [ConstructorCall] call to ClassWithDestructor
-# 2263| Type = [VoidType] void
-# 2263| ValueCategory = prvalue
-# 2264| getStmt(1): [ExprStmt] ExprStmt
-# 2264| getExpr(): [FunctionCall] call to call_destructor
-# 2264| Type = [VoidType] void
-# 2264| ValueCategory = prvalue
-# 2264| getArgument(0): [VariableAccess] c
-# 2264| Type = [Class] ClassWithDestructor
-# 2264| ValueCategory = lvalue
-# 2264| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2264| Type = [LValueReferenceType] ClassWithDestructor &
-# 2264| ValueCategory = prvalue
-# 2265| getStmt(2): [ReturnStmt] return ...
-# 2265| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2250| getStmt(3): [ReturnStmt] return ...
+# 2250| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2250| Type = [VoidType] void
+# 2250| ValueCategory = prvalue
+# 2250| getQualifier(): [VariableAccess] b
+# 2250| Type = [Class] ClassWithDestructor
+# 2250| ValueCategory = lvalue
+# 2250| getImplicitDestructorCall(1): [DestructorCall] call to ~ClassWithDestructor
+# 2250| Type = [VoidType] void
+# 2250| ValueCategory = prvalue
+# 2250| getQualifier(): [VariableAccess] a
+# 2250| Type = [Class] ClassWithDestructor
+# 2250| ValueCategory = lvalue
+# 2252| [GlobalVariable] ClassWithDestructor global_class_with_destructor
+# 2252| getInitializer(): [Initializer] initializer for global_class_with_destructor
+# 2252| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2252| Type = [VoidType] void
+# 2252| ValueCategory = prvalue
+# 2256| [FunctionTemplateInstantiation,TopLevelFunction] ClassWithDestructor& vacuous_destructor_call::get(ClassWithDestructor&)
+# 2256| :
+# 2256| getParameter(0): [Parameter] t
+# 2256| Type = [LValueReferenceType] ClassWithDestructor &
+# 2256| getEntryPoint(): [BlockStmt] { ... }
+# 2256| getStmt(0): [ReturnStmt] return ...
+# 2256| getExpr(): [VariableAccess] t
+# 2256| Type = [LValueReferenceType] ClassWithDestructor &
+# 2256| ValueCategory = prvalue(load)
+# 2256| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2256| Type = [LValueReferenceType] ClassWithDestructor &
+# 2256| ValueCategory = prvalue
+# 2256| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
+# 2256| Type = [Class] ClassWithDestructor
+# 2256| ValueCategory = lvalue
+# 2256| [TemplateFunction,TopLevelFunction] T& vacuous_destructor_call::get(T&)
+# 2256| :
+# 2256| getParameter(0): [Parameter] t
+# 2256| Type = [LValueReferenceType] T &
+# 2256| getEntryPoint(): [BlockStmt] { ... }
+# 2256| getStmt(0): [ReturnStmt] return ...
+# 2256| getExpr(): [VariableAccess] t
+# 2256| Type = [LValueReferenceType] T &
+# 2256| ValueCategory = prvalue(load)
+# 2256| getExpr().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2256| Type = [TemplateParameter] T
+# 2256| ValueCategory = lvalue
+# 2256| [FunctionTemplateInstantiation,TopLevelFunction] int& vacuous_destructor_call::get(int&)
+# 2256| :
+# 2256| getParameter(0): [Parameter] t
+# 2256| Type = [LValueReferenceType] int &
+# 2256| getEntryPoint(): [BlockStmt] { ... }
+# 2256| getStmt(0): [ReturnStmt] return ...
+# 2256| getExpr(): [VariableAccess] t
+# 2256| Type = [LValueReferenceType] int &
+# 2256| ValueCategory = prvalue(load)
+# 2256| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2256| Type = [LValueReferenceType] int &
+# 2256| ValueCategory = prvalue
+# 2256| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
+# 2256| Type = [IntType] int
+# 2256| ValueCategory = lvalue
+# 2259| [FunctionTemplateInstantiation,TopLevelFunction] void vacuous_destructor_call::call_destructor(ClassWithDestructor&)
+# 2259| :
+# 2259| getParameter(0): [Parameter] t
+# 2259| Type = [LValueReferenceType] ClassWithDestructor &
+# 2259| getEntryPoint(): [BlockStmt] { ... }
+# 2260| getStmt(0): [ExprStmt] ExprStmt
+# 2260| getExpr(): [DestructorCall] call to ~ClassWithDestructor
+# 2260| Type = [VoidType] void
+# 2260| ValueCategory = prvalue
+# 2260| getQualifier(): [FunctionCall] call to get
+# 2260| Type = [LValueReferenceType] ClassWithDestructor &
+# 2260| ValueCategory = prvalue
+# 2260| getArgument(0): [VariableAccess] t
+# 2260| Type = [LValueReferenceType] ClassWithDestructor &
+# 2260| ValueCategory = prvalue(load)
+# 2260| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2260| Type = [LValueReferenceType] ClassWithDestructor &
+# 2260| ValueCategory = prvalue
+# 2260| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
+# 2260| Type = [Class] ClassWithDestructor
+# 2260| ValueCategory = lvalue
+# 2260| getQualifier().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2260| Type = [Class] ClassWithDestructor
+# 2260| ValueCategory = lvalue
+# 2261| getStmt(1): [ReturnStmt] return ...
+# 2259| [TemplateFunction,TopLevelFunction] void vacuous_destructor_call::call_destructor(T&)
+# 2259| :
+# 2259| getParameter(0): [Parameter] t
+# 2259| Type = [LValueReferenceType] T &
+# 2259| getEntryPoint(): [BlockStmt] { ... }
+# 2260| getStmt(0): [ExprStmt] ExprStmt
+# 2260| getExpr(): [ExprCall] call to expression
+# 2260| Type = [UnknownType] unknown
+# 2260| ValueCategory = prvalue
+# 2260| getExpr(): [Literal] Unknown literal
+# 2260| Type = [UnknownType] unknown
+# 2260| ValueCategory = prvalue
+# 2260| getChild(-1): [ExprCall] call to expression
+# 2260| Type = [UnknownType] unknown
+# 2260| ValueCategory = prvalue
+# 2260| getExpr(): [Literal] Unknown literal
+# 2260| Type = [UnknownType] unknown
+# 2260| ValueCategory = prvalue
+# 2260| getArgument(0): [VariableAccess] t
+# 2260| Type = [LValueReferenceType] T &
+# 2260| ValueCategory = prvalue(load)
+# 2260| getArgument(0).getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2260| Type = [TemplateParameter] T
+# 2260| ValueCategory = lvalue
+# 2261| getStmt(1): [ReturnStmt] return ...
+# 2259| [FunctionTemplateInstantiation,TopLevelFunction] void vacuous_destructor_call::call_destructor(int&)
+# 2259| :
+# 2259| getParameter(0): [Parameter] t
+# 2259| Type = [LValueReferenceType] int &
+# 2259| getEntryPoint(): [BlockStmt] { ... }
+# 2260| getStmt(0): [ExprStmt] ExprStmt
+# 2260| getExpr(): [VacuousDestructorCall] (vacuous destructor call)
+# 2260| Type = [VoidType] void
+# 2260| ValueCategory = prvalue
+# 2260| getChild(0): [FunctionCall] call to get
+# 2260| Type = [LValueReferenceType] int &
+# 2260| ValueCategory = prvalue
+# 2260| getArgument(0): [VariableAccess] t
+# 2260| Type = [LValueReferenceType] int &
+# 2260| ValueCategory = prvalue(load)
+# 2260| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2260| Type = [LValueReferenceType] int &
+# 2260| ValueCategory = prvalue
+# 2260| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
+# 2260| Type = [IntType] int
+# 2260| ValueCategory = lvalue
+# 2260| getChild(0).getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2260| Type = [IntType] int
+# 2260| ValueCategory = lvalue
+# 2261| getStmt(1): [ReturnStmt] return ...
+# 2263| [TopLevelFunction] void vacuous_destructor_call::non_vacuous_destructor_call()
+# 2263| :
+# 2263| getEntryPoint(): [BlockStmt] { ... }
+# 2264| getStmt(0): [DeclStmt] declaration
+# 2264| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
+# 2264| Type = [Class] ClassWithDestructor
+# 2264| getVariable().getInitializer(): [Initializer] initializer for c
+# 2264| getExpr(): [ConstructorCall] call to ClassWithDestructor
+# 2264| Type = [VoidType] void
+# 2264| ValueCategory = prvalue
+# 2265| getStmt(1): [ExprStmt] ExprStmt
+# 2265| getExpr(): [FunctionCall] call to call_destructor
# 2265| Type = [VoidType] void
# 2265| ValueCategory = prvalue
-# 2265| getQualifier(): [VariableAccess] c
+# 2265| getArgument(0): [VariableAccess] c
# 2265| Type = [Class] ClassWithDestructor
# 2265| ValueCategory = lvalue
-# 2267| [TopLevelFunction] void vacuous_destructor_call::vacuous_destructor_call()
-# 2267| :
-# 2267| getEntryPoint(): [BlockStmt] { ... }
-# 2268| getStmt(0): [DeclStmt] declaration
-# 2268| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
-# 2268| Type = [IntType] int
-# 2269| getStmt(1): [ExprStmt] ExprStmt
-# 2269| getExpr(): [FunctionCall] call to call_destructor
-# 2269| Type = [VoidType] void
-# 2269| ValueCategory = prvalue
-# 2269| getArgument(0): [VariableAccess] i
-# 2269| Type = [IntType] int
-# 2269| ValueCategory = lvalue
-# 2269| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2269| Type = [LValueReferenceType] int &
-# 2269| ValueCategory = prvalue
-# 2270| getStmt(2): [ReturnStmt] return ...
-# 2273| [TopLevelFunction] void TryCatchDestructors(bool)
-# 2273| :
-# 2273| getParameter(0): [Parameter] b
-# 2273| Type = [BoolType] bool
-# 2273| getEntryPoint(): [BlockStmt] { ... }
-# 2274| getStmt(0): [TryStmt] try { ... }
-# 2274| getStmt(): [BlockStmt] { ... }
-# 2275| getStmt(0): [DeclStmt] declaration
-# 2275| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2275| Type = [Struct] String
-# 2275| getVariable().getInitializer(): [Initializer] initializer for s
-# 2275| getExpr(): [ConstructorCall] call to String
-# 2275| Type = [VoidType] void
-# 2275| ValueCategory = prvalue
-# 2276| getStmt(1): [IfStmt] if (...) ...
-# 2276| getCondition(): [VariableAccess] b
-# 2276| Type = [BoolType] bool
-# 2276| ValueCategory = prvalue(load)
-# 2276| getThen(): [BlockStmt] { ... }
-# 2277| getStmt(0): [ExprStmt] ExprStmt
-# 2277| getExpr(): [ThrowExpr] throw ...
-# 2277| Type = [PointerType] const char *
-# 2277| ValueCategory = prvalue
-# 2277| getExpr(): string literal
-# 2277| Type = [ArrayType] const char[15]
-# 2277| Value = [StringLiteral] "string literal"
-# 2277| ValueCategory = lvalue
-# 2280| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2280| Type = [VoidType] void
-# 2280| ValueCategory = prvalue
-# 2280| getQualifier(): [VariableAccess] s
-# 2280| Type = [Struct] String
-# 2280| ValueCategory = lvalue
-# 2277| getExpr().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
-# 2277| Type = [PointerType] const char *
-# 2277| ValueCategory = prvalue
-# 2279| getStmt(2): [DeclStmt] declaration
-# 2279| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
-# 2279| Type = [Struct] String
-# 2279| getVariable().getInitializer(): [Initializer] initializer for s2
-# 2279| getExpr(): [ConstructorCall] call to String
-# 2279| Type = [VoidType] void
-# 2279| ValueCategory = prvalue
-# 2280| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2280| Type = [VoidType] void
-# 2280| ValueCategory = prvalue
-# 2280| getQualifier(): [VariableAccess] s2
+# 2265| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2265| Type = [LValueReferenceType] ClassWithDestructor &
+# 2265| ValueCategory = prvalue
+# 2266| getStmt(2): [ReturnStmt] return ...
+# 2266| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2266| Type = [VoidType] void
+# 2266| ValueCategory = prvalue
+# 2266| getQualifier(): [VariableAccess] c
+# 2266| Type = [Class] ClassWithDestructor
+# 2266| ValueCategory = lvalue
+# 2268| [TopLevelFunction] void vacuous_destructor_call::vacuous_destructor_call()
+# 2268| :
+# 2268| getEntryPoint(): [BlockStmt] { ... }
+# 2269| getStmt(0): [DeclStmt] declaration
+# 2269| getDeclarationEntry(0): [VariableDeclarationEntry] definition of i
+# 2269| Type = [IntType] int
+# 2270| getStmt(1): [ExprStmt] ExprStmt
+# 2270| getExpr(): [FunctionCall] call to call_destructor
+# 2270| Type = [VoidType] void
+# 2270| ValueCategory = prvalue
+# 2270| getArgument(0): [VariableAccess] i
+# 2270| Type = [IntType] int
+# 2270| ValueCategory = lvalue
+# 2270| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2270| Type = [LValueReferenceType] int &
+# 2270| ValueCategory = prvalue
+# 2271| getStmt(2): [ReturnStmt] return ...
+# 2274| [TopLevelFunction] void TryCatchDestructors(bool)
+# 2274| :
+# 2274| getParameter(0): [Parameter] b
+# 2274| Type = [BoolType] bool
+# 2274| getEntryPoint(): [BlockStmt] { ... }
+# 2275| getStmt(0): [TryStmt] try { ... }
+# 2275| getStmt(): [BlockStmt] { ... }
+# 2276| getStmt(0): [DeclStmt] declaration
+# 2276| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2276| Type = [Struct] String
+# 2276| getVariable().getInitializer(): [Initializer] initializer for s
+# 2276| getExpr(): [ConstructorCall] call to String
+# 2276| Type = [VoidType] void
+# 2276| ValueCategory = prvalue
+# 2277| getStmt(1): [IfStmt] if (...) ...
+# 2277| getCondition(): [VariableAccess] b
+# 2277| Type = [BoolType] bool
+# 2277| ValueCategory = prvalue(load)
+# 2277| getThen(): [BlockStmt] { ... }
+# 2278| getStmt(0): [ExprStmt] ExprStmt
+# 2278| getExpr(): [ThrowExpr] throw ...
+# 2278| Type = [PointerType] const char *
+# 2278| ValueCategory = prvalue
+# 2278| getExpr(): string literal
+# 2278| Type = [ArrayType] const char[15]
+# 2278| Value = [StringLiteral] "string literal"
+# 2278| ValueCategory = lvalue
+# 2281| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2281| Type = [VoidType] void
+# 2281| ValueCategory = prvalue
+# 2281| getQualifier(): [VariableAccess] s
+# 2281| Type = [Struct] String
+# 2281| ValueCategory = lvalue
+# 2278| getExpr().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
+# 2278| Type = [PointerType] const char *
+# 2278| ValueCategory = prvalue
+# 2280| getStmt(2): [DeclStmt] declaration
+# 2280| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
# 2280| Type = [Struct] String
-# 2280| ValueCategory = lvalue
-# 2280| getImplicitDestructorCall(1): [DestructorCall] call to ~String
-# 2280| Type = [VoidType] void
-# 2280| ValueCategory = prvalue
-# 2280| getQualifier(): [VariableAccess] s
-# 2280| Type = [Struct] String
-# 2280| ValueCategory = lvalue
-# 2281| getChild(1): [Handler]
-# 2281| getBlock(): [CatchBlock] { ... }
-# 2282| getStmt(0): [ExprStmt] ExprStmt
-# 2282| getExpr(): [ThrowExpr] throw ...
-# 2282| Type = [Struct] String
-# 2282| ValueCategory = prvalue
-# 2282| getExpr(): [ConstructorCall] call to String
-# 2282| Type = [VoidType] void
-# 2282| ValueCategory = prvalue
-# 2282| getArgument(0): [VariableAccess] s
-# 2282| Type = [PointerType] const char *
-# 2282| ValueCategory = prvalue(load)
-# 2284| getChild(2): [Handler]
-# 2284| getBlock(): [CatchBlock] { ... }
-# 2286| getChild(3): [Handler]
-# 2286| getBlock(): [CatchAnyBlock] { ... }
-# 2287| getStmt(0): [ExprStmt] ExprStmt
-# 2287| getExpr(): [ReThrowExpr] re-throw exception
-# 2287| Type = [VoidType] void
-# 2287| ValueCategory = prvalue
-# 2289| getStmt(1): [ReturnStmt] return ...
-# 2291| [TopLevelFunction] void IfDestructors(bool)
-# 2291| :
-# 2291| getParameter(0): [Parameter] b
-# 2291| Type = [BoolType] bool
-# 2291| getEntryPoint(): [BlockStmt] { ... }
-# 2292| getStmt(0): [DeclStmt] declaration
-# 2292| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s1
-# 2292| Type = [Struct] String
-# 2292| getVariable().getInitializer(): [Initializer] initializer for s1
-# 2292| getExpr(): [ConstructorCall] call to String
-# 2292| Type = [VoidType] void
-# 2292| ValueCategory = prvalue
-# 2293| getStmt(1): [IfStmt] if (...) ...
-# 2293| getCondition(): [VariableAccess] b
-# 2293| Type = [BoolType] bool
-# 2293| ValueCategory = prvalue(load)
-# 2293| getThen(): [BlockStmt] { ... }
-# 2294| getStmt(0): [DeclStmt] declaration
-# 2294| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
-# 2294| Type = [Struct] String
-# 2294| getVariable().getInitializer(): [Initializer] initializer for s2
-# 2294| getExpr(): [ConstructorCall] call to String
-# 2294| Type = [VoidType] void
-# 2294| ValueCategory = prvalue
-# 2295| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2295| Type = [VoidType] void
-# 2295| ValueCategory = prvalue
-# 2295| getQualifier(): [VariableAccess] s2
+# 2280| getVariable().getInitializer(): [Initializer] initializer for s2
+# 2280| getExpr(): [ConstructorCall] call to String
+# 2280| Type = [VoidType] void
+# 2280| ValueCategory = prvalue
+# 2281| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2281| Type = [VoidType] void
+# 2281| ValueCategory = prvalue
+# 2281| getQualifier(): [VariableAccess] s2
+# 2281| Type = [Struct] String
+# 2281| ValueCategory = lvalue
+# 2281| getImplicitDestructorCall(1): [DestructorCall] call to ~String
+# 2281| Type = [VoidType] void
+# 2281| ValueCategory = prvalue
+# 2281| getQualifier(): [VariableAccess] s
+# 2281| Type = [Struct] String
+# 2281| ValueCategory = lvalue
+# 2282| getChild(1): [Handler]
+# 2282| getBlock(): [CatchBlock] { ... }
+# 2283| getStmt(0): [ExprStmt] ExprStmt
+# 2283| getExpr(): [ThrowExpr] throw ...
+# 2283| Type = [Struct] String
+# 2283| ValueCategory = prvalue
+# 2283| getExpr(): [ConstructorCall] call to String
+# 2283| Type = [VoidType] void
+# 2283| ValueCategory = prvalue
+# 2283| getArgument(0): [VariableAccess] s
+# 2283| Type = [PointerType] const char *
+# 2283| ValueCategory = prvalue(load)
+# 2285| getChild(2): [Handler]
+# 2285| getBlock(): [CatchBlock] { ... }
+# 2287| getChild(3): [Handler]
+# 2287| getBlock(): [CatchAnyBlock] { ... }
+# 2288| getStmt(0): [ExprStmt] ExprStmt
+# 2288| getExpr(): [ReThrowExpr] re-throw exception
+# 2288| Type = [VoidType] void
+# 2288| ValueCategory = prvalue
+# 2290| getStmt(1): [ReturnStmt] return ...
+# 2292| [TopLevelFunction] void IfDestructors(bool)
+# 2292| :
+# 2292| getParameter(0): [Parameter] b
+# 2292| Type = [BoolType] bool
+# 2292| getEntryPoint(): [BlockStmt] { ... }
+# 2293| getStmt(0): [DeclStmt] declaration
+# 2293| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s1
+# 2293| Type = [Struct] String
+# 2293| getVariable().getInitializer(): [Initializer] initializer for s1
+# 2293| getExpr(): [ConstructorCall] call to String
+# 2293| Type = [VoidType] void
+# 2293| ValueCategory = prvalue
+# 2294| getStmt(1): [IfStmt] if (...) ...
+# 2294| getCondition(): [VariableAccess] b
+# 2294| Type = [BoolType] bool
+# 2294| ValueCategory = prvalue(load)
+# 2294| getThen(): [BlockStmt] { ... }
+# 2295| getStmt(0): [DeclStmt] declaration
+# 2295| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
# 2295| Type = [Struct] String
-# 2295| ValueCategory = lvalue
-# 2295| getElse(): [BlockStmt] { ... }
-# 2296| getStmt(0): [DeclStmt] declaration
-# 2296| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s3
+# 2295| getVariable().getInitializer(): [Initializer] initializer for s2
+# 2295| getExpr(): [ConstructorCall] call to String
+# 2295| Type = [VoidType] void
+# 2295| ValueCategory = prvalue
+# 2296| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2296| Type = [VoidType] void
+# 2296| ValueCategory = prvalue
+# 2296| getQualifier(): [VariableAccess] s2
# 2296| Type = [Struct] String
-# 2296| getVariable().getInitializer(): [Initializer] initializer for s3
-# 2296| getExpr(): [ConstructorCall] call to String
-# 2296| Type = [VoidType] void
-# 2296| ValueCategory = prvalue
-# 2297| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2297| Type = [VoidType] void
-# 2297| ValueCategory = prvalue
-# 2297| getQualifier(): [VariableAccess] s3
+# 2296| ValueCategory = lvalue
+# 2296| getElse(): [BlockStmt] { ... }
+# 2297| getStmt(0): [DeclStmt] declaration
+# 2297| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s3
# 2297| Type = [Struct] String
-# 2297| ValueCategory = lvalue
-# 2298| getStmt(2): [DeclStmt] declaration
-# 2298| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s4
-# 2298| Type = [Struct] String
-# 2298| getVariable().getInitializer(): [Initializer] initializer for s4
-# 2298| getExpr(): [ConstructorCall] call to String
-# 2298| Type = [VoidType] void
-# 2298| ValueCategory = prvalue
-# 2299| getStmt(3): [ReturnStmt] return ...
-# 2299| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2299| Type = [VoidType] void
-# 2299| ValueCategory = prvalue
-# 2299| getQualifier(): [VariableAccess] s4
-# 2299| Type = [Struct] String
-# 2299| ValueCategory = lvalue
-# 2299| getImplicitDestructorCall(1): [DestructorCall] call to ~String
-# 2299| Type = [VoidType] void
-# 2299| ValueCategory = prvalue
-# 2299| getQualifier(): [VariableAccess] s1
-# 2299| Type = [Struct] String
-# 2299| ValueCategory = lvalue
-# 2301| [TopLevelFunction] void ForDestructors()
-# 2301| :
-# 2301| getEntryPoint(): [BlockStmt] { ... }
-# 2302| getStmt(0): [DeclStmt] declaration
-# 2302| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
-# 2302| Type = [PlainCharType] char
-# 2302| getVariable().getInitializer(): [Initializer] initializer for c
-# 2302| getExpr(): [CharLiteral] 97
-# 2302| Type = [PlainCharType] char
-# 2302| Value = [CharLiteral] 97
-# 2302| ValueCategory = prvalue
-# 2303| getStmt(1): [ForStmt] for(...;...;...) ...
-# 2303| getInitialization(): [DeclStmt] declaration
-# 2303| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2303| Type = [Struct] String
-# 2303| getVariable().getInitializer(): [Initializer] initializer for s
-# 2303| getExpr(): [ConstructorCall] call to String
-# 2303| Type = [VoidType] void
-# 2303| ValueCategory = prvalue
-# 2303| getArgument(0): hello
-# 2303| Type = [ArrayType] const char[6]
-# 2303| Value = [StringLiteral] "hello"
-# 2303| ValueCategory = lvalue
-# 2303| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
-# 2303| Type = [PointerType] const char *
-# 2303| ValueCategory = prvalue
-# 2303| getCondition(): [NEExpr] ... != ...
-# 2303| Type = [BoolType] bool
-# 2303| ValueCategory = prvalue
-# 2303| getLeftOperand(): [VariableAccess] c
-# 2303| Type = [PlainCharType] char
-# 2303| ValueCategory = prvalue(load)
-# 2303| getRightOperand(): [Literal] 0
-# 2303| Type = [IntType] int
-# 2303| Value = [Literal] 0
-# 2303| ValueCategory = prvalue
-# 2303| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
-# 2303| Conversion = [IntegralConversion] integral conversion
-# 2303| Type = [IntType] int
-# 2303| ValueCategory = prvalue
-# 2303| getUpdate(): [AssignExpr] ... = ...
+# 2297| getVariable().getInitializer(): [Initializer] initializer for s3
+# 2297| getExpr(): [ConstructorCall] call to String
+# 2297| Type = [VoidType] void
+# 2297| ValueCategory = prvalue
+# 2298| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2298| Type = [VoidType] void
+# 2298| ValueCategory = prvalue
+# 2298| getQualifier(): [VariableAccess] s3
+# 2298| Type = [Struct] String
+# 2298| ValueCategory = lvalue
+# 2299| getStmt(2): [DeclStmt] declaration
+# 2299| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s4
+# 2299| Type = [Struct] String
+# 2299| getVariable().getInitializer(): [Initializer] initializer for s4
+# 2299| getExpr(): [ConstructorCall] call to String
+# 2299| Type = [VoidType] void
+# 2299| ValueCategory = prvalue
+# 2300| getStmt(3): [ReturnStmt] return ...
+# 2300| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2300| Type = [VoidType] void
+# 2300| ValueCategory = prvalue
+# 2300| getQualifier(): [VariableAccess] s4
+# 2300| Type = [Struct] String
+# 2300| ValueCategory = lvalue
+# 2300| getImplicitDestructorCall(1): [DestructorCall] call to ~String
+# 2300| Type = [VoidType] void
+# 2300| ValueCategory = prvalue
+# 2300| getQualifier(): [VariableAccess] s1
+# 2300| Type = [Struct] String
+# 2300| ValueCategory = lvalue
+# 2302| [TopLevelFunction] void ForDestructors()
+# 2302| :
+# 2302| getEntryPoint(): [BlockStmt] { ... }
+# 2303| getStmt(0): [DeclStmt] declaration
+# 2303| getDeclarationEntry(0): [VariableDeclarationEntry] definition of c
# 2303| Type = [PlainCharType] char
-# 2303| ValueCategory = lvalue
-# 2303| getLValue(): [VariableAccess] c
-# 2303| Type = [PlainCharType] char
-# 2303| ValueCategory = lvalue
-# 2303| getRValue(): [FunctionCall] call to pop_back
-# 2303| Type = [PlainCharType] char
-# 2303| ValueCategory = prvalue
-# 2303| getQualifier(): [VariableAccess] s
-# 2303| Type = [Struct] String
-# 2303| ValueCategory = lvalue
-# 2303| getStmt(): [BlockStmt] { ... }
-# 2304| getStmt(0): [DeclStmt] declaration
-# 2304| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
-# 2304| Type = [Struct] String
-# 2304| getVariable().getInitializer(): [Initializer] initializer for s2
-# 2304| getExpr(): [ConstructorCall] call to String
-# 2304| Type = [VoidType] void
+# 2303| getVariable().getInitializer(): [Initializer] initializer for c
+# 2303| getExpr(): [CharLiteral] 97
+# 2303| Type = [PlainCharType] char
+# 2303| Value = [CharLiteral] 97
+# 2303| ValueCategory = prvalue
+# 2304| getStmt(1): [ForStmt] for(...;...;...) ...
+# 2304| getInitialization(): [DeclStmt] declaration
+# 2304| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2304| Type = [Struct] String
+# 2304| getVariable().getInitializer(): [Initializer] initializer for s
+# 2304| getExpr(): [ConstructorCall] call to String
+# 2304| Type = [VoidType] void
+# 2304| ValueCategory = prvalue
+# 2304| getArgument(0): hello
+# 2304| Type = [ArrayType] const char[6]
+# 2304| Value = [StringLiteral] "hello"
+# 2304| ValueCategory = lvalue
+# 2304| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
+# 2304| Type = [PointerType] const char *
# 2304| ValueCategory = prvalue
-# 2305| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2305| Type = [VoidType] void
-# 2305| ValueCategory = prvalue
-# 2305| getQualifier(): [VariableAccess] s2
+# 2304| getCondition(): [NEExpr] ... != ...
+# 2304| Type = [BoolType] bool
+# 2304| ValueCategory = prvalue
+# 2304| getLeftOperand(): [VariableAccess] c
+# 2304| Type = [PlainCharType] char
+# 2304| ValueCategory = prvalue(load)
+# 2304| getRightOperand(): [Literal] 0
+# 2304| Type = [IntType] int
+# 2304| Value = [Literal] 0
+# 2304| ValueCategory = prvalue
+# 2304| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
+# 2304| Conversion = [IntegralConversion] integral conversion
+# 2304| Type = [IntType] int
+# 2304| ValueCategory = prvalue
+# 2304| getUpdate(): [AssignExpr] ... = ...
+# 2304| Type = [PlainCharType] char
+# 2304| ValueCategory = lvalue
+# 2304| getLValue(): [VariableAccess] c
+# 2304| Type = [PlainCharType] char
+# 2304| ValueCategory = lvalue
+# 2304| getRValue(): [FunctionCall] call to pop_back
+# 2304| Type = [PlainCharType] char
+# 2304| ValueCategory = prvalue
+# 2304| getQualifier(): [VariableAccess] s
+# 2304| Type = [Struct] String
+# 2304| ValueCategory = lvalue
+# 2304| getStmt(): [BlockStmt] { ... }
+# 2305| getStmt(0): [DeclStmt] declaration
+# 2305| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
# 2305| Type = [Struct] String
-# 2305| ValueCategory = lvalue
-# 2303| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2303| Type = [VoidType] void
-# 2303| ValueCategory = prvalue
-# 2303| getQualifier(): [VariableAccess] s
-# 2303| Type = [Struct] String
-# 2303| ValueCategory = lvalue
-# 2307| getStmt(2): [RangeBasedForStmt] for(...:...) ...
-# 2307| getChild(1): [DeclStmt] declaration
-# 2307| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
-# 2307| Type = [RValueReferenceType] vector &&
+# 2305| getVariable().getInitializer(): [Initializer] initializer for s2
+# 2305| getExpr(): [ConstructorCall] call to String
+# 2305| Type = [VoidType] void
+# 2305| ValueCategory = prvalue
+# 2306| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2306| Type = [VoidType] void
+# 2306| ValueCategory = prvalue
+# 2306| getQualifier(): [VariableAccess] s2
+# 2306| Type = [Struct] String
+# 2306| ValueCategory = lvalue
+# 2304| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2304| Type = [VoidType] void
+# 2304| ValueCategory = prvalue
+# 2304| getQualifier(): [VariableAccess] s
+# 2304| Type = [Struct] String
+# 2304| ValueCategory = lvalue
+# 2308| getStmt(2): [RangeBasedForStmt] for(...:...) ...
+# 2308| getChild(1): [DeclStmt] declaration
+# 2308| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
+# 2308| Type = [RValueReferenceType] vector &&
#-----| getVariable().getInitializer(): [Initializer] initializer for (__range)
-# 2307| getExpr(): [ConstructorCall] call to vector
-# 2307| Type = [VoidType] void
-# 2307| ValueCategory = prvalue
-# 2307| getArgument(0): [ConstructorCall] call to String
-# 2307| Type = [VoidType] void
-# 2307| ValueCategory = prvalue
-# 2307| getArgument(0): hello
-# 2307| Type = [ArrayType] const char[6]
-# 2307| Value = [StringLiteral] "hello"
-# 2307| ValueCategory = lvalue
-# 2307| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
-# 2307| Type = [PointerType] const char *
-# 2307| ValueCategory = prvalue
-# 2307| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2307| Type = [Struct] String
-# 2307| ValueCategory = lvalue
-# 2307| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2307| Type = [LValueReferenceType] vector &
-# 2307| ValueCategory = prvalue
-# 2307| getExpr(): [TemporaryObjectExpr] temporary object
-# 2307| Type = [ClassTemplateInstantiation,Struct] vector
-# 2307| ValueCategory = xvalue
-# 2307| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2307| Type = [VoidType] void
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2307| Type = [Struct] String
-# 2307| ValueCategory = xvalue
-# 2307| getBeginEndDeclaration(): [DeclStmt] declaration
-# 2307| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| getExpr(): [ConstructorCall] call to vector
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getArgument(0): [ConstructorCall] call to String
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getArgument(0): hello
+# 2308| Type = [ArrayType] const char[6]
+# 2308| Value = [StringLiteral] "hello"
+# 2308| ValueCategory = lvalue
+# 2308| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
+# 2308| Type = [PointerType] const char *
+# 2308| ValueCategory = prvalue
+# 2308| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2308| Type = [Struct] String
+# 2308| ValueCategory = lvalue
+# 2308| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2308| Type = [LValueReferenceType] vector &
+# 2308| ValueCategory = prvalue
+# 2308| getExpr(): [TemporaryObjectExpr] temporary object
+# 2308| Type = [ClassTemplateInstantiation,Struct] vector
+# 2308| ValueCategory = xvalue
+# 2308| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2308| Type = [Struct] String
+# 2308| ValueCategory = xvalue
+# 2308| getBeginEndDeclaration(): [DeclStmt] declaration
+# 2308| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__begin)
-# 2307| getExpr(): [FunctionCall] call to begin
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [VariableAccess] (__range)
-# 2307| Type = [RValueReferenceType] vector &&
-# 2307| ValueCategory = prvalue(load)
+# 2308| getExpr(): [FunctionCall] call to begin
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [VariableAccess] (__range)
+# 2308| Type = [RValueReferenceType] vector &&
+# 2308| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -20573,15 +20591,15 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2307| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| getDeclarationEntry(1): [VariableDeclarationEntry] declaration of (__end)
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__end)
-# 2307| getExpr(): [FunctionCall] call to end
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [VariableAccess] (__range)
-# 2307| Type = [RValueReferenceType] vector &&
-# 2307| ValueCategory = prvalue(load)
+# 2308| getExpr(): [FunctionCall] call to end
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [VariableAccess] (__range)
+# 2308| Type = [RValueReferenceType] vector &&
+# 2308| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const vector
@@ -20589,18 +20607,18 @@ ir.cpp:
#-----| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
#-----| Type = [ClassTemplateInstantiation,Struct] vector
#-----| ValueCategory = lvalue
-# 2307| getCondition(): [FunctionCall] call to operator!=
-# 2307| Type = [BoolType] bool
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [VariableAccess] (__begin)
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2307| ValueCategory = lvalue
-# 2307| getArgument(0): [ConstructorCall] call to iterator
-# 2307| Type = [VoidType] void
-# 2307| ValueCategory = prvalue
-# 2307| getArgument(0): [VariableAccess] (__end)
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2307| ValueCategory = lvalue
+# 2308| getCondition(): [FunctionCall] call to operator!=
+# 2308| Type = [BoolType] bool
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [VariableAccess] (__begin)
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| ValueCategory = lvalue
+# 2308| getArgument(0): [ConstructorCall] call to iterator
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getArgument(0): [VariableAccess] (__end)
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| ValueCategory = lvalue
#-----| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
#-----| Type = [LValueReferenceType] const iterator &
#-----| ValueCategory = prvalue
@@ -20615,1491 +20633,1497 @@ ir.cpp:
#-----| getArgument(0).getFullyConverted(): [TemporaryObjectExpr] temporary object
#-----| Type = [ClassTemplateInstantiation,Struct] iterator
#-----| ValueCategory = lvalue
-# 2307| getUpdate(): [FunctionCall] call to operator++
-# 2307| Type = [LValueReferenceType] iterator &
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [VariableAccess] (__begin)
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2307| ValueCategory = lvalue
-# 2307| getChild(5): [DeclStmt] declaration
-# 2307| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2307| Type = [Struct] String
-# 2307| getVariable().getInitializer(): [Initializer] initializer for s
-# 2307| getExpr(): [ConstructorCall] call to String
-# 2307| Type = [VoidType] void
-# 2307| ValueCategory = prvalue
-# 2307| getArgument(0): [OverloadedPointerDereferenceExpr] call to operator*
-# 2307| Type = [LValueReferenceType] String &
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [VariableAccess] (__begin)
-# 2307| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2307| ValueCategory = lvalue
+# 2308| getUpdate(): [FunctionCall] call to operator++
+# 2308| Type = [LValueReferenceType] iterator &
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [VariableAccess] (__begin)
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| ValueCategory = lvalue
+# 2308| getChild(5): [DeclStmt] declaration
+# 2308| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2308| Type = [Struct] String
+# 2308| getVariable().getInitializer(): [Initializer] initializer for s
+# 2308| getExpr(): [ConstructorCall] call to String
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getArgument(0): [OverloadedPointerDereferenceExpr] call to operator*
+# 2308| Type = [LValueReferenceType] String &
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [VariableAccess] (__begin)
+# 2308| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2308| ValueCategory = lvalue
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const iterator)...
#-----| Conversion = [GlvalueConversion] glvalue conversion
#-----| Type = [SpecifiedType] const iterator
#-----| ValueCategory = lvalue
-# 2307| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2307| Type = [LValueReferenceType] const String &
-# 2307| ValueCategory = prvalue
-# 2307| getExpr(): [CStyleCast] (const String)...
-# 2307| Conversion = [GlvalueConversion] glvalue conversion
-# 2307| Type = [SpecifiedType] const String
-# 2307| ValueCategory = lvalue
-# 2307| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
-# 2307| Type = [Struct] String
-# 2307| ValueCategory = lvalue
-# 2307| getStmt(): [BlockStmt] { ... }
-# 2308| getStmt(0): [DeclStmt] declaration
-# 2308| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
-# 2308| Type = [Struct] String
-# 2308| getVariable().getInitializer(): [Initializer] initializer for s2
-# 2308| getExpr(): [ConstructorCall] call to String
-# 2308| Type = [VoidType] void
+# 2308| getArgument(0).getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2308| Type = [LValueReferenceType] const String &
# 2308| ValueCategory = prvalue
-# 2309| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2309| Type = [VoidType] void
-# 2309| ValueCategory = prvalue
-# 2309| getQualifier(): [VariableAccess] s2
+# 2308| getExpr(): [CStyleCast] (const String)...
+# 2308| Conversion = [GlvalueConversion] glvalue conversion
+# 2308| Type = [SpecifiedType] const String
+# 2308| ValueCategory = lvalue
+# 2308| getExpr(): [ReferenceDereferenceExpr] (reference dereference)
+# 2308| Type = [Struct] String
+# 2308| ValueCategory = lvalue
+# 2308| getStmt(): [BlockStmt] { ... }
+# 2309| getStmt(0): [DeclStmt] declaration
+# 2309| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
# 2309| Type = [Struct] String
-# 2309| ValueCategory = lvalue
-# 2307| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
-# 2307| Type = [ClassTemplateInstantiation,Struct] iterator
-# 2307| ValueCategory = lvalue
-# 2307| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2307| Type = [VoidType] void
-# 2307| ValueCategory = prvalue
-# 2307| getQualifier(): [VariableAccess] s
-# 2307| Type = [Struct] String
-# 2307| ValueCategory = lvalue
-# 2311| getStmt(3): [ForStmt] for(...;...;...) ...
-# 2311| getInitialization(): [DeclStmt] declaration
-# 2311| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2311| Type = [Struct] String
-# 2311| getVariable().getInitializer(): [Initializer] initializer for s
-# 2311| getExpr(): [ConstructorCall] call to String
-# 2311| Type = [VoidType] void
-# 2311| ValueCategory = prvalue
-# 2311| getArgument(0): hello
-# 2311| Type = [ArrayType] const char[6]
-# 2311| Value = [StringLiteral] "hello"
-# 2311| ValueCategory = lvalue
-# 2311| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
-# 2311| Type = [PointerType] const char *
-# 2311| ValueCategory = prvalue
-# 2311| getDeclarationEntry(1): [VariableDeclarationEntry] definition of s2
-# 2311| Type = [Struct] String
-# 2311| getVariable().getInitializer(): [Initializer] initializer for s2
-# 2311| getExpr(): [ConstructorCall] call to String
-# 2311| Type = [VoidType] void
-# 2311| ValueCategory = prvalue
-# 2311| getArgument(0): world
-# 2311| Type = [ArrayType] const char[6]
-# 2311| Value = [StringLiteral] "world"
-# 2311| ValueCategory = lvalue
-# 2311| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
-# 2311| Type = [PointerType] const char *
-# 2311| ValueCategory = prvalue
-# 2311| getCondition(): [NEExpr] ... != ...
-# 2311| Type = [BoolType] bool
-# 2311| ValueCategory = prvalue
-# 2311| getLeftOperand(): [VariableAccess] c
-# 2311| Type = [PlainCharType] char
-# 2311| ValueCategory = prvalue(load)
-# 2311| getRightOperand(): [Literal] 0
-# 2311| Type = [IntType] int
-# 2311| Value = [Literal] 0
-# 2311| ValueCategory = prvalue
-# 2311| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
-# 2311| Conversion = [IntegralConversion] integral conversion
-# 2311| Type = [IntType] int
-# 2311| ValueCategory = prvalue
-# 2311| getUpdate(): [AssignExpr] ... = ...
-# 2311| Type = [PlainCharType] char
-# 2311| ValueCategory = lvalue
-# 2311| getLValue(): [VariableAccess] c
-# 2311| Type = [PlainCharType] char
-# 2311| ValueCategory = lvalue
-# 2311| getRValue(): [FunctionCall] call to pop_back
-# 2311| Type = [PlainCharType] char
-# 2311| ValueCategory = prvalue
-# 2311| getQualifier(): [VariableAccess] s
-# 2311| Type = [Struct] String
-# 2311| ValueCategory = lvalue
-# 2311| getStmt(): [BlockStmt] { ... }
-# 2312| getStmt(0): [ExprStmt] ExprStmt
-# 2312| getExpr(): [AssignExpr] ... = ...
-# 2312| Type = [PlainCharType] char
+# 2309| getVariable().getInitializer(): [Initializer] initializer for s2
+# 2309| getExpr(): [ConstructorCall] call to String
+# 2309| Type = [VoidType] void
+# 2309| ValueCategory = prvalue
+# 2310| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2310| Type = [VoidType] void
+# 2310| ValueCategory = prvalue
+# 2310| getQualifier(): [VariableAccess] s2
+# 2310| Type = [Struct] String
+# 2310| ValueCategory = lvalue
+# 2308| getImplicitDestructorCall(0): [DestructorCall] call to ~vector
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2308| Type = [ClassTemplateInstantiation,Struct] vector
+# 2308| ValueCategory = xvalue
+# 2308| getUpdate().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
+# 2308| Type = [ClassTemplateInstantiation,Struct] iterator
+# 2308| ValueCategory = lvalue
+# 2308| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2308| Type = [VoidType] void
+# 2308| ValueCategory = prvalue
+# 2308| getQualifier(): [VariableAccess] s
+# 2308| Type = [Struct] String
+# 2308| ValueCategory = lvalue
+# 2312| getStmt(3): [ForStmt] for(...;...;...) ...
+# 2312| getInitialization(): [DeclStmt] declaration
+# 2312| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2312| Type = [Struct] String
+# 2312| getVariable().getInitializer(): [Initializer] initializer for s
+# 2312| getExpr(): [ConstructorCall] call to String
+# 2312| Type = [VoidType] void
+# 2312| ValueCategory = prvalue
+# 2312| getArgument(0): hello
+# 2312| Type = [ArrayType] const char[6]
+# 2312| Value = [StringLiteral] "hello"
+# 2312| ValueCategory = lvalue
+# 2312| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
+# 2312| Type = [PointerType] const char *
+# 2312| ValueCategory = prvalue
+# 2312| getDeclarationEntry(1): [VariableDeclarationEntry] definition of s2
+# 2312| Type = [Struct] String
+# 2312| getVariable().getInitializer(): [Initializer] initializer for s2
+# 2312| getExpr(): [ConstructorCall] call to String
+# 2312| Type = [VoidType] void
+# 2312| ValueCategory = prvalue
+# 2312| getArgument(0): world
+# 2312| Type = [ArrayType] const char[6]
+# 2312| Value = [StringLiteral] "world"
+# 2312| ValueCategory = lvalue
+# 2312| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
+# 2312| Type = [PointerType] const char *
+# 2312| ValueCategory = prvalue
+# 2312| getCondition(): [NEExpr] ... != ...
+# 2312| Type = [BoolType] bool
+# 2312| ValueCategory = prvalue
+# 2312| getLeftOperand(): [VariableAccess] c
+# 2312| Type = [PlainCharType] char
+# 2312| ValueCategory = prvalue(load)
+# 2312| getRightOperand(): [Literal] 0
+# 2312| Type = [IntType] int
+# 2312| Value = [Literal] 0
+# 2312| ValueCategory = prvalue
+# 2312| getLeftOperand().getFullyConverted(): [CStyleCast] (int)...
+# 2312| Conversion = [IntegralConversion] integral conversion
+# 2312| Type = [IntType] int
+# 2312| ValueCategory = prvalue
+# 2312| getUpdate(): [AssignExpr] ... = ...
+# 2312| Type = [PlainCharType] char
+# 2312| ValueCategory = lvalue
+# 2312| getLValue(): [VariableAccess] c
+# 2312| Type = [PlainCharType] char
+# 2312| ValueCategory = lvalue
+# 2312| getRValue(): [FunctionCall] call to pop_back
+# 2312| Type = [PlainCharType] char
+# 2312| ValueCategory = prvalue
+# 2312| getQualifier(): [VariableAccess] s
+# 2312| Type = [Struct] String
# 2312| ValueCategory = lvalue
-# 2312| getLValue(): [VariableAccess] c
-# 2312| Type = [PlainCharType] char
-# 2312| ValueCategory = lvalue
-# 2312| getRValue(): [Literal] 0
-# 2312| Type = [IntType] int
-# 2312| Value = [Literal] 0
-# 2312| ValueCategory = prvalue
-# 2312| getRValue().getFullyConverted(): [CStyleCast] (char)...
-# 2312| Conversion = [IntegralConversion] integral conversion
-# 2312| Type = [PlainCharType] char
-# 2312| Value = [CStyleCast] 0
-# 2312| ValueCategory = prvalue
-# 2311| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2311| Type = [VoidType] void
-# 2311| ValueCategory = prvalue
-# 2311| getQualifier(): [VariableAccess] s2
-# 2311| Type = [Struct] String
-# 2311| ValueCategory = lvalue
-# 2311| getImplicitDestructorCall(1): [DestructorCall] call to ~String
-# 2311| Type = [VoidType] void
-# 2311| ValueCategory = prvalue
-# 2311| getQualifier(): [VariableAccess] s
-# 2311| Type = [Struct] String
-# 2311| ValueCategory = lvalue
-# 2314| getStmt(4): [ReturnStmt] return ...
-# 2316| [TopLevelFunction] void IfDestructors2(bool)
-# 2316| :
-# 2316| getParameter(0): [Parameter] b
-# 2316| Type = [BoolType] bool
-# 2316| getEntryPoint(): [BlockStmt] { ... }
-# 2317| getStmt(0): [IfStmt] if (...) ...
-# 2317| getInitialization(): [DeclStmt] declaration
-# 2317| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2317| Type = [Struct] String
-# 2317| getVariable().getInitializer(): [Initializer] initializer for s
-# 2317| getExpr(): [ConstructorCall] call to String
-# 2317| Type = [VoidType] void
-# 2317| ValueCategory = prvalue
-# 2317| getArgument(0): hello
-# 2317| Type = [ArrayType] const char[6]
-# 2317| Value = [StringLiteral] "hello"
-# 2317| ValueCategory = lvalue
-# 2317| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
-# 2317| Type = [PointerType] const char *
-# 2317| ValueCategory = prvalue
-# 2317| getCondition(): [VariableAccess] b
-# 2317| Type = [BoolType] bool
-# 2317| ValueCategory = prvalue(load)
-# 2317| getThen(): [BlockStmt] { ... }
-# 2318| getStmt(0): [DeclStmt] declaration
-# 2318| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2318| Type = [IntType] int
-# 2318| getVariable().getInitializer(): [Initializer] initializer for x
-# 2318| getExpr(): [Literal] 0
-# 2318| Type = [IntType] int
-# 2318| Value = [Literal] 0
+# 2312| getStmt(): [BlockStmt] { ... }
+# 2313| getStmt(0): [ExprStmt] ExprStmt
+# 2313| getExpr(): [AssignExpr] ... = ...
+# 2313| Type = [PlainCharType] char
+# 2313| ValueCategory = lvalue
+# 2313| getLValue(): [VariableAccess] c
+# 2313| Type = [PlainCharType] char
+# 2313| ValueCategory = lvalue
+# 2313| getRValue(): [Literal] 0
+# 2313| Type = [IntType] int
+# 2313| Value = [Literal] 0
+# 2313| ValueCategory = prvalue
+# 2313| getRValue().getFullyConverted(): [CStyleCast] (char)...
+# 2313| Conversion = [IntegralConversion] integral conversion
+# 2313| Type = [PlainCharType] char
+# 2313| Value = [CStyleCast] 0
+# 2313| ValueCategory = prvalue
+# 2312| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2312| Type = [VoidType] void
+# 2312| ValueCategory = prvalue
+# 2312| getQualifier(): [VariableAccess] s2
+# 2312| Type = [Struct] String
+# 2312| ValueCategory = lvalue
+# 2312| getImplicitDestructorCall(1): [DestructorCall] call to ~String
+# 2312| Type = [VoidType] void
+# 2312| ValueCategory = prvalue
+# 2312| getQualifier(): [VariableAccess] s
+# 2312| Type = [Struct] String
+# 2312| ValueCategory = lvalue
+# 2315| getStmt(4): [ReturnStmt] return ...
+# 2317| [TopLevelFunction] void IfDestructors2(bool)
+# 2317| :
+# 2317| getParameter(0): [Parameter] b
+# 2317| Type = [BoolType] bool
+# 2317| getEntryPoint(): [BlockStmt] { ... }
+# 2318| getStmt(0): [IfStmt] if (...) ...
+# 2318| getInitialization(): [DeclStmt] declaration
+# 2318| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2318| Type = [Struct] String
+# 2318| getVariable().getInitializer(): [Initializer] initializer for s
+# 2318| getExpr(): [ConstructorCall] call to String
+# 2318| Type = [VoidType] void
+# 2318| ValueCategory = prvalue
+# 2318| getArgument(0): hello
+# 2318| Type = [ArrayType] const char[6]
+# 2318| Value = [StringLiteral] "hello"
+# 2318| ValueCategory = lvalue
+# 2318| getArgument(0).getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
+# 2318| Type = [PointerType] const char *
# 2318| ValueCategory = prvalue
-# 2319| getElse(): [BlockStmt] { ... }
-# 2320| getStmt(0): [DeclStmt] declaration
-# 2320| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
-# 2320| Type = [IntType] int
-# 2320| getVariable().getInitializer(): [Initializer] initializer for y
-# 2320| getExpr(): [Literal] 0
-# 2320| Type = [IntType] int
-# 2320| Value = [Literal] 0
-# 2320| ValueCategory = prvalue
-# 2321| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2321| Type = [VoidType] void
-# 2321| ValueCategory = prvalue
-# 2321| getQualifier(): [VariableAccess] s
-# 2321| Type = [Struct] String
-# 2321| ValueCategory = lvalue
-# 2322| getStmt(1): [ReturnStmt] return ...
-# 2324| [CopyAssignmentOperator] Bool& Bool::operator=(Bool const&)
-# 2324| :
+# 2318| getCondition(): [VariableAccess] b
+# 2318| Type = [BoolType] bool
+# 2318| ValueCategory = prvalue(load)
+# 2318| getThen(): [BlockStmt] { ... }
+# 2319| getStmt(0): [DeclStmt] declaration
+# 2319| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
+# 2319| Type = [IntType] int
+# 2319| getVariable().getInitializer(): [Initializer] initializer for x
+# 2319| getExpr(): [Literal] 0
+# 2319| Type = [IntType] int
+# 2319| Value = [Literal] 0
+# 2319| ValueCategory = prvalue
+# 2320| getElse(): [BlockStmt] { ... }
+# 2321| getStmt(0): [DeclStmt] declaration
+# 2321| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
+# 2321| Type = [IntType] int
+# 2321| getVariable().getInitializer(): [Initializer] initializer for y
+# 2321| getExpr(): [Literal] 0
+# 2321| Type = [IntType] int
+# 2321| Value = [Literal] 0
+# 2321| ValueCategory = prvalue
+# 2322| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2322| Type = [VoidType] void
+# 2322| ValueCategory = prvalue
+# 2322| getQualifier(): [VariableAccess] s
+# 2322| Type = [Struct] String
+# 2322| ValueCategory = lvalue
+# 2323| getStmt(1): [ReturnStmt] return ...
+# 2325| [CopyAssignmentOperator] Bool& Bool::operator=(Bool const&)
+# 2325| :
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Bool &
-# 2324| [CopyConstructor] void Bool::Bool(Bool const&)
-# 2324| :
+# 2325| [CopyConstructor] void Bool::Bool(Bool const&)
+# 2325| :
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Bool &
-# 2326| [Constructor] void Bool::Bool(bool)
-# 2326| :
-# 2326| getParameter(0): [Parameter] b_
-# 2326| Type = [BoolType] bool
-# 2327| [ConversionOperator] bool Bool::operator bool()
+# 2327| [Constructor] void Bool::Bool(bool)
# 2327| :
-# 2328| [Destructor] void Bool::~Bool()
+# 2327| getParameter(0): [Parameter] b_
+# 2327| Type = [BoolType] bool
+# 2328| [ConversionOperator] bool Bool::operator bool()
# 2328| :
-# 2331| [TopLevelFunction] void IfDestructors3(bool)
-# 2331| :
-# 2331| getParameter(0): [Parameter] b
-# 2331| Type = [BoolType] bool
-# 2331| getEntryPoint(): [BlockStmt] { ... }
-# 2332| getStmt(0): [IfStmt] if (...) ...
-# 2332| getCondition(): [ConditionDeclExpr] (condition decl)
-# 2332| Type = [BoolType] bool
-# 2332| ValueCategory = prvalue
-# 2332| getChild(0): [FunctionCall] call to operator bool
-# 2332| Type = [BoolType] bool
-# 2332| ValueCategory = prvalue
-# 2332| getQualifier(): [VariableAccess] B
-# 2332| Type = [Class] Bool
-# 2332| ValueCategory = prvalue(load)
-# 2332| getInitializingExpr(): [ConstructorCall] call to Bool
-# 2332| Type = [VoidType] void
-# 2332| ValueCategory = prvalue
-# 2332| getArgument(0): [VariableAccess] b
-# 2332| Type = [BoolType] bool
-# 2332| ValueCategory = prvalue(load)
-# 2332| getThen(): [BlockStmt] { ... }
-# 2333| getStmt(0): [DeclStmt] declaration
-# 2333| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s1
-# 2333| Type = [Struct] String
-# 2333| getVariable().getInitializer(): [Initializer] initializer for s1
-# 2333| getExpr(): [ConstructorCall] call to String
-# 2333| Type = [VoidType] void
-# 2333| ValueCategory = prvalue
-# 2334| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2334| Type = [VoidType] void
-# 2334| ValueCategory = prvalue
-# 2334| getQualifier(): [VariableAccess] s1
+# 2329| [Destructor] void Bool::~Bool()
+# 2329| :
+# 2332| [TopLevelFunction] void IfDestructors3(bool)
+# 2332| :
+# 2332| getParameter(0): [Parameter] b
+# 2332| Type = [BoolType] bool
+# 2332| getEntryPoint(): [BlockStmt] { ... }
+# 2333| getStmt(0): [IfStmt] if (...) ...
+# 2333| getCondition(): [ConditionDeclExpr] (condition decl)
+# 2333| Type = [BoolType] bool
+# 2333| ValueCategory = prvalue
+# 2333| getChild(0): [FunctionCall] call to operator bool
+# 2333| Type = [BoolType] bool
+# 2333| ValueCategory = prvalue
+# 2333| getQualifier(): [VariableAccess] B
+# 2333| Type = [Class] Bool
+# 2333| ValueCategory = prvalue(load)
+# 2333| getInitializingExpr(): [ConstructorCall] call to Bool
+# 2333| Type = [VoidType] void
+# 2333| ValueCategory = prvalue
+# 2333| getArgument(0): [VariableAccess] b
+# 2333| Type = [BoolType] bool
+# 2333| ValueCategory = prvalue(load)
+# 2333| getThen(): [BlockStmt] { ... }
+# 2334| getStmt(0): [DeclStmt] declaration
+# 2334| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s1
# 2334| Type = [Struct] String
-# 2334| ValueCategory = lvalue
-# 2334| getElse(): [BlockStmt] { ... }
-# 2335| getStmt(0): [DeclStmt] declaration
-# 2335| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
+# 2334| getVariable().getInitializer(): [Initializer] initializer for s1
+# 2334| getExpr(): [ConstructorCall] call to String
+# 2334| Type = [VoidType] void
+# 2334| ValueCategory = prvalue
+# 2335| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2335| Type = [VoidType] void
+# 2335| ValueCategory = prvalue
+# 2335| getQualifier(): [VariableAccess] s1
# 2335| Type = [Struct] String
-# 2335| getVariable().getInitializer(): [Initializer] initializer for s2
-# 2335| getExpr(): [ConstructorCall] call to String
-# 2335| Type = [VoidType] void
-# 2335| ValueCategory = prvalue
-# 2336| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2336| Type = [VoidType] void
-# 2336| ValueCategory = prvalue
-# 2336| getQualifier(): [VariableAccess] s2
+# 2335| ValueCategory = lvalue
+# 2335| getElse(): [BlockStmt] { ... }
+# 2336| getStmt(0): [DeclStmt] declaration
+# 2336| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s2
# 2336| Type = [Struct] String
-# 2336| ValueCategory = lvalue
-# 2336| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
-# 2336| Type = [VoidType] void
-# 2336| ValueCategory = prvalue
-# 2336| getQualifier(): [VariableAccess] B
-# 2336| Type = [Class] Bool
-# 2336| ValueCategory = lvalue
-# 2337| getStmt(1): [ReturnStmt] return ...
-# 2339| [TopLevelFunction] void WhileLoopDestructors(bool)
-# 2339| :
-# 2339| getParameter(0): [Parameter] b
-# 2339| Type = [BoolType] bool
-# 2339| getEntryPoint(): [BlockStmt] { ... }
-# 2340| getStmt(0): [BlockStmt] { ... }
-# 2341| getStmt(0): [DeclStmt] declaration
-# 2341| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2341| Type = [Struct] String
-# 2341| getVariable().getInitializer(): [Initializer] initializer for s
-# 2341| getExpr(): [ConstructorCall] call to String
-# 2341| Type = [VoidType] void
-# 2341| ValueCategory = prvalue
-# 2342| getStmt(1): [WhileStmt] while (...) ...
-# 2342| getCondition(): [VariableAccess] b
-# 2342| Type = [BoolType] bool
-# 2342| ValueCategory = prvalue(load)
-# 2342| getStmt(): [BlockStmt] { ... }
-# 2343| getStmt(0): [ExprStmt] ExprStmt
-# 2343| getExpr(): [AssignExpr] ... = ...
-# 2343| Type = [BoolType] bool
-# 2343| ValueCategory = lvalue
-# 2343| getLValue(): [VariableAccess] b
-# 2343| Type = [BoolType] bool
-# 2343| ValueCategory = lvalue
-# 2343| getRValue(): [Literal] 0
-# 2343| Type = [BoolType] bool
-# 2343| Value = [Literal] 0
-# 2343| ValueCategory = prvalue
-# 2345| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2345| Type = [VoidType] void
-# 2345| ValueCategory = prvalue
-# 2345| getQualifier(): [VariableAccess] s
-# 2345| Type = [Struct] String
-# 2345| ValueCategory = lvalue
-# 2347| getStmt(1): [BlockStmt] { ... }
-# 2348| getStmt(0): [WhileStmt] while (...) ...
-# 2348| getCondition(): [ConditionDeclExpr] (condition decl)
-# 2348| Type = [BoolType] bool
-# 2348| ValueCategory = prvalue
-# 2348| getChild(0): [FunctionCall] call to operator bool
-# 2348| Type = [BoolType] bool
-# 2348| ValueCategory = prvalue
-# 2348| getQualifier(): [VariableAccess] B
-# 2348| Type = [Class] Bool
-# 2348| ValueCategory = prvalue(load)
-# 2348| getInitializingExpr(): [ConstructorCall] call to Bool
-# 2348| Type = [VoidType] void
-# 2348| ValueCategory = prvalue
-# 2348| getArgument(0): [VariableAccess] b
-# 2348| Type = [BoolType] bool
-# 2348| ValueCategory = prvalue(load)
-# 2348| getStmt(): [BlockStmt] { ... }
-# 2349| getStmt(0): [ExprStmt] ExprStmt
-# 2349| getExpr(): [AssignExpr] ... = ...
+# 2336| getVariable().getInitializer(): [Initializer] initializer for s2
+# 2336| getExpr(): [ConstructorCall] call to String
+# 2336| Type = [VoidType] void
+# 2336| ValueCategory = prvalue
+# 2337| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2337| Type = [VoidType] void
+# 2337| ValueCategory = prvalue
+# 2337| getQualifier(): [VariableAccess] s2
+# 2337| Type = [Struct] String
+# 2337| ValueCategory = lvalue
+# 2337| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
+# 2337| Type = [VoidType] void
+# 2337| ValueCategory = prvalue
+# 2337| getQualifier(): [VariableAccess] B
+# 2337| Type = [Class] Bool
+# 2337| ValueCategory = lvalue
+# 2338| getStmt(1): [ReturnStmt] return ...
+# 2340| [TopLevelFunction] void WhileLoopDestructors(bool)
+# 2340| :
+# 2340| getParameter(0): [Parameter] b
+# 2340| Type = [BoolType] bool
+# 2340| getEntryPoint(): [BlockStmt] { ... }
+# 2341| getStmt(0): [BlockStmt] { ... }
+# 2342| getStmt(0): [DeclStmt] declaration
+# 2342| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2342| Type = [Struct] String
+# 2342| getVariable().getInitializer(): [Initializer] initializer for s
+# 2342| getExpr(): [ConstructorCall] call to String
+# 2342| Type = [VoidType] void
+# 2342| ValueCategory = prvalue
+# 2343| getStmt(1): [WhileStmt] while (...) ...
+# 2343| getCondition(): [VariableAccess] b
+# 2343| Type = [BoolType] bool
+# 2343| ValueCategory = prvalue(load)
+# 2343| getStmt(): [BlockStmt] { ... }
+# 2344| getStmt(0): [ExprStmt] ExprStmt
+# 2344| getExpr(): [AssignExpr] ... = ...
+# 2344| Type = [BoolType] bool
+# 2344| ValueCategory = lvalue
+# 2344| getLValue(): [VariableAccess] b
+# 2344| Type = [BoolType] bool
+# 2344| ValueCategory = lvalue
+# 2344| getRValue(): [Literal] 0
+# 2344| Type = [BoolType] bool
+# 2344| Value = [Literal] 0
+# 2344| ValueCategory = prvalue
+# 2346| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2346| Type = [VoidType] void
+# 2346| ValueCategory = prvalue
+# 2346| getQualifier(): [VariableAccess] s
+# 2346| Type = [Struct] String
+# 2346| ValueCategory = lvalue
+# 2348| getStmt(1): [BlockStmt] { ... }
+# 2349| getStmt(0): [WhileStmt] while (...) ...
+# 2349| getCondition(): [ConditionDeclExpr] (condition decl)
+# 2349| Type = [BoolType] bool
+# 2349| ValueCategory = prvalue
+# 2349| getChild(0): [FunctionCall] call to operator bool
+# 2349| Type = [BoolType] bool
+# 2349| ValueCategory = prvalue
+# 2349| getQualifier(): [VariableAccess] B
+# 2349| Type = [Class] Bool
+# 2349| ValueCategory = prvalue(load)
+# 2349| getInitializingExpr(): [ConstructorCall] call to Bool
+# 2349| Type = [VoidType] void
+# 2349| ValueCategory = prvalue
+# 2349| getArgument(0): [VariableAccess] b
# 2349| Type = [BoolType] bool
-# 2349| ValueCategory = lvalue
-# 2349| getLValue(): [VariableAccess] b
-# 2349| Type = [BoolType] bool
-# 2349| ValueCategory = lvalue
-# 2349| getRValue(): [Literal] 0
-# 2349| Type = [BoolType] bool
-# 2349| Value = [Literal] 0
-# 2349| ValueCategory = prvalue
-# 2350| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
-# 2350| Type = [VoidType] void
-# 2350| ValueCategory = prvalue
-# 2350| getQualifier(): [VariableAccess] B
-# 2350| Type = [Class] Bool
+# 2349| ValueCategory = prvalue(load)
+# 2349| getStmt(): [BlockStmt] { ... }
+# 2350| getStmt(0): [ExprStmt] ExprStmt
+# 2350| getExpr(): [AssignExpr] ... = ...
+# 2350| Type = [BoolType] bool
# 2350| ValueCategory = lvalue
-# 2350| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
-# 2350| Type = [VoidType] void
-# 2350| ValueCategory = prvalue
-# 2350| getQualifier(): [VariableAccess] B
-# 2350| Type = [Class] Bool
-# 2350| ValueCategory = lvalue
-# 2352| getStmt(2): [ReturnStmt] return ...
-# 2354| [TopLevelFunction] void VoidFunc()
-# 2354| :
-# 2354| getEntryPoint(): [BlockStmt] { ... }
-# 2354| getStmt(0): [ReturnStmt] return ...
-# 2356| [TopLevelFunction] void IfReturnDestructors(bool)
-# 2356| :
-# 2356| getParameter(0): [Parameter] b
-# 2356| Type = [BoolType] bool
-# 2356| getEntryPoint(): [BlockStmt] { ... }
-# 2357| getStmt(0): [DeclStmt] declaration
-# 2357| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2357| Type = [Struct] String
-# 2357| getVariable().getInitializer(): [Initializer] initializer for s
-# 2357| getExpr(): [ConstructorCall] call to String
-# 2357| Type = [VoidType] void
-# 2357| ValueCategory = prvalue
-# 2358| getStmt(1): [IfStmt] if (...) ...
-# 2358| getCondition(): [VariableAccess] b
-# 2358| Type = [BoolType] bool
-# 2358| ValueCategory = prvalue(load)
-# 2358| getThen(): [BlockStmt] { ... }
-# 2359| getStmt(0): [ReturnStmt] return ...
-# 2365| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2365| Type = [VoidType] void
-# 2365| ValueCategory = prvalue
-# 2365| getQualifier(): [VariableAccess] s
-# 2365| Type = [Struct] String
-# 2365| ValueCategory = lvalue
-# 2361| getStmt(2): [IfStmt] if (...) ...
-# 2361| getCondition(): [VariableAccess] b
-# 2361| Type = [BoolType] bool
-# 2361| ValueCategory = prvalue(load)
-# 2361| getThen(): [BlockStmt] { ... }
-# 2362| getStmt(0): [ReturnStmt] return ...
-# 2362| getExpr(): [FunctionCall] call to VoidFunc
-# 2362| Type = [VoidType] void
-# 2362| ValueCategory = prvalue
-# 2365| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2365| Type = [VoidType] void
-# 2365| ValueCategory = prvalue
-# 2365| getQualifier(): [VariableAccess] s
-# 2365| Type = [Struct] String
-# 2365| ValueCategory = lvalue
-# 2364| getStmt(3): [ExprStmt] ExprStmt
-# 2364| getExpr(): [VariableAccess] s
-# 2364| Type = [Struct] String
-# 2364| ValueCategory = lvalue
-# 2365| getStmt(4): [ReturnStmt] return ...
-# 2365| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2365| Type = [VoidType] void
-# 2365| ValueCategory = prvalue
-# 2365| getQualifier(): [VariableAccess] s
-# 2365| Type = [Struct] String
-# 2365| ValueCategory = lvalue
-# 2367| [TopLevelFunction] int IfReturnDestructors3(bool)
-# 2367| :
-# 2367| getParameter(0): [Parameter] b
-# 2367| Type = [BoolType] bool
-# 2367| getEntryPoint(): [BlockStmt] { ... }
-# 2368| getStmt(0): [DeclStmt] declaration
-# 2368| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2368| Type = [Struct] String
-# 2368| getVariable().getInitializer(): [Initializer] initializer for s
-# 2368| getExpr(): [ConstructorCall] call to String
-# 2368| Type = [VoidType] void
-# 2368| ValueCategory = prvalue
-# 2369| getStmt(1): [IfStmt] if (...) ...
-# 2369| getCondition(): [VariableAccess] b
-# 2369| Type = [BoolType] bool
-# 2369| ValueCategory = prvalue(load)
-# 2369| getThen(): [BlockStmt] { ... }
-# 2370| getStmt(0): [ReturnStmt] return ...
-# 2370| getExpr(): [Literal] 1
-# 2370| Type = [IntType] int
-# 2370| Value = [Literal] 1
-# 2370| ValueCategory = prvalue
-# 2373| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2373| Type = [VoidType] void
-# 2373| ValueCategory = prvalue
-# 2373| getQualifier(): [VariableAccess] s
-# 2373| Type = [Struct] String
-# 2373| ValueCategory = lvalue
-# 2372| getStmt(2): [ReturnStmt] return ...
-# 2372| getExpr(): [Literal] 0
-# 2372| Type = [IntType] int
-# 2372| Value = [Literal] 0
-# 2372| ValueCategory = prvalue
-# 2373| getImplicitDestructorCall(0): [DestructorCall] call to ~String
-# 2373| Type = [VoidType] void
+# 2350| getLValue(): [VariableAccess] b
+# 2350| Type = [BoolType] bool
+# 2350| ValueCategory = lvalue
+# 2350| getRValue(): [Literal] 0
+# 2350| Type = [BoolType] bool
+# 2350| Value = [Literal] 0
+# 2350| ValueCategory = prvalue
+# 2351| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
+# 2351| Type = [VoidType] void
+# 2351| ValueCategory = prvalue
+# 2351| getQualifier(): [VariableAccess] B
+# 2351| Type = [Class] Bool
+# 2351| ValueCategory = lvalue
+# 2351| getImplicitDestructorCall(0): [DestructorCall] call to ~Bool
+# 2351| Type = [VoidType] void
+# 2351| ValueCategory = prvalue
+# 2351| getQualifier(): [VariableAccess] B
+# 2351| Type = [Class] Bool
+# 2351| ValueCategory = lvalue
+# 2353| getStmt(2): [ReturnStmt] return ...
+# 2355| [TopLevelFunction] void VoidFunc()
+# 2355| :
+# 2355| getEntryPoint(): [BlockStmt] { ... }
+# 2355| getStmt(0): [ReturnStmt] return ...
+# 2357| [TopLevelFunction] void IfReturnDestructors(bool)
+# 2357| :
+# 2357| getParameter(0): [Parameter] b
+# 2357| Type = [BoolType] bool
+# 2357| getEntryPoint(): [BlockStmt] { ... }
+# 2358| getStmt(0): [DeclStmt] declaration
+# 2358| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2358| Type = [Struct] String
+# 2358| getVariable().getInitializer(): [Initializer] initializer for s
+# 2358| getExpr(): [ConstructorCall] call to String
+# 2358| Type = [VoidType] void
+# 2358| ValueCategory = prvalue
+# 2359| getStmt(1): [IfStmt] if (...) ...
+# 2359| getCondition(): [VariableAccess] b
+# 2359| Type = [BoolType] bool
+# 2359| ValueCategory = prvalue(load)
+# 2359| getThen(): [BlockStmt] { ... }
+# 2360| getStmt(0): [ReturnStmt] return ...
+# 2366| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2366| Type = [VoidType] void
+# 2366| ValueCategory = prvalue
+# 2366| getQualifier(): [VariableAccess] s
+# 2366| Type = [Struct] String
+# 2366| ValueCategory = lvalue
+# 2362| getStmt(2): [IfStmt] if (...) ...
+# 2362| getCondition(): [VariableAccess] b
+# 2362| Type = [BoolType] bool
+# 2362| ValueCategory = prvalue(load)
+# 2362| getThen(): [BlockStmt] { ... }
+# 2363| getStmt(0): [ReturnStmt] return ...
+# 2363| getExpr(): [FunctionCall] call to VoidFunc
+# 2363| Type = [VoidType] void
+# 2363| ValueCategory = prvalue
+# 2366| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2366| Type = [VoidType] void
+# 2366| ValueCategory = prvalue
+# 2366| getQualifier(): [VariableAccess] s
+# 2366| Type = [Struct] String
+# 2366| ValueCategory = lvalue
+# 2365| getStmt(3): [ExprStmt] ExprStmt
+# 2365| getExpr(): [VariableAccess] s
+# 2365| Type = [Struct] String
+# 2365| ValueCategory = lvalue
+# 2366| getStmt(4): [ReturnStmt] return ...
+# 2366| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2366| Type = [VoidType] void
+# 2366| ValueCategory = prvalue
+# 2366| getQualifier(): [VariableAccess] s
+# 2366| Type = [Struct] String
+# 2366| ValueCategory = lvalue
+# 2368| [TopLevelFunction] int IfReturnDestructors3(bool)
+# 2368| :
+# 2368| getParameter(0): [Parameter] b
+# 2368| Type = [BoolType] bool
+# 2368| getEntryPoint(): [BlockStmt] { ... }
+# 2369| getStmt(0): [DeclStmt] declaration
+# 2369| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2369| Type = [Struct] String
+# 2369| getVariable().getInitializer(): [Initializer] initializer for s
+# 2369| getExpr(): [ConstructorCall] call to String
+# 2369| Type = [VoidType] void
+# 2369| ValueCategory = prvalue
+# 2370| getStmt(1): [IfStmt] if (...) ...
+# 2370| getCondition(): [VariableAccess] b
+# 2370| Type = [BoolType] bool
+# 2370| ValueCategory = prvalue(load)
+# 2370| getThen(): [BlockStmt] { ... }
+# 2371| getStmt(0): [ReturnStmt] return ...
+# 2371| getExpr(): [Literal] 1
+# 2371| Type = [IntType] int
+# 2371| Value = [Literal] 1
+# 2371| ValueCategory = prvalue
+# 2374| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2374| Type = [VoidType] void
+# 2374| ValueCategory = prvalue
+# 2374| getQualifier(): [VariableAccess] s
+# 2374| Type = [Struct] String
+# 2374| ValueCategory = lvalue
+# 2373| getStmt(2): [ReturnStmt] return ...
+# 2373| getExpr(): [Literal] 0
+# 2373| Type = [IntType] int
+# 2373| Value = [Literal] 0
# 2373| ValueCategory = prvalue
-# 2373| getQualifier(): [VariableAccess] s
-# 2373| Type = [Struct] String
-# 2373| ValueCategory = lvalue
-# 2375| [TopLevelFunction] void VoidReturnDestructors()
-# 2375| :
-# 2375| getEntryPoint(): [BlockStmt] { ... }
-# 2376| getStmt(0): [DeclStmt] declaration
-# 2376| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
-# 2376| Type = [Struct] String
-# 2376| getVariable().getInitializer(): [Initializer] initializer for s
-# 2376| getExpr(): [ConstructorCall] call to String
-# 2376| Type = [VoidType] void
-# 2376| ValueCategory = prvalue
-# 2377| getStmt(1): [ReturnStmt] return ...
-# 2377| getExpr(): [FunctionCall] call to VoidFunc
-# 2377| Type = [VoidType] void
-# 2377| ValueCategory = prvalue
-# 2378| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2374| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2374| Type = [VoidType] void
+# 2374| ValueCategory = prvalue
+# 2374| getQualifier(): [VariableAccess] s
+# 2374| Type = [Struct] String
+# 2374| ValueCategory = lvalue
+# 2376| [TopLevelFunction] void VoidReturnDestructors()
+# 2376| :
+# 2376| getEntryPoint(): [BlockStmt] { ... }
+# 2377| getStmt(0): [DeclStmt] declaration
+# 2377| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
+# 2377| Type = [Struct] String
+# 2377| getVariable().getInitializer(): [Initializer] initializer for s
+# 2377| getExpr(): [ConstructorCall] call to String
+# 2377| Type = [VoidType] void
+# 2377| ValueCategory = prvalue
+# 2378| getStmt(1): [ReturnStmt] return ...
+# 2378| getExpr(): [FunctionCall] call to VoidFunc
# 2378| Type = [VoidType] void
# 2378| ValueCategory = prvalue
-# 2378| getQualifier(): [VariableAccess] s
-# 2378| Type = [Struct] String
-# 2378| ValueCategory = lvalue
-# 2381| [CopyAssignmentOperator] return_routine_type::HasVoidToIntFunc& return_routine_type::HasVoidToIntFunc::operator=(return_routine_type::HasVoidToIntFunc const&)
-# 2381| :
+# 2379| getImplicitDestructorCall(0): [DestructorCall] call to ~String
+# 2379| Type = [VoidType] void
+# 2379| ValueCategory = prvalue
+# 2379| getQualifier(): [VariableAccess] s
+# 2379| Type = [Struct] String
+# 2379| ValueCategory = lvalue
+# 2382| [CopyAssignmentOperator] return_routine_type::HasVoidToIntFunc& return_routine_type::HasVoidToIntFunc::operator=(return_routine_type::HasVoidToIntFunc const&)
+# 2382| :
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const HasVoidToIntFunc &
-# 2381| [MoveAssignmentOperator] return_routine_type::HasVoidToIntFunc& return_routine_type::HasVoidToIntFunc::operator=(return_routine_type::HasVoidToIntFunc&&)
-# 2381| :
+# 2382| [MoveAssignmentOperator] return_routine_type::HasVoidToIntFunc& return_routine_type::HasVoidToIntFunc::operator=(return_routine_type::HasVoidToIntFunc&&)
+# 2382| :
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] HasVoidToIntFunc &&
-# 2383| [MemberFunction] void return_routine_type::HasVoidToIntFunc::VoidToInt(int)
-# 2383| :
-# 2383| getParameter(0): [Parameter] (unnamed parameter 0)
-# 2383| Type = [IntType] int
-# 2388| [TopLevelFunction] return_routine_type::VoidToIntMemberFunc return_routine_type::GetVoidToIntFunc()
-# 2388| :
-# 2389| getEntryPoint(): [BlockStmt] { ... }
-# 2390| getStmt(0): [ReturnStmt] return ...
-# 2390| getExpr(): [FunctionAccess] VoidToInt
-# 2390| Type = [RoutineType] ..()(..)
-# 2390| ValueCategory = prvalue
-# 2395| [TopLevelFunction] int small_operation_should_not_be_constant_folded()
-# 2395| :
-# 2395| getEntryPoint(): [BlockStmt] { ... }
-# 2396| getStmt(0): [ReturnStmt] return ...
-# 2396| getExpr(): [BitwiseXorExpr] ... ^ ...
-# 2396| Type = [IntType] int
-# 2396| Value = [BitwiseXorExpr] 3
-# 2396| ValueCategory = prvalue
-# 2396| getLeftOperand(): [Literal] 1
-# 2396| Type = [IntType] int
-# 2396| Value = [Literal] 1
-# 2396| ValueCategory = prvalue
-# 2396| getRightOperand(): [Literal] 2
-# 2396| Type = [IntType] int
-# 2396| Value = [Literal] 2
-# 2396| ValueCategory = prvalue
-# 2406| [TopLevelFunction] int large_operation_should_be_constant_folded()
-# 2406| :
-# 2406| getEntryPoint(): [BlockStmt] { ... }
-# 2407| getStmt(0): [ReturnStmt] return ...
-# 2407| getExpr(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [BitwiseXorExpr] ... ^ ...
-# 2407| Type = [IntType] int
-# 2407| Value = [BitwiseXorExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand(): [Literal] 1
-# 2407| Type = [IntType] int
-# 2407| Value = [Literal] 1
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2407| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
-# 2407| Type = [IntType] int
-# 2407| Value = [ParenthesisExpr] 0
-# 2407| ValueCategory = prvalue
-# 2410| [TopLevelFunction] void initialization_with_temp_destructor()
-# 2410| :
-# 2410| getEntryPoint(): [BlockStmt] { ... }
-# 2411| getStmt(0): [IfStmt] if (...) ...
-# 2411| getCondition(): [ConditionDeclExpr] (condition decl)
-# 2411| Type = [BoolType] bool
-# 2411| ValueCategory = prvalue
-# 2411| getVariableAccess(): [VariableAccess] x
-# 2411| Type = [PlainCharType] char
-# 2411| ValueCategory = prvalue(load)
-# 2411| getInitializingExpr(): [FunctionCall] call to get_x
-# 2411| Type = [PlainCharType] char
-# 2411| ValueCategory = prvalue
-# 2411| getQualifier(): [ConstructorCall] call to ClassWithDestructor
-# 2411| Type = [VoidType] void
-# 2411| ValueCategory = prvalue
-# 2411| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2411| Type = [VoidType] void
-# 2411| ValueCategory = prvalue
-# 2411| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2411| Type = [Class] ClassWithDestructor
-# 2411| ValueCategory = xvalue
-# 2411| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2411| Type = [Class] ClassWithDestructor
-# 2411| ValueCategory = prvalue(load)
-# 2411| getVariableAccess().getFullyConverted(): [CStyleCast] (bool)...
-# 2411| Conversion = [BoolConversion] conversion to bool
-# 2411| Type = [BoolType] bool
-# 2411| ValueCategory = prvalue
-# 2412| getThen(): [ExprStmt] ExprStmt
-# 2412| getExpr(): [PostfixIncrExpr] ... ++
+# 2384| [MemberFunction] void return_routine_type::HasVoidToIntFunc::VoidToInt(int)
+# 2384| :
+# 2384| getParameter(0): [Parameter] (unnamed parameter 0)
+# 2384| Type = [IntType] int
+# 2389| [TopLevelFunction] return_routine_type::VoidToIntMemberFunc return_routine_type::GetVoidToIntFunc()
+# 2389| :
+# 2390| getEntryPoint(): [BlockStmt] { ... }
+# 2391| getStmt(0): [ReturnStmt] return ...
+# 2391| getExpr(): [FunctionAccess] VoidToInt
+# 2391| Type = [RoutineType] ..()(..)
+# 2391| ValueCategory = prvalue
+# 2396| [TopLevelFunction] int small_operation_should_not_be_constant_folded()
+# 2396| :
+# 2396| getEntryPoint(): [BlockStmt] { ... }
+# 2397| getStmt(0): [ReturnStmt] return ...
+# 2397| getExpr(): [BitwiseXorExpr] ... ^ ...
+# 2397| Type = [IntType] int
+# 2397| Value = [BitwiseXorExpr] 3
+# 2397| ValueCategory = prvalue
+# 2397| getLeftOperand(): [Literal] 1
+# 2397| Type = [IntType] int
+# 2397| Value = [Literal] 1
+# 2397| ValueCategory = prvalue
+# 2397| getRightOperand(): [Literal] 2
+# 2397| Type = [IntType] int
+# 2397| Value = [Literal] 2
+# 2397| ValueCategory = prvalue
+# 2407| [TopLevelFunction] int large_operation_should_be_constant_folded()
+# 2407| :
+# 2407| getEntryPoint(): [BlockStmt] { ... }
+# 2408| getStmt(0): [ReturnStmt] return ...
+# 2408| getExpr(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [BitwiseXorExpr] ... ^ ...
+# 2408| Type = [IntType] int
+# 2408| Value = [BitwiseXorExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand(): [Literal] 1
+# 2408| Type = [IntType] int
+# 2408| Value = [Literal] 1
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getLeftOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2408| getExpr().getFullyConverted(): [ParenthesisExpr] (...)
+# 2408| Type = [IntType] int
+# 2408| Value = [ParenthesisExpr] 0
+# 2408| ValueCategory = prvalue
+# 2411| [TopLevelFunction] void initialization_with_temp_destructor()
+# 2411| :
+# 2411| getEntryPoint(): [BlockStmt] { ... }
+# 2412| getStmt(0): [IfStmt] if (...) ...
+# 2412| getCondition(): [ConditionDeclExpr] (condition decl)
+# 2412| Type = [BoolType] bool
+# 2412| ValueCategory = prvalue
+# 2412| getVariableAccess(): [VariableAccess] x
+# 2412| Type = [PlainCharType] char
+# 2412| ValueCategory = prvalue(load)
+# 2412| getInitializingExpr(): [FunctionCall] call to get_x
# 2412| Type = [PlainCharType] char
# 2412| ValueCategory = prvalue
-# 2412| getOperand(): [VariableAccess] x
-# 2412| Type = [PlainCharType] char
-# 2412| ValueCategory = lvalue
-# 2414| getStmt(1): [IfStmt] if (...) ...
-# 2414| getInitialization(): [DeclStmt] declaration
-# 2414| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2414| Type = [PlainCharType] char
-# 2414| getVariable().getInitializer(): [Initializer] initializer for x
-# 2414| getExpr(): [FunctionCall] call to get_x
-# 2414| Type = [PlainCharType] char
-# 2414| ValueCategory = prvalue
-# 2414| getQualifier(): [ConstructorCall] call to ClassWithDestructor
-# 2414| Type = [VoidType] void
-# 2414| ValueCategory = prvalue
-# 2414| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2414| Type = [VoidType] void
-# 2414| ValueCategory = prvalue
-# 2414| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2414| Type = [Class] ClassWithDestructor
-# 2414| ValueCategory = xvalue
-# 2414| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2414| Type = [Class] ClassWithDestructor
-# 2414| ValueCategory = prvalue(load)
-# 2414| getCondition(): [VariableAccess] x
-# 2414| Type = [PlainCharType] char
-# 2414| ValueCategory = prvalue(load)
-# 2415| getThen(): [ExprStmt] ExprStmt
-# 2415| getExpr(): [PostfixIncrExpr] ... ++
+# 2412| getQualifier(): [ConstructorCall] call to ClassWithDestructor
+# 2412| Type = [VoidType] void
+# 2412| ValueCategory = prvalue
+# 2412| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2412| Type = [VoidType] void
+# 2412| ValueCategory = prvalue
+# 2412| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2412| Type = [Class] ClassWithDestructor
+# 2412| ValueCategory = xvalue
+# 2412| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2412| Type = [Class] ClassWithDestructor
+# 2412| ValueCategory = prvalue(load)
+# 2412| getVariableAccess().getFullyConverted(): [CStyleCast] (bool)...
+# 2412| Conversion = [BoolConversion] conversion to bool
+# 2412| Type = [BoolType] bool
+# 2412| ValueCategory = prvalue
+# 2413| getThen(): [ExprStmt] ExprStmt
+# 2413| getExpr(): [PostfixIncrExpr] ... ++
+# 2413| Type = [PlainCharType] char
+# 2413| ValueCategory = prvalue
+# 2413| getOperand(): [VariableAccess] x
+# 2413| Type = [PlainCharType] char
+# 2413| ValueCategory = lvalue
+# 2415| getStmt(1): [IfStmt] if (...) ...
+# 2415| getInitialization(): [DeclStmt] declaration
+# 2415| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2415| Type = [PlainCharType] char
-# 2415| ValueCategory = prvalue
-# 2415| getOperand(): [VariableAccess] x
-# 2415| Type = [PlainCharType] char
-# 2415| ValueCategory = lvalue
-# 2414| getCondition().getFullyConverted(): [CStyleCast] (bool)...
-# 2414| Conversion = [BoolConversion] conversion to bool
-# 2414| Type = [BoolType] bool
-# 2414| ValueCategory = prvalue
-# 2417| getStmt(2): [ConstexprIfStmt] if constexpr (...) ...
-# 2417| getInitialization(): [DeclStmt] declaration
-# 2417| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2417| Type = [PlainCharType] char
-# 2417| getVariable().getInitializer(): [Initializer] initializer for x
-# 2417| getExpr(): [FunctionCall] call to get_x
-# 2417| Type = [PlainCharType] char
-# 2417| ValueCategory = prvalue
-# 2417| getQualifier(): [ConstructorCall] call to ClassWithDestructor
-# 2417| Type = [VoidType] void
-# 2417| ValueCategory = prvalue
-# 2417| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2417| Type = [VoidType] void
-# 2417| ValueCategory = prvalue
-# 2417| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2417| Type = [Class] ClassWithDestructor
-# 2417| ValueCategory = xvalue
-# 2417| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2417| Type = [Class] ClassWithDestructor
-# 2417| ValueCategory = prvalue(load)
-# 2417| getCondition(): [VariableAccess] initialization_with_destructor_bool
-# 2417| Type = [BoolType] bool
-# 2417| Value = [VariableAccess] 1
-# 2417| ValueCategory = prvalue(load)
-# 2418| getThen(): [ExprStmt] ExprStmt
-# 2418| getExpr(): [PostfixIncrExpr] ... ++
+# 2415| getVariable().getInitializer(): [Initializer] initializer for x
+# 2415| getExpr(): [FunctionCall] call to get_x
+# 2415| Type = [PlainCharType] char
+# 2415| ValueCategory = prvalue
+# 2415| getQualifier(): [ConstructorCall] call to ClassWithDestructor
+# 2415| Type = [VoidType] void
+# 2415| ValueCategory = prvalue
+# 2415| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2415| Type = [VoidType] void
+# 2415| ValueCategory = prvalue
+# 2415| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2415| Type = [Class] ClassWithDestructor
+# 2415| ValueCategory = xvalue
+# 2415| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2415| Type = [Class] ClassWithDestructor
+# 2415| ValueCategory = prvalue(load)
+# 2415| getCondition(): [VariableAccess] x
+# 2415| Type = [PlainCharType] char
+# 2415| ValueCategory = prvalue(load)
+# 2416| getThen(): [ExprStmt] ExprStmt
+# 2416| getExpr(): [PostfixIncrExpr] ... ++
+# 2416| Type = [PlainCharType] char
+# 2416| ValueCategory = prvalue
+# 2416| getOperand(): [VariableAccess] x
+# 2416| Type = [PlainCharType] char
+# 2416| ValueCategory = lvalue
+# 2415| getCondition().getFullyConverted(): [CStyleCast] (bool)...
+# 2415| Conversion = [BoolConversion] conversion to bool
+# 2415| Type = [BoolType] bool
+# 2415| ValueCategory = prvalue
+# 2418| getStmt(2): [ConstexprIfStmt] if constexpr (...) ...
+# 2418| getInitialization(): [DeclStmt] declaration
+# 2418| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2418| Type = [PlainCharType] char
-# 2418| ValueCategory = prvalue
-# 2418| getOperand(): [VariableAccess] x
-# 2418| Type = [PlainCharType] char
-# 2418| ValueCategory = lvalue
-# 2420| getStmt(3): [SwitchStmt] switch (...) ...
-# 2420| getExpr(): [ConditionDeclExpr] (condition decl)
-# 2420| Type = [IntType] int
-# 2420| ValueCategory = prvalue
-# 2420| getVariableAccess(): [VariableAccess] x
-# 2420| Type = [PlainCharType] char
-# 2420| ValueCategory = prvalue(load)
-# 2420| getInitializingExpr(): [FunctionCall] call to get_x
-# 2420| Type = [PlainCharType] char
-# 2420| ValueCategory = prvalue
-# 2420| getQualifier(): [ConstructorCall] call to ClassWithDestructor
-# 2420| Type = [VoidType] void
-# 2420| ValueCategory = prvalue
-# 2420| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2420| Type = [VoidType] void
-# 2420| ValueCategory = prvalue
-# 2420| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2420| Type = [Class] ClassWithDestructor
-# 2420| ValueCategory = xvalue
-# 2420| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2420| Type = [Class] ClassWithDestructor
-# 2420| ValueCategory = prvalue(load)
-# 2420| getVariableAccess().getFullyConverted(): [CStyleCast] (int)...
-# 2420| Conversion = [IntegralConversion] integral conversion
-# 2420| Type = [IntType] int
-# 2420| ValueCategory = prvalue
-# 2420| getStmt(): [BlockStmt] { ... }
-# 2421| getStmt(0): [SwitchCase] case ...:
-# 2421| getExpr(): [CharLiteral] 97
-# 2421| Type = [PlainCharType] char
-# 2421| Value = [CharLiteral] 97
+# 2418| getVariable().getInitializer(): [Initializer] initializer for x
+# 2418| getExpr(): [FunctionCall] call to get_x
+# 2418| Type = [PlainCharType] char
+# 2418| ValueCategory = prvalue
+# 2418| getQualifier(): [ConstructorCall] call to ClassWithDestructor
+# 2418| Type = [VoidType] void
+# 2418| ValueCategory = prvalue
+# 2418| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2418| Type = [VoidType] void
+# 2418| ValueCategory = prvalue
+# 2418| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2418| Type = [Class] ClassWithDestructor
+# 2418| ValueCategory = xvalue
+# 2418| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2418| Type = [Class] ClassWithDestructor
+# 2418| ValueCategory = prvalue(load)
+# 2418| getCondition(): [VariableAccess] initialization_with_destructor_bool
+# 2418| Type = [BoolType] bool
+# 2418| Value = [VariableAccess] 1
+# 2418| ValueCategory = prvalue(load)
+# 2419| getThen(): [ExprStmt] ExprStmt
+# 2419| getExpr(): [PostfixIncrExpr] ... ++
+# 2419| Type = [PlainCharType] char
+# 2419| ValueCategory = prvalue
+# 2419| getOperand(): [VariableAccess] x
+# 2419| Type = [PlainCharType] char
+# 2419| ValueCategory = lvalue
+# 2421| getStmt(3): [SwitchStmt] switch (...) ...
+# 2421| getExpr(): [ConditionDeclExpr] (condition decl)
+# 2421| Type = [IntType] int
+# 2421| ValueCategory = prvalue
+# 2421| getVariableAccess(): [VariableAccess] x
+# 2421| Type = [PlainCharType] char
+# 2421| ValueCategory = prvalue(load)
+# 2421| getInitializingExpr(): [FunctionCall] call to get_x
+# 2421| Type = [PlainCharType] char
+# 2421| ValueCategory = prvalue
+# 2421| getQualifier(): [ConstructorCall] call to ClassWithDestructor
+# 2421| Type = [VoidType] void
# 2421| ValueCategory = prvalue
-# 2421| getExpr().getFullyConverted(): [CStyleCast] (int)...
-# 2421| Conversion = [IntegralConversion] integral conversion
-# 2421| Type = [IntType] int
-# 2421| Value = [CStyleCast] 97
+# 2421| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2421| Type = [VoidType] void
# 2421| ValueCategory = prvalue
-# 2422| getStmt(1): [ExprStmt] ExprStmt
-# 2422| getExpr(): [PostfixIncrExpr] ... ++
+# 2421| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2421| Type = [Class] ClassWithDestructor
+# 2421| ValueCategory = xvalue
+# 2421| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2421| Type = [Class] ClassWithDestructor
+# 2421| ValueCategory = prvalue(load)
+# 2421| getVariableAccess().getFullyConverted(): [CStyleCast] (int)...
+# 2421| Conversion = [IntegralConversion] integral conversion
+# 2421| Type = [IntType] int
+# 2421| ValueCategory = prvalue
+# 2421| getStmt(): [BlockStmt] { ... }
+# 2422| getStmt(0): [SwitchCase] case ...:
+# 2422| getExpr(): [CharLiteral] 97
# 2422| Type = [PlainCharType] char
+# 2422| Value = [CharLiteral] 97
# 2422| ValueCategory = prvalue
-# 2422| getOperand(): [VariableAccess] x
-# 2422| Type = [PlainCharType] char
-# 2422| ValueCategory = lvalue
-# 2425| getStmt(4): [SwitchStmt] switch (...) ...
-# 2425| getInitialization(): [DeclStmt] declaration
-# 2425| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2425| Type = [PlainCharType] char
-# 2425| getVariable().getInitializer(): [Initializer] initializer for x
-# 2425| getExpr(): [FunctionCall] call to get_x
-# 2425| Type = [PlainCharType] char
-# 2425| ValueCategory = prvalue
-# 2425| getQualifier(): [ConstructorCall] call to ClassWithDestructor
-# 2425| Type = [VoidType] void
-# 2425| ValueCategory = prvalue
-# 2425| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2425| Type = [VoidType] void
-# 2425| ValueCategory = prvalue
-# 2425| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2425| Type = [Class] ClassWithDestructor
-# 2425| ValueCategory = xvalue
-# 2425| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2425| Type = [Class] ClassWithDestructor
-# 2425| ValueCategory = prvalue(load)
-# 2425| getExpr(): [VariableAccess] x
-# 2425| Type = [PlainCharType] char
-# 2425| ValueCategory = prvalue(load)
-# 2425| getStmt(): [BlockStmt] { ... }
-# 2426| getStmt(0): [SwitchCase] case ...:
-# 2426| getExpr(): [CharLiteral] 97
-# 2426| Type = [PlainCharType] char
-# 2426| Value = [CharLiteral] 97
-# 2426| ValueCategory = prvalue
-# 2426| getExpr().getFullyConverted(): [CStyleCast] (int)...
-# 2426| Conversion = [IntegralConversion] integral conversion
-# 2426| Type = [IntType] int
-# 2426| Value = [CStyleCast] 97
-# 2426| ValueCategory = prvalue
-# 2427| getStmt(1): [ExprStmt] ExprStmt
-# 2427| getExpr(): [PostfixIncrExpr] ... ++
+# 2422| getExpr().getFullyConverted(): [CStyleCast] (int)...
+# 2422| Conversion = [IntegralConversion] integral conversion
+# 2422| Type = [IntType] int
+# 2422| Value = [CStyleCast] 97
+# 2422| ValueCategory = prvalue
+# 2423| getStmt(1): [ExprStmt] ExprStmt
+# 2423| getExpr(): [PostfixIncrExpr] ... ++
+# 2423| Type = [PlainCharType] char
+# 2423| ValueCategory = prvalue
+# 2423| getOperand(): [VariableAccess] x
+# 2423| Type = [PlainCharType] char
+# 2423| ValueCategory = lvalue
+# 2426| getStmt(4): [SwitchStmt] switch (...) ...
+# 2426| getInitialization(): [DeclStmt] declaration
+# 2426| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
+# 2426| Type = [PlainCharType] char
+# 2426| getVariable().getInitializer(): [Initializer] initializer for x
+# 2426| getExpr(): [FunctionCall] call to get_x
+# 2426| Type = [PlainCharType] char
+# 2426| ValueCategory = prvalue
+# 2426| getQualifier(): [ConstructorCall] call to ClassWithDestructor
+# 2426| Type = [VoidType] void
+# 2426| ValueCategory = prvalue
+# 2426| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2426| Type = [VoidType] void
+# 2426| ValueCategory = prvalue
+# 2426| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2426| Type = [Class] ClassWithDestructor
+# 2426| ValueCategory = xvalue
+# 2426| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2426| Type = [Class] ClassWithDestructor
+# 2426| ValueCategory = prvalue(load)
+# 2426| getExpr(): [VariableAccess] x
+# 2426| Type = [PlainCharType] char
+# 2426| ValueCategory = prvalue(load)
+# 2426| getStmt(): [BlockStmt] { ... }
+# 2427| getStmt(0): [SwitchCase] case ...:
+# 2427| getExpr(): [CharLiteral] 97
# 2427| Type = [PlainCharType] char
+# 2427| Value = [CharLiteral] 97
# 2427| ValueCategory = prvalue
-# 2427| getOperand(): [VariableAccess] x
-# 2427| Type = [PlainCharType] char
-# 2427| ValueCategory = lvalue
-# 2425| getExpr().getFullyConverted(): [CStyleCast] (int)...
-# 2425| Conversion = [IntegralConversion] integral conversion
-# 2425| Type = [IntType] int
-# 2425| ValueCategory = prvalue
-# 2430| getStmt(5): [RangeBasedForStmt] for(...:...) ...
-# 2430| getInitialization(): [DeclStmt] declaration
-# 2430| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
-# 2430| Type = [PlainCharType] char
-# 2430| getVariable().getInitializer(): [Initializer] initializer for x
-# 2430| getExpr(): [FunctionCall] call to get_x
-# 2430| Type = [PlainCharType] char
-# 2430| ValueCategory = prvalue
-# 2430| getQualifier(): [ConstructorCall] call to ClassWithDestructor
-# 2430| Type = [VoidType] void
-# 2430| ValueCategory = prvalue
-# 2430| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
-# 2430| Type = [VoidType] void
-# 2430| ValueCategory = prvalue
-# 2430| getQualifier(): [ReuseExpr] reuse of temporary object
-# 2430| Type = [Class] ClassWithDestructor
-# 2430| ValueCategory = xvalue
-# 2430| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
-# 2430| Type = [Class] ClassWithDestructor
-# 2430| ValueCategory = prvalue(load)
-# 2430| getChild(1): [DeclStmt] declaration
-# 2430| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
-# 2430| Type = [RValueReferenceType] vector &&
+# 2427| getExpr().getFullyConverted(): [CStyleCast] (int)...
+# 2427| Conversion = [IntegralConversion] integral conversion
+# 2427| Type = [IntType] int
+# 2427| Value = [CStyleCast] 97
+# 2427| ValueCategory = prvalue
+# 2428| getStmt(1): [ExprStmt] ExprStmt
+# 2428| getExpr(): [PostfixIncrExpr] ... ++
+# 2428| Type = [PlainCharType] char
+# 2428| ValueCategory = prvalue
+# 2428| getOperand(): [VariableAccess] x
+# 2428| Type = [PlainCharType] char
+# 2428| ValueCategory = lvalue
+# 2426| getExpr().getFullyConverted(): [CStyleCast] (int)...
+# 2426| Conversion = [IntegralConversion] integral conversion
+# 2426| Type = [IntType] int
+# 2426| ValueCategory = prvalue
+# 2431| getStmt(5): [RangeBasedForStmt] for(...:...) ...
+# 2431| getInitialization(): [DeclStmt] declaration
+# 2431| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
+# 2431| Type = [PlainCharType] char
+# 2431| getVariable().getInitializer(): [Initializer] initializer for x
+# 2431| getExpr(): [FunctionCall] call to get_x
+# 2431| Type = [PlainCharType] char
+# 2431| ValueCategory = prvalue
+# 2431| getQualifier(): [ConstructorCall] call to ClassWithDestructor
+# 2431| Type = [VoidType] void
+# 2431| ValueCategory = prvalue
+# 2431| getImplicitDestructorCall(0): [DestructorCall] call to ~ClassWithDestructor
+# 2431| Type = [VoidType] void
+# 2431| ValueCategory = prvalue
+# 2431| getQualifier(): [ReuseExpr] reuse of temporary object
+# 2431| Type = [Class] ClassWithDestructor
+# 2431| ValueCategory = xvalue
+# 2431| getQualifier().getFullyConverted(): [TemporaryObjectExpr] temporary object
+# 2431| Type = [Class] ClassWithDestructor
+# 2431| ValueCategory = prvalue(load)
+# 2431| getChild(1): [DeclStmt] declaration
+# 2431| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__range)
+# 2431| Type = [RValueReferenceType] vector &&
#-----| getVariable().getInitializer(): [Initializer] initializer for (__range)
-# 2430| getExpr(): [ConstructorCall] call to vector
-# 2430| Type = [VoidType] void
-# 2430| ValueCategory = prvalue
-# 2430| getArgument(0): [VariableAccess] x
-# 2430| Type = [PlainCharType] char
-# 2430| ValueCategory = prvalue(load)
-# 2430| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
-# 2430| Type = [LValueReferenceType] vector &
-# 2430| ValueCategory = prvalue
-# 2430| getExpr(): [TemporaryObjectExpr] temporary object
-# 2430| Type = [ClassTemplateInstantiation,Struct] vector
-# 2430| ValueCategory = xvalue
-# 2430| getBeginEndDeclaration(): [DeclStmt] declaration
-# 2430| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
-# 2430| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2431| getExpr(): [ConstructorCall] call to vector
+# 2431| Type = [VoidType] void
+# 2431| ValueCategory = prvalue
+# 2431| getArgument(0): [VariableAccess] x
+# 2431| Type = [PlainCharType] char
+# 2431| ValueCategory = prvalue(load)
+# 2431| getExpr().getFullyConverted(): [ReferenceToExpr] (reference to)
+# 2431| Type = [LValueReferenceType] vector &
+# 2431| ValueCategory = prvalue
+# 2431| getExpr(): [TemporaryObjectExpr] temporary object
+# 2431| Type = [ClassTemplateInstantiation,Struct] vector
+# 2431| ValueCategory = xvalue
+# 2431| getBeginEndDeclaration(): [DeclStmt] declaration
+# 2431| getDeclarationEntry(0): [VariableDeclarationEntry] declaration of (__begin)
+# 2431| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
#-----| getVariable().getInitializer(): [Initializer] initializer for (__begin)
-# 2430| getExpr(): [FunctionCall] call to begin
-# 2430| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
-# 2430| ValueCategory = prvalue
-# 2430| getQualifier(): [VariableAccess] (__range)
-# 2430| Type = [RValueReferenceType] vector &&
-# 2430| ValueCategory = prvalue(load)
+# 2431| getExpr(): [FunctionCall] call to begin
+# 2431| Type = [NestedTypedefType,UsingAliasTypedefType] iterator
+# 2431| ValueCategory = prvalue
+# 2431| getQualifier(): [VariableAccess] (__range)
+# 2431| Type = [RValueReferenceType] vector &&
+# 2431| ValueCategory = prvalue(load)
#-----| getQualifier().getFullyConverted(): [CStyleCast] (const vector