mirror of
https://github.com/github/codeql.git
synced 2026-05-26 17:11:24 +02:00
Compare commits
6 Commits
rc/3.10
...
rdmarsh2/i
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
06be3aec3e | ||
|
|
cb93684287 | ||
|
|
fd1ade8e50 | ||
|
|
536f9f9cca | ||
|
|
f4d3cdeca9 | ||
|
|
d0c603f2eb |
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"extensions": [
|
||||
"rust-lang.rust-analyzer",
|
||||
"rust-lang.rust",
|
||||
"bungcip.better-toml",
|
||||
"github.vscode-codeql",
|
||||
"hbenl.vscode-test-explorer",
|
||||
|
||||
3
.github/labeler.yml
vendored
3
.github/labeler.yml
vendored
@@ -11,7 +11,7 @@ Go:
|
||||
- change-notes/**/*go.*
|
||||
|
||||
Java:
|
||||
- any: [ 'java/**/*', '!java/kotlin-extractor/**/*', '!java/ql/test/kotlin/**/*' ]
|
||||
- any: [ 'java/**/*', '!java/kotlin-extractor/**/*', '!java/kotlin-explorer/**/*', '!java/ql/test/kotlin/**/*' ]
|
||||
- change-notes/**/*java.*
|
||||
|
||||
JS:
|
||||
@@ -20,6 +20,7 @@ JS:
|
||||
|
||||
Kotlin:
|
||||
- java/kotlin-extractor/**/*
|
||||
- java/kotlin-explorer/**/*
|
||||
- java/ql/test/kotlin/**/*
|
||||
|
||||
Python:
|
||||
|
||||
5
.github/workflows/check-change-note.yml
vendored
5
.github/workflows/check-change-note.yml
vendored
@@ -11,6 +11,7 @@ on:
|
||||
- "*/ql/lib/**/*.yml"
|
||||
- "!**/experimental/**"
|
||||
- "!ql/**"
|
||||
- "!swift/**"
|
||||
- ".github/workflows/check-change-note.yml"
|
||||
|
||||
jobs:
|
||||
@@ -26,9 +27,9 @@ jobs:
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq 'any(.[].filename ; test("/change-notes/.*[.]md$"))' |
|
||||
grep true -c
|
||||
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md', 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text, or released/x.y.z.md for released change-notes
|
||||
- name: Fail if the change note filename doesn't match the expected format. The file name must be of the form 'YYYY-MM-DD.md' or 'YYYY-MM-DD-{title}.md', where '{title}' is arbitrary text.
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$") or test("/change-notes/released/[0-9]*[.][0-9]*[.][0-9]*[.]md$"))' |
|
||||
gh api 'repos/${{github.repository}}/pulls/${{github.event.number}}/files' --paginate --jq '[.[].filename | select(test("/change-notes/.*[.]md$"))] | all(test("/change-notes/[0-9]{4}-[0-9]{2}-[0-9]{2}.*[.]md$"))' |
|
||||
grep true -c
|
||||
|
||||
@@ -10,7 +10,6 @@ on:
|
||||
- "*/ql/src/**/*.qll"
|
||||
- "*/ql/lib/**/*.ql"
|
||||
- "*/ql/lib/**/*.qll"
|
||||
- "*/ql/lib/ext/**/*.yml"
|
||||
- "misc/scripts/library-coverage/*.py"
|
||||
# input data files
|
||||
- "*/documentation/library-coverage/cwe-sink.csv"
|
||||
|
||||
2
.github/workflows/ql-for-ql-build.yml
vendored
2
.github/workflows/ql-for-ql-build.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
path: |
|
||||
ql/extractor-pack/
|
||||
ql/target/release/buramu
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('shared/tree-sitter-extractor') }}-${{ hashFiles('ql/**/*.rs') }}
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-extractor-${{ hashFiles('ql/**/Cargo.lock') }}-${{ hashFiles('ql/**/*.rs') }}
|
||||
- name: Cache cargo
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
uses: actions/cache@v3
|
||||
|
||||
2
.github/workflows/ruby-build.yml
vendored
2
.github/workflows/ruby-build.yml
vendored
@@ -61,7 +61,7 @@ jobs:
|
||||
ruby/extractor/target/release/codeql-extractor-ruby
|
||||
ruby/extractor/target/release/codeql-extractor-ruby.exe
|
||||
ruby/extractor/ql/lib/codeql/ruby/ast/internal/TreeSitter.qll
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}-${{ hashFiles('shared/tree-sitter-extractor') }}-${{ hashFiles('ruby/extractor/**/*.rs') }}
|
||||
key: ${{ runner.os }}-${{ steps.os_version.outputs.version }}-ruby-extractor-${{ hashFiles('ruby/extractor/rust-toolchain.toml', 'ruby/extractor/Cargo.lock') }}--${{ hashFiles('ruby/extractor/**/*.rs') }}
|
||||
- uses: actions/cache@v3
|
||||
if: steps.cache-extractor.outputs.cache-hit != 'true'
|
||||
with:
|
||||
|
||||
2
.github/workflows/swift.yml
vendored
2
.github/workflows/swift.yml
vendored
@@ -16,7 +16,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- rc/*
|
||||
- codeql-cli-*
|
||||
push:
|
||||
paths:
|
||||
- "swift/**"
|
||||
@@ -31,7 +30,6 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- rc/*
|
||||
- codeql-cli-*
|
||||
|
||||
jobs:
|
||||
# not using a matrix as you cannot depend on a specific job in a matrix, and we want to start linux checks
|
||||
|
||||
2
.github/workflows/sync-files.yml
vendored
2
.github/workflows/sync-files.yml
vendored
@@ -17,6 +17,4 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check synchronized files
|
||||
run: python config/sync-files.py
|
||||
- name: Check dbscheme fragments
|
||||
run: python config/sync-dbscheme-fragments.py
|
||||
|
||||
|
||||
46
.github/workflows/tree-sitter-extractor-test.yml
vendored
46
.github/workflows/tree-sitter-extractor-test.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Test tree-sitter-extractor
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
- .github/workflows/tree-sitter-extractor-test.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
pull_request:
|
||||
paths:
|
||||
- "shared/tree-sitter-extractor/**"
|
||||
- .github/workflows/tree-sitter-extractor-test.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
env:
|
||||
CARGO_TERM_COLOR: always
|
||||
|
||||
defaults:
|
||||
run:
|
||||
working-directory: shared/tree-sitter-extractor
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check formatting
|
||||
run: cargo fmt --all -- --check
|
||||
- name: Run tests
|
||||
run: cargo test --verbose
|
||||
fmt:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Check formatting
|
||||
run: cargo fmt --check
|
||||
clippy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Run clippy
|
||||
run: cargo clippy -- --no-deps -D warnings -A clippy::new_without_default -A clippy::too_many_arguments
|
||||
18
.vscode/tasks.json
vendored
18
.vscode/tasks.json
vendored
@@ -22,22 +22,6 @@
|
||||
"command": "${config:python.pythonPath}",
|
||||
},
|
||||
"problemMatcher": []
|
||||
},
|
||||
{
|
||||
"label": "Accept .expected changes from CI",
|
||||
"type": "process",
|
||||
// Non-Windows OS will usually have Python 3 already installed at /usr/bin/python3.
|
||||
"command": "python3",
|
||||
"args": [
|
||||
"misc/scripts/accept-expected-changes-from-ci.py"
|
||||
],
|
||||
"group": "build",
|
||||
"windows": {
|
||||
// On Windows, use whatever Python interpreter is configured for this workspace. The default is
|
||||
// just `python`, so if Python is already on the path, this will find it.
|
||||
"command": "${config:python.pythonPath}",
|
||||
},
|
||||
"problemMatcher": []
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@
|
||||
/swift/ @github/codeql-swift
|
||||
/misc/codegen/ @github/codeql-swift
|
||||
/java/kotlin-extractor/ @github/codeql-kotlin
|
||||
/java/kotlin-explorer/ @github/codeql-kotlin
|
||||
|
||||
# ML-powered queries
|
||||
/javascript/ql/experimental/adaptivethreatmodeling/ @github/codeql-ml-powered-queries-reviewers
|
||||
@@ -39,6 +40,3 @@ WORKSPACE.bazel @github/codeql-ci-reviewers
|
||||
/.github/workflows/ql-for-ql-* @github/codeql-ql-for-ql-reviewers
|
||||
/.github/workflows/ruby-* @github/codeql-ruby
|
||||
/.github/workflows/swift.yml @github/codeql-swift
|
||||
|
||||
# Misc
|
||||
/misc/scripts/accept-expected-changes-from-ci.py @RasmusWL
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
{
|
||||
"files": [
|
||||
"javascript/ql/lib/semmlecode.javascript.dbscheme",
|
||||
"python/ql/lib/semmlecode.python.dbscheme",
|
||||
"ruby/ql/lib/ruby.dbscheme",
|
||||
"ql/ql/src/ql.dbscheme"
|
||||
],
|
||||
"fragments": [
|
||||
"/*- External data -*/",
|
||||
"/*- Files and folders -*/",
|
||||
"/*- Diagnostic messages -*/",
|
||||
"/*- Diagnostic messages: severity -*/",
|
||||
"/*- Source location prefix -*/",
|
||||
"/*- Lines of code -*/",
|
||||
"/*- Configuration files with key value pairs -*/",
|
||||
"/*- YAML -*/",
|
||||
"/*- XML Files -*/",
|
||||
"/*- XML: sourceline -*/",
|
||||
"/*- DEPRECATED: External defects and metrics -*/",
|
||||
"/*- DEPRECATED: Snapshot date -*/",
|
||||
"/*- DEPRECATED: Duplicate code -*/",
|
||||
"/*- DEPRECATED: Version control data -*/",
|
||||
"/*- JavaScript-specific part -*/",
|
||||
"/*- Ruby dbscheme -*/",
|
||||
"/*- Erb dbscheme -*/",
|
||||
"/*- QL dbscheme -*/",
|
||||
"/*- Dbscheme dbscheme -*/",
|
||||
"/*- Yaml dbscheme -*/",
|
||||
"/*- Blame dbscheme -*/",
|
||||
"/*- JSON dbscheme -*/",
|
||||
"/*- Python dbscheme -*/"
|
||||
]
|
||||
}
|
||||
@@ -40,6 +40,7 @@
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl1.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImpl2.qll",
|
||||
"go/ql/lib/semmle/go/dataflow/internal/DataFlowImplForStringsNewReplacer.qll",
|
||||
@@ -47,6 +48,7 @@
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll",
|
||||
"python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImplForRegExp.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl1.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll",
|
||||
"ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll",
|
||||
@@ -511,8 +513,7 @@
|
||||
"SensitiveDataHeuristics Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/internal/SensitiveDataHeuristics.qll",
|
||||
"python/ql/lib/semmle/python/security/internal/SensitiveDataHeuristics.qll",
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll",
|
||||
"swift/ql/lib/codeql/swift/security/internal/SensitiveDataHeuristics.qll"
|
||||
"ruby/ql/lib/codeql/ruby/security/internal/SensitiveDataHeuristics.qll"
|
||||
],
|
||||
"CFG": [
|
||||
"csharp/ql/lib/semmle/code/csharp/controlflow/internal/ControlFlowGraphImplShared.qll",
|
||||
@@ -599,4 +600,4 @@
|
||||
"python/ql/lib/semmle/python/security/internal/EncryptionKeySizes.qll",
|
||||
"java/ql/lib/semmle/code/java/security/internal/EncryptionKeySizes.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,86 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import os
|
||||
import pathlib
|
||||
import re
|
||||
|
||||
|
||||
def make_groups(blocks):
|
||||
groups = {}
|
||||
for block in blocks:
|
||||
groups.setdefault("".join(block["lines"]), []).append(block)
|
||||
return list(groups.values())
|
||||
|
||||
|
||||
def validate_fragments(fragments):
|
||||
ok = True
|
||||
for header, blocks in fragments.items():
|
||||
groups = make_groups(blocks)
|
||||
if len(groups) > 1:
|
||||
ok = False
|
||||
print("Warning: dbscheme fragments with header '{}' are different for {}".format(header, ["{}:{}:{}".format(
|
||||
group[0]["file"], group[0]["start"], group[0]["end"]) for group in groups]))
|
||||
return ok
|
||||
|
||||
|
||||
def main():
|
||||
script_path = os.path.realpath(__file__)
|
||||
script_dir = os.path.dirname(script_path)
|
||||
parser = argparse.ArgumentParser(
|
||||
prog=os.path.basename(script_path),
|
||||
description='Sync dbscheme fragments across files.'
|
||||
)
|
||||
parser.add_argument('files', metavar='dbscheme_file', type=pathlib.Path, nargs='*', default=[],
|
||||
help='dbscheme files to check')
|
||||
args = parser.parse_args()
|
||||
|
||||
with open(os.path.join(script_dir, "dbscheme-fragments.json"), "r") as f:
|
||||
config = json.load(f)
|
||||
|
||||
fragment_headers = set(config["fragments"])
|
||||
fragments = {}
|
||||
ok = True
|
||||
for file in args.files + config["files"]:
|
||||
with open(os.path.join(os.path.dirname(script_dir), file), "r") as dbscheme:
|
||||
header = None
|
||||
line_number = 1
|
||||
block = {"file": file, "start": line_number,
|
||||
"end": None, "lines": []}
|
||||
|
||||
def end_block():
|
||||
block["end"] = line_number - 1
|
||||
if len(block["lines"]) > 0:
|
||||
if header is None:
|
||||
if re.match(r'(?m)\A(\s|//.*$|/\*(\**[^\*])*\*+/)*\Z', "".join(block["lines"])):
|
||||
# Ignore comments at the beginning of the file
|
||||
pass
|
||||
else:
|
||||
ok = False
|
||||
print("Warning: dbscheme fragment without header: {}:{}:{}".format(
|
||||
block["file"], block["start"], block["end"]))
|
||||
else:
|
||||
fragments.setdefault(header, []).append(block)
|
||||
for line in dbscheme:
|
||||
m = re.match(r"^\/\*-.*-\*\/$", line)
|
||||
if m:
|
||||
end_block()
|
||||
header = line.strip()
|
||||
if header not in fragment_headers:
|
||||
ok = False
|
||||
print("Warning: unknown header for dbscheme fragment: '{}': {}:{}".format(
|
||||
header, file, line_number))
|
||||
block = {"file": file, "start": line_number,
|
||||
"end": None, "lines": []}
|
||||
block["lines"].append(line)
|
||||
line_number += 1
|
||||
block["lines"].append('\n')
|
||||
line_number += 1
|
||||
end_block()
|
||||
if not ok or not validate_fragments(fragments):
|
||||
exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -1,35 +1,3 @@
|
||||
## 0.7.4
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `hasCopyConstructor` predicate from the `Class` class in `Class.qll`.
|
||||
* Deleted many deprecated predicates and classes with uppercase `AST`, `SSA`, `CFG`, `API`, etc. in their names. Use the PascalCased versions instead.
|
||||
* Deleted the deprecated `CodeDuplication.qll` file.
|
||||
|
||||
## 0.7.2
|
||||
|
||||
### New Features
|
||||
|
||||
* Added an AST-based interface (`semmle.code.cpp.rangeanalysis.new.RangeAnalysis`) for the relative range analysis library.
|
||||
* A new predicate `BarrierGuard::getAnIndirectBarrierNode` has been added to the new dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) to mark indirect expressions as barrier nodes using the `BarrierGuard` API.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* In the intermediate representation, handling of control flow after non-returning calls has been improved. This should remove false positives in queries that use the intermedite representation or libraries based on it, including the new data flow library.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `StdNamespace` class now also includes all inline namespaces that are children of `std` namespace.
|
||||
* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables.
|
||||
|
||||
## 0.7.1
|
||||
|
||||
No user-facing changes.
|
||||
|
||||
## 0.7.0
|
||||
|
||||
### Breaking Changes
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.7.1
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,15 +0,0 @@
|
||||
## 0.7.2
|
||||
|
||||
### New Features
|
||||
|
||||
* Added an AST-based interface (`semmle.code.cpp.rangeanalysis.new.RangeAnalysis`) for the relative range analysis library.
|
||||
* A new predicate `BarrierGuard::getAnIndirectBarrierNode` has been added to the new dataflow library (`semmle.code.cpp.dataflow.new.DataFlow`) to mark indirect expressions as barrier nodes using the `BarrierGuard` API.
|
||||
|
||||
### Major Analysis Improvements
|
||||
|
||||
* In the intermediate representation, handling of control flow after non-returning calls has been improved. This should remove false positives in queries that use the intermedite representation or libraries based on it, including the new data flow library.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* The `StdNamespace` class now also includes all inline namespaces that are children of `std` namespace.
|
||||
* The new dataflow (`semmle.code.cpp.dataflow.new.DataFlow`) and taint-tracking libraries (`semmle.code.cpp.dataflow.new.TaintTracking`) now support tracking flow through static local variables.
|
||||
@@ -1,7 +0,0 @@
|
||||
## 0.7.3
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Deleted the deprecated `hasCopyConstructor` predicate from the `Class` class in `Class.qll`.
|
||||
* Deleted many deprecated predicates and classes with uppercase `AST`, `SSA`, `CFG`, `API`, etc. in their names. Use the PascalCased versions instead.
|
||||
* Deleted the deprecated `CodeDuplication.qll` file.
|
||||
@@ -1,3 +0,0 @@
|
||||
## 0.7.4
|
||||
|
||||
No user-facing changes.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.7.4
|
||||
lastReleaseVersion: 0.7.0
|
||||
|
||||
@@ -1,29 +1,7 @@
|
||||
/**
|
||||
* Provides a library for global (inter-procedural) data flow analysis of two
|
||||
* values "simultaneously". This can be used, for example, if you want to track
|
||||
* a memory allocation as well as the size of the allocation.
|
||||
*
|
||||
* Intuitively, you can think of this as regular dataflow, but where each node
|
||||
* in the dataflow graph has been replaced by a pair of nodes `(node1, node2)`,
|
||||
* and two node pairs `(n11, n12)`, `(n21, n22)` is then connected by a dataflow
|
||||
* edge if there's a regular dataflow edge between `n11` and `n21`, and `n12`
|
||||
* and `n22`.
|
||||
*
|
||||
* Note that the above intuition does not reflect the actual implementation.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.dataflow.new.DataFlow
|
||||
private import DataFlowPrivate
|
||||
private import DataFlowUtil
|
||||
private import DataFlowImplCommon
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import codeql.util.Unit
|
||||
|
||||
/**
|
||||
* Provides classes for performing global (inter-procedural) data flow analyses
|
||||
* on a product dataflow graph.
|
||||
*/
|
||||
module ProductFlow {
|
||||
/** An input configuration for product data-flow. */
|
||||
signature module ConfigSig {
|
||||
/**
|
||||
* Holds if `(source1, source2)` is a relevant data flow source.
|
||||
@@ -89,9 +67,6 @@ module ProductFlow {
|
||||
default predicate isBarrierIn2(DataFlow::Node node) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output of a global data flow computation.
|
||||
*/
|
||||
module Global<ConfigSig Config> {
|
||||
private module StateConfig implements StateConfigSig {
|
||||
class FlowState1 = Unit;
|
||||
@@ -160,7 +135,6 @@ module ProductFlow {
|
||||
import GlobalWithState<StateConfig>
|
||||
}
|
||||
|
||||
/** An input configuration for data flow using flow state. */
|
||||
signature module StateConfigSig {
|
||||
bindingset[this]
|
||||
class FlowState1;
|
||||
@@ -270,9 +244,6 @@ module ProductFlow {
|
||||
default predicate isBarrierIn2(DataFlow::Node node) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The output of a global data flow computation.
|
||||
*/
|
||||
module GlobalWithState<StateConfigSig Config> {
|
||||
class PathNode1 = Flow1::PathNode;
|
||||
|
||||
@@ -286,7 +257,6 @@ module ProductFlow {
|
||||
|
||||
class FlowState2 = Config::FlowState2;
|
||||
|
||||
/** Holds if data can flow from `(source1, source2)` to `(sink1, sink2)`. */
|
||||
predicate flowPath(
|
||||
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
|
||||
) {
|
||||
@@ -317,9 +287,9 @@ module ProductFlow {
|
||||
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn1(node) }
|
||||
}
|
||||
|
||||
private module Flow1 = DataFlow::GlobalWithState<Config1>;
|
||||
module Flow1 = DataFlow::GlobalWithState<Config1>;
|
||||
|
||||
private module Config2 implements DataFlow::StateConfigSig {
|
||||
module Config2 implements DataFlow::StateConfigSig {
|
||||
class FlowState = FlowState2;
|
||||
|
||||
predicate isSource(DataFlow::Node source, FlowState state) {
|
||||
@@ -349,90 +319,27 @@ module ProductFlow {
|
||||
predicate isBarrierIn(DataFlow::Node node) { Config::isBarrierIn2(node) }
|
||||
}
|
||||
|
||||
private module Flow2 = DataFlow::GlobalWithState<Config2>;
|
||||
|
||||
private predicate isSourcePair(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
|
||||
}
|
||||
|
||||
private predicate isSinkPair(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
Config::isSinkPair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState())
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate fwdReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
isSourcePair(node1, node2)
|
||||
or
|
||||
fwdIsSuccessor(_, _, node1, node2)
|
||||
}
|
||||
module Flow2 = DataFlow::GlobalWithState<Config2>;
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate fwdIsSuccessorExit(
|
||||
Flow1::PathNode mid1, Flow2::PathNode mid2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
private predicate reachableInterprocEntry(
|
||||
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode node1, Flow2::PathNode node2
|
||||
) {
|
||||
isSinkPair(mid1, mid2) and
|
||||
succ1 = mid1 and
|
||||
succ2 = mid2
|
||||
Config::isSourcePair(node1.getNode(), node1.getState(), node2.getNode(), node2.getState()) and
|
||||
node1 = source1 and
|
||||
node2 = source2
|
||||
or
|
||||
interprocEdgePair(mid1, mid2, succ1, succ2)
|
||||
}
|
||||
|
||||
private predicate fwdIsSuccessor1(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
|
||||
Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
fwdReachableInterprocEntry(pred1, pred2) and
|
||||
localPathStep1*(pred1, mid1) and
|
||||
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
|
||||
}
|
||||
|
||||
private predicate fwdIsSuccessor2(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode mid1, Flow2::PathNode mid2,
|
||||
Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
fwdReachableInterprocEntry(pred1, pred2) and
|
||||
localPathStep2*(pred2, mid2) and
|
||||
fwdIsSuccessorExit(pragma[only_bind_into](mid1), pragma[only_bind_into](mid2), succ1, succ2)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
private predicate fwdIsSuccessor(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
|
||||
fwdIsSuccessor1(pred1, pred2, mid1, mid2, succ1, succ2) and
|
||||
fwdIsSuccessor2(pred1, pred2, mid1, mid2, succ1, succ2)
|
||||
exists(
|
||||
Flow1::PathNode midEntry1, Flow2::PathNode midEntry2, Flow1::PathNode midExit1,
|
||||
Flow2::PathNode midExit2
|
||||
|
|
||||
reachableInterprocEntry(source1, source2, midEntry1, midEntry2) and
|
||||
interprocEdgePair(midExit1, midExit2, node1, node2) and
|
||||
localPathStep1*(midEntry1, midExit1) and
|
||||
localPathStep2*(midEntry2, midExit2)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[assume_small_delta]
|
||||
pragma[nomagic]
|
||||
private predicate revReachableInterprocEntry(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
fwdReachableInterprocEntry(node1, node2) and
|
||||
isSinkPair(node1, node2)
|
||||
or
|
||||
exists(Flow1::PathNode succ1, Flow2::PathNode succ2 |
|
||||
revReachableInterprocEntry(succ1, succ2) and
|
||||
fwdIsSuccessor(node1, node2, succ1, succ2)
|
||||
)
|
||||
}
|
||||
|
||||
private newtype TNodePair =
|
||||
TMkNodePair(Flow1::PathNode node1, Flow2::PathNode node2) {
|
||||
revReachableInterprocEntry(node1, node2)
|
||||
}
|
||||
|
||||
private predicate pathSucc(TNodePair n1, TNodePair n2) {
|
||||
exists(Flow1::PathNode n11, Flow2::PathNode n12, Flow1::PathNode n21, Flow2::PathNode n22 |
|
||||
n1 = TMkNodePair(n11, n12) and
|
||||
n2 = TMkNodePair(n21, n22) and
|
||||
fwdIsSuccessor(n11, n12, n21, n22)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate pathSuccPlus(TNodePair n1, TNodePair n2) = fastTC(pathSucc/2)(n1, n2)
|
||||
|
||||
private predicate localPathStep1(Flow1::PathNode pred, Flow1::PathNode succ) {
|
||||
Flow1::PathGraph::edges(pred, succ) and
|
||||
pragma[only_bind_out](pred.getNode().getEnclosingCallable()) =
|
||||
@@ -445,133 +352,43 @@ module ProductFlow {
|
||||
pragma[only_bind_out](succ.getNode().getEnclosingCallable())
|
||||
}
|
||||
|
||||
private newtype TKind =
|
||||
TInto(DataFlowCall call) {
|
||||
intoImpl1(_, _, call) or
|
||||
intoImpl2(_, _, call)
|
||||
} or
|
||||
TOutOf(DataFlowCall call) {
|
||||
outImpl1(_, _, call) or
|
||||
outImpl2(_, _, call)
|
||||
} or
|
||||
TJump()
|
||||
|
||||
private predicate intoImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
pred1.getNode().(ArgumentNode).getCall() = call and
|
||||
succ1.getNode() instanceof ParameterNode
|
||||
}
|
||||
|
||||
private predicate into1(Flow1::PathNode pred1, Flow1::PathNode succ1, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
kind = TInto(call) and
|
||||
intoImpl1(pred1, succ1, call)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outImpl1(Flow1::PathNode pred1, Flow1::PathNode succ1, DataFlowCall call) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ1.getNode() = returnKind.getAnOutNode(call) and
|
||||
pred1.getNode().(ReturnNodeExt).getKind() = returnKind
|
||||
)
|
||||
}
|
||||
|
||||
private predicate out1(Flow1::PathNode pred1, Flow1::PathNode succ1, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
outImpl1(pred1, succ1, call) and
|
||||
kind = TOutOf(call)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate intoImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
pred2.getNode().(ArgumentNode).getCall() = call and
|
||||
succ2.getNode() instanceof ParameterNode
|
||||
}
|
||||
|
||||
private predicate into2(Flow2::PathNode pred2, Flow2::PathNode succ2, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
kind = TInto(call) and
|
||||
intoImpl2(pred2, succ2, call)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate outImpl2(Flow2::PathNode pred2, Flow2::PathNode succ2, DataFlowCall call) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
exists(ReturnKindExt returnKind |
|
||||
succ2.getNode() = returnKind.getAnOutNode(call) and
|
||||
pred2.getNode().(ReturnNodeExt).getKind() = returnKind
|
||||
)
|
||||
}
|
||||
|
||||
private predicate out2(Flow2::PathNode pred2, Flow2::PathNode succ2, TKind kind) {
|
||||
exists(DataFlowCall call |
|
||||
kind = TOutOf(call) and
|
||||
outImpl2(pred2, succ2, call)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate interprocEdge1(
|
||||
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1,
|
||||
TKind kind
|
||||
Declaration predDecl, Declaration succDecl, Flow1::PathNode pred1, Flow1::PathNode succ1
|
||||
) {
|
||||
Flow1::PathGraph::edges(pred1, succ1) and
|
||||
predDecl != succDecl and
|
||||
pred1.getNode().getEnclosingCallable() = predDecl and
|
||||
succ1.getNode().getEnclosingCallable() = succDecl and
|
||||
(
|
||||
into1(pred1, succ1, kind)
|
||||
or
|
||||
out1(pred1, succ1, kind)
|
||||
or
|
||||
kind = TJump() and
|
||||
not into1(pred1, succ1, _) and
|
||||
not out1(pred1, succ1, _)
|
||||
)
|
||||
succ1.getNode().getEnclosingCallable() = succDecl
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate interprocEdge2(
|
||||
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2,
|
||||
TKind kind
|
||||
Declaration predDecl, Declaration succDecl, Flow2::PathNode pred2, Flow2::PathNode succ2
|
||||
) {
|
||||
Flow2::PathGraph::edges(pred2, succ2) and
|
||||
predDecl != succDecl and
|
||||
pred2.getNode().getEnclosingCallable() = predDecl and
|
||||
succ2.getNode().getEnclosingCallable() = succDecl and
|
||||
(
|
||||
into2(pred2, succ2, kind)
|
||||
or
|
||||
out2(pred2, succ2, kind)
|
||||
or
|
||||
kind = TJump() and
|
||||
not into2(pred2, succ2, _) and
|
||||
not out2(pred2, succ2, _)
|
||||
)
|
||||
succ2.getNode().getEnclosingCallable() = succDecl
|
||||
}
|
||||
|
||||
private predicate interprocEdgePair(
|
||||
Flow1::PathNode pred1, Flow2::PathNode pred2, Flow1::PathNode succ1, Flow2::PathNode succ2
|
||||
) {
|
||||
exists(Declaration predDecl, Declaration succDecl, TKind kind |
|
||||
interprocEdge1(predDecl, succDecl, pred1, succ1, kind) and
|
||||
interprocEdge2(predDecl, succDecl, pred2, succ2, kind)
|
||||
exists(Declaration predDecl, Declaration succDecl |
|
||||
interprocEdge1(predDecl, succDecl, pred1, succ1) and
|
||||
interprocEdge2(predDecl, succDecl, pred2, succ2)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate reachable(
|
||||
Flow1::PathNode source1, Flow2::PathNode source2, Flow1::PathNode sink1, Flow2::PathNode sink2
|
||||
) {
|
||||
isSourcePair(source1, source2) and
|
||||
isSinkPair(sink1, sink2) and
|
||||
exists(TNodePair n1, TNodePair n2 |
|
||||
n1 = TMkNodePair(source1, source2) and
|
||||
n2 = TMkNodePair(sink1, sink2)
|
||||
|
|
||||
pathSuccPlus(n1, n2) or
|
||||
n1 = n2
|
||||
exists(Flow1::PathNode mid1, Flow2::PathNode mid2 |
|
||||
reachableInterprocEntry(source1, source2, mid1, mid2) and
|
||||
Config::isSinkPair(sink1.getNode(), sink1.getState(), sink2.getNode(), sink2.getState()) and
|
||||
localPathStep1*(mid1, sink1) and
|
||||
localPathStep2*(mid2, sink2)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -238,7 +238,7 @@ class NoReason extends Reason, TNoReason {
|
||||
class CondReason extends Reason, TCondReason {
|
||||
IRGuardCondition getCond() { this = TCondReason(result) }
|
||||
|
||||
override string toString() { result = this.getCond().toString() }
|
||||
override string toString() { result = getCond().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -260,14 +260,14 @@ private predicate typeBound(IRIntegerType typ, int lowerbound, int upperbound) {
|
||||
private class NarrowingCastInstruction extends ConvertInstruction {
|
||||
NarrowingCastInstruction() {
|
||||
not this instanceof SafeCastInstruction and
|
||||
typeBound(this.getResultIRType(), _, _)
|
||||
typeBound(getResultIRType(), _, _)
|
||||
}
|
||||
|
||||
/** Gets the lower bound of the resulting type. */
|
||||
int getLowerBound() { typeBound(this.getResultIRType(), result, _) }
|
||||
int getLowerBound() { typeBound(getResultIRType(), result, _) }
|
||||
|
||||
/** Gets the upper bound of the resulting type. */
|
||||
int getUpperBound() { typeBound(this.getResultIRType(), _, result) }
|
||||
int getUpperBound() { typeBound(getResultIRType(), _, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -109,8 +109,8 @@ private predicate safeCast(IRIntegerType fromtyp, IRIntegerType totyp) {
|
||||
*/
|
||||
class PtrToPtrCastInstruction extends ConvertInstruction {
|
||||
PtrToPtrCastInstruction() {
|
||||
this.getResultIRType() instanceof IRAddressType and
|
||||
this.getUnary().getResultIRType() instanceof IRAddressType
|
||||
getResultIRType() instanceof IRAddressType and
|
||||
getUnary().getResultIRType() instanceof IRAddressType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -119,7 +119,7 @@ class PtrToPtrCastInstruction extends ConvertInstruction {
|
||||
* that cannot overflow or underflow.
|
||||
*/
|
||||
class SafeIntCastInstruction extends ConvertInstruction {
|
||||
SafeIntCastInstruction() { safeCast(this.getUnary().getResultIRType(), this.getResultIRType()) }
|
||||
SafeIntCastInstruction() { safeCast(getUnary().getResultIRType(), getResultIRType()) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -50,8 +50,8 @@ private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr {
|
||||
// If an operand can have negative values, the lower bound is unconstrained.
|
||||
// Otherwise, the lower bound is zero.
|
||||
exists(float lLower, float rLower |
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
(
|
||||
(lLower < 0 or rLower < 0) and
|
||||
result = exprMinVal(this)
|
||||
@@ -68,10 +68,10 @@ private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr {
|
||||
// If an operand can have negative values, the upper bound is unconstrained.
|
||||
// Otherwise, the upper bound is the minimum of the upper bounds of the operands
|
||||
exists(float lLower, float lUpper, float rLower, float rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
(
|
||||
(lLower < 0 or rLower < 0) and
|
||||
result = exprMaxVal(this)
|
||||
@@ -85,6 +85,6 @@ private class ConstantBitwiseAndExprRange extends SimpleRangeAnalysisExpr {
|
||||
}
|
||||
|
||||
override predicate dependsOnChild(Expr child) {
|
||||
child = this.getLeftOperand() or child = this.getRightOperand()
|
||||
child = getLeftOperand() or child = getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
* We don't handle the case where `a` and `b` are both non-constant values.
|
||||
*/
|
||||
ConstantRShiftExprRange() {
|
||||
this.getUnspecifiedType() instanceof IntegralType and
|
||||
getUnspecifiedType() instanceof IntegralType and
|
||||
exists(Expr l, Expr r |
|
||||
l = this.(RShiftExpr).getLeftOperand() and
|
||||
r = this.(RShiftExpr).getRightOperand()
|
||||
@@ -84,10 +84,10 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getLowerBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -95,8 +95,8 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -111,10 +111,10 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getUpperBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -122,8 +122,8 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -137,7 +137,7 @@ class ConstantRShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
}
|
||||
|
||||
override predicate dependsOnChild(Expr child) {
|
||||
child = this.getLeftOperand() or child = this.getRightOperand()
|
||||
child = getLeftOperand() or child = getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,7 +163,7 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
* We don't handle the case where `a` and `b` are both non-constant values.
|
||||
*/
|
||||
ConstantLShiftExprRange() {
|
||||
this.getUnspecifiedType() instanceof IntegralType and
|
||||
getUnspecifiedType() instanceof IntegralType and
|
||||
exists(Expr l, Expr r |
|
||||
l = this.(LShiftExpr).getLeftOperand() and
|
||||
r = this.(LShiftExpr).getRightOperand()
|
||||
@@ -197,10 +197,10 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getLowerBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -208,8 +208,8 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -228,10 +228,10 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
|
||||
override float getUpperBounds() {
|
||||
exists(int lLower, int lUpper, int rLower, int rUpper |
|
||||
lLower = getFullyConvertedLowerBounds(this.getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(this.getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(this.getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(this.getRightOperand()) and
|
||||
lLower = getFullyConvertedLowerBounds(getLeftOperand()) and
|
||||
lUpper = getFullyConvertedUpperBounds(getLeftOperand()) and
|
||||
rLower = getFullyConvertedLowerBounds(getRightOperand()) and
|
||||
rUpper = getFullyConvertedUpperBounds(getRightOperand()) and
|
||||
lLower <= lUpper and
|
||||
rLower <= rUpper
|
||||
|
|
||||
@@ -239,8 +239,8 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
lLower < 0
|
||||
or
|
||||
not (
|
||||
isValidShiftExprShift(rLower, this.getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, this.getLeftOperand())
|
||||
isValidShiftExprShift(rLower, getLeftOperand()) and
|
||||
isValidShiftExprShift(rUpper, getLeftOperand())
|
||||
)
|
||||
then
|
||||
// We don't want to deal with shifting negative numbers at the moment,
|
||||
@@ -258,6 +258,6 @@ class ConstantLShiftExprRange extends SimpleRangeAnalysisExpr {
|
||||
}
|
||||
|
||||
override predicate dependsOnChild(Expr child) {
|
||||
child = this.getLeftOperand() or child = this.getRightOperand()
|
||||
child = getLeftOperand() or child = getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,23 +83,20 @@ private class ExprRangeNode extends DataFlow::ExprNode {
|
||||
private string getCallBounds(Call e) {
|
||||
result =
|
||||
getExprBoundAsString(e) + "(" +
|
||||
concat(Expr arg, int i |
|
||||
arg = e.getArgument(i)
|
||||
|
|
||||
this.getIntegralBounds(arg), "," order by i
|
||||
) + ")"
|
||||
concat(Expr arg, int i | arg = e.getArgument(i) | getIntegralBounds(arg) order by i, ",") +
|
||||
")"
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
exists(Expr e | e = this.getExpr() |
|
||||
exists(Expr e | e = getExpr() |
|
||||
if hasIntegralOrReferenceIntegralType(e)
|
||||
then
|
||||
result = super.toString() + ": " + this.getOperationBounds(e)
|
||||
result = super.toString() + ": " + getOperationBounds(e)
|
||||
or
|
||||
result = super.toString() + ": " + this.getCallBounds(e)
|
||||
result = super.toString() + ": " + getCallBounds(e)
|
||||
or
|
||||
not exists(this.getOperationBounds(e)) and
|
||||
not exists(this.getCallBounds(e)) and
|
||||
not exists(getOperationBounds(e)) and
|
||||
not exists(getCallBounds(e)) and
|
||||
result = super.toString() + ": " + getExprBoundAsString(e)
|
||||
else result = super.toString()
|
||||
)
|
||||
@@ -111,8 +108,8 @@ private class ExprRangeNode extends DataFlow::ExprNode {
|
||||
*/
|
||||
private class ReferenceArgumentRangeNode extends DataFlow::DefinitionByReferenceNode {
|
||||
override string toString() {
|
||||
if hasIntegralOrReferenceIntegralType(this.asDefiningArgument())
|
||||
then result = super.toString() + ": " + getExprBoundAsString(this.getArgument())
|
||||
if hasIntegralOrReferenceIntegralType(asDefiningArgument())
|
||||
then result = super.toString() + ": " + getExprBoundAsString(getArgument())
|
||||
else result = super.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@ private import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysi
|
||||
*/
|
||||
class StrlenLiteralRangeExpr extends SimpleRangeAnalysisExpr, FunctionCall {
|
||||
StrlenLiteralRangeExpr() {
|
||||
this.getTarget().hasGlobalOrStdName("strlen") and this.getArgument(0).isConstant()
|
||||
getTarget().hasGlobalOrStdName("strlen") and getArgument(0).isConstant()
|
||||
}
|
||||
|
||||
override int getLowerBounds() { result = this.getArgument(0).getValue().length() }
|
||||
override int getLowerBounds() { result = getArgument(0).getValue().length() }
|
||||
|
||||
override int getUpperBounds() { result = this.getArgument(0).getValue().length() }
|
||||
override int getUpperBounds() { result = getArgument(0).getValue().length() }
|
||||
|
||||
override predicate dependsOnChild(Expr e) { none() }
|
||||
}
|
||||
|
||||
@@ -3,8 +3,8 @@ import experimental.semmle.code.cpp.models.interfaces.SimpleRangeAnalysisExpr
|
||||
private class SelfSub extends SimpleRangeAnalysisExpr, SubExpr {
|
||||
SelfSub() {
|
||||
// Match `x - x` but not `myInt - (unsigned char)myInt`.
|
||||
this.getLeftOperand().getExplicitlyConverted().(VariableAccess).getTarget() =
|
||||
this.getRightOperand().getExplicitlyConverted().(VariableAccess).getTarget()
|
||||
getLeftOperand().getExplicitlyConverted().(VariableAccess).getTarget() =
|
||||
getRightOperand().getExplicitlyConverted().(VariableAccess).getTarget()
|
||||
}
|
||||
|
||||
override float getLowerBounds() { result = 0 }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.7.5-dev
|
||||
version: 0.7.1-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
@@ -9,4 +9,3 @@ dependencies:
|
||||
codeql/ssa: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
codeql/util: ${workspace}
|
||||
warnOnImplicitThis: true
|
||||
|
||||
@@ -176,6 +176,20 @@ class Class extends UserType {
|
||||
/** Holds if this class, struct or union has a constructor. */
|
||||
predicate hasConstructor() { exists(this.getAConstructor()) }
|
||||
|
||||
/**
|
||||
* Holds if this class has a copy constructor that is either explicitly
|
||||
* declared (though possibly `= delete`) or is auto-generated, non-trivial
|
||||
* and called from somewhere.
|
||||
*
|
||||
* DEPRECATED: There is more than one reasonable definition of what it means
|
||||
* to have a copy constructor, and we do not want to promote one particular
|
||||
* definition by naming it with this predicate. Having a copy constructor
|
||||
* could mean that such a member is declared or defined in the source or that
|
||||
* it is callable by a particular caller. For C++11, there's also a question
|
||||
* of whether to include members that are defaulted or deleted.
|
||||
*/
|
||||
deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor }
|
||||
|
||||
/**
|
||||
* Like accessOfBaseMember but returns multiple results if there are multiple
|
||||
* paths to `base` through the inheritance graph.
|
||||
|
||||
@@ -42,7 +42,7 @@ class Compilation extends @compilation {
|
||||
}
|
||||
|
||||
/** Gets a file compiled during this invocation. */
|
||||
File getAFileCompiled() { result = this.getFileCompiled(_) }
|
||||
File getAFileCompiled() { result = getFileCompiled(_) }
|
||||
|
||||
/** Gets the `i`th file compiled during this invocation */
|
||||
File getFileCompiled(int i) { compilation_compiling_files(this, i, unresolveElement(result)) }
|
||||
@@ -74,7 +74,7 @@ class Compilation extends @compilation {
|
||||
/**
|
||||
* Gets an argument passed to the extractor on this invocation.
|
||||
*/
|
||||
string getAnArgument() { result = this.getArgument(_) }
|
||||
string getAnArgument() { result = getArgument(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th argument passed to the extractor on this invocation.
|
||||
|
||||
@@ -39,8 +39,7 @@ class Field extends MemberVariable {
|
||||
* complete most-derived object.
|
||||
*/
|
||||
int getAByteOffsetIn(Class mostDerivedClass) {
|
||||
result =
|
||||
mostDerivedClass.getABaseClassByteOffset(this.getDeclaringType()) + this.getByteOffset()
|
||||
result = mostDerivedClass.getABaseClassByteOffset(getDeclaringType()) + getByteOffset()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,10 +116,10 @@ class BitField extends Field {
|
||||
int getBitOffset() { fieldoffsets(underlyingElement(this), _, result) }
|
||||
|
||||
/** Holds if this bitfield is anonymous. */
|
||||
predicate isAnonymous() { this.hasName("(unnamed bitfield)") }
|
||||
predicate isAnonymous() { hasName("(unnamed bitfield)") }
|
||||
|
||||
override predicate isInitializable() {
|
||||
// Anonymous bitfields are not initializable.
|
||||
not this.isAnonymous()
|
||||
not isAnonymous()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,10 +24,10 @@ class LinkTarget extends @link_target {
|
||||
* captured as part of the snapshot, then everything is grouped together
|
||||
* into a single dummy link target.
|
||||
*/
|
||||
predicate isDummy() { this.getBinary().getAbsolutePath() = "" }
|
||||
predicate isDummy() { getBinary().getAbsolutePath() = "" }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = this.getBinary().getAbsolutePath() }
|
||||
string toString() { result = getBinary().getAbsolutePath() }
|
||||
|
||||
/**
|
||||
* Gets a function which was compiled into this link target, or had its
|
||||
|
||||
@@ -34,7 +34,7 @@ class Macro extends PreprocessorDirective, @ppd_define {
|
||||
* Gets the name of the macro. For example, `MAX` in
|
||||
* `#define MAX(x,y) (((x)>(y))?(x):(y))`.
|
||||
*/
|
||||
string getName() { result = this.getHead().regexpCapture("([^(]*+).*", 1) }
|
||||
string getName() { result = this.getHead().splitAt("(", 0) }
|
||||
|
||||
/** Holds if the macro has name `name`. */
|
||||
predicate hasName(string name) { this.getName() = name }
|
||||
|
||||
@@ -24,7 +24,7 @@ class NameQualifier extends NameQualifiableElement, @namequalifier {
|
||||
* Gets the expression ultimately qualified by the chain of name
|
||||
* qualifiers. For example, `f()` in `N1::N2::f()`.
|
||||
*/
|
||||
Expr getExpr() { result = this.getQualifiedElement+() }
|
||||
Expr getExpr() { result = getQualifiedElement+() }
|
||||
|
||||
/** Gets a location for this name qualifier. */
|
||||
override Location getLocation() { namequalifiers(underlyingElement(this), _, _, result) }
|
||||
@@ -56,12 +56,12 @@ class NameQualifier extends NameQualifiableElement, @namequalifier {
|
||||
if nqe instanceof SpecialNameQualifyingElement
|
||||
then
|
||||
exists(Access a |
|
||||
a = this.getQualifiedElement() and
|
||||
a = getQualifiedElement() and
|
||||
result = a.getTarget().getDeclaringType()
|
||||
)
|
||||
or
|
||||
exists(FunctionCall c |
|
||||
c = this.getQualifiedElement() and
|
||||
c = getQualifiedElement() and
|
||||
result = c.getTarget().getDeclaringType()
|
||||
)
|
||||
else result = nqe
|
||||
@@ -109,7 +109,7 @@ class NameQualifiableElement extends Element, @namequalifiableelement {
|
||||
* namespace.
|
||||
*/
|
||||
predicate hasGlobalQualifiedName() {
|
||||
this.getNameQualifier*().getQualifyingElement() instanceof GlobalNamespace
|
||||
getNameQualifier*().getQualifyingElement() instanceof GlobalNamespace
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -119,7 +119,7 @@ class NameQualifiableElement extends Element, @namequalifiableelement {
|
||||
*/
|
||||
predicate hasSuperQualifiedName() {
|
||||
exists(NameQualifier nq, SpecialNameQualifyingElement snqe |
|
||||
nq = this.getNameQualifier*() and
|
||||
nq = getNameQualifier*() and
|
||||
namequalifiers(unresolveElement(nq), _, unresolveElement(snqe), _) and
|
||||
snqe.getName() = "__super"
|
||||
)
|
||||
@@ -164,5 +164,5 @@ library class SpecialNameQualifyingElement extends NameQualifyingElement,
|
||||
/** Gets the name of this special qualifying element. */
|
||||
override string getName() { specialnamequalifyingelements(underlyingElement(this), result) }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
override string toString() { result = getName() }
|
||||
}
|
||||
|
||||
@@ -230,12 +230,8 @@ class GlobalNamespace extends Namespace {
|
||||
}
|
||||
|
||||
/**
|
||||
* The C++ `std::` namespace and its inline namespaces.
|
||||
* The C++ `std::` namespace.
|
||||
*/
|
||||
class StdNamespace extends Namespace {
|
||||
StdNamespace() {
|
||||
this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace
|
||||
or
|
||||
this.isInline() and this.getParentNamespace() instanceof StdNamespace
|
||||
}
|
||||
StdNamespace() { this.hasName("std") and this.getParentNamespace() instanceof GlobalNamespace }
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class NestedFieldAccess extends FieldAccess {
|
||||
|
||||
NestedFieldAccess() {
|
||||
ultimateQualifier = getUltimateQualifier(this) and
|
||||
this.getTarget() = getANestedField(ultimateQualifier.getType().stripType())
|
||||
getTarget() = getANestedField(ultimateQualifier.getType().stripType())
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -27,6 +27,9 @@ class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
predicate shouldPrintFunction(Function func) { any() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrintAstConfiguration */
|
||||
deprecated class PrintASTConfiguration = PrintAstConfiguration;
|
||||
|
||||
private predicate shouldPrintFunction(Function func) {
|
||||
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
|
||||
}
|
||||
@@ -127,7 +130,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
|
||||
result =
|
||||
rank[childIndex](PrintAstNode child, int nonConvertedIndex, boolean isConverted |
|
||||
this.childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
||||
childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
||||
|
|
||||
// Unconverted children come first, then sort by original child index within each group.
|
||||
child order by isConverted, nonConvertedIndex
|
||||
@@ -140,7 +143,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
*/
|
||||
private PrintAstNode getConvertedChild(int childIndex) {
|
||||
exists(Expr expr |
|
||||
expr = this.getChildInternal(childIndex).(AstNode).getAst() and
|
||||
expr = getChildInternal(childIndex).(AstNode).getAst() and
|
||||
expr.getFullyConverted() instanceof Conversion and
|
||||
result.(AstNode).getAst() = expr.getFullyConverted() and
|
||||
not expr instanceof Conversion
|
||||
@@ -152,8 +155,8 @@ class PrintAstNode extends TPrintAstNode {
|
||||
* at index `childIndex`, if that node has any conversions.
|
||||
*/
|
||||
private string getConvertedChildAccessorPredicate(int childIndex) {
|
||||
exists(this.getConvertedChild(childIndex)) and
|
||||
result = this.getChildAccessorPredicateInternal(childIndex) + ".getFullyConverted()"
|
||||
exists(getConvertedChild(childIndex)) and
|
||||
result = getChildAccessorPredicateInternal(childIndex) + ".getFullyConverted()"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -161,12 +164,12 @@ class PrintAstNode extends TPrintAstNode {
|
||||
* within a function are printed, but the query can override
|
||||
* `PrintASTConfiguration.shouldPrintFunction` to filter the output.
|
||||
*/
|
||||
final predicate shouldPrint() { shouldPrintFunction(this.getEnclosingFunction()) }
|
||||
final predicate shouldPrint() { shouldPrintFunction(getEnclosingFunction()) }
|
||||
|
||||
/**
|
||||
* Gets the children of this node.
|
||||
*/
|
||||
final PrintAstNode getAChild() { result = this.getChild(_) }
|
||||
final PrintAstNode getAChild() { result = getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the parent of this node, if any.
|
||||
@@ -184,7 +187,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and
|
||||
result = this.toString()
|
||||
result = toString()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,12 +201,12 @@ class PrintAstNode extends TPrintAstNode {
|
||||
private predicate childAndAccessorPredicate(
|
||||
PrintAstNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
|
||||
) {
|
||||
child = this.getChildInternal(nonConvertedIndex) and
|
||||
childPredicate = this.getChildAccessorPredicateInternal(nonConvertedIndex) and
|
||||
child = getChildInternal(nonConvertedIndex) and
|
||||
childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and
|
||||
isConverted = false
|
||||
or
|
||||
child = this.getConvertedChild(nonConvertedIndex) and
|
||||
childPredicate = this.getConvertedChildAccessorPredicate(nonConvertedIndex) and
|
||||
child = getConvertedChild(nonConvertedIndex) and
|
||||
childPredicate = getConvertedChildAccessorPredicate(nonConvertedIndex) and
|
||||
isConverted = true
|
||||
}
|
||||
|
||||
@@ -215,7 +218,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
// The exact value of `childIndex` doesn't matter, as long as we preserve the correct order.
|
||||
result =
|
||||
rank[childIndex](string childPredicate, int nonConvertedIndex, boolean isConverted |
|
||||
this.childAndAccessorPredicate(_, childPredicate, nonConvertedIndex, isConverted)
|
||||
childAndAccessorPredicate(_, childPredicate, nonConvertedIndex, isConverted)
|
||||
|
|
||||
// Unconverted children come first, then sort by original child index within each group.
|
||||
childPredicate order by isConverted, nonConvertedIndex
|
||||
@@ -231,11 +234,12 @@ class PrintAstNode extends TPrintAstNode {
|
||||
/**
|
||||
* Gets the `Function` that contains this node.
|
||||
*/
|
||||
private Function getEnclosingFunction() {
|
||||
result = this.getParent*().(FunctionNode).getFunction()
|
||||
}
|
||||
private Function getEnclosingFunction() { result = getParent*().(FunctionNode).getFunction() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for PrintAstNode */
|
||||
deprecated class PrintASTNode = PrintAstNode;
|
||||
|
||||
/**
|
||||
* Class that restricts the elements that we compute `qlClass` for.
|
||||
*/
|
||||
@@ -249,7 +253,7 @@ private class PrintableElement extends Element {
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
string getAPrimaryQlClass0() { result = this.getAPrimaryQlClass() }
|
||||
string getAPrimaryQlClass0() { result = getAPrimaryQlClass() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -277,9 +281,12 @@ abstract class BaseAstNode extends PrintAstNode {
|
||||
final Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = this.getAst() }
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for BaseAstNode */
|
||||
deprecated class BaseASTNode = BaseAstNode;
|
||||
|
||||
/**
|
||||
* A node representing an AST node other than a `DeclarationEntry`.
|
||||
*/
|
||||
@@ -287,6 +294,9 @@ abstract class AstNode extends BaseAstNode, TAstNode {
|
||||
AstNode() { this = TAstNode(ast) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AstNode */
|
||||
deprecated class ASTNode = AstNode;
|
||||
|
||||
/**
|
||||
* A node representing an `Expr`.
|
||||
*/
|
||||
@@ -301,7 +311,7 @@ class ExprNode extends AstNode {
|
||||
result = super.getProperty(key)
|
||||
or
|
||||
key = "Value" and
|
||||
result = qlClass(expr) + this.getValue()
|
||||
result = qlClass(expr) + getValue()
|
||||
or
|
||||
key = "Type" and
|
||||
result = qlClass(expr.getType()) + expr.getType().toString()
|
||||
@@ -311,7 +321,7 @@ class ExprNode extends AstNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -431,7 +441,7 @@ class StmtNode extends AstNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, this.getChildInternal(childIndex).getAst())
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -507,7 +517,7 @@ class ParametersNode extends PrintAstNode, TParametersNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
exists(getChildInternal(childIndex)) and
|
||||
result = "getParameter(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
@@ -534,7 +544,7 @@ class ConstructorInitializersNode extends PrintAstNode, TConstructorInitializers
|
||||
}
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
exists(getChildInternal(childIndex)) and
|
||||
result = "getInitializer(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
@@ -561,7 +571,7 @@ class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNo
|
||||
}
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
exists(this.getChildInternal(childIndex)) and
|
||||
exists(getChildInternal(childIndex)) and
|
||||
result = "getDestruction(" + childIndex.toString() + ")"
|
||||
}
|
||||
|
||||
@@ -618,7 +628,7 @@ class FunctionNode extends AstNode {
|
||||
override string getProperty(string key) {
|
||||
result = super.getProperty(key)
|
||||
or
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1699,28 +1699,7 @@ class AutoType extends TemplateParameter {
|
||||
|
||||
private predicate suppressUnusedThis(Type t) { any() }
|
||||
|
||||
/**
|
||||
* A source code location referring to a user-defined type.
|
||||
*
|
||||
* Note that only _user-defined_ types have `TypeMention`s. In particular,
|
||||
* built-in types, and derived types with built-in types as their base don't
|
||||
* have any `TypeMention`s. For example, given
|
||||
* ```cpp
|
||||
* struct S { ... };
|
||||
* void f(S s1, int i1) {
|
||||
* S s2;
|
||||
* S* s3;
|
||||
* S& s4 = s2;
|
||||
* decltype(s2) s5;
|
||||
*
|
||||
* int i2;
|
||||
* int* i3;
|
||||
* int i4[10];
|
||||
* }
|
||||
* ```
|
||||
* there will be a `TypeMention` for the mention of `S` at `S s1`, `S s2`, and `S& s4 = s2`,
|
||||
* but not at `decltype(s2) s5`. Additionally, there will be no `TypeMention`s for `int`.
|
||||
*/
|
||||
/** A source code location referring to a type */
|
||||
class TypeMention extends Locatable, @type_mention {
|
||||
override string toString() { result = "type mention" }
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import cpp
|
||||
*/
|
||||
deprecated class StrcatFunction extends Function {
|
||||
StrcatFunction() {
|
||||
this.getName() =
|
||||
getName() =
|
||||
[
|
||||
"strcat", // strcat(dst, src)
|
||||
"strncat", // strncat(dst, src, max_amount)
|
||||
|
||||
@@ -98,7 +98,7 @@ library class DefOrUse extends ControlFlowNodeBase {
|
||||
|
||||
pragma[noinline]
|
||||
private predicate reaches_helper(boolean isDef, SemanticStackVariable v, BasicBlock bb, int i) {
|
||||
this.getVariable(isDef) = v and
|
||||
getVariable(isDef) = v and
|
||||
bb.getNode(i) = this
|
||||
}
|
||||
|
||||
@@ -118,21 +118,21 @@ library class DefOrUse extends ControlFlowNodeBase {
|
||||
* predicates are duplicated for now.
|
||||
*/
|
||||
|
||||
exists(BasicBlock bb, int i | this.reaches_helper(isDef, v, bb, i) |
|
||||
exists(BasicBlock bb, int i | reaches_helper(isDef, v, bb, i) |
|
||||
exists(int j |
|
||||
j > i and
|
||||
(bbDefAt(bb, j, v, defOrUse) or bbUseAt(bb, j, v, defOrUse)) and
|
||||
not exists(int k | this.firstBarrierAfterThis(isDef, k, v) and k < j)
|
||||
not exists(int k | firstBarrierAfterThis(isDef, k, v) and k < j)
|
||||
)
|
||||
or
|
||||
not this.firstBarrierAfterThis(isDef, _, v) and
|
||||
not firstBarrierAfterThis(isDef, _, v) and
|
||||
bbSuccessorEntryReachesDefOrUse(bb, v, defOrUse, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate firstBarrierAfterThis(boolean isDef, int j, SemanticStackVariable v) {
|
||||
exists(BasicBlock bb, int i |
|
||||
this.getVariable(isDef) = v and
|
||||
getVariable(isDef) = v and
|
||||
bb.getNode(i) = this and
|
||||
j = min(int k | bbBarrierAt(bb, k, v, _) and k > i)
|
||||
)
|
||||
|
||||
@@ -14,6 +14,9 @@ library class StandardSsa extends SsaHelper {
|
||||
StandardSsa() { this = 0 }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for StandardSsa */
|
||||
deprecated class StandardSSA = StandardSsa;
|
||||
|
||||
/**
|
||||
* A definition of one or more SSA variables, including phi node definitions.
|
||||
* An _SSA variable_, as defined in the literature, is effectively the pair of
|
||||
|
||||
@@ -130,7 +130,7 @@ library class SsaHelper extends int {
|
||||
* Remove any custom phi nodes that are invalid.
|
||||
*/
|
||||
private predicate sanitized_custom_phi_node(StackVariable v, BasicBlock b) {
|
||||
this.custom_phi_node(v, b) and
|
||||
custom_phi_node(v, b) and
|
||||
not addressTakenVariable(v) and
|
||||
not isReferenceVar(v) and
|
||||
b.isReachable()
|
||||
@@ -142,7 +142,7 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
predicate phi_node(StackVariable v, BasicBlock b) {
|
||||
this.frontier_phi_node(v, b) or this.sanitized_custom_phi_node(v, b)
|
||||
frontier_phi_node(v, b) or sanitized_custom_phi_node(v, b)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,15 +154,14 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
private predicate frontier_phi_node(StackVariable v, BasicBlock b) {
|
||||
exists(BasicBlock x |
|
||||
dominanceFrontier(x, b) and
|
||||
this.ssa_defn_rec(pragma[only_bind_into](v), pragma[only_bind_into](x))
|
||||
dominanceFrontier(x, b) and ssa_defn_rec(pragma[only_bind_into](v), pragma[only_bind_into](x))
|
||||
) and
|
||||
/* We can also eliminate those nodes where the variable is not live on any incoming edge */
|
||||
live_at_start_of_bb(pragma[only_bind_into](v), b)
|
||||
}
|
||||
|
||||
private predicate ssa_defn_rec(StackVariable v, BasicBlock b) {
|
||||
this.phi_node(v, b)
|
||||
phi_node(v, b)
|
||||
or
|
||||
variableUpdate(v, _, b, _)
|
||||
}
|
||||
@@ -173,7 +172,7 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
predicate ssa_defn(StackVariable v, ControlFlowNode node, BasicBlock b, int index) {
|
||||
this.phi_node(v, b) and b.getStart() = node and index = -1
|
||||
phi_node(v, b) and b.getStart() = node and index = -1
|
||||
or
|
||||
variableUpdate(v, node, b, index)
|
||||
}
|
||||
@@ -197,7 +196,7 @@ library class SsaHelper extends int {
|
||||
* basic blocks.
|
||||
*/
|
||||
private predicate defUseRank(StackVariable v, BasicBlock b, int rankix, int i) {
|
||||
i = rank[rankix](int j | this.ssa_defn(v, _, b, j) or ssa_use(v, _, b, j))
|
||||
i = rank[rankix](int j | ssa_defn(v, _, b, j) or ssa_use(v, _, b, j))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -207,7 +206,7 @@ library class SsaHelper extends int {
|
||||
* the block.
|
||||
*/
|
||||
private int lastRank(StackVariable v, BasicBlock b) {
|
||||
result = max(int rankix | this.defUseRank(v, b, rankix, _)) + 1
|
||||
result = max(int rankix | defUseRank(v, b, rankix, _)) + 1
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -216,8 +215,8 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
private predicate ssaDefRank(StackVariable v, ControlFlowNode def, BasicBlock b, int rankix) {
|
||||
exists(int i |
|
||||
this.ssa_defn(v, def, b, i) and
|
||||
this.defUseRank(v, b, rankix, i)
|
||||
ssa_defn(v, def, b, i) and
|
||||
defUseRank(v, b, rankix, i)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -233,21 +232,21 @@ library class SsaHelper extends int {
|
||||
// use is understood to happen _before_ the definition. Phi nodes are
|
||||
// at rankidx -1 and will therefore always reach the first node in the
|
||||
// basic block.
|
||||
this.ssaDefRank(v, def, b, rankix - 1)
|
||||
ssaDefRank(v, def, b, rankix - 1)
|
||||
or
|
||||
this.ssaDefReachesRank(v, def, b, rankix - 1) and
|
||||
rankix <= this.lastRank(v, b) and // Without this, the predicate would be infinite.
|
||||
not this.ssaDefRank(v, _, b, rankix - 1) // Range is inclusive of but not past next def.
|
||||
ssaDefReachesRank(v, def, b, rankix - 1) and
|
||||
rankix <= lastRank(v, b) and // Without this, the predicate would be infinite.
|
||||
not ssaDefRank(v, _, b, rankix - 1) // Range is inclusive of but not past next def.
|
||||
}
|
||||
|
||||
/** Holds if SSA variable `(v, def)` reaches the end of block `b`. */
|
||||
cached
|
||||
predicate ssaDefinitionReachesEndOfBB(StackVariable v, ControlFlowNode def, BasicBlock b) {
|
||||
live_at_exit_of_bb(v, b) and this.ssaDefReachesRank(v, def, b, this.lastRank(v, b))
|
||||
live_at_exit_of_bb(v, b) and ssaDefReachesRank(v, def, b, lastRank(v, b))
|
||||
or
|
||||
exists(BasicBlock idom |
|
||||
this.ssaDefinitionReachesEndOfBB(v, def, idom) and
|
||||
this.noDefinitionsSinceIDominator(v, idom, b)
|
||||
ssaDefinitionReachesEndOfBB(v, def, idom) and
|
||||
noDefinitionsSinceIDominator(v, idom, b)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -261,7 +260,7 @@ library class SsaHelper extends int {
|
||||
private predicate noDefinitionsSinceIDominator(StackVariable v, BasicBlock idom, BasicBlock b) {
|
||||
bbIDominates(idom, b) and // It is sufficient to traverse the dominator graph, cf. discussion above.
|
||||
live_at_exit_of_bb(v, b) and
|
||||
not this.ssa_defn(v, _, b, _)
|
||||
not ssa_defn(v, _, b, _)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,8 +269,8 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
private predicate ssaDefinitionReachesUseWithinBB(StackVariable v, ControlFlowNode def, Expr use) {
|
||||
exists(BasicBlock b, int rankix, int i |
|
||||
this.ssaDefReachesRank(v, def, b, rankix) and
|
||||
this.defUseRank(v, b, rankix, i) and
|
||||
ssaDefReachesRank(v, def, b, rankix) and
|
||||
defUseRank(v, b, rankix, i) and
|
||||
ssa_use(v, use, b, i)
|
||||
)
|
||||
}
|
||||
@@ -280,12 +279,12 @@ library class SsaHelper extends int {
|
||||
* Holds if SSA variable `(v, def)` reaches the control-flow node `use`.
|
||||
*/
|
||||
private predicate ssaDefinitionReaches(StackVariable v, ControlFlowNode def, Expr use) {
|
||||
this.ssaDefinitionReachesUseWithinBB(v, def, use)
|
||||
ssaDefinitionReachesUseWithinBB(v, def, use)
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
ssa_use(v, use, b, _) and
|
||||
this.ssaDefinitionReachesEndOfBB(v, def, b.getAPredecessor()) and
|
||||
not this.ssaDefinitionReachesUseWithinBB(v, _, use)
|
||||
ssaDefinitionReachesEndOfBB(v, def, b.getAPredecessor()) and
|
||||
not ssaDefinitionReachesUseWithinBB(v, _, use)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -295,10 +294,10 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
string toString(ControlFlowNode node, StackVariable v) {
|
||||
if this.phi_node(v, node)
|
||||
if phi_node(v, node)
|
||||
then result = "SSA phi(" + v.getName() + ")"
|
||||
else (
|
||||
this.ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")"
|
||||
ssa_defn(v, node, _, _) and result = "SSA def(" + v.getName() + ")"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -308,7 +307,10 @@ library class SsaHelper extends int {
|
||||
*/
|
||||
cached
|
||||
VariableAccess getAUse(ControlFlowNode def, StackVariable v) {
|
||||
this.ssaDefinitionReaches(v, def, result) and
|
||||
ssaDefinitionReaches(v, def, result) and
|
||||
ssa_use(v, result, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SsaHelper */
|
||||
deprecated class SSAHelper = SsaHelper;
|
||||
|
||||
@@ -25,7 +25,7 @@ import cpp
|
||||
*/
|
||||
abstract class StackVariableReachability extends string {
|
||||
bindingset[this]
|
||||
StackVariableReachability() { this.length() >= 0 }
|
||||
StackVariableReachability() { length() >= 0 }
|
||||
|
||||
/** Holds if `node` is a source for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSource(ControlFlowNode node, StackVariable v);
|
||||
@@ -227,7 +227,7 @@ predicate bbSuccessorEntryReachesLoopInvariant(
|
||||
*/
|
||||
abstract class StackVariableReachabilityWithReassignment extends StackVariableReachability {
|
||||
bindingset[this]
|
||||
StackVariableReachabilityWithReassignment() { this.length() >= 0 }
|
||||
StackVariableReachabilityWithReassignment() { length() >= 0 }
|
||||
|
||||
/** Override this predicate rather than `isSource` (`isSource` is used internally). */
|
||||
abstract predicate isSourceActual(ControlFlowNode node, StackVariable v);
|
||||
@@ -330,7 +330,7 @@ abstract class StackVariableReachabilityWithReassignment extends StackVariableRe
|
||||
*/
|
||||
abstract class StackVariableReachabilityExt extends string {
|
||||
bindingset[this]
|
||||
StackVariableReachabilityExt() { this.length() >= 0 }
|
||||
StackVariableReachabilityExt() { length() >= 0 }
|
||||
|
||||
/** `node` is a source for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSource(ControlFlowNode node, StackVariable v);
|
||||
|
||||
@@ -1385,6 +1385,9 @@ private module Cached {
|
||||
conditionalSuccessor(n1, _, n2)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for qlCfgSuccessor */
|
||||
deprecated predicate qlCFGSuccessor = qlCfgSuccessor/2;
|
||||
|
||||
/**
|
||||
* Holds if `n2` is a control-flow node such that the control-flow
|
||||
* edge `(n1, n2)` may be taken when `n1` is an expression that is true.
|
||||
@@ -1395,6 +1398,9 @@ private module Cached {
|
||||
not conditionalSuccessor(n1, false, n2)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for qlCfgTrueSuccessor */
|
||||
deprecated predicate qlCFGTrueSuccessor = qlCfgTrueSuccessor/2;
|
||||
|
||||
/**
|
||||
* Holds if `n2` is a control-flow node such that the control-flow
|
||||
* edge `(n1, n2)` may be taken when `n1` is an expression that is false.
|
||||
@@ -1404,4 +1410,7 @@ private module Cached {
|
||||
conditionalSuccessor(n1, false, n2) and
|
||||
not conditionalSuccessor(n1, true, n2)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for qlCfgFalseSuccessor */
|
||||
deprecated predicate qlCFGFalseSuccessor = qlCfgFalseSuccessor/2;
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -815,15 +815,7 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `c`.
|
||||
*
|
||||
* This includes reverse steps through reads when the result of the read has
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate store(
|
||||
private predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
exists(ContentSet cs |
|
||||
@@ -831,6 +823,18 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
*
|
||||
* This includes reverse steps through reads when the result of the read has
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) {
|
||||
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `fromNode` to `toNode` because they are the post-update
|
||||
* nodes of some function output and input respectively, where the output and input
|
||||
@@ -928,15 +932,36 @@ private module Cached {
|
||||
TReturnCtxNoFlowThrough() or
|
||||
TReturnCtxMaybeFlowThrough(ReturnPosition pos)
|
||||
|
||||
cached
|
||||
newtype TTypedContentApprox =
|
||||
MkTypedContentApprox(ContentApprox c, DataFlowType t) {
|
||||
exists(Content cont |
|
||||
c = getContentApprox(cont) and
|
||||
store(_, cont, _, _, t)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
|
||||
|
||||
cached
|
||||
TypedContent getATypedContent(TypedContentApprox c) {
|
||||
exists(ContentApprox cls, DataFlowType t, Content cont |
|
||||
c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and
|
||||
result = MkTypedContent(cont, pragma[only_bind_into](t)) and
|
||||
cls = getContentApprox(cont)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil() or
|
||||
TFrontHead(Content c)
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(TypedContent tc)
|
||||
|
||||
cached
|
||||
newtype TApproxAccessPathFront =
|
||||
TApproxFrontNil() or
|
||||
TApproxFrontHead(ContentApprox c)
|
||||
TApproxFrontNil(DataFlowType t) or
|
||||
TApproxFrontHead(TypedContentApprox tc)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
@@ -961,16 +986,8 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode instanceof Node {
|
||||
class CastingNode extends Node {
|
||||
CastingNode() { castingNode(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
@@ -1118,17 +1135,9 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode instanceof Node {
|
||||
class ParamNode extends Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
@@ -1137,17 +1146,9 @@ class ParamNode instanceof Node {
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
class ArgNode instanceof Node {
|
||||
class ArgNode extends Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
@@ -1158,17 +1159,9 @@ class ArgNode instanceof Node {
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt instanceof Node {
|
||||
class ReturnNodeExt extends Node {
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
@@ -1177,16 +1170,8 @@ class ReturnNodeExt instanceof Node {
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt instanceof Node {
|
||||
class OutNodeExt extends Node {
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1402,37 +1387,67 @@ class ReturnCtx extends TReturnCtx {
|
||||
}
|
||||
}
|
||||
|
||||
/** An approximated `Content` tagged with the type of a containing object. */
|
||||
class TypedContentApprox extends MkTypedContentApprox {
|
||||
private ContentApprox c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContentApprox() { this = MkTypedContentApprox(c, t) }
|
||||
|
||||
/** Gets a typed content approximated by this value. */
|
||||
TypedContent getATypedContent() { result = getATypedContent(this) }
|
||||
|
||||
/** Gets the content. */
|
||||
ContentApprox getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this approximated content. */
|
||||
string toString() { result = c.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an approximated access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
ContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
|
||||
pragma[nomagic]
|
||||
Content getAHead() {
|
||||
exists(ContentApprox cont |
|
||||
TypedContent getAHead() {
|
||||
exists(TypedContentApprox cont |
|
||||
this = TApproxFrontHead(cont) and
|
||||
cont = getContentApprox(result)
|
||||
result = cont.getATypedContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil {
|
||||
override string toString() { result = "nil" }
|
||||
private DataFlowType t;
|
||||
|
||||
ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
|
||||
private ContentApprox c;
|
||||
private TypedContentApprox tc;
|
||||
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) }
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) }
|
||||
|
||||
override string toString() { result = c.toString() }
|
||||
override string toString() { result = tc.toString() }
|
||||
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
@@ -1446,31 +1461,65 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContent() { this = MkTypedContent(c, t) }
|
||||
|
||||
/** Gets the content. */
|
||||
Content getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this content. */
|
||||
string toString() { result = c.toString() }
|
||||
|
||||
/**
|
||||
* Holds if access paths with this `TypedContent` at their head always should
|
||||
* be tracked at high precision. This disables adaptive access path precision
|
||||
* for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision() { forceHighPrecision(c) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract ApproxAccessPathFront toApprox();
|
||||
|
||||
Content getHead() { this = TFrontHead(result) }
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
override string toString() { result = "nil" }
|
||||
private DataFlowType t;
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() }
|
||||
AccessPathFrontNil() { this = TFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
private Content c;
|
||||
private TypedContent tc;
|
||||
|
||||
AccessPathFrontHead() { this = TFrontHead(c) }
|
||||
AccessPathFrontHead() { this = TFrontHead(tc) }
|
||||
|
||||
override string toString() { result = c.toString() }
|
||||
override string toString() { result = tc.toString() }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = c }
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = tc }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
|
||||
@@ -58,9 +58,6 @@ module Consistency {
|
||||
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
|
||||
none()
|
||||
}
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `identityLocalStep`. */
|
||||
predicate identityLocalStepExclude(Node n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
@@ -290,10 +287,4 @@ module Consistency {
|
||||
not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and
|
||||
msg = "Non-unique content approximation."
|
||||
}
|
||||
|
||||
query predicate identityLocalStep(Node n, string msg) {
|
||||
simpleLocalFlowStep(n, n) and
|
||||
not any(ConsistencyConfiguration c).identityLocalStepExclude(n) and
|
||||
msg = "Node steps to itself"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,9 +76,9 @@ class GTExpr extends RelationalOperation, @gtexpr {
|
||||
|
||||
override string getOperator() { result = ">" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
override Expr getGreaterOperand() { result = getLeftOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
override Expr getLesserOperand() { result = getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,9 +92,9 @@ class LTExpr extends RelationalOperation, @ltexpr {
|
||||
|
||||
override string getOperator() { result = "<" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
override Expr getGreaterOperand() { result = getRightOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
override Expr getLesserOperand() { result = getLeftOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,9 +108,9 @@ class GEExpr extends RelationalOperation, @geexpr {
|
||||
|
||||
override string getOperator() { result = ">=" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
override Expr getGreaterOperand() { result = getLeftOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
override Expr getLesserOperand() { result = getRightOperand() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -124,7 +124,7 @@ class LEExpr extends RelationalOperation, @leexpr {
|
||||
|
||||
override string getOperator() { result = "<=" }
|
||||
|
||||
override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
override Expr getGreaterOperand() { result = getRightOperand() }
|
||||
|
||||
override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
override Expr getLesserOperand() { result = getLeftOperand() }
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -815,15 +815,7 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `c`.
|
||||
*
|
||||
* This includes reverse steps through reads when the result of the read has
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate store(
|
||||
private predicate store(
|
||||
Node node1, Content c, Node node2, DataFlowType contentType, DataFlowType containerType
|
||||
) {
|
||||
exists(ContentSet cs |
|
||||
@@ -831,6 +823,18 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` via a direct assignment to
|
||||
* `f`.
|
||||
*
|
||||
* This includes reverse steps through reads when the result of the read has
|
||||
* been stored into, in order to handle cases like `x.f1.f2 = y`.
|
||||
*/
|
||||
cached
|
||||
predicate store(Node node1, TypedContent tc, Node node2, DataFlowType contentType) {
|
||||
store(node1, tc.getContent(), node2, contentType, tc.getContainerType())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `fromNode` to `toNode` because they are the post-update
|
||||
* nodes of some function output and input respectively, where the output and input
|
||||
@@ -928,15 +932,36 @@ private module Cached {
|
||||
TReturnCtxNoFlowThrough() or
|
||||
TReturnCtxMaybeFlowThrough(ReturnPosition pos)
|
||||
|
||||
cached
|
||||
newtype TTypedContentApprox =
|
||||
MkTypedContentApprox(ContentApprox c, DataFlowType t) {
|
||||
exists(Content cont |
|
||||
c = getContentApprox(cont) and
|
||||
store(_, cont, _, _, t)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TTypedContent = MkTypedContent(Content c, DataFlowType t) { store(_, c, _, _, t) }
|
||||
|
||||
cached
|
||||
TypedContent getATypedContent(TypedContentApprox c) {
|
||||
exists(ContentApprox cls, DataFlowType t, Content cont |
|
||||
c = MkTypedContentApprox(cls, pragma[only_bind_into](t)) and
|
||||
result = MkTypedContent(cont, pragma[only_bind_into](t)) and
|
||||
cls = getContentApprox(cont)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
newtype TAccessPathFront =
|
||||
TFrontNil() or
|
||||
TFrontHead(Content c)
|
||||
TFrontNil(DataFlowType t) or
|
||||
TFrontHead(TypedContent tc)
|
||||
|
||||
cached
|
||||
newtype TApproxAccessPathFront =
|
||||
TApproxFrontNil() or
|
||||
TApproxFrontHead(ContentApprox c)
|
||||
TApproxFrontNil(DataFlowType t) or
|
||||
TApproxFrontHead(TypedContentApprox tc)
|
||||
|
||||
cached
|
||||
newtype TAccessPathFrontOption =
|
||||
@@ -961,16 +986,8 @@ predicate recordDataFlowCallSite(DataFlowCall call, DataFlowCallable callable) {
|
||||
/**
|
||||
* A `Node` at which a cast can occur such that the type should be checked.
|
||||
*/
|
||||
class CastingNode instanceof Node {
|
||||
class CastingNode extends Node {
|
||||
CastingNode() { castingNode(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
private predicate readStepWithTypes(
|
||||
@@ -1118,17 +1135,9 @@ LocalCallContext getLocalCallContext(CallContext ctx, DataFlowCallable callable)
|
||||
* The value of a parameter at function entry, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
class ParamNode instanceof Node {
|
||||
class ParamNode extends Node {
|
||||
ParamNode() { parameterNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this node is the parameter of callable `c` at the specified
|
||||
* position.
|
||||
@@ -1137,17 +1146,9 @@ class ParamNode instanceof Node {
|
||||
}
|
||||
|
||||
/** A data-flow node that represents a call argument. */
|
||||
class ArgNode instanceof Node {
|
||||
class ArgNode extends Node {
|
||||
ArgNode() { argumentNode(this, _, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Holds if this argument occurs at the given position in the given call. */
|
||||
final predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||
argumentNode(this, call, pos)
|
||||
@@ -1158,17 +1159,9 @@ class ArgNode instanceof Node {
|
||||
* A node from which flow can return to the caller. This is either a regular
|
||||
* `ReturnNode` or a `PostUpdateNode` corresponding to the value of a parameter.
|
||||
*/
|
||||
class ReturnNodeExt instanceof Node {
|
||||
class ReturnNodeExt extends Node {
|
||||
ReturnNodeExt() { returnNodeExt(this, _) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets the kind of this returned value. */
|
||||
ReturnKindExt getKind() { returnNodeExt(this, result) }
|
||||
}
|
||||
@@ -1177,16 +1170,8 @@ class ReturnNodeExt instanceof Node {
|
||||
* A node to which data can flow from a call. Either an ordinary out node
|
||||
* or a post-update node associated with a call argument.
|
||||
*/
|
||||
class OutNodeExt instanceof Node {
|
||||
class OutNodeExt extends Node {
|
||||
OutNodeExt() { outNodeExt(this) }
|
||||
|
||||
string toString() { result = super.toString() }
|
||||
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1402,37 +1387,67 @@ class ReturnCtx extends TReturnCtx {
|
||||
}
|
||||
}
|
||||
|
||||
/** An approximated `Content` tagged with the type of a containing object. */
|
||||
class TypedContentApprox extends MkTypedContentApprox {
|
||||
private ContentApprox c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContentApprox() { this = MkTypedContentApprox(c, t) }
|
||||
|
||||
/** Gets a typed content approximated by this value. */
|
||||
TypedContent getATypedContent() { result = getATypedContent(this) }
|
||||
|
||||
/** Gets the content. */
|
||||
ContentApprox getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this approximated content. */
|
||||
string toString() { result = c.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an approximated access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class ApproxAccessPathFront extends TApproxAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract boolean toBoolNonEmpty();
|
||||
|
||||
ContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
TypedContentApprox getHead() { this = TApproxFrontHead(result) }
|
||||
|
||||
pragma[nomagic]
|
||||
Content getAHead() {
|
||||
exists(ContentApprox cont |
|
||||
TypedContent getAHead() {
|
||||
exists(TypedContentApprox cont |
|
||||
this = TApproxFrontHead(cont) and
|
||||
cont = getContentApprox(result)
|
||||
result = cont.getATypedContent()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontNil extends ApproxAccessPathFront, TApproxFrontNil {
|
||||
override string toString() { result = "nil" }
|
||||
private DataFlowType t;
|
||||
|
||||
ApproxAccessPathFrontNil() { this = TApproxFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = false }
|
||||
}
|
||||
|
||||
class ApproxAccessPathFrontHead extends ApproxAccessPathFront, TApproxFrontHead {
|
||||
private ContentApprox c;
|
||||
private TypedContentApprox tc;
|
||||
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(c) }
|
||||
ApproxAccessPathFrontHead() { this = TApproxFrontHead(tc) }
|
||||
|
||||
override string toString() { result = c.toString() }
|
||||
override string toString() { result = tc.toString() }
|
||||
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
|
||||
override boolean toBoolNonEmpty() { result = true }
|
||||
}
|
||||
@@ -1446,31 +1461,65 @@ class ApproxAccessPathFrontOption extends TApproxAccessPathFrontOption {
|
||||
}
|
||||
}
|
||||
|
||||
/** A `Content` tagged with the type of a containing object. */
|
||||
class TypedContent extends MkTypedContent {
|
||||
private Content c;
|
||||
private DataFlowType t;
|
||||
|
||||
TypedContent() { this = MkTypedContent(c, t) }
|
||||
|
||||
/** Gets the content. */
|
||||
Content getContent() { result = c }
|
||||
|
||||
/** Gets the container type. */
|
||||
DataFlowType getContainerType() { result = t }
|
||||
|
||||
/** Gets a textual representation of this content. */
|
||||
string toString() { result = c.toString() }
|
||||
|
||||
/**
|
||||
* Holds if access paths with this `TypedContent` at their head always should
|
||||
* be tracked at high precision. This disables adaptive access path precision
|
||||
* for such access paths.
|
||||
*/
|
||||
predicate forceHighPrecision() { forceHighPrecision(c) }
|
||||
}
|
||||
|
||||
/**
|
||||
* The front of an access path. This is either a head or a nil.
|
||||
*/
|
||||
abstract class AccessPathFront extends TAccessPathFront {
|
||||
abstract string toString();
|
||||
|
||||
abstract DataFlowType getType();
|
||||
|
||||
abstract ApproxAccessPathFront toApprox();
|
||||
|
||||
Content getHead() { this = TFrontHead(result) }
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
override string toString() { result = "nil" }
|
||||
private DataFlowType t;
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil() }
|
||||
AccessPathFrontNil() { this = TFrontNil(t) }
|
||||
|
||||
override string toString() { result = ppReprType(t) }
|
||||
|
||||
override DataFlowType getType() { result = t }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result = TApproxFrontNil(t) }
|
||||
}
|
||||
|
||||
class AccessPathFrontHead extends AccessPathFront, TFrontHead {
|
||||
private Content c;
|
||||
private TypedContent tc;
|
||||
|
||||
AccessPathFrontHead() { this = TFrontHead(c) }
|
||||
AccessPathFrontHead() { this = TFrontHead(tc) }
|
||||
|
||||
override string toString() { result = c.toString() }
|
||||
override string toString() { result = tc.toString() }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = c }
|
||||
override DataFlowType getType() { result = tc.getContainerType() }
|
||||
|
||||
override ApproxAccessPathFront toApprox() { result.getAHead() = tc }
|
||||
}
|
||||
|
||||
/** An optional access path front. */
|
||||
|
||||
@@ -58,9 +58,6 @@ module Consistency {
|
||||
predicate uniqueParameterNodePositionExclude(DataFlowCallable c, ParameterPosition pos, Node p) {
|
||||
none()
|
||||
}
|
||||
|
||||
/** Holds if `n` should be excluded from the consistency test `identityLocalStep`. */
|
||||
predicate identityLocalStepExclude(Node n) { none() }
|
||||
}
|
||||
|
||||
private class RelevantNode extends Node {
|
||||
@@ -290,10 +287,4 @@ module Consistency {
|
||||
not exists(unique(ContentApprox approx | approx = getContentApprox(c))) and
|
||||
msg = "Non-unique content approximation."
|
||||
}
|
||||
|
||||
query predicate identityLocalStep(Node n, string msg) {
|
||||
simpleLocalFlowStep(n, n) and
|
||||
not any(ConsistencyConfiguration c).identityLocalStepExclude(n) and
|
||||
msg = "Node steps to itself"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -210,8 +210,8 @@ class IndirectOperand extends Node {
|
||||
this.(RawIndirectOperand).getOperand() = operand and
|
||||
this.(RawIndirectOperand).getIndirectionIndex() = indirectionIndex
|
||||
or
|
||||
nodeHasOperand(this, Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex),
|
||||
indirectionIndex - 1)
|
||||
this.(OperandNode).getOperand() =
|
||||
Ssa::getIRRepresentationOfIndirectOperand(operand, indirectionIndex)
|
||||
}
|
||||
|
||||
/** Gets the underlying operand. */
|
||||
@@ -250,8 +250,8 @@ class IndirectInstruction extends Node {
|
||||
this.(RawIndirectInstruction).getInstruction() = instr and
|
||||
this.(RawIndirectInstruction).getIndirectionIndex() = indirectionIndex
|
||||
or
|
||||
nodeHasInstruction(this, Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex),
|
||||
indirectionIndex - 1)
|
||||
this.(InstructionNode).getInstruction() =
|
||||
Ssa::getIRRepresentationOfIndirectInstruction(instr, indirectionIndex)
|
||||
}
|
||||
|
||||
/** Gets the underlying instruction. */
|
||||
@@ -607,21 +607,13 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
|
||||
result.getReturnKind() = kind
|
||||
}
|
||||
|
||||
/** A variable that behaves like a global variable. */
|
||||
class GlobalLikeVariable extends Variable {
|
||||
GlobalLikeVariable() {
|
||||
this instanceof Cpp::GlobalOrNamespaceVariable or
|
||||
this instanceof Cpp::StaticLocalVariable
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data can flow from `node1` to `node2` in a way that loses the
|
||||
* calling context. For example, this would happen with flow through a
|
||||
* global or static variable.
|
||||
*/
|
||||
predicate jumpStep(Node n1, Node n2) {
|
||||
exists(GlobalLikeVariable v |
|
||||
exists(Cpp::GlobalOrNamespaceVariable v |
|
||||
exists(Ssa::GlobalUse globalUse |
|
||||
v = globalUse.getVariable() and
|
||||
n1.(FinalGlobalValue).getGlobalUse() = globalUse
|
||||
|
||||
@@ -562,14 +562,6 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
|
||||
/** Gets the source variable underlying this phi node. */
|
||||
Ssa::SourceVariable getSourceVariable() { result = phi.getSourceVariable() }
|
||||
|
||||
/**
|
||||
* Holds if this phi node is a phi-read node.
|
||||
*
|
||||
* Phi-read nodes are like normal phi nodes, but they are inserted based
|
||||
* on reads instead of writes.
|
||||
*/
|
||||
predicate isPhiRead() { phi.isPhiRead() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1548,7 +1540,7 @@ private module Cached {
|
||||
cached
|
||||
predicate simpleLocalFlowStep(Node nodeFrom, Node nodeTo) {
|
||||
// Post update node -> Node flow
|
||||
Ssa::postUpdateFlow(nodeFrom, nodeTo)
|
||||
Ssa::ssaFlow(nodeFrom.(PostUpdateNode).getPreUpdateNode(), nodeTo)
|
||||
or
|
||||
// Def-use/Use-use flow
|
||||
Ssa::ssaFlow(nodeFrom, nodeTo)
|
||||
@@ -1640,15 +1632,8 @@ predicate localInstructionFlow(Instruction e1, Instruction e2) {
|
||||
localFlow(instructionNode(e1), instructionNode(e2))
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Ideally this module would be private, but the `asExprInternal` predicate is
|
||||
* needed in `DefaultTaintTrackingImpl`. Once `DefaultTaintTrackingImpl` is gone
|
||||
* we can make this module private.
|
||||
*/
|
||||
cached
|
||||
module ExprFlowCached {
|
||||
private module ExprFlowCached {
|
||||
/**
|
||||
* Holds if `n` is an indirect operand of a `PointerArithmeticInstruction`, and
|
||||
* `e` is the result of loading from the `PointerArithmeticInstruction`.
|
||||
@@ -1699,8 +1684,7 @@ module ExprFlowCached {
|
||||
* `x[i]` steps to the expression `x[i - 1]` without traversing the
|
||||
* entire chain.
|
||||
*/
|
||||
cached
|
||||
Expr asExprInternal(Node n) {
|
||||
private Expr asExpr(Node n) {
|
||||
isIndirectBaseOfArrayAccess(n, result)
|
||||
or
|
||||
not isIndirectBaseOfArrayAccess(n, _) and
|
||||
@@ -1712,7 +1696,7 @@ module ExprFlowCached {
|
||||
* dataflow step.
|
||||
*/
|
||||
private predicate localStepFromNonExpr(Node n1, Node n2) {
|
||||
not exists(asExprInternal(n1)) and
|
||||
not exists(asExpr(n1)) and
|
||||
localFlowStep(n1, n2)
|
||||
}
|
||||
|
||||
@@ -1723,7 +1707,7 @@ module ExprFlowCached {
|
||||
pragma[nomagic]
|
||||
private predicate localStepsToExpr(Node n1, Node n2, Expr e2) {
|
||||
localStepFromNonExpr*(n1, n2) and
|
||||
e2 = asExprInternal(n2)
|
||||
e2 = asExpr(n2)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1734,7 +1718,7 @@ module ExprFlowCached {
|
||||
exists(Node mid |
|
||||
localFlowStep(n1, mid) and
|
||||
localStepsToExpr(mid, n2, e2) and
|
||||
e1 = asExprInternal(n1)
|
||||
e1 = asExpr(n1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1919,38 +1903,7 @@ signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch);
|
||||
* in data flow and taint tracking.
|
||||
*/
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
/**
|
||||
* Gets an expression node that is safely guarded by the given guard check.
|
||||
*
|
||||
* For example, given the following code:
|
||||
* ```cpp
|
||||
* int x = source();
|
||||
* // ...
|
||||
* if(is_safe_int(x)) {
|
||||
* sink(x);
|
||||
* }
|
||||
* ```
|
||||
* and the following barrier guard predicate:
|
||||
* ```ql
|
||||
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
|
||||
* exists(Call call |
|
||||
* g.getUnconvertedResultExpression() = call and
|
||||
* call.getTarget().hasName("is_safe_int") and
|
||||
* e = call.getAnArgument() and
|
||||
* branch = true
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
* implementing `isBarrier` as:
|
||||
* ```ql
|
||||
* predicate isBarrier(DataFlow::Node barrier) {
|
||||
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getABarrierNode()
|
||||
* }
|
||||
* ```
|
||||
* will block flow from `x = source()` to `sink(x)`.
|
||||
*
|
||||
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
|
||||
*/
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
ExprNode getABarrierNode() {
|
||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
@@ -1959,84 +1912,6 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an indirect expression node that is safely guarded by the given guard check.
|
||||
*
|
||||
* For example, given the following code:
|
||||
* ```cpp
|
||||
* int* p;
|
||||
* // ...
|
||||
* *p = source();
|
||||
* if(is_safe_pointer(p)) {
|
||||
* sink(*p);
|
||||
* }
|
||||
* ```
|
||||
* and the following barrier guard check:
|
||||
* ```ql
|
||||
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
|
||||
* exists(Call call |
|
||||
* g.getUnconvertedResultExpression() = call and
|
||||
* call.getTarget().hasName("is_safe_pointer") and
|
||||
* e = call.getAnArgument() and
|
||||
* branch = true
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
* implementing `isBarrier` as:
|
||||
* ```ql
|
||||
* predicate isBarrier(DataFlow::Node barrier) {
|
||||
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getAnIndirectBarrierNode()
|
||||
* }
|
||||
* ```
|
||||
* will block flow from `x = source()` to `sink(x)`.
|
||||
*
|
||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||
*/
|
||||
IndirectExprNode getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
|
||||
|
||||
/**
|
||||
* Gets an indirect expression node with indirection index `indirectionIndex` that is
|
||||
* safely guarded by the given guard check.
|
||||
*
|
||||
* For example, given the following code:
|
||||
* ```cpp
|
||||
* int* p;
|
||||
* // ...
|
||||
* *p = source();
|
||||
* if(is_safe_pointer(p)) {
|
||||
* sink(*p);
|
||||
* }
|
||||
* ```
|
||||
* and the following barrier guard check:
|
||||
* ```ql
|
||||
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
|
||||
* exists(Call call |
|
||||
* g.getUnconvertedResultExpression() = call and
|
||||
* call.getTarget().hasName("is_safe_pointer") and
|
||||
* e = call.getAnArgument() and
|
||||
* branch = true
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
* implementing `isBarrier` as:
|
||||
* ```ql
|
||||
* predicate isBarrier(DataFlow::Node barrier) {
|
||||
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getAnIndirectBarrierNode(1)
|
||||
* }
|
||||
* ```
|
||||
* will block flow from `x = source()` to `sink(x)`.
|
||||
*
|
||||
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
|
||||
*/
|
||||
IndirectExprNode getAnIndirectBarrierNode(int indirectionIndex) {
|
||||
exists(IRGuardCondition g, Expr e, ValueNumber value, boolean edge |
|
||||
e = value.getAnInstruction().getConvertedResultExpression() and
|
||||
result.getConvertedExpr(indirectionIndex) = e and
|
||||
guardChecks(g, value.getAnInstruction().getConvertedResultExpression(), edge) and
|
||||
g.controls(result.getBasicBlock(), edge)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -60,7 +60,7 @@ private DataFlow::Node getNodeForSource(Expr source) {
|
||||
}
|
||||
|
||||
private DataFlow::Node getNodeForExpr(Expr node) {
|
||||
node = DataFlow::ExprFlowCached::asExprInternal(result)
|
||||
result = DataFlow::exprNode(node)
|
||||
or
|
||||
// Some of the sources in `isUserInput` are intended to match the value of
|
||||
// an expression, while others (those modeled below) are intended to match
|
||||
@@ -221,7 +221,7 @@ private module Cached {
|
||||
predicate nodeIsBarrierIn(DataFlow::Node node) {
|
||||
// don't use dataflow into taint sources, as this leads to duplicate results.
|
||||
exists(Expr source | isUserInput(source, _) |
|
||||
source = DataFlow::ExprFlowCached::asExprInternal(node)
|
||||
node = DataFlow::exprNode(source)
|
||||
or
|
||||
// This case goes together with the similar (but not identical) rule in
|
||||
// `getNodeForSource`.
|
||||
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Print the dataflow local store steps in IR dumps.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import PrintIRUtilities
|
||||
|
||||
/** A property provider for local IR dataflow store steps. */
|
||||
class FieldFlowPropertyProvider extends IRPropertyProvider {
|
||||
override string getOperandProperty(Operand operand, string key) {
|
||||
exists(PostFieldUpdateNode pfun, Content content |
|
||||
key = "store " + content.toString() and
|
||||
operand = pfun.getPreUpdateNode().(IndirectOperand).getOperand() and
|
||||
result =
|
||||
strictconcat(string element, Node node |
|
||||
storeStep(node, content, pfun) and
|
||||
element = nodeId(node, _, _)
|
||||
|
|
||||
element, ", "
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Node node2, Content content |
|
||||
key = "read " + content.toString() and
|
||||
operand = node2.(IndirectOperand).getOperand() and
|
||||
result =
|
||||
strictconcat(string element, Node node1 |
|
||||
readStep(node1, content, node2) and
|
||||
element = nodeId(node1, _, _)
|
||||
|
|
||||
element, ", "
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -1,44 +1,119 @@
|
||||
private import cpp
|
||||
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
|
||||
// that the cached IR gets the same checksum here as it does in queries that use
|
||||
// `ValueNumbering` without `DataFlow`.
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import SsaInternals as Ssa
|
||||
private import PrintIRUtilities
|
||||
|
||||
/**
|
||||
* Gets the local dataflow from other nodes in the same function to this node.
|
||||
*/
|
||||
private string getFromFlow(Node node2, int order1, int order2) {
|
||||
exists(Node node1 |
|
||||
simpleLocalFlowStep(node1, node2) and
|
||||
result = nodeId(node1, order1, order2)
|
||||
private string getFromFlow(DataFlow::Node useNode, int order1, int order2) {
|
||||
exists(DataFlow::Node defNode, string prefix |
|
||||
(
|
||||
simpleLocalFlowStep(defNode, useNode) and prefix = ""
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and
|
||||
defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and
|
||||
prefix = "+"
|
||||
) and
|
||||
if defNode.asInstruction() = useNode.asOperand().getAnyDef()
|
||||
then
|
||||
// Shorthand for flow from the def of this operand.
|
||||
result = prefix + "def" and
|
||||
order1 = -1 and
|
||||
order2 = 0
|
||||
else
|
||||
if defNode.asOperand().getUse() = useNode.asInstruction()
|
||||
then
|
||||
// Shorthand for flow from an operand of this instruction
|
||||
result = prefix + defNode.asOperand().getDumpId() and
|
||||
order1 = -1 and
|
||||
order2 = defNode.asOperand().getDumpSortOrder()
|
||||
else result = prefix + nodeId(defNode, order1, order2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the local dataflow from this node to other nodes in the same function.
|
||||
*/
|
||||
private string getToFlow(Node node1, int order1, int order2) {
|
||||
exists(Node node2 |
|
||||
simpleLocalFlowStep(node1, node2) and
|
||||
result = nodeId(node2, order1, order2)
|
||||
private string getToFlow(DataFlow::Node defNode, int order1, int order2) {
|
||||
exists(DataFlow::Node useNode, string prefix |
|
||||
(
|
||||
simpleLocalFlowStep(defNode, useNode) and prefix = ""
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isAdditionalFlowStep(defNode, useNode) and
|
||||
defNode.getEnclosingCallable() = useNode.getEnclosingCallable() and
|
||||
prefix = "+"
|
||||
) and
|
||||
if useNode.asInstruction() = defNode.asOperand().getUse()
|
||||
then
|
||||
// Shorthand for flow to this operand's instruction.
|
||||
result = prefix + "result" and
|
||||
order1 = -1 and
|
||||
order2 = 0
|
||||
else result = prefix + nodeId(useNode, order1, order2)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the properties of the dataflow node `node`.
|
||||
*/
|
||||
private string getNodeProperty(Node node, string key) {
|
||||
private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
// List dataflow into and out of this node. Flow into this node is printed as `src->@`, and flow
|
||||
// out of this node is printed as `@->dest`.
|
||||
key = "flow" and
|
||||
result =
|
||||
strictconcat(string flow, boolean to, int order1, int order2 |
|
||||
flow = getFromFlow(node, order1, order2) + "->" + starsForNode(node) + "@" and to = false
|
||||
flow = getFromFlow(node, order1, order2) + "->@" and to = false
|
||||
or
|
||||
flow = starsForNode(node) + "@->" + getToFlow(node, order1, order2) and to = true
|
||||
flow = "@->" + getToFlow(node, order1, order2) and to = true
|
||||
|
|
||||
flow, ", " order by to, order1, order2, flow
|
||||
)
|
||||
or
|
||||
// Is this node a dataflow sink?
|
||||
key = "sink" and
|
||||
any(DataFlow::Configuration cfg).isSink(node) and
|
||||
result = "true"
|
||||
or
|
||||
// Is this node a dataflow source?
|
||||
key = "source" and
|
||||
any(DataFlow::Configuration cfg).isSource(node) and
|
||||
result = "true"
|
||||
or
|
||||
// Is this node a dataflow barrier, and if so, what kind?
|
||||
key = "barrier" and
|
||||
result =
|
||||
strictconcat(string kind |
|
||||
any(DataFlow::Configuration cfg).isBarrier(node) and kind = "full"
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isBarrierIn(node) and kind = "in"
|
||||
or
|
||||
any(DataFlow::Configuration cfg).isBarrierOut(node) and kind = "out"
|
||||
|
|
||||
kind, ", "
|
||||
)
|
||||
// or
|
||||
// // Is there partial flow from a source to this node?
|
||||
// // This property will only be emitted if partial flow is enabled by overriding
|
||||
// // `DataFlow::Configuration::explorationLimit()`.
|
||||
// key = "pflow" and
|
||||
// result =
|
||||
// strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist,
|
||||
// int order1, int order2 |
|
||||
// any(DataFlow::Configuration cfg).hasPartialFlow(sourceNode, destNode, dist) and
|
||||
// destNode.getNode() = node and
|
||||
// // Only print flow from a source in the same function.
|
||||
// sourceNode.getNode().getEnclosingCallable() = node.getEnclosingCallable()
|
||||
// |
|
||||
// nodeId(sourceNode.getNode(), order1, order2) + "+" + dist.toString(), ", "
|
||||
// order by
|
||||
// order1, order2, dist desc
|
||||
// )
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,21 +121,16 @@ private string getNodeProperty(Node node, string key) {
|
||||
*/
|
||||
class LocalFlowPropertyProvider extends IRPropertyProvider {
|
||||
override string getOperandProperty(Operand operand, string key) {
|
||||
exists(Node node |
|
||||
operand = [node.asOperand(), node.(RawIndirectOperand).getOperand()] and
|
||||
exists(DataFlow::Node node |
|
||||
operand = node.asOperand() and
|
||||
result = getNodeProperty(node, key)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionProperty(Instruction instruction, string key) {
|
||||
exists(Node node |
|
||||
instruction = [node.asInstruction(), node.(RawIndirectInstruction).getInstruction()]
|
||||
|
|
||||
exists(DataFlow::Node node |
|
||||
instruction = node.asInstruction() and
|
||||
result = getNodeProperty(node, key)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate shouldPrintOperand(Operand operand) { not Ssa::ignoreOperand(operand) }
|
||||
|
||||
override predicate shouldPrintInstruction(Instruction instr) { not Ssa::ignoreInstruction(instr) }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/**
|
||||
* Print the dataflow local store steps in IR dumps.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
|
||||
// that the cached IR gets the same checksum here as it does in queries that use
|
||||
// `ValueNumbering` without `DataFlow`.
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
private import PrintIRUtilities
|
||||
|
||||
/**
|
||||
* Property provider for local IR dataflow store steps.
|
||||
*/
|
||||
class LocalFlowPropertyProvider extends IRPropertyProvider {
|
||||
override string getInstructionProperty(Instruction instruction, string key) {
|
||||
exists(DataFlow::Node objectNode, Content content |
|
||||
key = "content[" + content.toString() + "]" and
|
||||
instruction = objectNode.asInstruction() and
|
||||
result =
|
||||
strictconcat(string element, DataFlow::Node fieldNode |
|
||||
storeStep(fieldNode, content, objectNode) and
|
||||
element = nodeId(fieldNode, _, _)
|
||||
|
|
||||
element, ", "
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -3,59 +3,37 @@
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
// The `ValueNumbering` library has to be imported right after `cpp` to ensure
|
||||
// that the cached IR gets the same checksum here as it does in queries that use
|
||||
// `ValueNumbering` without `DataFlow`.
|
||||
private import semmle.code.cpp.ir.ValueNumbering
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowUtil
|
||||
private import semmle.code.cpp.ir.dataflow.internal.DataFlowPrivate
|
||||
|
||||
private string stars(int k) {
|
||||
k =
|
||||
[0 .. max([
|
||||
any(RawIndirectInstruction n).getIndirectionIndex(),
|
||||
any(RawIndirectOperand n).getIndirectionIndex()
|
||||
]
|
||||
)] and
|
||||
(if k = 0 then result = "" else result = "*" + stars(k - 1))
|
||||
}
|
||||
|
||||
string starsForNode(Node node) {
|
||||
result = stars(node.(IndirectInstruction).getIndirectionIndex())
|
||||
or
|
||||
result = stars(node.(IndirectOperand).getIndirectionIndex())
|
||||
or
|
||||
not node instanceof IndirectInstruction and
|
||||
not node instanceof IndirectOperand and
|
||||
result = ""
|
||||
}
|
||||
|
||||
private Instruction getInstruction(Node n, string stars) {
|
||||
result = [n.asInstruction(), n.(RawIndirectInstruction).getInstruction()] and
|
||||
stars = starsForNode(n)
|
||||
}
|
||||
|
||||
private Operand getOperand(Node n, string stars) {
|
||||
result = [n.asOperand(), n.(RawIndirectOperand).getOperand()] and
|
||||
stars = starsForNode(n)
|
||||
}
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
|
||||
/**
|
||||
* Gets a short ID for an IR dataflow node.
|
||||
* - For `Instruction`s, this is just the result ID of the instruction (e.g. `m128`).
|
||||
* - For `Operand`s, this is the label of the operand, prefixed with the result ID of the
|
||||
* instruction and a dot (e.g. `m128.left`).
|
||||
* - For `Variable`s, this is the qualified name of the variable.
|
||||
*/
|
||||
string nodeId(Node node, int order1, int order2) {
|
||||
exists(Instruction instruction, string stars | instruction = getInstruction(node, stars) |
|
||||
result = stars + instruction.getResultId() and
|
||||
string nodeId(DataFlow::Node node, int order1, int order2) {
|
||||
exists(Instruction instruction | instruction = node.asInstruction() |
|
||||
result = instruction.getResultId() and
|
||||
order1 = instruction.getBlock().getDisplayIndex() and
|
||||
order2 = instruction.getDisplayIndexInBlock()
|
||||
)
|
||||
or
|
||||
exists(Operand operand, Instruction instruction, string stars |
|
||||
operand = getOperand(node, stars) and
|
||||
exists(Operand operand, Instruction instruction |
|
||||
operand = node.asOperand() and
|
||||
instruction = operand.getUse()
|
||||
|
|
||||
result = stars + instruction.getResultId() + "." + operand.getDumpId() and
|
||||
result = instruction.getResultId() + "." + operand.getDumpId() and
|
||||
order1 = instruction.getBlock().getDisplayIndex() and
|
||||
order2 = instruction.getDisplayIndexInBlock()
|
||||
)
|
||||
or
|
||||
result = "var(" + node.asVariable().getQualifiedName() + ")" and
|
||||
order1 = 1000000 and
|
||||
order2 = 0
|
||||
}
|
||||
|
||||
@@ -145,14 +145,14 @@ private newtype TDefOrUseImpl =
|
||||
or
|
||||
// Since the pruning stage doesn't know about global variables we can't use the above check to
|
||||
// rule out dead assignments to globals.
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof GlobalLikeVariable
|
||||
base.(VariableAddressInstruction).getAstVariable() instanceof Cpp::GlobalOrNamespaceVariable
|
||||
)
|
||||
} or
|
||||
TUseImpl(Operand operand, int indirectionIndex) {
|
||||
isUse(_, operand, _, _, indirectionIndex) and
|
||||
not isDef(_, _, operand, _, _, _)
|
||||
} or
|
||||
TGlobalUse(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
TGlobalUse(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
|
||||
// Represents a final "use" of a global variable to ensure that
|
||||
// the assignment to a global variable isn't ruled out as dead.
|
||||
exists(VariableAddressInstruction vai, int defIndex |
|
||||
@@ -162,7 +162,7 @@ private newtype TDefOrUseImpl =
|
||||
indirectionIndex = [0 .. defIndex] + 1
|
||||
)
|
||||
} or
|
||||
TGlobalDefImpl(GlobalLikeVariable v, IRFunction f, int indirectionIndex) {
|
||||
TGlobalDefImpl(Cpp::GlobalOrNamespaceVariable v, IRFunction f, int indirectionIndex) {
|
||||
// Represents the initial "definition" of a global variable when entering
|
||||
// a function body.
|
||||
exists(VariableAddressInstruction vai |
|
||||
@@ -458,7 +458,7 @@ class FinalParameterUse extends UseImpl, TFinalParameterUse {
|
||||
}
|
||||
|
||||
class GlobalUse extends UseImpl, TGlobalUse {
|
||||
GlobalLikeVariable global;
|
||||
Cpp::GlobalOrNamespaceVariable global;
|
||||
IRFunction f;
|
||||
|
||||
GlobalUse() { this = TGlobalUse(global, f, ind) }
|
||||
@@ -468,7 +468,7 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
override int getIndirection() { result = ind + 1 }
|
||||
|
||||
/** Gets the global variable associated with this use. */
|
||||
GlobalLikeVariable getVariable() { result = global }
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
|
||||
|
||||
/** Gets the `IRFunction` whose body is exited from after this use. */
|
||||
IRFunction getIRFunction() { result = f }
|
||||
@@ -496,14 +496,14 @@ class GlobalUse extends UseImpl, TGlobalUse {
|
||||
}
|
||||
|
||||
class GlobalDefImpl extends DefOrUseImpl, TGlobalDefImpl {
|
||||
GlobalLikeVariable global;
|
||||
Cpp::GlobalOrNamespaceVariable global;
|
||||
IRFunction f;
|
||||
int indirectionIndex;
|
||||
|
||||
GlobalDefImpl() { this = TGlobalDefImpl(global, f, indirectionIndex) }
|
||||
|
||||
/** Gets the global variable associated with this definition. */
|
||||
GlobalLikeVariable getVariable() { result = global }
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global }
|
||||
|
||||
/** Gets the `IRFunction` whose body is evaluated after this definition. */
|
||||
IRFunction getIRFunction() { result = f }
|
||||
@@ -657,20 +657,27 @@ 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 |
|
||||
indirectConversionFlowStep*(adjusted, pun.getPreUpdateNode()) and
|
||||
nodeToDefOrUse(adjusted, defOrUse, _) and
|
||||
private predicate adjustForPointerArith(
|
||||
DefOrUse defOrUse, Node nodeFrom, UseOrPhi use, boolean uncertain
|
||||
) {
|
||||
nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
|
||||
exists(Node adjusted |
|
||||
indirectConversionFlowStep*(adjusted, nodeFrom) and
|
||||
nodeToDefOrUse(adjusted, defOrUse, uncertain) and
|
||||
adjacentDefRead(defOrUse, use)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate ssaFlowImpl(SsaDefOrUse defOrUse, Node nodeFrom, Node nodeTo, boolean uncertain) {
|
||||
// `nodeFrom = any(PostUpdateNode pun).getPreUpdateNode()` is implied by adjustedForPointerArith.
|
||||
exists(UseOrPhi use |
|
||||
adjustForPointerArith(defOrUse, nodeFrom, use, uncertain) and
|
||||
useToNode(use, nodeTo)
|
||||
or
|
||||
not nodeFrom = any(PostUpdateNode pun).getPreUpdateNode() and
|
||||
nodeToDefOrUse(nodeFrom, defOrUse, uncertain) and
|
||||
adjacentDefRead(defOrUse, use) and
|
||||
useToNode(use, nodeTo) and
|
||||
nodeFrom != nodeTo
|
||||
useToNode(use, nodeTo)
|
||||
or
|
||||
// Initial global variable value to a first use
|
||||
nodeFrom.(InitialGlobalValue).getGlobalDef() = defOrUse and
|
||||
@@ -705,28 +712,11 @@ private Node getAPriorDefinition(SsaDefOrUse defOrUse) {
|
||||
/** 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 nodeFrom != nodeTo
|
||||
|
|
||||
ssaFlowImpl(defOrUse, nFrom, nodeTo, uncertain) and
|
||||
if uncertain = true then nodeFrom = [nFrom, getAPriorDefinition(defOrUse)] else nodeFrom = nFrom
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isArgumentOfCallable(DataFlowCall call, ArgumentNode arg) {
|
||||
arg.argumentOf(call, _)
|
||||
}
|
||||
|
||||
/** Holds if there is def-use or use-use flow from `pun` to `nodeTo`. */
|
||||
predicate postUpdateFlow(PostUpdateNode pun, Node nodeTo) {
|
||||
exists(UseOrPhi use, Node preUpdate |
|
||||
adjustForPointerArith(pun, use) and
|
||||
useToNode(use, nodeTo) and
|
||||
preUpdate = pun.getPreUpdateNode() and
|
||||
not exists(DataFlowCall call |
|
||||
isArgumentOfCallable(call, preUpdate) and isArgumentOfCallable(call, nodeTo)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `use` is a use of `sv` and is a next adjacent use of `phi` in
|
||||
* index `i1` in basic block `bb1`.
|
||||
@@ -752,7 +742,6 @@ predicate fromPhiNode(SsaPhiNode nodeFrom, Node nodeTo) {
|
||||
fromPhiNodeToUse(phi, sv, bb1, i1, use)
|
||||
or
|
||||
exists(PhiNode phiTo |
|
||||
phi != phiTo and
|
||||
lastRefRedefExt(phi, _, _, phiTo) and
|
||||
nodeTo.(SsaPhiNode).getPhiNode() = phiTo
|
||||
)
|
||||
@@ -771,14 +760,13 @@ private predicate variableWriteCand(IRBlock bb, int i, SourceVariable v) {
|
||||
}
|
||||
|
||||
private predicate sourceVariableIsGlobal(
|
||||
SourceVariable sv, GlobalLikeVariable global, IRFunction func, int indirectionIndex
|
||||
SourceVariable sv, Cpp::GlobalOrNamespaceVariable global, IRFunction func, int indirectionIndex
|
||||
) {
|
||||
exists(IRVariable irVar, BaseIRVariable base |
|
||||
sourceVariableHasBaseAndIndex(sv, base, indirectionIndex) and
|
||||
irVar = base.getIRVariable() and
|
||||
irVar.getEnclosingIRFunction() = func and
|
||||
global = irVar.getAst() and
|
||||
not irVar instanceof IRDynamicInitializationFlag
|
||||
global = irVar.getAst()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -931,7 +919,7 @@ class GlobalDef extends TGlobalDef, SsaDefOrUse {
|
||||
IRFunction getIRFunction() { result = global.getIRFunction() }
|
||||
|
||||
/** Gets the global variable associated with this definition. */
|
||||
GlobalLikeVariable getVariable() { result = global.getVariable() }
|
||||
Cpp::GlobalOrNamespaceVariable getVariable() { result = global.getVariable() }
|
||||
}
|
||||
|
||||
class Phi extends TPhi, SsaDefOrUse {
|
||||
@@ -1009,14 +997,6 @@ class PhiNode extends SsaImpl::DefinitionExt {
|
||||
this instanceof SsaImpl::PhiNode or
|
||||
this instanceof SsaImpl::PhiReadNode
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this phi node is a phi-read node.
|
||||
*
|
||||
* Phi-read nodes are like normal phi nodes, but they are inserted based
|
||||
* on reads instead of writes.
|
||||
*/
|
||||
predicate isPhiRead() { this instanceof SsaImpl::PhiReadNode }
|
||||
}
|
||||
|
||||
class DefinitionExt = SsaImpl::DefinitionExt;
|
||||
|
||||
@@ -144,20 +144,6 @@ class AllocationInstruction extends CallInstruction {
|
||||
AllocationInstruction() { this.getStaticCallTarget() instanceof Cpp::AllocationFunction }
|
||||
}
|
||||
|
||||
private predicate isIndirectionType(Type t) { t instanceof Indirection }
|
||||
|
||||
private predicate hasUnspecifiedBaseType(Indirection t, Type base) {
|
||||
base = t.getBaseType().getUnspecifiedType()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `t2` is the same type as `t1`, but after stripping away `result` number
|
||||
* of indirections.
|
||||
* Furthermore, specifies in `t2` been deeply stripped and typedefs has been resolved.
|
||||
*/
|
||||
private int getNumberOfIndirectionsImpl(Type t1, Type t2) =
|
||||
shortestDistances(isIndirectionType/1, hasUnspecifiedBaseType/2)(t1, t2, result)
|
||||
|
||||
/**
|
||||
* An abstract class for handling indirections.
|
||||
*
|
||||
@@ -176,10 +162,7 @@ abstract class Indirection extends Type {
|
||||
* For example, the number of indirections of a variable `p` of type
|
||||
* `int**` is `3` (i.e., `p`, `*p` and `**p`).
|
||||
*/
|
||||
final int getNumberOfIndirections() {
|
||||
result =
|
||||
getNumberOfIndirectionsImpl(this.getType(), any(Type end | not end instanceof Indirection))
|
||||
}
|
||||
abstract int getNumberOfIndirections();
|
||||
|
||||
/**
|
||||
* Holds if `deref` is an instruction that behaves as a `LoadInstruction`
|
||||
@@ -217,11 +200,19 @@ private class PointerOrArrayOrReferenceTypeIndirection extends Indirection insta
|
||||
PointerOrArrayOrReferenceTypeIndirection() {
|
||||
baseType = PointerOrArrayOrReferenceType.super.getBaseType()
|
||||
}
|
||||
|
||||
override int getNumberOfIndirections() {
|
||||
result = 1 + countIndirections(this.getBaseType().getUnspecifiedType())
|
||||
}
|
||||
}
|
||||
|
||||
private class PointerWrapperTypeIndirection extends Indirection instanceof PointerWrapper {
|
||||
PointerWrapperTypeIndirection() { baseType = PointerWrapper.super.getBaseType() }
|
||||
|
||||
override int getNumberOfIndirections() {
|
||||
result = 1 + countIndirections(this.getBaseType().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override predicate isAdditionalDereference(Instruction deref, Operand address) {
|
||||
exists(CallInstruction call |
|
||||
operandForFullyConvertedCall(getAUse(deref), call) and
|
||||
@@ -242,6 +233,10 @@ private module IteratorIndirections {
|
||||
baseType = super.getValueType()
|
||||
}
|
||||
|
||||
override int getNumberOfIndirections() {
|
||||
result = 1 + countIndirections(this.getBaseType().getUnspecifiedType())
|
||||
}
|
||||
|
||||
override predicate isAdditionalDereference(Instruction deref, Operand address) {
|
||||
exists(CallInstruction call |
|
||||
operandForFullyConvertedCall(getAUse(deref), call) and
|
||||
|
||||
@@ -39,7 +39,7 @@ class IRType extends TIRType {
|
||||
* Gets a string that uniquely identifies this `IRType`. This string is often the same as the
|
||||
* result of `IRType.toString()`, but for some types it may be more verbose to ensure uniqueness.
|
||||
*/
|
||||
string getIdentityString() { result = this.toString() }
|
||||
string getIdentityString() { result = toString() }
|
||||
|
||||
/**
|
||||
* Gets the size of the type, in bytes, if known.
|
||||
@@ -206,7 +206,7 @@ class IRFloatingPointType extends IRNumericType, TIRFloatingPointType {
|
||||
IRFloatingPointType() { this = TIRFloatingPointType(_, base, domain) }
|
||||
|
||||
final override string toString() {
|
||||
result = this.getDomainPrefix() + this.getBaseString() + byteSize.toString()
|
||||
result = getDomainPrefix() + getBaseString() + byteSize.toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getCanonicalLanguageType() {
|
||||
|
||||
@@ -135,11 +135,11 @@ class Opcode extends TOpcode {
|
||||
* Holds if the instruction must have an operand with the specified `OperandTag`.
|
||||
*/
|
||||
final predicate hasOperand(OperandTag tag) {
|
||||
this.hasOperandInternal(tag)
|
||||
hasOperandInternal(tag)
|
||||
or
|
||||
this.hasAddressOperand() and tag instanceof AddressOperandTag
|
||||
hasAddressOperand() and tag instanceof AddressOperandTag
|
||||
or
|
||||
this.hasBufferSizeOperand() and tag instanceof BufferSizeOperandTag
|
||||
hasBufferSizeOperand() and tag instanceof BufferSizeOperandTag
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -77,16 +77,4 @@ class IRPropertyProvider extends TIRPropertyProvider {
|
||||
* Gets the value of the property named `key` for the specified operand.
|
||||
*/
|
||||
string getOperandProperty(Operand operand, string key) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `instr` should be included when printing
|
||||
* the IR instructions.
|
||||
*/
|
||||
predicate shouldPrintInstruction(Instruction instr) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the operand `operand` should be included when printing the an
|
||||
* instruction's operand list.
|
||||
*/
|
||||
predicate shouldPrintOperand(Operand operand) { any() }
|
||||
}
|
||||
|
||||
@@ -45,9 +45,7 @@ class IRFunction extends IRFunctionBase {
|
||||
* Gets the block containing the entry point of this function.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock getEntryBlock() {
|
||||
result.getFirstInstruction() = this.getEnterFunctionInstruction()
|
||||
}
|
||||
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
|
||||
|
||||
/**
|
||||
* Gets all instructions in this function.
|
||||
|
||||
@@ -39,12 +39,12 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, false) }
|
||||
final Language::Type getType() { getLanguageType().hasType(result, false) }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
@@ -58,7 +58,7 @@ class IRVariable extends TIRVariable {
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -69,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -91,15 +91,15 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
final override string toString() { result = this.getVariable().toString() }
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -166,9 +166,9 @@ class IRGeneratedVariable extends IRVariable {
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = this.getBaseString() + this.getLocationString() }
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
@@ -272,7 +272,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + this.getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
@@ -303,8 +303,7 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result =
|
||||
"Init: " + this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
@@ -333,5 +332,5 @@ class IRParameter extends IRAutomaticVariable {
|
||||
* An IR variable representing a positional parameter.
|
||||
*/
|
||||
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
|
||||
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
|
||||
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
|
||||
}
|
||||
|
||||
@@ -210,6 +210,9 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -460,6 +463,9 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,14 +42,6 @@ private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i))
|
||||
}
|
||||
|
||||
private predicate shouldPrintOperand(Operand operand) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand))
|
||||
}
|
||||
|
||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
|
||||
}
|
||||
@@ -92,9 +84,7 @@ private string getOperandPropertyString(Operand operand) {
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
}
|
||||
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
|
||||
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
@@ -137,13 +127,13 @@ abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
* Gets the value of the node property with the specified key.
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and result = this.getLabel()
|
||||
key = "semmle.label" and result = getLabel()
|
||||
or
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
or
|
||||
key = "semmle.graphKind" and result = this.getGraphKind()
|
||||
key = "semmle.graphKind" and result = getGraphKind()
|
||||
or
|
||||
key = "semmle.forceText" and this.forceText() and result = "true"
|
||||
key = "semmle.forceText" and forceText() and result = "true"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +178,7 @@ private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
|
||||
override string toString() { result = this.getLabel() }
|
||||
override string toString() { result = getLabel() }
|
||||
|
||||
override Language::Location getLocation() { result = block.getLocation() }
|
||||
|
||||
@@ -233,7 +223,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
|
|
||||
resultString = instr.getResultString() and
|
||||
operationString = instr.getOperationString() and
|
||||
operandsString = this.getOperandsString() and
|
||||
operandsString = getOperandsString() and
|
||||
columnWidths(block, resultWidth, operationWidth) and
|
||||
result =
|
||||
resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
|
||||
@@ -262,8 +252,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
private string getOperandsString() {
|
||||
result =
|
||||
concat(Operand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
shouldPrintOperand(operand)
|
||||
operand = instr.getAnOperand()
|
||||
|
|
||||
operand.getDumpString() + getOperandPropertyString(operand), ", "
|
||||
order by
|
||||
|
||||
@@ -7,19 +7,17 @@ private import internal.ValueNumberingImports
|
||||
class ValueNumber extends TValueNumber {
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() {
|
||||
result = strictconcat(this.getAnInstruction().getResultId(), ", ")
|
||||
}
|
||||
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
|
||||
|
||||
final Language::Location getLocation() {
|
||||
if
|
||||
exists(Instruction i |
|
||||
i = this.getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
i = getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
)
|
||||
then
|
||||
result =
|
||||
min(Language::Location l |
|
||||
l = this.getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
l = getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -42,7 +40,7 @@ class ValueNumber extends TValueNumber {
|
||||
final Instruction getExampleInstruction() {
|
||||
result =
|
||||
min(Instruction instr |
|
||||
instr = this.getAnInstruction()
|
||||
instr = getAnInstruction()
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
|
||||
@@ -22,7 +22,7 @@ private newtype TAllocation =
|
||||
abstract class Allocation extends TAllocation {
|
||||
abstract string toString();
|
||||
|
||||
final string getAllocationString() { result = this.toString() }
|
||||
final string getAllocationString() { result = toString() }
|
||||
|
||||
abstract Instruction getABaseInstruction();
|
||||
|
||||
|
||||
@@ -95,9 +95,7 @@ private newtype TMemoryLocation =
|
||||
*/
|
||||
abstract class MemoryLocation extends TMemoryLocation {
|
||||
final string toString() {
|
||||
if this.isMayAccess()
|
||||
then result = "?" + this.toStringInternal()
|
||||
else result = this.toStringInternal()
|
||||
if isMayAccess() then result = "?" + toStringInternal() else result = toStringInternal()
|
||||
}
|
||||
|
||||
abstract string toStringInternal();
|
||||
@@ -112,7 +110,7 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
|
||||
abstract Location getLocation();
|
||||
|
||||
final IRType getIRType() { result = this.getType().getIRType() }
|
||||
final IRType getIRType() { result = getType().getIRType() }
|
||||
|
||||
abstract predicate isMayAccess();
|
||||
|
||||
@@ -138,7 +136,7 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
final predicate canReuseSsa() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsa */
|
||||
deprecated predicate canReuseSSA() { this.canReuseSsa() }
|
||||
deprecated predicate canReuseSSA() { canReuseSsa() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,19 +191,19 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
|
||||
}
|
||||
|
||||
private string getIntervalString() {
|
||||
if this.coversEntireVariable()
|
||||
if coversEntireVariable()
|
||||
then result = ""
|
||||
else result = Interval::getIntervalString(startBitOffset, endBitOffset)
|
||||
}
|
||||
|
||||
private string getTypeString() {
|
||||
if this.coversEntireVariable() and type = var.getIRType()
|
||||
if coversEntireVariable() and type = var.getIRType()
|
||||
then result = ""
|
||||
else result = "<" + languageType.toString() + ">"
|
||||
}
|
||||
|
||||
final override string toStringInternal() {
|
||||
result = var.toString() + this.getIntervalString() + this.getTypeString()
|
||||
result = var.toString() + getIntervalString() + getTypeString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getType() {
|
||||
@@ -238,7 +236,7 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
|
||||
/**
|
||||
* Holds if this memory location covers the entire variable.
|
||||
*/
|
||||
final predicate coversEntireVariable() { this.varIRTypeHasBitRange(startBitOffset, endBitOffset) }
|
||||
final predicate coversEntireVariable() { varIRTypeHasBitRange(startBitOffset, endBitOffset) }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate varIRTypeHasBitRange(int start, int end) {
|
||||
@@ -264,7 +262,7 @@ class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation,
|
||||
class EntireAllocationVirtualVariable extends EntireAllocationMemoryLocation, VirtualVariable {
|
||||
EntireAllocationVirtualVariable() {
|
||||
not allocationEscapes(var) and
|
||||
not this.isMayAccess()
|
||||
not isMayAccess()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,8 +275,8 @@ class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
|
||||
VariableVirtualVariable() {
|
||||
not allocationEscapes(var) and
|
||||
type = var.getIRType() and
|
||||
this.coversEntireVariable() and
|
||||
not this.isMayAccess()
|
||||
coversEntireVariable() and
|
||||
not isMayAccess()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -339,7 +337,7 @@ class AllNonLocalMemory extends TAllNonLocalMemory, MemoryLocation {
|
||||
// instruction, which provides the initial definition for all memory outside of the current
|
||||
// function's stack frame. This memory includes string literals and other read-only globals, so
|
||||
// we allow such an access to be the definition for a use of a read-only location.
|
||||
not this.isMayAccess()
|
||||
not isMayAccess()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -362,7 +360,7 @@ class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
|
||||
|
||||
final override Location getLocation() { result = irFunc.getLocation() }
|
||||
|
||||
final override string getUniqueId() { result = " " + this.toString() }
|
||||
final override string getUniqueId() { result = " " + toString() }
|
||||
|
||||
final override VirtualVariable getVirtualVariable() { result = TAllAliasedMemory(irFunc, false) }
|
||||
|
||||
@@ -371,7 +369,7 @@ class AllAliasedMemory extends TAllAliasedMemory, MemoryLocation {
|
||||
|
||||
/** A virtual variable that groups all escaped memory within a function. */
|
||||
class AliasedVirtualVariable extends AllAliasedMemory, VirtualVariable {
|
||||
AliasedVirtualVariable() { not this.isMayAccess() }
|
||||
AliasedVirtualVariable() { not isMayAccess() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -577,6 +575,9 @@ private Overlap getVariableMemoryLocationOverlap(
|
||||
*/
|
||||
predicate canReuseSsaForOldResult(Instruction instr) { OldSsa::canReuseSsaForMemoryResult(instr) }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForOldResult */
|
||||
deprecated predicate canReuseSSAForOldResult = canReuseSsaForOldResult/1;
|
||||
|
||||
bindingset[result, b]
|
||||
private boolean unbindBool(boolean b) { result != b.booleanNot() }
|
||||
|
||||
|
||||
@@ -422,6 +422,12 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
cached
|
||||
deprecated Language::AST getInstructionAST(Instruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
cached
|
||||
Language::LanguageType getInstructionResultType(Instruction instr) {
|
||||
result = instr.(RawIR::Instruction).getResultLanguageType()
|
||||
@@ -987,6 +993,9 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
||||
// We don't support reusing SSA for any location that could create a `Chi` instruction.
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForMemoryResult */
|
||||
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
@@ -996,6 +1005,9 @@ module DebugSsa {
|
||||
import DefUse
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DebugSsa */
|
||||
deprecated module DebugSSA = DebugSsa;
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
@@ -6,7 +6,7 @@ private import IRFunctionBaseInternal
|
||||
|
||||
private newtype TIRFunction =
|
||||
TFunctionIRFunction(Language::Function func) { IRConstruction::Raw::functionHasIR(func) } or
|
||||
TVarInitIRFunction(Language::Variable var) { IRConstruction::Raw::varHasIRFunc(var) }
|
||||
TVarInitIRFunction(Language::GlobalVariable var) { IRConstruction::Raw::varHasIRFunc(var) }
|
||||
|
||||
/**
|
||||
* The IR for a function. This base class contains only the predicates that are the same between all
|
||||
|
||||
@@ -40,9 +40,7 @@ abstract class OperandTag extends TOperandTag {
|
||||
/**
|
||||
* Gets a label that will appear before the operand when the IR is printed.
|
||||
*/
|
||||
final string getLabel() {
|
||||
if this.alwaysPrintLabel() then result = this.getId() + ":" else result = ""
|
||||
}
|
||||
final string getLabel() { if alwaysPrintLabel() then result = getId() + ":" else result = "" }
|
||||
|
||||
/**
|
||||
* Gets an identifier that uniquely identifies this operand within its instruction.
|
||||
|
||||
@@ -73,6 +73,9 @@ module UnaliasedSsaInstructions {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for UnaliasedSsaInstructions */
|
||||
deprecated module UnaliasedSSAInstructions = UnaliasedSsaInstructions;
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TInstruction` that is used by the
|
||||
* aliased SSA stage.
|
||||
@@ -104,3 +107,6 @@ module AliasedSsaInstructions {
|
||||
result = TAliasedSsaUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaInstructions */
|
||||
deprecated module AliasedSSAInstructions = AliasedSsaInstructions;
|
||||
|
||||
@@ -74,12 +74,20 @@ private module Shared {
|
||||
|
||||
class TNonSsaMemoryOperand = Internal::TNonSsaMemoryOperand;
|
||||
|
||||
/** DEPRECATED: Alias for TNonSsaMemoryOperand */
|
||||
deprecated class TNonSSAMemoryOperand = TNonSsaMemoryOperand;
|
||||
|
||||
/**
|
||||
* Returns the non-Phi memory operand with the specified parameters.
|
||||
*/
|
||||
TNonSsaMemoryOperand nonSsaMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
|
||||
result = Internal::TNonSsaMemoryOperand(useInstr, tag)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for nonSsaMemoryOperand */
|
||||
deprecated TNonSSAMemoryOperand nonSSAMemoryOperand(TRawInstruction useInstr, MemoryOperandTag tag) {
|
||||
result = nonSsaMemoryOperand(useInstr, tag)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -159,6 +167,9 @@ module UnaliasedSsaOperands {
|
||||
TChiOperand chiOperand(Unaliased::Instruction useInstr, ChiOperandTag tag) { none() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for UnaliasedSsaOperands */
|
||||
deprecated module UnaliasedSSAOperands = UnaliasedSsaOperands;
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
|
||||
* aliased SSA stage.
|
||||
@@ -206,3 +217,6 @@ module AliasedSsaOperands {
|
||||
result = Internal::TAliasedChiOperand(useInstr, tag)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaOperands */
|
||||
deprecated module AliasedSSAOperands = AliasedSsaOperands;
|
||||
|
||||
@@ -77,16 +77,4 @@ class IRPropertyProvider extends TIRPropertyProvider {
|
||||
* Gets the value of the property named `key` for the specified operand.
|
||||
*/
|
||||
string getOperandProperty(Operand operand, string key) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `instr` should be included when printing
|
||||
* the IR instructions.
|
||||
*/
|
||||
predicate shouldPrintInstruction(Instruction instr) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the operand `operand` should be included when printing the an
|
||||
* instruction's operand list.
|
||||
*/
|
||||
predicate shouldPrintOperand(Operand operand) { any() }
|
||||
}
|
||||
|
||||
@@ -45,9 +45,7 @@ class IRFunction extends IRFunctionBase {
|
||||
* Gets the block containing the entry point of this function.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock getEntryBlock() {
|
||||
result.getFirstInstruction() = this.getEnterFunctionInstruction()
|
||||
}
|
||||
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
|
||||
|
||||
/**
|
||||
* Gets all instructions in this function.
|
||||
|
||||
@@ -39,12 +39,12 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, false) }
|
||||
final Language::Type getType() { getLanguageType().hasType(result, false) }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
@@ -58,7 +58,7 @@ class IRVariable extends TIRVariable {
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -69,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -91,15 +91,15 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
final override string toString() { result = this.getVariable().toString() }
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -166,9 +166,9 @@ class IRGeneratedVariable extends IRVariable {
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = this.getBaseString() + this.getLocationString() }
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
@@ -272,7 +272,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + this.getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
@@ -303,8 +303,7 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result =
|
||||
"Init: " + this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
@@ -333,5 +332,5 @@ class IRParameter extends IRAutomaticVariable {
|
||||
* An IR variable representing a positional parameter.
|
||||
*/
|
||||
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
|
||||
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
|
||||
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
|
||||
}
|
||||
|
||||
@@ -210,6 +210,9 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -460,6 +463,9 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,14 +42,6 @@ private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i))
|
||||
}
|
||||
|
||||
private predicate shouldPrintOperand(Operand operand) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand))
|
||||
}
|
||||
|
||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
|
||||
}
|
||||
@@ -92,9 +84,7 @@ private string getOperandPropertyString(Operand operand) {
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
}
|
||||
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
|
||||
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
@@ -137,13 +127,13 @@ abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
* Gets the value of the node property with the specified key.
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and result = this.getLabel()
|
||||
key = "semmle.label" and result = getLabel()
|
||||
or
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
or
|
||||
key = "semmle.graphKind" and result = this.getGraphKind()
|
||||
key = "semmle.graphKind" and result = getGraphKind()
|
||||
or
|
||||
key = "semmle.forceText" and this.forceText() and result = "true"
|
||||
key = "semmle.forceText" and forceText() and result = "true"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +178,7 @@ private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
|
||||
override string toString() { result = this.getLabel() }
|
||||
override string toString() { result = getLabel() }
|
||||
|
||||
override Language::Location getLocation() { result = block.getLocation() }
|
||||
|
||||
@@ -233,7 +223,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
|
|
||||
resultString = instr.getResultString() and
|
||||
operationString = instr.getOperationString() and
|
||||
operandsString = this.getOperandsString() and
|
||||
operandsString = getOperandsString() and
|
||||
columnWidths(block, resultWidth, operationWidth) and
|
||||
result =
|
||||
resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
|
||||
@@ -262,8 +252,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
private string getOperandsString() {
|
||||
result =
|
||||
concat(Operand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
shouldPrintOperand(operand)
|
||||
operand = instr.getAnOperand()
|
||||
|
|
||||
operand.getDumpString() + getOperandPropertyString(operand), ", "
|
||||
order by
|
||||
|
||||
@@ -7,19 +7,17 @@ private import internal.ValueNumberingImports
|
||||
class ValueNumber extends TValueNumber {
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() {
|
||||
result = strictconcat(this.getAnInstruction().getResultId(), ", ")
|
||||
}
|
||||
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
|
||||
|
||||
final Language::Location getLocation() {
|
||||
if
|
||||
exists(Instruction i |
|
||||
i = this.getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
i = getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
)
|
||||
then
|
||||
result =
|
||||
min(Language::Location l |
|
||||
l = this.getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
l = getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -42,7 +40,7 @@ class ValueNumber extends TValueNumber {
|
||||
final Instruction getExampleInstruction() {
|
||||
result =
|
||||
min(Instruction instr |
|
||||
instr = this.getAnInstruction()
|
||||
instr = getAnInstruction()
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
|
||||
@@ -37,13 +37,7 @@ module Raw {
|
||||
predicate functionHasIR(Function func) { exists(getTranslatedFunction(func)) }
|
||||
|
||||
cached
|
||||
predicate varHasIRFunc(Variable var) {
|
||||
(
|
||||
var instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
not var.isFromUninstantiatedTemplate(_) and
|
||||
var instanceof StaticInitializedStaticLocalVariable
|
||||
) and
|
||||
predicate varHasIRFunc(GlobalOrNamespaceVariable var) {
|
||||
var.hasInitializer() and
|
||||
(
|
||||
not var.getType().isDeeplyConst()
|
||||
@@ -81,10 +75,9 @@ module Raw {
|
||||
}
|
||||
|
||||
cached
|
||||
predicate hasDynamicInitializationFlag(
|
||||
Function func, RuntimeInitializedStaticLocalVariable var, CppType type
|
||||
) {
|
||||
predicate hasDynamicInitializationFlag(Function func, StaticLocalVariable var, CppType type) {
|
||||
var.getFunction() = func and
|
||||
var.hasDynamicInitialization() and
|
||||
type = getBoolType()
|
||||
}
|
||||
|
||||
@@ -375,6 +368,11 @@ Locatable getInstructionAst(TStageInstruction instr) {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
deprecated Locatable getInstructionAST(TStageInstruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
CppType getInstructionResultType(TStageInstruction instr) {
|
||||
getInstructionTranslatedElement(instr).hasInstruction(_, getInstructionTag(instr), result)
|
||||
or
|
||||
|
||||
@@ -31,42 +31,42 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
// The qualifier is evaluated before the call target, because the value of
|
||||
// the call target may depend on the value of the qualifier for virtual
|
||||
// calls.
|
||||
id = -2 and result = this.getQualifier()
|
||||
id = -2 and result = getQualifier()
|
||||
or
|
||||
id = -1 and result = this.getCallTarget()
|
||||
id = -1 and result = getCallTarget()
|
||||
or
|
||||
result = this.getArgument(id)
|
||||
result = getArgument(id)
|
||||
or
|
||||
id = this.getNumberOfArguments() and result = this.getSideEffects()
|
||||
id = getNumberOfArguments() and result = getSideEffects()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
if exists(this.getQualifier())
|
||||
then result = this.getQualifier().getFirstInstruction()
|
||||
else result = this.getFirstCallTargetInstruction()
|
||||
if exists(getQualifier())
|
||||
then result = getQualifier().getFirstInstruction()
|
||||
else result = getFirstCallTargetInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = CallTag() and
|
||||
opcode instanceof Opcode::Call and
|
||||
resultType = getTypeForPRValue(this.getCallResultType())
|
||||
resultType = getTypeForPRValue(getCallResultType())
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getQualifier() and
|
||||
result = this.getFirstCallTargetInstruction()
|
||||
child = getQualifier() and
|
||||
result = getFirstCallTargetInstruction()
|
||||
or
|
||||
child = this.getCallTarget() and
|
||||
result = this.getFirstArgumentOrCallInstruction()
|
||||
child = getCallTarget() and
|
||||
result = getFirstArgumentOrCallInstruction()
|
||||
or
|
||||
exists(int argIndex |
|
||||
child = this.getArgument(argIndex) and
|
||||
if exists(this.getArgument(argIndex + 1))
|
||||
then result = this.getArgument(argIndex + 1).getFirstInstruction()
|
||||
else result = this.getInstruction(CallTag())
|
||||
child = getArgument(argIndex) and
|
||||
if exists(getArgument(argIndex + 1))
|
||||
then result = getArgument(argIndex + 1).getFirstInstruction()
|
||||
else result = getInstruction(CallTag())
|
||||
)
|
||||
or
|
||||
child = this.getSideEffects() and
|
||||
child = getSideEffects() and
|
||||
if this.isNoReturn()
|
||||
then
|
||||
result =
|
||||
@@ -79,26 +79,26 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
tag = CallTag() and
|
||||
result = this.getSideEffects().getFirstInstruction()
|
||||
result = getSideEffects().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = CallTag() and
|
||||
(
|
||||
operandTag instanceof CallTargetOperandTag and
|
||||
result = this.getCallTargetResult()
|
||||
result = getCallTargetResult()
|
||||
or
|
||||
operandTag instanceof ThisArgumentOperandTag and
|
||||
result = this.getQualifierResult()
|
||||
result = getQualifierResult()
|
||||
or
|
||||
exists(PositionalArgumentOperandTag argTag |
|
||||
argTag = operandTag and
|
||||
result = this.getArgument(argTag.getArgIndex()).getResult()
|
||||
result = getArgument(argTag.getArgIndex()).getResult()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getResult() { result = this.getInstruction(CallTag()) }
|
||||
final override Instruction getResult() { result = getInstruction(CallTag()) }
|
||||
|
||||
/**
|
||||
* Gets the result type of the call.
|
||||
@@ -108,7 +108,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
/**
|
||||
* Holds if the call has a `this` argument.
|
||||
*/
|
||||
predicate hasQualifier() { exists(this.getQualifier()) }
|
||||
predicate hasQualifier() { exists(getQualifier()) }
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedExpr` for the indirect target of the call, if any.
|
||||
@@ -121,9 +121,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* it can be overridden by a subclass for cases where there is a call target
|
||||
* that is not computed from an expression (e.g. a direct call).
|
||||
*/
|
||||
Instruction getFirstCallTargetInstruction() {
|
||||
result = this.getCallTarget().getFirstInstruction()
|
||||
}
|
||||
Instruction getFirstCallTargetInstruction() { result = getCallTarget().getFirstInstruction() }
|
||||
|
||||
/**
|
||||
* Gets the instruction whose result value is the target of the call. By
|
||||
@@ -131,7 +129,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* overridden by a subclass for cases where there is a call target that is not
|
||||
* computed from an expression (e.g. a direct call).
|
||||
*/
|
||||
Instruction getCallTargetResult() { result = this.getCallTarget().getResult() }
|
||||
Instruction getCallTargetResult() { result = getCallTarget().getResult() }
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedExpr` for the qualifier of the call (i.e. the value
|
||||
@@ -145,7 +143,7 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* overridden by a subclass for cases where there is a `this` argument that is
|
||||
* not computed from a child expression (e.g. a constructor call).
|
||||
*/
|
||||
Instruction getQualifierResult() { result = this.getQualifier().getResult() }
|
||||
Instruction getQualifierResult() { result = getQualifier().getResult() }
|
||||
|
||||
/**
|
||||
* Gets the argument with the specified `index`. Does not include the `this`
|
||||
@@ -160,9 +158,9 @@ abstract class TranslatedCall extends TranslatedExpr {
|
||||
* argument. Otherwise, returns the call instruction.
|
||||
*/
|
||||
final Instruction getFirstArgumentOrCallInstruction() {
|
||||
if this.hasArguments()
|
||||
then result = this.getArgument(0).getFirstInstruction()
|
||||
else result = this.getInstruction(CallTag())
|
||||
if hasArguments()
|
||||
then result = getArgument(0).getFirstInstruction()
|
||||
else result = getInstruction(CallTag())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -186,17 +184,17 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
/** Gets the expression whose side effects are being modeled. */
|
||||
abstract Expr getExpr();
|
||||
|
||||
final override Locatable getAst() { result = this.getExpr() }
|
||||
final override Locatable getAst() { result = getExpr() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Declaration getFunction() { result = getEnclosingDeclaration(this.getExpr()) }
|
||||
final override Declaration getFunction() { result = getExpr().getEnclosingDeclaration() }
|
||||
|
||||
final override TranslatedElement getChild(int i) {
|
||||
result =
|
||||
rank[i + 1](TranslatedSideEffect tse, int group, int indexInGroup |
|
||||
tse.getPrimaryExpr() = this.getExpr() and
|
||||
tse.getPrimaryExpr() = getExpr() and
|
||||
tse.sortOrder(group, indexInGroup)
|
||||
|
|
||||
tse order by group, indexInGroup
|
||||
@@ -205,10 +203,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement te) {
|
||||
exists(int i |
|
||||
this.getChild(i) = te and
|
||||
if exists(this.getChild(i + 1))
|
||||
then result = this.getChild(i + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
getChild(i) = te and
|
||||
if exists(getChild(i + 1))
|
||||
then result = getChild(i + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -217,10 +215,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getChild(0).getFirstInstruction()
|
||||
result = getChild(0).getFirstInstruction()
|
||||
or
|
||||
// Some functions, like `std::move()`, have no side effects whatsoever.
|
||||
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
not exists(getChild(0)) and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
@@ -236,10 +234,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
*/
|
||||
abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
final override Instruction getFirstCallTargetInstruction() {
|
||||
result = this.getInstruction(CallTargetTag())
|
||||
result = getInstruction(CallTargetTag())
|
||||
}
|
||||
|
||||
final override Instruction getCallTargetResult() { result = this.getInstruction(CallTargetTag()) }
|
||||
final override Instruction getCallTargetResult() { result = getInstruction(CallTargetTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedCall.super.hasInstruction(opcode, tag, resultType)
|
||||
@@ -254,7 +252,7 @@ abstract class TranslatedDirectCall extends TranslatedCall {
|
||||
or
|
||||
tag = CallTargetTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getFirstArgumentOrCallInstruction()
|
||||
result = getFirstArgumentOrCallInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,12 +301,12 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
|
||||
}
|
||||
|
||||
override Instruction getQualifierResult() {
|
||||
this.hasQualifier() and
|
||||
result = this.getQualifier().getResult()
|
||||
hasQualifier() and
|
||||
result = getQualifier().getResult()
|
||||
}
|
||||
|
||||
override predicate hasQualifier() {
|
||||
exists(this.getQualifier()) and
|
||||
exists(getQualifier()) and
|
||||
not exists(MemberFunction func | expr.getTarget() = func and func.isStatic())
|
||||
}
|
||||
}
|
||||
@@ -324,7 +322,7 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
|
||||
|
||||
override Instruction getQualifierResult() {
|
||||
exists(StructorCallContext context |
|
||||
context = this.getParent() and
|
||||
context = getParent() and
|
||||
result = context.getReceiver()
|
||||
)
|
||||
}
|
||||
@@ -375,26 +373,24 @@ abstract class TranslatedSideEffect extends TranslatedElement {
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) { none() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = OnlyInstructionTag() and
|
||||
this.sideEffectInstruction(opcode, type)
|
||||
sideEffectInstruction(opcode, type)
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
final override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
final override Declaration getFunction() { result = getParent().getFunction() }
|
||||
|
||||
final override Instruction getPrimaryInstructionForSideEffect(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().(TranslatedSideEffects).getPrimaryInstruction()
|
||||
result = getParent().(TranslatedSideEffects).getPrimaryInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -432,18 +428,18 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
TranslatedArgumentSideEffect() { any() }
|
||||
|
||||
override string toString() {
|
||||
this.isWrite() and
|
||||
result = "(write side effect for " + this.getArgString() + ")"
|
||||
isWrite() and
|
||||
result = "(write side effect for " + getArgString() + ")"
|
||||
or
|
||||
not this.isWrite() and
|
||||
result = "(read side effect for " + this.getArgString() + ")"
|
||||
not isWrite() and
|
||||
result = "(read side effect for " + getArgString() + ")"
|
||||
}
|
||||
|
||||
override Call getPrimaryExpr() { result = call }
|
||||
|
||||
override predicate sortOrder(int group, int indexInGroup) {
|
||||
indexInGroup = index and
|
||||
if this.isWrite() then group = argumentWriteGroup() else group = argumentReadGroup()
|
||||
if isWrite() then group = argumentWriteGroup() else group = argumentReadGroup()
|
||||
}
|
||||
|
||||
final override int getInstructionIndex(InstructionTag tag) {
|
||||
@@ -454,20 +450,20 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
final override predicate sideEffectInstruction(Opcode opcode, CppType type) {
|
||||
opcode = sideEffectOpcode and
|
||||
(
|
||||
this.isWrite() and
|
||||
isWrite() and
|
||||
(
|
||||
opcode instanceof BufferAccessOpcode and
|
||||
type = getUnknownType()
|
||||
or
|
||||
not opcode instanceof BufferAccessOpcode and
|
||||
exists(Type indirectionType | indirectionType = this.getIndirectionType() |
|
||||
exists(Type indirectionType | indirectionType = getIndirectionType() |
|
||||
if indirectionType instanceof VoidType
|
||||
then type = getUnknownType()
|
||||
else type = getTypeForPRValueOrUnknown(indirectionType)
|
||||
)
|
||||
)
|
||||
or
|
||||
not this.isWrite() and
|
||||
not isWrite() and
|
||||
type = getVoidType()
|
||||
)
|
||||
}
|
||||
@@ -475,7 +471,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
final override CppType getInstructionMemoryOperandType(
|
||||
InstructionTag tag, TypedOperandTag operandTag
|
||||
) {
|
||||
not this.isWrite() and
|
||||
not isWrite() and
|
||||
if sideEffectOpcode instanceof BufferAccessOpcode
|
||||
then
|
||||
result = getUnknownType() and
|
||||
@@ -484,7 +480,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
else
|
||||
exists(Type operandType |
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandType = this.getIndirectionType() and
|
||||
operandType = getIndirectionType() and
|
||||
operandTag instanceof SideEffectOperandTag
|
||||
|
|
||||
// If the type we select is an incomplete type (e.g. a forward-declared `struct`), there will
|
||||
@@ -496,7 +492,7 @@ abstract class TranslatedArgumentSideEffect extends TranslatedSideEffect {
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getArgInstruction()
|
||||
result = getArgInstruction()
|
||||
or
|
||||
tag instanceof OnlyInstructionTag and
|
||||
operandTag instanceof BufferSizeOperandTag and
|
||||
@@ -537,7 +533,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
final override Locatable getAst() { result = arg }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Type getIndirectionType() {
|
||||
result = arg.getUnspecifiedType().(DerivedType).getBaseType()
|
||||
@@ -572,7 +568,7 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
|
||||
|
||||
@@ -596,7 +592,7 @@ class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSide
|
||||
override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Expr getPrimaryExpr() { result = expr }
|
||||
|
||||
@@ -637,7 +633,7 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
|
||||
override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Expr getPrimaryExpr() { result = expr }
|
||||
|
||||
@@ -650,7 +646,7 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag = addressOperand() and
|
||||
result = this.getPrimaryInstructionForSideEffect(OnlyInstructionTag())
|
||||
result = getPrimaryInstructionForSideEffect(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
override predicate sideEffectInstruction(Opcode opcode, CppType type) {
|
||||
|
||||
@@ -22,17 +22,13 @@ abstract class TranslatedCondition extends TranslatedElement {
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final ConditionContext getConditionContext() { result = this.getParent() }
|
||||
final ConditionContext getConditionContext() { result = getParent() }
|
||||
|
||||
final Expr getExpr() { result = expr }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(expr) or
|
||||
result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable)
|
||||
}
|
||||
final override Function getFunction() { result = expr.getEnclosingFunction() }
|
||||
|
||||
final Type getResultType() { result = expr.getUnspecifiedType() }
|
||||
}
|
||||
@@ -42,11 +38,9 @@ abstract class TranslatedFlexibleCondition extends TranslatedCondition, Conditio
|
||||
{
|
||||
TranslatedFlexibleCondition() { this = TTranslatedFlexibleCondition(expr) }
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getOperand() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getOperand() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getOperand().getFirstInstruction()
|
||||
}
|
||||
final override Instruction getFirstInstruction() { result = getOperand().getFirstInstruction() }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -63,13 +57,13 @@ class TranslatedParenthesisCondition extends TranslatedFlexibleCondition {
|
||||
override ParenthesisExpr expr;
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
|
||||
final override TranslatedCondition getOperand() {
|
||||
@@ -81,13 +75,13 @@ class TranslatedNotCondition extends TranslatedFlexibleCondition {
|
||||
override NotExpr expr;
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
child = getOperand() and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedCondition getOperand() {
|
||||
@@ -105,13 +99,13 @@ abstract class TranslatedBinaryLogicalOperation extends TranslatedNativeConditio
|
||||
override BinaryLogicalOperation expr;
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getLeftOperand()
|
||||
id = 0 and result = getLeftOperand()
|
||||
or
|
||||
id = 1 and result = this.getRightOperand()
|
||||
id = 1 and result = getRightOperand()
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getLeftOperand().getFirstInstruction()
|
||||
result = getLeftOperand().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -133,16 +127,16 @@ class TranslatedLogicalAndExpr extends TranslatedBinaryLogicalOperation {
|
||||
TranslatedLogicalAndExpr() { expr instanceof LogicalAndExpr }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getLeftOperand() and
|
||||
result = this.getRightOperand().getFirstInstruction()
|
||||
child = getLeftOperand() and
|
||||
result = getRightOperand().getFirstInstruction()
|
||||
or
|
||||
child = this.getRightOperand() and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
child = getRightOperand() and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
(child = this.getLeftOperand() or child = this.getRightOperand()) and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
(child = getLeftOperand() or child = getRightOperand()) and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,25 +144,25 @@ class TranslatedLogicalOrExpr extends TranslatedBinaryLogicalOperation {
|
||||
override LogicalOrExpr expr;
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
(child = this.getLeftOperand() or child = this.getRightOperand()) and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
(child = getLeftOperand() or child = getRightOperand()) and
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getLeftOperand() and
|
||||
result = this.getRightOperand().getFirstInstruction()
|
||||
child = getLeftOperand() and
|
||||
result = getRightOperand().getFirstInstruction()
|
||||
or
|
||||
child = this.getRightOperand() and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
child = getRightOperand() and
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCondition {
|
||||
TranslatedValueCondition() { this = TTranslatedValueCondition(expr) }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getValueExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getValueExpr() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getValueExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = getValueExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
@@ -177,25 +171,25 @@ class TranslatedValueCondition extends TranslatedCondition, TTranslatedValueCond
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getValueExpr() and
|
||||
result = this.getInstruction(ValueConditionConditionalBranchTag())
|
||||
child = getValueExpr() and
|
||||
result = getInstruction(ValueConditionConditionalBranchTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
result = this.getConditionContext().getChildTrueSuccessor(this)
|
||||
result = getConditionContext().getChildTrueSuccessor(this)
|
||||
or
|
||||
kind instanceof FalseEdge and
|
||||
result = this.getConditionContext().getChildFalseSuccessor(this)
|
||||
result = getConditionContext().getChildFalseSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = ValueConditionConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = this.getValueExpr().getResult()
|
||||
result = getValueExpr().getResult()
|
||||
}
|
||||
|
||||
private TranslatedExpr getValueExpr() { result = getTranslatedExpr(expr) }
|
||||
|
||||
@@ -28,14 +28,9 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
|
||||
|
||||
TranslatedDeclarationEntry() { this = TTranslatedDeclarationEntry(entry) }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
exists(DeclStmt stmt | stmt = entry.getStmt() |
|
||||
result = entry.getDeclaration().(StaticInitializedStaticLocalVariable)
|
||||
or
|
||||
result = entry.getDeclaration().(GlobalOrNamespaceVariable)
|
||||
or
|
||||
not entry.getDeclaration() instanceof StaticInitializedStaticLocalVariable and
|
||||
not entry.getDeclaration() instanceof GlobalOrNamespaceVariable and
|
||||
final override Function getFunction() {
|
||||
exists(DeclStmt stmt |
|
||||
stmt = entry.getStmt() and
|
||||
result = stmt.getEnclosingFunction()
|
||||
)
|
||||
}
|
||||
@@ -47,7 +42,7 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
|
||||
final override Locatable getAst() { result = entry.getAst() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -60,19 +55,19 @@ abstract class TranslatedLocalVariableDeclaration extends TranslatedVariableInit
|
||||
*/
|
||||
abstract LocalVariable getVariable();
|
||||
|
||||
final override Type getTargetType() { result = getVariableType(this.getVariable()) }
|
||||
final override Type getTargetType() { result = getVariableType(getVariable()) }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
result =
|
||||
getTranslatedInitialization(this.getVariable().getInitializer().getExpr().getFullyConverted())
|
||||
getTranslatedInitialization(getVariable().getInitializer().getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
final override Instruction getInitializationSuccessor() {
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override IRVariable getIRVariable() {
|
||||
result = getIRUserVariable(this.getFunction(), this.getVariable())
|
||||
result = getIRUserVariable(getFunction(), getVariable())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,7 +118,7 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
|
||||
TranslatedStaticLocalVariableDeclarationEntry() { var = entry.getDeclaration() }
|
||||
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType type) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
@@ -148,39 +143,39 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(DynamicInitializationFlagAddressTag())
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = DynamicInitializationFlagAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
result = getInstruction(DynamicInitializationFlagLoadTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
result = getInstruction(DynamicInitializationConditionalBranchTag())
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
(
|
||||
kind instanceof TrueEdge and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
or
|
||||
kind instanceof FalseEdge and
|
||||
result = this.getInitialization().getFirstInstruction()
|
||||
result = getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
tag = DynamicInitializationFlagConstantTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(DynamicInitializationFlagStoreTag())
|
||||
result = getInstruction(DynamicInitializationFlagStoreTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag())
|
||||
child = getInitialization() and
|
||||
result = getInstruction(DynamicInitializationFlagConstantTag())
|
||||
}
|
||||
|
||||
final override IRDynamicInitializationFlag getInstructionVariable(InstructionTag tag) {
|
||||
@@ -196,20 +191,20 @@ class TranslatedStaticLocalVariableDeclarationEntry extends TranslatedDeclaratio
|
||||
tag = DynamicInitializationFlagLoadTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(DynamicInitializationFlagAddressTag())
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
)
|
||||
or
|
||||
tag = DynamicInitializationConditionalBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = this.getInstruction(DynamicInitializationFlagLoadTag())
|
||||
result = getInstruction(DynamicInitializationFlagLoadTag())
|
||||
or
|
||||
tag = DynamicInitializationFlagStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(DynamicInitializationFlagAddressTag())
|
||||
result = getInstruction(DynamicInitializationFlagAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInstruction(DynamicInitializationFlagConstantTag())
|
||||
result = getInstruction(DynamicInitializationFlagConstantTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -238,11 +233,11 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
|
||||
final override Locatable getAst() { result = entry.getAst() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override LocalVariable getVariable() { result = var }
|
||||
|
||||
final override Declaration getFunction() { result = var.getFunction() }
|
||||
final override Function getFunction() { result = var.getFunction() }
|
||||
}
|
||||
|
||||
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
|
||||
@@ -267,9 +262,9 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
|
||||
override Locatable getAst() { result = conditionDeclExpr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Declaration getFunction() { result = getEnclosingFunction(conditionDeclExpr) }
|
||||
override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() }
|
||||
|
||||
override LocalVariable getVariable() { result = conditionDeclExpr.getVariable() }
|
||||
}
|
||||
|
||||
@@ -62,6 +62,15 @@ private predicate ignoreExprAndDescendants(Expr expr) {
|
||||
// constant value.
|
||||
isIRConstant(getRealParent(expr))
|
||||
or
|
||||
// Only translate the initializer of a static local if it uses run-time data.
|
||||
// Otherwise the initializer does not run in function scope.
|
||||
exists(Initializer init, StaticStorageDurationVariable var |
|
||||
init = var.getInitializer() and
|
||||
not var.hasDynamicInitialization() and
|
||||
expr = init.getExpr().getFullyConverted() and
|
||||
not var instanceof GlobalOrNamespaceVariable
|
||||
)
|
||||
or
|
||||
// Ignore descendants of `__assume` expressions, since we translated these to `NoOp`.
|
||||
getRealParent(expr) instanceof AssumeExpr
|
||||
or
|
||||
@@ -109,8 +118,8 @@ private predicate ignoreExprOnly(Expr expr) {
|
||||
// should not be translated.
|
||||
exists(NewOrNewArrayExpr new | expr = new.getAllocatorCall().getArgument(0))
|
||||
or
|
||||
not translateFunction(getEnclosingFunction(expr)) and
|
||||
not Raw::varHasIRFunc(getEnclosingVariable(expr))
|
||||
not translateFunction(expr.getEnclosingFunction()) and
|
||||
not Raw::varHasIRFunc(expr.getEnclosingVariable())
|
||||
or
|
||||
// We do not yet translate destructors properly, so for now we ignore the
|
||||
// destructor call. We do, however, translate the expression being
|
||||
@@ -429,17 +438,6 @@ predicate hasTranslatedSyntheticTemporaryObject(Expr expr) {
|
||||
not expr.hasLValueToRValueConversion()
|
||||
}
|
||||
|
||||
class StaticInitializedStaticLocalVariable extends StaticLocalVariable {
|
||||
StaticInitializedStaticLocalVariable() {
|
||||
this.hasInitializer() and
|
||||
not this.hasDynamicInitialization()
|
||||
}
|
||||
}
|
||||
|
||||
class RuntimeInitializedStaticLocalVariable extends StaticLocalVariable {
|
||||
RuntimeInitializedStaticLocalVariable() { this.hasDynamicInitialization() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the specified `DeclarationEntry` needs an IR translation. An IR translation is only
|
||||
* necessary for automatic local variables, or for static local variables with dynamic
|
||||
@@ -455,7 +453,7 @@ private predicate translateDeclarationEntry(IRDeclarationEntry entry) {
|
||||
not var.isStatic()
|
||||
or
|
||||
// Ignore static variables unless they have a dynamic initializer.
|
||||
var instanceof RuntimeInitializedStaticLocalVariable
|
||||
var.(StaticLocalVariable).hasDynamicInitialization()
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -757,7 +755,7 @@ newtype TTranslatedElement =
|
||||
} or
|
||||
// The side effect that initializes newly-allocated memory.
|
||||
TTranslatedAllocationSideEffect(AllocationExpr expr) { not ignoreSideEffects(expr) } or
|
||||
TTranslatedStaticStorageDurationVarInit(Variable var) { Raw::varHasIRFunc(var) }
|
||||
TTranslatedGlobalOrNamespaceVarInit(GlobalOrNamespaceVariable var) { Raw::varHasIRFunc(var) }
|
||||
|
||||
/**
|
||||
* Gets the index of the first explicitly initialized element in `initList`
|
||||
@@ -821,7 +819,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
abstract Locatable getAst();
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = this.getAst() }
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Get the first instruction to be executed in the evaluation of this element.
|
||||
@@ -831,7 +829,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Get the immediate child elements of this element.
|
||||
*/
|
||||
final TranslatedElement getAChild() { result = this.getChild(_) }
|
||||
final TranslatedElement getAChild() { result = getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the immediate child element of this element. The `id` is unique
|
||||
@@ -844,29 +842,25 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* Gets the an identifier string for the element. This id is unique within
|
||||
* the scope of the element's function.
|
||||
*/
|
||||
final int getId() { result = this.getUniqueId() }
|
||||
final int getId() { result = getUniqueId() }
|
||||
|
||||
private TranslatedElement getChildByRank(int rankIndex) {
|
||||
result =
|
||||
rank[rankIndex + 1](TranslatedElement child, int id |
|
||||
child = this.getChild(id)
|
||||
|
|
||||
child order by id
|
||||
)
|
||||
rank[rankIndex + 1](TranslatedElement child, int id | child = getChild(id) | child order by id)
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
private int getDescendantCount() {
|
||||
result =
|
||||
1 + sum(TranslatedElement child | child = this.getChildByRank(_) | child.getDescendantCount())
|
||||
1 + sum(TranslatedElement child | child = getChildByRank(_) | child.getDescendantCount())
|
||||
}
|
||||
|
||||
private int getUniqueId() {
|
||||
if not exists(this.getParent())
|
||||
if not exists(getParent())
|
||||
then result = 0
|
||||
else
|
||||
exists(TranslatedElement parent |
|
||||
parent = this.getParent() and
|
||||
parent = getParent() and
|
||||
if this = parent.getChildByRank(0)
|
||||
then result = 1 + parent.getUniqueId()
|
||||
else
|
||||
@@ -912,7 +906,7 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
* there is no enclosing `try`.
|
||||
*/
|
||||
Instruction getExceptionSuccessorInstruction() {
|
||||
result = this.getParent().getExceptionSuccessorInstruction()
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1026,14 +1020,14 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
exists(Locatable ast |
|
||||
result.getAst() = ast and
|
||||
result.getTag() = tag and
|
||||
this.hasTempVariableAndAst(tag, ast)
|
||||
hasTempVariableAndAst(tag, ast)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) {
|
||||
this.hasTempVariable(tag, _) and
|
||||
ast = this.getAst()
|
||||
hasTempVariable(tag, _) and
|
||||
ast = getAst()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1049,6 +1043,6 @@ abstract class TranslatedRootElement extends TranslatedElement {
|
||||
TranslatedRootElement() {
|
||||
this instanceof TTranslatedFunction
|
||||
or
|
||||
this instanceof TTranslatedStaticStorageDurationVarInit
|
||||
this instanceof TTranslatedGlobalOrNamespaceVarInit
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,10 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
final override Declaration getFunction() { result = getEnclosingDeclaration(expr) }
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Declaration getFunction() { result = expr.getEnclosingDeclaration() }
|
||||
|
||||
/**
|
||||
* Gets the expression from which this `TranslatedExpr` is generated.
|
||||
@@ -87,57 +90,12 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
* Gets the `TranslatedFunction` containing this expression.
|
||||
*/
|
||||
final TranslatedRootElement getEnclosingFunction() {
|
||||
result = getTranslatedFunction(getEnclosingFunction(expr))
|
||||
result = getTranslatedFunction(expr.getEnclosingFunction())
|
||||
or
|
||||
result = getTranslatedVarInit(getEnclosingVariable(expr))
|
||||
result = getTranslatedVarInit(expr.getEnclosingVariable())
|
||||
}
|
||||
}
|
||||
|
||||
Function getEnclosingFunction(Expr e) {
|
||||
not exists(getEnclosingVariable(e)) and
|
||||
result = e.getEnclosingFunction()
|
||||
}
|
||||
|
||||
Declaration getEnclosingDeclaration0(Expr e) {
|
||||
result = getEnclosingDeclaration0(e.getParentWithConversions())
|
||||
or
|
||||
exists(Initializer i, Variable v |
|
||||
i.getExpr().getFullyConverted() = e and
|
||||
v = i.getDeclaration()
|
||||
|
|
||||
if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable
|
||||
then result = v
|
||||
else result = e.getEnclosingDeclaration()
|
||||
)
|
||||
}
|
||||
|
||||
Declaration getEnclosingDeclaration(Expr e) {
|
||||
result = getEnclosingDeclaration0(e)
|
||||
or
|
||||
not exists(getEnclosingDeclaration0(e)) and
|
||||
result = e.getEnclosingDeclaration()
|
||||
}
|
||||
|
||||
Variable getEnclosingVariable0(Expr e) {
|
||||
result = getEnclosingVariable0(e.getParentWithConversions())
|
||||
or
|
||||
exists(Initializer i, Variable v |
|
||||
i.getExpr().getFullyConverted() = e and
|
||||
v = i.getDeclaration()
|
||||
|
|
||||
if v instanceof StaticInitializedStaticLocalVariable or v instanceof GlobalOrNamespaceVariable
|
||||
then result = v
|
||||
else result = e.getEnclosingVariable()
|
||||
)
|
||||
}
|
||||
|
||||
Variable getEnclosingVariable(Expr e) {
|
||||
result = getEnclosingVariable0(e)
|
||||
or
|
||||
not exists(getEnclosingVariable0(e)) and
|
||||
result = e.getEnclosingVariable()
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of the "core" part of an expression. This is the part of
|
||||
* the expression that produces the result value of the expression, before any
|
||||
@@ -885,21 +843,10 @@ class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
exists(Declaration d, Variable v |
|
||||
accessHasEnclosingDeclarationAndVariable(d, v, expr) and
|
||||
result = getIRUserVariable(d, v)
|
||||
)
|
||||
result = getIRUserVariable(expr.getEnclosingDeclaration(), expr.getTarget())
|
||||
}
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private predicate accessHasEnclosingDeclarationAndVariable(
|
||||
Declaration d, Variable v, VariableAccess va
|
||||
) {
|
||||
d = getEnclosingDeclaration(va) and
|
||||
v = va.getTarget()
|
||||
}
|
||||
|
||||
class TranslatedFieldAccess extends TranslatedVariableAccess {
|
||||
override FieldAccess expr;
|
||||
|
||||
@@ -2053,7 +2000,7 @@ class TranslatedDestructorFieldDestruction extends TranslatedNonConstantExpr, St
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getTranslatedFunction(getEnclosingFunction(expr)).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(expr.getEnclosingFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override Field getInstructionField(InstructionTag tag) {
|
||||
|
||||
@@ -68,7 +68,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets the function being translated.
|
||||
@@ -76,15 +76,15 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = -5 and result = this.getReadEffects()
|
||||
id = -5 and result = getReadEffects()
|
||||
or
|
||||
id = -4 and result = this.getConstructorInitList()
|
||||
id = -4 and result = getConstructorInitList()
|
||||
or
|
||||
id = -3 and result = this.getBody()
|
||||
id = -3 and result = getBody()
|
||||
or
|
||||
id = -2 and result = this.getDestructorDestructionList()
|
||||
id = -2 and result = getDestructorDestructionList()
|
||||
or
|
||||
id >= -1 and result = this.getParameter(id)
|
||||
id >= -1 and result = getParameter(id)
|
||||
}
|
||||
|
||||
final private TranslatedConstructorInitList getConstructorInitList() {
|
||||
@@ -109,66 +109,64 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
result = getTranslatedEllipsisParameter(func)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(EnterFunctionTag())
|
||||
}
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(EnterFunctionTag()) }
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = EnterFunctionTag() and
|
||||
result = this.getInstruction(AliasedDefinitionTag())
|
||||
result = getInstruction(AliasedDefinitionTag())
|
||||
or
|
||||
tag = AliasedDefinitionTag() and
|
||||
result = this.getInstruction(InitializeNonLocalTag())
|
||||
result = getInstruction(InitializeNonLocalTag())
|
||||
or
|
||||
(
|
||||
tag = InitializeNonLocalTag() and
|
||||
if exists(this.getThisType())
|
||||
then result = this.getParameter(-1).getFirstInstruction()
|
||||
if exists(getThisType())
|
||||
then result = getParameter(-1).getFirstInstruction()
|
||||
else
|
||||
if exists(this.getParameter(0))
|
||||
then result = this.getParameter(0).getFirstInstruction()
|
||||
else result = this.getBody().getFirstInstruction()
|
||||
if exists(getParameter(0))
|
||||
then result = getParameter(0).getFirstInstruction()
|
||||
else result = getBody().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
tag = ReturnValueAddressTag() and
|
||||
result = this.getInstruction(ReturnTag())
|
||||
result = getInstruction(ReturnTag())
|
||||
or
|
||||
tag = ReturnTag() and
|
||||
result = this.getInstruction(AliasedUseTag())
|
||||
result = getInstruction(AliasedUseTag())
|
||||
or
|
||||
tag = UnwindTag() and
|
||||
result = this.getInstruction(AliasedUseTag())
|
||||
result = getInstruction(AliasedUseTag())
|
||||
or
|
||||
tag = AliasedUseTag() and
|
||||
result = this.getInstruction(ExitFunctionTag())
|
||||
result = getInstruction(ExitFunctionTag())
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int paramIndex |
|
||||
child = this.getParameter(paramIndex) and
|
||||
child = getParameter(paramIndex) and
|
||||
if
|
||||
exists(func.getParameter(paramIndex + 1)) or
|
||||
getEllipsisParameterIndexForFunction(func) = paramIndex + 1
|
||||
then result = this.getParameter(paramIndex + 1).getFirstInstruction()
|
||||
else result = this.getConstructorInitList().getFirstInstruction()
|
||||
then result = getParameter(paramIndex + 1).getFirstInstruction()
|
||||
else result = getConstructorInitList().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
child = this.getConstructorInitList() and
|
||||
result = this.getBody().getFirstInstruction()
|
||||
child = getConstructorInitList() and
|
||||
result = getBody().getFirstInstruction()
|
||||
or
|
||||
child = this.getBody() and
|
||||
result = this.getReturnSuccessorInstruction()
|
||||
child = getBody() and
|
||||
result = getReturnSuccessorInstruction()
|
||||
or
|
||||
child = this.getDestructorDestructionList() and
|
||||
result = this.getReadEffects().getFirstInstruction()
|
||||
child = getDestructorDestructionList() and
|
||||
result = getReadEffects().getFirstInstruction()
|
||||
or
|
||||
child = this.getReadEffects() and
|
||||
if this.hasReturnValue()
|
||||
then result = this.getInstruction(ReturnValueAddressTag())
|
||||
else result = this.getInstruction(ReturnTag())
|
||||
child = getReadEffects() and
|
||||
if hasReturnValue()
|
||||
then result = getInstruction(ReturnValueAddressTag())
|
||||
else result = getInstruction(ReturnTag())
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -187,13 +185,13 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
or
|
||||
tag = ReturnValueAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(this.getReturnType()) and
|
||||
this.hasReturnValue()
|
||||
resultType = getTypeForGLValue(getReturnType()) and
|
||||
hasReturnValue()
|
||||
or
|
||||
(
|
||||
tag = ReturnTag() and
|
||||
resultType = getVoidType() and
|
||||
if this.hasReturnValue()
|
||||
if hasReturnValue()
|
||||
then opcode instanceof Opcode::ReturnValue
|
||||
else opcode instanceof Opcode::ReturnVoid
|
||||
)
|
||||
@@ -219,23 +217,23 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
}
|
||||
|
||||
final override Instruction getExceptionSuccessorInstruction() {
|
||||
result = this.getInstruction(UnwindTag())
|
||||
result = getInstruction(UnwindTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = ReturnTag() and
|
||||
this.hasReturnValue() and
|
||||
hasReturnValue() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(ReturnValueAddressTag())
|
||||
result = getInstruction(ReturnValueAddressTag())
|
||||
}
|
||||
|
||||
final override CppType getInstructionMemoryOperandType(
|
||||
InstructionTag tag, TypedOperandTag operandTag
|
||||
) {
|
||||
tag = ReturnTag() and
|
||||
this.hasReturnValue() and
|
||||
hasReturnValue() and
|
||||
operandTag instanceof LoadOperandTag and
|
||||
result = getTypeForPRValue(this.getReturnType())
|
||||
result = getTypeForPRValue(getReturnType())
|
||||
or
|
||||
tag = AliasedUseTag() and
|
||||
operandTag instanceof SideEffectOperandTag and
|
||||
@@ -244,7 +242,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = ReturnValueAddressTag() and
|
||||
result = this.getReturnVariable()
|
||||
result = getReturnVariable()
|
||||
}
|
||||
|
||||
final override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
@@ -253,15 +251,15 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
|
||||
final override predicate hasTempVariable(TempVariableTag tag, CppType type) {
|
||||
tag = ReturnValueTempVar() and
|
||||
this.hasReturnValue() and
|
||||
type = getTypeForPRValue(this.getReturnType())
|
||||
hasReturnValue() and
|
||||
type = getTypeForPRValue(getReturnType())
|
||||
or
|
||||
tag = EllipsisTempVar() and
|
||||
func.isVarargs() and
|
||||
type = getEllipsisVariablePRValueType()
|
||||
or
|
||||
tag = ThisTempVar() and
|
||||
type = getTypeForGLValue(this.getThisType())
|
||||
type = getTypeForGLValue(getThisType())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -269,7 +267,7 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
* statement.
|
||||
*/
|
||||
final Instruction getReturnSuccessorInstruction() {
|
||||
result = this.getDestructorDestructionList().getFirstInstruction()
|
||||
result = getDestructorDestructionList().getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -324,13 +322,11 @@ class TranslatedFunction extends TranslatedRootElement, TTranslatedFunction {
|
||||
(
|
||||
var instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
var instanceof StaticLocalVariable
|
||||
or
|
||||
var instanceof MemberVariable and not var instanceof Field
|
||||
) and
|
||||
exists(VariableAccess access |
|
||||
access.getTarget() = var and
|
||||
getEnclosingFunction(access) = func
|
||||
access.getEnclosingFunction() = func
|
||||
)
|
||||
or
|
||||
var.(LocalScopeVariable).getFunction() = func
|
||||
@@ -370,25 +366,25 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
final override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
if this.hasIndirection()
|
||||
then result = this.getInstruction(InitializerIndirectAddressTag())
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
if hasIndirection()
|
||||
then result = getInstruction(InitializerIndirectAddressTag())
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
or
|
||||
tag = InitializerIndirectAddressTag() and
|
||||
result = this.getInstruction(InitializerIndirectStoreTag())
|
||||
result = getInstruction(InitializerIndirectStoreTag())
|
||||
or
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -397,21 +393,21 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = this.getGLValueType()
|
||||
resultType = getGLValueType()
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::InitializeParameter and
|
||||
resultType = this.getPRValueType()
|
||||
resultType = getPRValueType()
|
||||
or
|
||||
this.hasIndirection() and
|
||||
hasIndirection() and
|
||||
tag = InitializerIndirectAddressTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = this.getPRValueType()
|
||||
resultType = getPRValueType()
|
||||
or
|
||||
this.hasIndirection() and
|
||||
hasIndirection() and
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
opcode instanceof Opcode::InitializeIndirection and
|
||||
resultType = this.getInitializationResultType()
|
||||
resultType = getInitializationResultType()
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
@@ -420,26 +416,26 @@ abstract class TranslatedParameter extends TranslatedElement {
|
||||
tag = InitializerVariableAddressTag() or
|
||||
tag = InitializerIndirectStoreTag()
|
||||
) and
|
||||
result = this.getIRVariable()
|
||||
result = getIRVariable()
|
||||
}
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
)
|
||||
or
|
||||
// this feels a little strange, but I think it's the best we can do
|
||||
tag = InitializerIndirectAddressTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
)
|
||||
or
|
||||
tag = InitializerIndirectStoreTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(InitializerIndirectAddressTag())
|
||||
result = getInstruction(InitializerIndirectAddressTag())
|
||||
}
|
||||
|
||||
abstract predicate hasIndirection();
|
||||
@@ -467,7 +463,7 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
@@ -502,7 +498,7 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
|
||||
final override Locatable getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() {
|
||||
result = param.getFunction() or
|
||||
@@ -524,7 +520,7 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
|
||||
final override CppType getInitializationResultType() { result = getUnknownType() }
|
||||
|
||||
final override IRAutomaticUserVariable getIRVariable() {
|
||||
result = getIRUserVariable(this.getFunction(), param)
|
||||
result = getIRUserVariable(getFunction(), param)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -542,7 +538,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
@@ -581,7 +577,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(ConstructorFieldInit fieldInit |
|
||||
@@ -601,9 +597,9 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -616,10 +612,10 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
then result = this.getChild(id + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
child = getChild(id) and
|
||||
if exists(getChild(id + 1))
|
||||
then result = getChild(id + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -653,7 +649,7 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(DestructorFieldDestruction fieldDestruction |
|
||||
@@ -668,9 +664,9 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -683,10 +679,10 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id |
|
||||
child = this.getChild(id) and
|
||||
if exists(this.getChild(id + 1))
|
||||
then result = this.getChild(id + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
child = getChild(id) and
|
||||
if exists(getChild(id + 1))
|
||||
then result = getChild(id + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -701,7 +697,7 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
@@ -715,25 +711,25 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(this.getAChild())
|
||||
if exists(getAChild())
|
||||
then
|
||||
result =
|
||||
min(TranslatedElement child, int id | child = this.getChild(id) | child order by id)
|
||||
min(TranslatedElement child, int id | child = getChild(id) | child order by id)
|
||||
.getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int id | child = this.getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = this.getChild(id2))
|
||||
exists(int id | child = getChild(id) |
|
||||
if exists(TranslatedReadEffect child2, int id2 | id2 > id and child2 = getChild(id2))
|
||||
then
|
||||
result =
|
||||
min(TranslatedReadEffect child2, int id2 |
|
||||
child2 = this.getChild(id2) and id2 > id
|
||||
child2 = getChild(id2) and id2 > id
|
||||
|
|
||||
child2 order by id2
|
||||
).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -760,10 +756,10 @@ abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind = EdgeKind::gotoEdge() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
opcode instanceof Opcode::ReturnIndirection and
|
||||
@@ -788,7 +784,7 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
@@ -814,7 +810,7 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
|
||||
override Locatable getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = "read effect: " + param.toString() }
|
||||
|
||||
@@ -828,6 +824,6 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = getIRUserVariable(this.getFunction(), param)
|
||||
result = getIRUserVariable(getFunction(), param)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.TranslatedElement
|
||||
private import TranslatedExpr
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
@@ -9,16 +8,16 @@ private import TranslatedInitialization
|
||||
private import InstructionTag
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
|
||||
class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
TTranslatedStaticStorageDurationVarInit, InitializationContext
|
||||
class TranslatedGlobalOrNamespaceVarInit extends TranslatedRootElement,
|
||||
TTranslatedGlobalOrNamespaceVarInit, InitializationContext
|
||||
{
|
||||
Variable var;
|
||||
GlobalOrNamespaceVariable var;
|
||||
|
||||
TranslatedStaticStorageDurationVarInit() { this = TTranslatedStaticStorageDurationVarInit(var) }
|
||||
TranslatedGlobalOrNamespaceVarInit() { this = TTranslatedGlobalOrNamespaceVarInit(var) }
|
||||
|
||||
override string toString() { result = var.toString() }
|
||||
|
||||
final override Variable getAst() { result = var }
|
||||
final override GlobalOrNamespaceVariable getAst() { result = var }
|
||||
|
||||
final override Declaration getFunction() { result = var }
|
||||
|
||||
@@ -112,13 +111,11 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
(
|
||||
varUsed instanceof GlobalOrNamespaceVariable
|
||||
or
|
||||
varUsed instanceof StaticLocalVariable
|
||||
or
|
||||
varUsed instanceof MemberVariable and not varUsed instanceof Field
|
||||
) and
|
||||
exists(VariableAccess access |
|
||||
access.getTarget() = varUsed and
|
||||
getEnclosingVariable(access) = var
|
||||
access.getEnclosingVariable() = var
|
||||
)
|
||||
or
|
||||
var = varUsed
|
||||
@@ -131,4 +128,6 @@ class TranslatedStaticStorageDurationVarInit extends TranslatedRootElement,
|
||||
}
|
||||
}
|
||||
|
||||
TranslatedStaticStorageDurationVarInit getTranslatedVarInit(Variable var) { result.getAst() = var }
|
||||
TranslatedGlobalOrNamespaceVarInit getTranslatedVarInit(GlobalOrNamespaceVariable var) {
|
||||
result.getAst() = var
|
||||
}
|
||||
|
||||
@@ -35,64 +35,64 @@ abstract class InitializationContext extends TranslatedElement {
|
||||
* declarations, `return` statements, and `throw` expressions.
|
||||
*/
|
||||
abstract class TranslatedVariableInitialization extends TranslatedElement, InitializationContext {
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
final override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerVariableAddressTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(this.getTargetType())
|
||||
resultType = getTypeForGLValue(getTargetType())
|
||||
or
|
||||
this.hasUninitializedInstruction() and
|
||||
hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Uninitialized and
|
||||
resultType = getTypeForPRValue(this.getTargetType())
|
||||
resultType = getTypeForPRValue(getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag() and
|
||||
kind instanceof GotoEdge and
|
||||
if this.hasUninitializedInstruction()
|
||||
then result = this.getInstruction(InitializerStoreTag())
|
||||
else result = this.getInitialization().getFirstInstruction()
|
||||
if hasUninitializedInstruction()
|
||||
then result = getInstruction(InitializerStoreTag())
|
||||
else result = getInitialization().getFirstInstruction()
|
||||
)
|
||||
or
|
||||
this.hasUninitializedInstruction() and
|
||||
hasUninitializedInstruction() and
|
||||
kind instanceof GotoEdge and
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
result = this.getInitialization().getFirstInstruction()
|
||||
result = getInitialization().getFirstInstruction()
|
||||
or
|
||||
not exists(this.getInitialization()) and result = this.getInitializationSuccessor()
|
||||
not exists(getInitialization()) and result = getInitializationSuccessor()
|
||||
)
|
||||
}
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and result = this.getInitializationSuccessor()
|
||||
child = getInitialization() and result = getInitializationSuccessor()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
this.hasUninitializedInstruction() and
|
||||
hasUninitializedInstruction() and
|
||||
tag = InitializerStoreTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
final override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
(
|
||||
tag = InitializerVariableAddressTag()
|
||||
or
|
||||
this.hasUninitializedInstruction() and tag = InitializerStoreTag()
|
||||
hasUninitializedInstruction() and tag = InitializerStoreTag()
|
||||
) and
|
||||
result = this.getIRVariable()
|
||||
result = getIRVariable()
|
||||
}
|
||||
|
||||
final override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(InitializerVariableAddressTag())
|
||||
result = getInstruction(InitializerVariableAddressTag())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -116,13 +116,13 @@ abstract class TranslatedVariableInitialization extends TranslatedElement, Initi
|
||||
*/
|
||||
final predicate hasUninitializedInstruction() {
|
||||
(
|
||||
not exists(this.getInitialization()) or
|
||||
this.getInitialization() instanceof TranslatedListInitialization or
|
||||
this.getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
this.getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
not exists(getInitialization()) or
|
||||
getInitialization() instanceof TranslatedListInitialization or
|
||||
getInitialization() instanceof TranslatedConstructorInitialization or
|
||||
getInitialization().(TranslatedStringLiteralInitialization).zeroInitRange(_, _)
|
||||
) and
|
||||
// Variables with static or thread-local storage duration are zero-initialized at program startup.
|
||||
this.getIRVariable() instanceof IRAutomaticVariable
|
||||
getIRVariable() instanceof IRAutomaticVariable
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,15 +138,14 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
final override string toString() { result = "init: " + expr.toString() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(expr) or
|
||||
result = getEnclosingVariable(expr).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(expr).(StaticInitializedStaticLocalVariable)
|
||||
result = expr.getEnclosingFunction() or
|
||||
result = expr.getEnclosingVariable().(GlobalOrNamespaceVariable)
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is doing the initialization.
|
||||
@@ -157,10 +156,10 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
* Gets the initialization context that describes the location being
|
||||
* initialized.
|
||||
*/
|
||||
final InitializationContext getContext() { result = this.getParent() }
|
||||
final InitializationContext getContext() { result = getParent() }
|
||||
|
||||
final TranslatedFunction getEnclosingFunction() {
|
||||
result = getTranslatedFunction(this.getFunction())
|
||||
result = getTranslatedFunction(expr.getEnclosingFunction())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -169,17 +168,17 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
*/
|
||||
abstract class TranslatedListInitialization extends TranslatedInitialization, InitializationContext {
|
||||
override Instruction getFirstInstruction() {
|
||||
result = this.getChild(0).getFirstInstruction()
|
||||
result = getChild(0).getFirstInstruction()
|
||||
or
|
||||
not exists(this.getChild(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
not exists(getChild(0)) and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
then result = this.getChild(index + 1).getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -189,9 +188,9 @@ abstract class TranslatedListInitialization extends TranslatedInitialization, In
|
||||
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getTargetAddress() { result = this.getContext().getTargetAddress() }
|
||||
override Instruction getTargetAddress() { result = getContext().getTargetAddress() }
|
||||
|
||||
override Type getTargetType() { result = this.getContext().getTargetType() }
|
||||
override Type getTargetType() { result = getContext().getTargetType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -237,11 +236,9 @@ class TranslatedArrayListInitialization extends TranslatedListInitialization {
|
||||
abstract class TranslatedDirectInitialization extends TranslatedInitialization {
|
||||
TranslatedDirectInitialization() { not expr instanceof AggregateLiteral }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitializer() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitializer() }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = this.getInitializer().getFirstInstruction()
|
||||
}
|
||||
override Instruction getFirstInstruction() { result = getInitializer().getFirstInstruction() }
|
||||
|
||||
final TranslatedExpr getInitializer() { result = getTranslatedExpr(expr) }
|
||||
}
|
||||
@@ -260,27 +257,27 @@ class TranslatedSimpleDirectInitialization extends TranslatedDirectInitializatio
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = InitializerStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(this.getContext().getTargetType())
|
||||
resultType = getTypeForPRValue(getContext().getTargetType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerStoreTag())
|
||||
child = getInitializer() and result = getInstruction(InitializerStoreTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getContext().getTargetAddress()
|
||||
result = getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInitializer().getResult()
|
||||
result = getInitializer().getResult()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -307,13 +304,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// If the initializer string isn't large enough to fill the target, then
|
||||
// we have to generate another instruction sequence to store a constant
|
||||
// zero into the remainder of the array.
|
||||
this.zeroInitRange(_, elementCount) and
|
||||
zeroInitRange(_, elementCount) and
|
||||
(
|
||||
// Create a constant zero whose size is the size of the remaining
|
||||
// space in the target array.
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
resultType = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
or
|
||||
// The index of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
@@ -323,12 +320,12 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
// Compute the address of the first element to be zero initialized.
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
or
|
||||
// Store the constant zero into the remainder of the string.
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
resultType = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -337,78 +334,78 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = InitializerLoadStringTag() and
|
||||
result = this.getInstruction(InitializerStoreTag())
|
||||
result = getInstruction(InitializerStoreTag())
|
||||
or
|
||||
if this.zeroInitRange(_, _)
|
||||
if zeroInitRange(_, _)
|
||||
then (
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getInstruction(ZeroPadStringConstantTag())
|
||||
result = getInstruction(ZeroPadStringConstantTag())
|
||||
or
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
result = this.getInstruction(ZeroPadStringElementIndexTag())
|
||||
result = getInstruction(ZeroPadStringElementIndexTag())
|
||||
or
|
||||
tag = ZeroPadStringElementIndexTag() and
|
||||
result = this.getInstruction(ZeroPadStringElementAddressTag())
|
||||
result = getInstruction(ZeroPadStringElementAddressTag())
|
||||
or
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
result = this.getInstruction(ZeroPadStringStoreTag())
|
||||
result = getInstruction(ZeroPadStringStoreTag())
|
||||
or
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
) else (
|
||||
tag = InitializerStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitializer() and result = this.getInstruction(InitializerLoadStringTag())
|
||||
child = getInitializer() and result = getInstruction(InitializerLoadStringTag())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = InitializerLoadStringTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInitializer().getResult()
|
||||
result = getInitializer().getResult()
|
||||
)
|
||||
or
|
||||
tag = InitializerStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getContext().getTargetAddress()
|
||||
result = getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInstruction(InitializerLoadStringTag())
|
||||
result = getInstruction(InitializerLoadStringTag())
|
||||
)
|
||||
or
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = this.getContext().getTargetAddress()
|
||||
result = getContext().getTargetAddress()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = this.getInstruction(ZeroPadStringElementIndexTag())
|
||||
result = getInstruction(ZeroPadStringElementIndexTag())
|
||||
)
|
||||
or
|
||||
tag = ZeroPadStringStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(ZeroPadStringElementAddressTag())
|
||||
result = getInstruction(ZeroPadStringElementAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInstruction(ZeroPadStringConstantTag())
|
||||
result = getInstruction(ZeroPadStringConstantTag())
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = ZeroPadStringElementAddressTag() and
|
||||
result = max(this.getElementType().getSize())
|
||||
result = max(getElementType().getSize())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
exists(int startIndex |
|
||||
this.zeroInitRange(startIndex, _) and
|
||||
zeroInitRange(startIndex, _) and
|
||||
(
|
||||
tag = ZeroPadStringConstantTag() and
|
||||
result = "0"
|
||||
@@ -421,13 +418,13 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
|
||||
override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
exists(int elementCount |
|
||||
this.zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * this.getElementType().getSize()
|
||||
zeroInitRange(_, elementCount) and
|
||||
byteSize = elementCount * getElementType().getSize()
|
||||
)
|
||||
}
|
||||
|
||||
private Type getElementType() {
|
||||
result = this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
result = getContext().getTargetType().getUnspecifiedType().(ArrayType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -437,8 +434,7 @@ class TranslatedStringLiteralInitialization extends TranslatedDirectInitializati
|
||||
predicate zeroInitRange(int startIndex, int elementCount) {
|
||||
exists(int targetCount |
|
||||
startIndex = expr.getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount =
|
||||
this.getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
targetCount = getContext().getTargetType().getUnspecifiedType().(ArrayType).getArraySize() and
|
||||
elementCount = targetCount - startIndex and
|
||||
elementCount > 0
|
||||
)
|
||||
@@ -457,14 +453,14 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitializer() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getInitializer() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getReceiver() { result = this.getContext().getTargetAddress() }
|
||||
override Instruction getReceiver() { result = getContext().getTargetAddress() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -494,17 +490,14 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final override Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(ast) or
|
||||
result = getEnclosingVariable(ast).(GlobalOrNamespaceVariable) or
|
||||
result = getEnclosingVariable(ast).(StaticInitializedStaticLocalVariable)
|
||||
result = ast.getEnclosingFunction() or
|
||||
result = ast.getEnclosingVariable().(GlobalOrNamespaceVariable)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getFieldAddressTag()) }
|
||||
|
||||
/**
|
||||
* Gets the zero-based index describing the order in which this field is to be
|
||||
@@ -513,19 +506,19 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
final int getOrder() { result = field.getInitializationOrder() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
tag = getFieldAddressTag() and
|
||||
opcode instanceof Opcode::FieldAddress and
|
||||
resultType = getTypeForGLValue(field.getType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
tag = getFieldAddressTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
}
|
||||
|
||||
override Field getInstructionField(InstructionTag tag) {
|
||||
tag = this.getFieldAddressTag() and result = field
|
||||
tag = getFieldAddressTag() and result = field
|
||||
}
|
||||
|
||||
final InstructionTag getFieldAddressTag() { result = InitializerFieldAddressTag() }
|
||||
@@ -550,23 +543,21 @@ class TranslatedExplicitFieldInitialization extends TranslatedFieldInitializatio
|
||||
this = TTranslatedExplicitFieldInitialization(ast, field, expr, position)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
}
|
||||
override Instruction getTargetAddress() { result = getInstruction(getFieldAddressTag()) }
|
||||
|
||||
override Type getTargetType() { result = field.getUnspecifiedType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction() and
|
||||
tag = getFieldAddressTag() and
|
||||
result = getInitialization().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
|
||||
private TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(expr)
|
||||
@@ -591,11 +582,11 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedFieldInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
tag = getFieldDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getTypeForPRValue(field.getType())
|
||||
or
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = getTypeForPRValue(field.getUnspecifiedType())
|
||||
}
|
||||
@@ -603,32 +594,32 @@ class TranslatedFieldValueInitialization extends TranslatedFieldInitialization,
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = this.getFieldAddressTag() and
|
||||
result = this.getInstruction(this.getFieldDefaultValueTag())
|
||||
tag = getFieldAddressTag() and
|
||||
result = getInstruction(getFieldDefaultValueTag())
|
||||
or
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
result = this.getInstruction(this.getFieldDefaultValueStoreTag())
|
||||
tag = getFieldDefaultValueTag() and
|
||||
result = getInstruction(getFieldDefaultValueStoreTag())
|
||||
or
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = this.getFieldDefaultValueTag() and
|
||||
tag = getFieldDefaultValueTag() and
|
||||
result = getZeroValue(field.getUnspecifiedType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedFieldInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = this.getFieldDefaultValueStoreTag() and
|
||||
tag = getFieldDefaultValueStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(this.getFieldAddressTag())
|
||||
result = getInstruction(getFieldAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInstruction(this.getFieldDefaultValueTag())
|
||||
result = getInstruction(getFieldDefaultValueTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -651,61 +642,57 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
ArrayOrVectorAggregateLiteral initList;
|
||||
|
||||
final override string toString() {
|
||||
result = initList.toString() + "[" + this.getElementIndex().toString() + "]"
|
||||
result = initList.toString() + "[" + getElementIndex().toString() + "]"
|
||||
}
|
||||
|
||||
final override Locatable getAst() { result = initList }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Declaration getFunction() {
|
||||
result = getEnclosingFunction(initList)
|
||||
result = initList.getEnclosingFunction()
|
||||
or
|
||||
result = getEnclosingVariable(initList).(GlobalOrNamespaceVariable)
|
||||
or
|
||||
result = getEnclosingVariable(initList).(StaticInitializedStaticLocalVariable)
|
||||
result = initList.getEnclosingVariable().(GlobalOrNamespaceVariable)
|
||||
}
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(this.getElementIndexTag())
|
||||
}
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(getElementIndexTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = this.getElementIndexTag() and
|
||||
tag = getElementIndexTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = getIntType()
|
||||
or
|
||||
tag = this.getElementAddressTag() and
|
||||
tag = getElementAddressTag() and
|
||||
opcode instanceof Opcode::PointerAdd and
|
||||
resultType = getTypeForGLValue(this.getElementType())
|
||||
resultType = getTypeForGLValue(getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getInstruction(this.getElementAddressTag()) and
|
||||
tag = getElementIndexTag() and
|
||||
result = getInstruction(getElementAddressTag()) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = this.getElementAddressTag() and
|
||||
tag = getElementAddressTag() and
|
||||
(
|
||||
operandTag instanceof LeftOperandTag and
|
||||
result = this.getParent().(InitializationContext).getTargetAddress()
|
||||
result = getParent().(InitializationContext).getTargetAddress()
|
||||
or
|
||||
operandTag instanceof RightOperandTag and
|
||||
result = this.getInstruction(this.getElementIndexTag())
|
||||
result = getInstruction(getElementIndexTag())
|
||||
)
|
||||
}
|
||||
|
||||
override int getInstructionElementSize(InstructionTag tag) {
|
||||
tag = this.getElementAddressTag() and
|
||||
result = max(this.getElementType().getSize())
|
||||
tag = getElementAddressTag() and
|
||||
result = max(getElementType().getSize())
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
tag = this.getElementIndexTag() and
|
||||
result = this.getElementIndex().toString()
|
||||
tag = getElementIndexTag() and
|
||||
result = getElementIndex().toString()
|
||||
}
|
||||
|
||||
abstract int getElementIndex();
|
||||
@@ -735,25 +722,23 @@ class TranslatedExplicitElementInitialization extends TranslatedElementInitializ
|
||||
this = TTranslatedExplicitElementInitialization(initList, elementIndex, position)
|
||||
}
|
||||
|
||||
override Instruction getTargetAddress() {
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
}
|
||||
override Instruction getTargetAddress() { result = getInstruction(getElementAddressTag()) }
|
||||
|
||||
override Type getTargetType() { result = this.getElementType() }
|
||||
override Type getTargetType() { result = getElementType() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
result = TranslatedElementInitialization.super.getInstructionSuccessor(tag, kind)
|
||||
or
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInitialization().getFirstInstruction() and
|
||||
tag = getElementAddressTag() and
|
||||
result = getInitialization().getFirstInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getInitialization() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getInitialization() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getInitialization() }
|
||||
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
@@ -784,13 +769,13 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
TranslatedElementInitialization.super.hasInstruction(opcode, tag, resultType)
|
||||
or
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
tag = getElementDefaultValueTag() and
|
||||
opcode instanceof Opcode::Constant and
|
||||
resultType = this.getDefaultValueType()
|
||||
resultType = getDefaultValueType()
|
||||
or
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
opcode instanceof Opcode::Store and
|
||||
resultType = this.getDefaultValueType()
|
||||
resultType = getDefaultValueType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -798,34 +783,34 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
or
|
||||
kind instanceof GotoEdge and
|
||||
(
|
||||
tag = this.getElementAddressTag() and
|
||||
result = this.getInstruction(this.getElementDefaultValueTag())
|
||||
tag = getElementAddressTag() and
|
||||
result = getInstruction(getElementDefaultValueTag())
|
||||
or
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
result = this.getInstruction(this.getElementDefaultValueStoreTag())
|
||||
tag = getElementDefaultValueTag() and
|
||||
result = getInstruction(getElementDefaultValueStoreTag())
|
||||
or
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
)
|
||||
}
|
||||
|
||||
override string getInstructionConstantValue(InstructionTag tag) {
|
||||
result = TranslatedElementInitialization.super.getInstructionConstantValue(tag)
|
||||
or
|
||||
tag = this.getElementDefaultValueTag() and
|
||||
result = getZeroValue(this.getElementType())
|
||||
tag = getElementDefaultValueTag() and
|
||||
result = getZeroValue(getElementType())
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
result = TranslatedElementInitialization.super.getInstructionRegisterOperand(tag, operandTag)
|
||||
or
|
||||
tag = this.getElementDefaultValueStoreTag() and
|
||||
tag = getElementDefaultValueStoreTag() and
|
||||
(
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(this.getElementAddressTag())
|
||||
result = getInstruction(getElementAddressTag())
|
||||
or
|
||||
operandTag instanceof StoreValueOperandTag and
|
||||
result = this.getInstruction(this.getElementDefaultValueTag())
|
||||
result = getInstruction(getElementDefaultValueTag())
|
||||
)
|
||||
}
|
||||
|
||||
@@ -836,7 +821,7 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
override int getElementIndex() { result = elementIndex }
|
||||
|
||||
override predicate needsUnknownOpaqueType(int byteSize) {
|
||||
elementCount != 0 and byteSize = elementCount * this.getElementType().getSize()
|
||||
elementCount != 0 and byteSize = elementCount * getElementType().getSize()
|
||||
}
|
||||
|
||||
private InstructionTag getElementDefaultValueTag() {
|
||||
@@ -849,8 +834,8 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
|
||||
private CppType getDefaultValueType() {
|
||||
if elementCount = 1
|
||||
then result = getTypeForPRValue(this.getElementType())
|
||||
else result = getUnknownOpaqueType(elementCount * this.getElementType().getSize())
|
||||
then result = getTypeForPRValue(getElementType())
|
||||
else result = getUnknownOpaqueType(elementCount * getElementType().getSize())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -860,18 +845,18 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = this.getStructorCall()
|
||||
result = getStructorCall()
|
||||
}
|
||||
|
||||
final override Function getFunction() { result = getEnclosingFunction(call) }
|
||||
final override Function getFunction() { result = call.getEnclosingFunction() }
|
||||
|
||||
final override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getStructorCall() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
child = getStructorCall() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
final TranslatedExpr getStructorCall() { result = getTranslatedExpr(call) }
|
||||
@@ -882,9 +867,7 @@ abstract class TranslatedStructorCallFromStructor extends TranslatedElement, Str
|
||||
* destructor from within a derived class constructor or destructor.
|
||||
*/
|
||||
abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStructor {
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
final override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -895,15 +878,15 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getStructorCall().getFirstInstruction()
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getReceiver() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
final override Instruction getReceiver() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
final override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = OnlyInstructionTag() and
|
||||
operandTag instanceof UnaryOperandTag and
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
|
||||
final override predicate getInstructionInheritance(
|
||||
@@ -911,7 +894,7 @@ abstract class TranslatedBaseStructorCall extends TranslatedStructorCallFromStru
|
||||
) {
|
||||
tag = OnlyInstructionTag() and
|
||||
baseClass = call.getTarget().getDeclaringType().getUnspecifiedType() and
|
||||
derivedClass = this.getFunction().getDeclaringType().getUnspecifiedType()
|
||||
derivedClass = getFunction().getDeclaringType().getUnspecifiedType()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -937,7 +920,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
final override string toString() { result = "delegation construct: " + call.toString() }
|
||||
|
||||
final override Instruction getFirstInstruction() {
|
||||
result = this.getStructorCall().getFirstInstruction()
|
||||
result = getStructorCall().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -947,7 +930,7 @@ class TranslatedConstructorDelegationInit extends TranslatedConstructorCallFromC
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getReceiver() {
|
||||
result = getTranslatedFunction(this.getFunction()).getInitializeThisInstruction()
|
||||
result = getTranslatedFunction(getFunction()).getInitializeThisInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -994,11 +977,11 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
override Locatable getAst() { result = init }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override string toString() { result = "construct base (no constructor)" }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getParent().getChildSuccessor(this) }
|
||||
override Instruction getFirstInstruction() { result = getParent().getChildSuccessor(this) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
@@ -1006,7 +989,7 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Declaration getFunction() { result = this.getParent().getFunction() }
|
||||
override Function getFunction() { result = getParent().getFunction() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
|
||||
@@ -240,7 +240,7 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
final override Locatable getAst() { result = stmt }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = stmt.getEnclosingFunction() }
|
||||
}
|
||||
@@ -254,7 +254,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -264,7 +264,7 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
@@ -279,19 +279,19 @@ class TranslatedEmptyStmt extends TranslatedStmt {
|
||||
class TranslatedDeclStmt extends TranslatedStmt {
|
||||
override DeclStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = this.getDeclarationEntry(id) }
|
||||
override TranslatedElement getChild(int id) { result = getDeclarationEntry(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = this.getDeclarationEntry(0).getFirstInstruction()
|
||||
result = getDeclarationEntry(0).getFirstInstruction()
|
||||
or
|
||||
not exists(this.getDeclarationEntry(0)) and result = this.getParent().getChildSuccessor(this)
|
||||
not exists(getDeclarationEntry(0)) and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private int getChildCount() { result = count(this.getDeclarationEntry(_)) }
|
||||
private int getChildCount() { result = count(getDeclarationEntry(_)) }
|
||||
|
||||
IRDeclarationEntry getIRDeclarationEntry(int index) {
|
||||
result.hasIndex(index) and
|
||||
@@ -319,10 +319,10 @@ class TranslatedDeclStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = this.getDeclarationEntry(index) and
|
||||
if index = (this.getChildCount() - 1)
|
||||
then result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getDeclarationEntry(index + 1).getFirstInstruction()
|
||||
child = getDeclarationEntry(index) and
|
||||
if index = (getChildCount() - 1)
|
||||
then result = getParent().getChildSuccessor(this)
|
||||
else result = getDeclarationEntry(index + 1).getFirstInstruction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -332,19 +332,19 @@ class TranslatedExprStmt extends TranslatedStmt {
|
||||
|
||||
TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr().getFullyConverted()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = this.getExpr() }
|
||||
override TranslatedElement getChild(int id) { id = 0 and result = getExpr() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getExpr() and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
child = getExpr() and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -363,18 +363,16 @@ class TranslatedReturnValueStmt extends TranslatedReturnStmt, TranslatedVariable
|
||||
TranslatedReturnValueStmt() { stmt.hasExpr() and hasReturnValue(stmt.getEnclosingFunction()) }
|
||||
|
||||
final override Instruction getInitializationSuccessor() {
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction()
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction()
|
||||
}
|
||||
|
||||
final override Type getTargetType() { result = this.getEnclosingFunction().getReturnType() }
|
||||
final override Type getTargetType() { result = getEnclosingFunction().getReturnType() }
|
||||
|
||||
final override TranslatedInitialization getInitialization() {
|
||||
result = getTranslatedInitialization(stmt.getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
final override IRVariable getIRVariable() {
|
||||
result = this.getEnclosingFunction().getReturnVariable()
|
||||
}
|
||||
final override IRVariable getIRVariable() { result = getEnclosingFunction().getReturnVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -387,10 +385,10 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
result = this.getExpr()
|
||||
result = getExpr()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = getExpr().getFirstInstruction() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -400,13 +398,13 @@ class TranslatedReturnVoidExpressionStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getExpr() and
|
||||
result = this.getInstruction(OnlyInstructionTag())
|
||||
child = getExpr() and
|
||||
result = getInstruction(OnlyInstructionTag())
|
||||
}
|
||||
|
||||
private TranslatedExpr getExpr() { result = getTranslatedExpr(stmt.getExpr()) }
|
||||
@@ -423,7 +421,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -433,7 +431,7 @@ class TranslatedReturnVoidStmt extends TranslatedReturnStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
result = getEnclosingFunction().getReturnSuccessorInstruction() and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
@@ -454,7 +452,7 @@ class TranslatedUnreachableReturnStmt extends TranslatedReturnStmt {
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = OnlyInstructionTag() and
|
||||
@@ -513,9 +511,9 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
override TryOrMicrosoftTryStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getBody()
|
||||
id = 0 and result = getBody()
|
||||
or
|
||||
result = this.getHandler(id - 1)
|
||||
result = getHandler(id - 1)
|
||||
or
|
||||
id = stmt.getNumberOfCatchClauses() + 1 and
|
||||
result = this.getFinally()
|
||||
@@ -527,7 +525,7 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
// All non-finally children go to the successor of the `try` if
|
||||
@@ -548,19 +546,19 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
|
||||
final Instruction getNextHandler(TranslatedHandler handler) {
|
||||
exists(int index |
|
||||
handler = this.getHandler(index) and
|
||||
result = this.getHandler(index + 1).getFirstInstruction()
|
||||
handler = getHandler(index) and
|
||||
result = getHandler(index + 1).getFirstInstruction()
|
||||
)
|
||||
or
|
||||
// The last catch clause flows to the exception successor of the parent
|
||||
// of the `try`, because the exception successor of the `try` itself is
|
||||
// the first catch clause.
|
||||
handler = this.getHandler(stmt.getNumberOfCatchClauses() - 1) and
|
||||
result = this.getParent().getExceptionSuccessorInstruction()
|
||||
handler = getHandler(stmt.getNumberOfCatchClauses() - 1) and
|
||||
result = getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getExceptionSuccessorInstruction() {
|
||||
result = this.getHandler(0).getFirstInstruction()
|
||||
result = getHandler(0).getFirstInstruction()
|
||||
}
|
||||
|
||||
private TranslatedElement getHandler(int index) { result = stmt.getTranslatedHandler(index) }
|
||||
@@ -573,19 +571,19 @@ class TranslatedTryStmt extends TranslatedStmt {
|
||||
class TranslatedBlock extends TranslatedStmt {
|
||||
override BlockStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { result = this.getStmt(id) }
|
||||
override TranslatedElement getChild(int id) { result = getStmt(id) }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
this.isEmpty() and
|
||||
isEmpty() and
|
||||
opcode instanceof Opcode::NoOp and
|
||||
tag = OnlyInstructionTag() and
|
||||
resultType = getVoidType()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if this.isEmpty()
|
||||
then result = this.getInstruction(OnlyInstructionTag())
|
||||
else result = this.getStmt(0).getFirstInstruction()
|
||||
if isEmpty()
|
||||
then result = getInstruction(OnlyInstructionTag())
|
||||
else result = getStmt(0).getFirstInstruction()
|
||||
}
|
||||
|
||||
private predicate isEmpty() { not exists(stmt.getStmt(0)) }
|
||||
@@ -596,16 +594,16 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = OnlyInstructionTag() and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = this.getStmt(index) and
|
||||
if index = (this.getStmtCount() - 1)
|
||||
then result = this.getParent().getChildSuccessor(this)
|
||||
else result = this.getStmt(index + 1).getFirstInstruction()
|
||||
child = getStmt(index) and
|
||||
if index = (getStmtCount() - 1)
|
||||
then result = getParent().getChildSuccessor(this)
|
||||
else result = getStmt(index + 1).getFirstInstruction()
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -616,18 +614,18 @@ class TranslatedBlock extends TranslatedStmt {
|
||||
abstract class TranslatedHandler extends TranslatedStmt {
|
||||
override Handler stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = this.getBlock() }
|
||||
override TranslatedElement getChild(int id) { id = 1 and result = getBlock() }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(CatchTag()) }
|
||||
override Instruction getFirstInstruction() { result = getInstruction(CatchTag()) }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getBlock() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getBlock() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getExceptionSuccessorInstruction() {
|
||||
// A throw from within a `catch` block flows to the handler for the parent of
|
||||
// the `try`.
|
||||
result = this.getParent().getParent().getExceptionSuccessorInstruction()
|
||||
result = getParent().getParent().getExceptionSuccessorInstruction()
|
||||
}
|
||||
|
||||
TranslatedStmt getBlock() { result = getTranslatedStmt(stmt.getBlock()) }
|
||||
@@ -649,23 +647,23 @@ class TranslatedCatchByTypeHandler extends TranslatedHandler {
|
||||
override TranslatedElement getChild(int id) {
|
||||
result = super.getChild(id)
|
||||
or
|
||||
id = 0 and result = this.getParameter()
|
||||
id = 0 and result = getParameter()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
result = super.getChildSuccessor(child)
|
||||
or
|
||||
child = this.getParameter() and result = this.getBlock().getFirstInstruction()
|
||||
child = getParameter() and result = getBlock().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
(
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getParameter().getFirstInstruction()
|
||||
result = getParameter().getFirstInstruction()
|
||||
or
|
||||
kind instanceof ExceptionEdge and
|
||||
result = this.getParent().(TranslatedTryStmt).getNextHandler(this)
|
||||
result = getParent().(TranslatedTryStmt).getNextHandler(this)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -694,7 +692,7 @@ class TranslatedCatchAnyHandler extends TranslatedHandler {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = CatchTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getBlock().getFirstInstruction()
|
||||
result = getBlock().getFirstInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -702,19 +700,19 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override IfStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
id = 0 and result = getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
id = 1 and result = getCondition()
|
||||
or
|
||||
id = 2 and result = this.getThen()
|
||||
id = 2 and result = getThen()
|
||||
or
|
||||
id = 3 and result = this.getElse()
|
||||
id = 3 and result = getElse()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
@@ -728,7 +726,7 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
}
|
||||
|
||||
private Instruction getFirstConditionInstruction() {
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
result = getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
private TranslatedStmt getThen() { result = getTranslatedStmt(stmt.getThen()) }
|
||||
@@ -740,23 +738,23 @@ class TranslatedIfStmt extends TranslatedStmt, ConditionContext {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getCondition() and
|
||||
result = this.getThen().getFirstInstruction()
|
||||
child = getCondition() and
|
||||
result = getThen().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getCondition() and
|
||||
if this.hasElse()
|
||||
then result = this.getElse().getFirstInstruction()
|
||||
else result = this.getParent().getChildSuccessor(this)
|
||||
child = getCondition() and
|
||||
if hasElse()
|
||||
then result = getElse().getFirstInstruction()
|
||||
else result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction()
|
||||
child = getInitialization() and
|
||||
result = getFirstConditionInstruction()
|
||||
or
|
||||
(child = this.getThen() or child = this.getElse()) and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
(child = getThen() or child = getElse()) and
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -774,17 +772,17 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
final TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
|
||||
|
||||
final Instruction getFirstConditionInstruction() {
|
||||
if this.hasCondition()
|
||||
then result = this.getCondition().getFirstInstruction()
|
||||
else result = this.getBody().getFirstInstruction()
|
||||
if hasCondition()
|
||||
then result = getCondition().getFirstInstruction()
|
||||
else result = getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
final predicate hasCondition() { exists(stmt.getCondition()) }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getCondition()
|
||||
id = 0 and result = getCondition()
|
||||
or
|
||||
id = 1 and result = this.getBody()
|
||||
id = 1 and result = getBody()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -794,31 +792,31 @@ abstract class TranslatedLoop extends TranslatedStmt, ConditionContext {
|
||||
final override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
final override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getCondition() and result = this.getBody().getFirstInstruction()
|
||||
child = getCondition() and result = getBody().getFirstInstruction()
|
||||
}
|
||||
|
||||
final override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getCondition() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedWhileStmt extends TranslatedLoop {
|
||||
TranslatedWhileStmt() { stmt instanceof WhileStmt }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getFirstConditionInstruction() }
|
||||
override Instruction getFirstInstruction() { result = getFirstConditionInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getBody() and result = this.getFirstConditionInstruction()
|
||||
child = getBody() and result = getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedDoStmt extends TranslatedLoop {
|
||||
TranslatedDoStmt() { stmt instanceof DoStmt }
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getBody().getFirstInstruction() }
|
||||
override Instruction getFirstInstruction() { result = getBody().getFirstInstruction() }
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getBody() and result = this.getFirstConditionInstruction()
|
||||
child = getBody() and result = getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -826,13 +824,13 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
override ForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
id = 0 and result = getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getCondition()
|
||||
id = 1 and result = getCondition()
|
||||
or
|
||||
id = 2 and result = this.getUpdate()
|
||||
id = 2 and result = getUpdate()
|
||||
or
|
||||
id = 3 and result = this.getBody()
|
||||
id = 3 and result = getBody()
|
||||
}
|
||||
|
||||
private TranslatedStmt getInitialization() {
|
||||
@@ -846,23 +844,23 @@ class TranslatedForStmt extends TranslatedLoop {
|
||||
private predicate hasUpdate() { exists(stmt.getUpdate()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and
|
||||
result = this.getFirstConditionInstruction()
|
||||
child = getInitialization() and
|
||||
result = getFirstConditionInstruction()
|
||||
or
|
||||
(
|
||||
child = this.getBody() and
|
||||
if this.hasUpdate()
|
||||
then result = this.getUpdate().getFirstInstruction()
|
||||
else result = this.getFirstConditionInstruction()
|
||||
child = getBody() and
|
||||
if hasUpdate()
|
||||
then result = getUpdate().getFirstInstruction()
|
||||
else result = getFirstConditionInstruction()
|
||||
)
|
||||
or
|
||||
child = this.getUpdate() and result = this.getFirstConditionInstruction()
|
||||
child = getUpdate() and result = getFirstConditionInstruction()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -877,39 +875,39 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override RangeBasedForStmt stmt;
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getRangeVariableDeclStmt()
|
||||
id = 0 and result = getRangeVariableDeclStmt()
|
||||
or
|
||||
// Note: `__begin` and `__end` are declared by the same `DeclStmt`
|
||||
id = 1 and result = this.getBeginEndVariableDeclStmt()
|
||||
id = 1 and result = getBeginEndVariableDeclStmt()
|
||||
or
|
||||
id = 2 and result = this.getCondition()
|
||||
id = 2 and result = getCondition()
|
||||
or
|
||||
id = 3 and result = this.getUpdate()
|
||||
id = 3 and result = getUpdate()
|
||||
or
|
||||
id = 4 and result = this.getVariableDeclStmt()
|
||||
id = 4 and result = getVariableDeclStmt()
|
||||
or
|
||||
id = 5 and result = this.getBody()
|
||||
id = 5 and result = getBody()
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
result = this.getRangeVariableDeclStmt().getFirstInstruction()
|
||||
result = getRangeVariableDeclStmt().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getRangeVariableDeclStmt() and
|
||||
result = this.getBeginEndVariableDeclStmt().getFirstInstruction()
|
||||
child = getRangeVariableDeclStmt() and
|
||||
result = getBeginEndVariableDeclStmt().getFirstInstruction()
|
||||
or
|
||||
child = this.getBeginEndVariableDeclStmt() and
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
child = getBeginEndVariableDeclStmt() and
|
||||
result = getCondition().getFirstInstruction()
|
||||
or
|
||||
child = this.getVariableDeclStmt() and
|
||||
result = this.getBody().getFirstInstruction()
|
||||
child = getVariableDeclStmt() and
|
||||
result = getBody().getFirstInstruction()
|
||||
or
|
||||
child = this.getBody() and
|
||||
result = this.getUpdate().getFirstInstruction()
|
||||
child = getBody() and
|
||||
result = getUpdate().getFirstInstruction()
|
||||
or
|
||||
child = this.getUpdate() and
|
||||
result = this.getCondition().getFirstInstruction()
|
||||
child = getUpdate() and
|
||||
result = getCondition().getFirstInstruction()
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -919,11 +917,11 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) { none() }
|
||||
|
||||
override Instruction getChildTrueSuccessor(TranslatedCondition child) {
|
||||
child = this.getCondition() and result = this.getVariableDeclStmt().getFirstInstruction()
|
||||
child = getCondition() and result = getVariableDeclStmt().getFirstInstruction()
|
||||
}
|
||||
|
||||
override Instruction getChildFalseSuccessor(TranslatedCondition child) {
|
||||
child = this.getCondition() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getCondition() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
private TranslatedDeclStmt getRangeVariableDeclStmt() {
|
||||
@@ -963,7 +961,7 @@ class TranslatedRangeBasedForStmt extends TranslatedStmt, ConditionContext {
|
||||
class TranslatedJumpStmt extends TranslatedStmt {
|
||||
override JumpStmt stmt;
|
||||
|
||||
override Instruction getFirstInstruction() { result = this.getInstruction(OnlyInstructionTag()) }
|
||||
override Instruction getFirstInstruction() { result = getInstruction(OnlyInstructionTag()) }
|
||||
|
||||
override TranslatedElement getChild(int id) { none() }
|
||||
|
||||
@@ -998,22 +996,22 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
result = getTranslatedExpr(stmt.getExpr().getFullyConverted())
|
||||
}
|
||||
|
||||
private Instruction getFirstExprInstruction() { result = this.getExpr().getFirstInstruction() }
|
||||
private Instruction getFirstExprInstruction() { result = getExpr().getFirstInstruction() }
|
||||
|
||||
private TranslatedStmt getBody() { result = getTranslatedStmt(stmt.getStmt()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if this.hasInitialization()
|
||||
then result = this.getInitialization().getFirstInstruction()
|
||||
else result = this.getFirstExprInstruction()
|
||||
if hasInitialization()
|
||||
then result = getInitialization().getFirstInstruction()
|
||||
else result = getFirstExprInstruction()
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
id = 0 and result = this.getInitialization()
|
||||
id = 0 and result = getInitialization()
|
||||
or
|
||||
id = 1 and result = this.getExpr()
|
||||
id = 1 and result = getExpr()
|
||||
or
|
||||
id = 2 and result = this.getBody()
|
||||
id = 2 and result = getBody()
|
||||
}
|
||||
|
||||
private predicate hasInitialization() { exists(stmt.getInitialization()) }
|
||||
@@ -1031,7 +1029,7 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = SwitchBranchTag() and
|
||||
operandTag instanceof ConditionOperandTag and
|
||||
result = this.getExpr().getResult()
|
||||
result = getExpr().getResult()
|
||||
}
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
@@ -1045,15 +1043,15 @@ class TranslatedSwitchStmt extends TranslatedStmt {
|
||||
not stmt.hasDefaultCase() and
|
||||
tag = SwitchBranchTag() and
|
||||
kind instanceof DefaultEdge and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
child = this.getInitialization() and result = this.getFirstExprInstruction()
|
||||
child = getInitialization() and result = getFirstExprInstruction()
|
||||
or
|
||||
child = this.getExpr() and result = this.getInstruction(SwitchBranchTag())
|
||||
child = getExpr() and result = getInstruction(SwitchBranchTag())
|
||||
or
|
||||
child = this.getBody() and result = this.getParent().getChildSuccessor(this)
|
||||
child = getBody() and result = getParent().getChildSuccessor(this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1065,9 +1063,9 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(this.getChild(0))
|
||||
then result = this.getChild(0).getFirstInstruction()
|
||||
else result = this.getInstruction(AsmTag())
|
||||
if exists(getChild(0))
|
||||
then result = getChild(0).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
}
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
@@ -1080,7 +1078,7 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
exists(int index |
|
||||
tag = AsmTag() and
|
||||
operandTag = asmOperand(index) and
|
||||
result = this.getChild(index).getResult()
|
||||
result = getChild(index).getResult()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1094,16 +1092,16 @@ class TranslatedAsmStmt extends TranslatedStmt {
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = AsmTag() and
|
||||
result = this.getParent().getChildSuccessor(this) and
|
||||
result = getParent().getChildSuccessor(this) and
|
||||
kind instanceof GotoEdge
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) {
|
||||
exists(int index |
|
||||
child = this.getChild(index) and
|
||||
if exists(this.getChild(index + 1))
|
||||
then result = this.getChild(index + 1).getFirstInstruction()
|
||||
else result = this.getInstruction(AsmTag())
|
||||
child = getChild(index) and
|
||||
if exists(getChild(index + 1))
|
||||
then result = getChild(index + 1).getFirstInstruction()
|
||||
else result = getInstruction(AsmTag())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,16 +77,4 @@ class IRPropertyProvider extends TIRPropertyProvider {
|
||||
* Gets the value of the property named `key` for the specified operand.
|
||||
*/
|
||||
string getOperandProperty(Operand operand, string key) { none() }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `instr` should be included when printing
|
||||
* the IR instructions.
|
||||
*/
|
||||
predicate shouldPrintInstruction(Instruction instr) { any() }
|
||||
|
||||
/**
|
||||
* Holds if the operand `operand` should be included when printing the an
|
||||
* instruction's operand list.
|
||||
*/
|
||||
predicate shouldPrintOperand(Operand operand) { any() }
|
||||
}
|
||||
|
||||
@@ -45,9 +45,7 @@ class IRFunction extends IRFunctionBase {
|
||||
* Gets the block containing the entry point of this function.
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock getEntryBlock() {
|
||||
result.getFirstInstruction() = this.getEnterFunctionInstruction()
|
||||
}
|
||||
final IRBlock getEntryBlock() { result.getFirstInstruction() = getEnterFunctionInstruction() }
|
||||
|
||||
/**
|
||||
* Gets all instructions in this function.
|
||||
|
||||
@@ -39,12 +39,12 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
*/
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, false) }
|
||||
final Language::Type getType() { getLanguageType().hasType(result, false) }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the variable.
|
||||
*/
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the variable.
|
||||
@@ -58,7 +58,7 @@ class IRVariable extends TIRVariable {
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -69,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -91,15 +91,15 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
IRUserVariable() { this = TIRUserVariable(var, type, func) }
|
||||
|
||||
final override string toString() { result = this.getVariable().toString() }
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
@@ -166,9 +166,9 @@ class IRGeneratedVariable extends IRVariable {
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = this.getAst() }
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = this.getBaseString() + this.getLocationString() }
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
override string getUniqueId() { none() }
|
||||
|
||||
@@ -272,7 +272,7 @@ class IRStringLiteral extends IRGeneratedVariable, TIRStringLiteral {
|
||||
final override predicate isReadOnly() { any() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = "String: " + this.getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
result = "String: " + getLocationString() + "=" + Language::getStringLiteralText(literal)
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#string" }
|
||||
@@ -303,8 +303,7 @@ class IRDynamicInitializationFlag extends IRGeneratedVariable, TIRDynamicInitial
|
||||
final Language::Variable getVariable() { result = var }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result =
|
||||
"Init: " + this.getVariable().toString() + " " + this.getVariable().getLocation().toString()
|
||||
result = "Init: " + getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
}
|
||||
|
||||
final override string getBaseString() { result = "#init:" + var.toString() + ":" }
|
||||
@@ -333,5 +332,5 @@ class IRParameter extends IRAutomaticVariable {
|
||||
* An IR variable representing a positional parameter.
|
||||
*/
|
||||
class IRPositionalParameter extends IRParameter, IRAutomaticUserVariable {
|
||||
final override int getIndex() { result = this.getVariable().(Language::Parameter).getIndex() }
|
||||
final override int getIndex() { result = getVariable().(Language::Parameter).getIndex() }
|
||||
}
|
||||
|
||||
@@ -210,6 +210,9 @@ class Instruction extends Construction::TStageInstruction {
|
||||
*/
|
||||
final Language::AST getAst() { result = Construction::getInstructionAst(this) }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = this.getAst() }
|
||||
|
||||
/**
|
||||
* Gets the location of the source code for this instruction.
|
||||
*/
|
||||
@@ -460,6 +463,9 @@ class VariableInstruction extends Instruction {
|
||||
* Gets the AST variable that this instruction's IR variable refers to, if one exists.
|
||||
*/
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,14 +42,6 @@ private predicate shouldPrintFunction(Language::Declaration decl) {
|
||||
exists(PrintIRConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
private predicate shouldPrintInstruction(Instruction i) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintInstruction(i))
|
||||
}
|
||||
|
||||
private predicate shouldPrintOperand(Operand operand) {
|
||||
exists(IRPropertyProvider provider | provider.shouldPrintOperand(operand))
|
||||
}
|
||||
|
||||
private string getAdditionalInstructionProperty(Instruction instr, string key) {
|
||||
exists(IRPropertyProvider provider | result = provider.getInstructionProperty(instr, key))
|
||||
}
|
||||
@@ -92,9 +84,7 @@ private string getOperandPropertyString(Operand operand) {
|
||||
private newtype TPrintableIRNode =
|
||||
TPrintableIRFunction(IRFunction irFunc) { shouldPrintFunction(irFunc.getFunction()) } or
|
||||
TPrintableIRBlock(IRBlock block) { shouldPrintFunction(block.getEnclosingFunction()) } or
|
||||
TPrintableInstruction(Instruction instr) {
|
||||
shouldPrintInstruction(instr) and shouldPrintFunction(instr.getEnclosingFunction())
|
||||
}
|
||||
TPrintableInstruction(Instruction instr) { shouldPrintFunction(instr.getEnclosingFunction()) }
|
||||
|
||||
/**
|
||||
* A node to be emitted in the IR graph.
|
||||
@@ -137,13 +127,13 @@ abstract private class PrintableIRNode extends TPrintableIRNode {
|
||||
* Gets the value of the node property with the specified key.
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and result = this.getLabel()
|
||||
key = "semmle.label" and result = getLabel()
|
||||
or
|
||||
key = "semmle.order" and result = this.getOrder().toString()
|
||||
key = "semmle.order" and result = getOrder().toString()
|
||||
or
|
||||
key = "semmle.graphKind" and result = this.getGraphKind()
|
||||
key = "semmle.graphKind" and result = getGraphKind()
|
||||
or
|
||||
key = "semmle.forceText" and this.forceText() and result = "true"
|
||||
key = "semmle.forceText" and forceText() and result = "true"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,7 +178,7 @@ private class PrintableIRBlock extends PrintableIRNode, TPrintableIRBlock {
|
||||
|
||||
PrintableIRBlock() { this = TPrintableIRBlock(block) }
|
||||
|
||||
override string toString() { result = this.getLabel() }
|
||||
override string toString() { result = getLabel() }
|
||||
|
||||
override Language::Location getLocation() { result = block.getLocation() }
|
||||
|
||||
@@ -233,7 +223,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
|
|
||||
resultString = instr.getResultString() and
|
||||
operationString = instr.getOperationString() and
|
||||
operandsString = this.getOperandsString() and
|
||||
operandsString = getOperandsString() and
|
||||
columnWidths(block, resultWidth, operationWidth) and
|
||||
result =
|
||||
resultString + getPaddingString(resultWidth - resultString.length()) + " = " +
|
||||
@@ -262,8 +252,7 @@ private class PrintableInstruction extends PrintableIRNode, TPrintableInstructio
|
||||
private string getOperandsString() {
|
||||
result =
|
||||
concat(Operand operand |
|
||||
operand = instr.getAnOperand() and
|
||||
shouldPrintOperand(operand)
|
||||
operand = instr.getAnOperand()
|
||||
|
|
||||
operand.getDumpString() + getOperandPropertyString(operand), ", "
|
||||
order by
|
||||
|
||||
@@ -7,19 +7,17 @@ private import internal.ValueNumberingImports
|
||||
class ValueNumber extends TValueNumber {
|
||||
final string toString() { result = "GVN" }
|
||||
|
||||
final string getDebugString() {
|
||||
result = strictconcat(this.getAnInstruction().getResultId(), ", ")
|
||||
}
|
||||
final string getDebugString() { result = strictconcat(getAnInstruction().getResultId(), ", ") }
|
||||
|
||||
final Language::Location getLocation() {
|
||||
if
|
||||
exists(Instruction i |
|
||||
i = this.getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
i = getAnInstruction() and not i.getLocation() instanceof Language::UnknownLocation
|
||||
)
|
||||
then
|
||||
result =
|
||||
min(Language::Location l |
|
||||
l = this.getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
l = getAnInstruction().getLocation() and not l instanceof Language::UnknownLocation
|
||||
|
|
||||
l
|
||||
order by
|
||||
@@ -42,7 +40,7 @@ class ValueNumber extends TValueNumber {
|
||||
final Instruction getExampleInstruction() {
|
||||
result =
|
||||
min(Instruction instr |
|
||||
instr = this.getAnInstruction()
|
||||
instr = getAnInstruction()
|
||||
|
|
||||
instr order by instr.getBlock().getDisplayIndex(), instr.getDisplayIndexInBlock()
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ private import AliasConfigurationImports
|
||||
class Allocation extends IRAutomaticVariable {
|
||||
VariableAddressInstruction getABaseInstruction() { result.getIRVariable() = this }
|
||||
|
||||
final string getAllocationString() { result = this.toString() }
|
||||
final string getAllocationString() { result = toString() }
|
||||
|
||||
predicate alwaysEscapes() {
|
||||
// An automatic variable only escapes if its address is taken and escapes.
|
||||
|
||||
@@ -422,6 +422,12 @@ private module Cached {
|
||||
)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
cached
|
||||
deprecated Language::AST getInstructionAST(Instruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
cached
|
||||
Language::LanguageType getInstructionResultType(Instruction instr) {
|
||||
result = instr.(RawIR::Instruction).getResultLanguageType()
|
||||
@@ -987,6 +993,9 @@ predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
||||
// We don't support reusing SSA for any location that could create a `Chi` instruction.
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsaForMemoryResult */
|
||||
deprecated predicate canReuseSSAForMemoryResult = canReuseSsaForMemoryResult/1;
|
||||
|
||||
/**
|
||||
* Expose some of the internal predicates to PrintSSA.qll. We do this by publicly importing those modules in the
|
||||
* `DebugSsa` module, which is then imported by PrintSSA.
|
||||
@@ -996,6 +1005,9 @@ module DebugSsa {
|
||||
import DefUse
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DebugSsa */
|
||||
deprecated module DebugSSA = DebugSsa;
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user