mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge branch 'main' into ruby/mad-prototype
This commit is contained in:
50
.github/workflows/check-qldoc.yml
vendored
Normal file
50
.github/workflows/check-qldoc.yml
vendored
Normal file
@@ -0,0 +1,50 @@
|
||||
name: "Check QLdoc coverage"
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "*/ql/lib/**"
|
||||
- .github/workflows/check-qldoc.yml
|
||||
branches:
|
||||
- main
|
||||
- "rc/*"
|
||||
|
||||
jobs:
|
||||
qldoc:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Install CodeQL
|
||||
run: |
|
||||
gh extension install github/gh-codeql
|
||||
gh codeql set-channel nightly
|
||||
gh codeql version
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ github.token }}
|
||||
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 2
|
||||
|
||||
- name: Check QLdoc coverage
|
||||
shell: bash
|
||||
run: |
|
||||
EXIT_CODE=0
|
||||
changed_lib_packs="$(git diff --name-only --diff-filter=ACMRT HEAD^ HEAD | { grep -o '^[a-z]*/ql/lib' || true; } | sort -u)"
|
||||
for pack_dir in ${changed_lib_packs}; do
|
||||
lang="${pack_dir%/ql/lib}"
|
||||
gh codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-current.txt" --dir="${pack_dir}"
|
||||
done
|
||||
git checkout HEAD^
|
||||
for pack_dir in ${changed_lib_packs}; do
|
||||
lang="${pack_dir%/ql/lib}"
|
||||
gh codeql generate library-doc-coverage --output="${RUNNER_TEMP}/${lang}-baseline.txt" --dir="${pack_dir}"
|
||||
awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-current.txt" | sort -u > "${RUNNER_TEMP}/current-undocumented.txt"
|
||||
awk -F, '{gsub(/"/,""); if ($4==0 && $6=="public") print "\""$3"\"" }' "${RUNNER_TEMP}/${lang}-baseline.txt" | sort -u > "${RUNNER_TEMP}/baseline-undocumented.txt"
|
||||
UNDOCUMENTED="$(grep -f <(comm -13 "${RUNNER_TEMP}/baseline-undocumented.txt" "${RUNNER_TEMP}/current-undocumented.txt") "${RUNNER_TEMP}/${lang}-current.txt" || true)"
|
||||
if [ -n "$UNDOCUMENTED" ]; then
|
||||
echo "$UNDOCUMENTED" | awk -F, '{gsub(/"/,""); print "::warning file='"${pack_dir}"'/"$1",line="$2"::Missing QLdoc for "$5, $3 }'
|
||||
EXIT_CODE=1
|
||||
fi
|
||||
done
|
||||
exit "${EXIT_CODE}"
|
||||
1
.github/workflows/ruby-qltest.yml
vendored
1
.github/workflows/ruby-qltest.yml
vendored
@@ -63,6 +63,7 @@ jobs:
|
||||
qltest:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
slice: ["1/2", "2/2"]
|
||||
steps:
|
||||
|
||||
29
.pre-commit-config.yaml
Normal file
29
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,29 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
exclude: /test/.*$(?<!\.ql)(?<!\.qll)(?<!\.qlref)
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v3.2.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: codeql-format
|
||||
name: Fix QL file formatting
|
||||
files: \.qll?$
|
||||
language: system
|
||||
entry: codeql query format --in-place
|
||||
|
||||
- id: sync-files
|
||||
name: Fix files required to be identical
|
||||
language: system
|
||||
entry: python3 config/sync-files.py --latest
|
||||
pass_filenames: false
|
||||
|
||||
- id: qhelp
|
||||
name: Check query help generation
|
||||
files: \.qhelp$
|
||||
language: system
|
||||
entry: python3 misc/scripts/check-qhelp.py
|
||||
@@ -42,7 +42,11 @@ If you have an idea for a query that you would like to share with other CodeQL u
|
||||
|
||||
- The queries and libraries must be autoformatted, for example using the "Format Document" command in [CodeQL for Visual Studio Code](https://help.semmle.com/codeql/codeql-for-vscode/procedures/about-codeql-for-vscode.html).
|
||||
|
||||
If you prefer, you can use this [pre-commit hook](misc/scripts/pre-commit) that automatically checks whether your files are correctly formatted. See the [pre-commit hook installation guide](docs/pre-commit-hook-setup.md) for instructions on how to install the hook.
|
||||
If you prefer, you can either:
|
||||
1. install the [pre-commit framework](https://pre-commit.com/) and install the configured hooks on this repo via `pre-commit install`, or
|
||||
2. use this [pre-commit hook](misc/scripts/pre-commit) that automatically checks whether your files are correctly formatted.
|
||||
|
||||
See the [pre-commit hook installation guide](docs/pre-commit-hook-setup.md) for instructions on the two approaches.
|
||||
|
||||
4. **Compilation**
|
||||
|
||||
@@ -63,6 +67,6 @@ After the experimental query is merged, we welcome pull requests to improve it.
|
||||
|
||||
## Using your personal data
|
||||
|
||||
If you contribute to this project, we will record your name and email address (as provided by you with your contributions) as part of the code repositories, which are public. We might also use this information to contact you in relation to your contributions, as well as in the normal course of software development. We also store records of CLA agreements signed in the past, but no longer require contributors to sign a CLA. Under GDPR legislation, we do this on the basis of our legitimate interest in creating the CodeQL product.
|
||||
If you contribute to this project, we will record your name and email address (as provided by you with your contributions) as part of the code repositories, which are public. We might also use this information to contact you in relation to your contributions, as well as in the normal course of software development. We also store records of CLA agreements signed in the past, but no longer require contributors to sign a CLA. Under GDPR legislation, we do this on the basis of our legitimate interest in creating the CodeQL product.
|
||||
|
||||
Please do get in touch (privacy@github.com) if you have any questions about this or our data protection policies.
|
||||
|
||||
58
config/blame-deprecations.mjs
Normal file
58
config/blame-deprecations.mjs
Normal file
@@ -0,0 +1,58 @@
|
||||
import fs from "fs";
|
||||
import path from "path";
|
||||
import cp from "child_process";
|
||||
function* walk(dir) {
|
||||
for (const file of fs.readdirSync(dir)) {
|
||||
const filePath = path.join(dir, file);
|
||||
if (fs.statSync(filePath).isDirectory()) {
|
||||
yield* walk(filePath);
|
||||
} else {
|
||||
yield filePath;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function* deprecatedFiles(dir) {
|
||||
for (const file of walk(dir)) {
|
||||
if (file.endsWith(".ql") || file.endsWith(".qll")) {
|
||||
const contents = fs.readFileSync(file, "utf8");
|
||||
if (/\sdeprecated\s/.test(contents)) {
|
||||
yield file;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const blameRegExp =
|
||||
/^(\^?\w+)\s.+\s+(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} (?:\+|-)\d{4})\s+(\d+)\).*$/;
|
||||
|
||||
function* deprecationMessages(dir) {
|
||||
for (const file of deprecatedFiles(dir)) {
|
||||
const blame = cp.execFileSync("git", ["blame", "--", file]);
|
||||
const lines = blame.toString().split("\n");
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (line.includes(" deprecated ")) {
|
||||
try {
|
||||
const [_, sha, time, lineNumber] = line.match(blameRegExp);
|
||||
const date = new Date(time);
|
||||
// check if it's within the last 14 months (a year, plus 2 months for safety, in case a PR was delayed)
|
||||
if (date.getTime() >= Date.now() - 14 * 31 * 24 * 60 * 60 * 1000) {
|
||||
continue;
|
||||
}
|
||||
const message = `${file}:${lineNumber} was last updated on ${date.getFullYear()}-${date.getMonth()}-${date.getDate()}`;
|
||||
yield [message, date];
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
console.log("----");
|
||||
console.log(line);
|
||||
console.log("----");
|
||||
process.exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
[...deprecationMessages(".")]
|
||||
.sort((a, b) => a[1].getTime() - b[1].getTime())
|
||||
.forEach((msg) => console.log(msg[0]));
|
||||
@@ -73,6 +73,14 @@
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/SsaReadPositionCommon.qll"
|
||||
],
|
||||
"Model as Data Generation Java/C# - Utils": [
|
||||
"java/ql/src/utils/model-generator/ModelGeneratorUtils.qll",
|
||||
"csharp/ql/src/utils/model-generator/ModelGeneratorUtils.qll"
|
||||
],
|
||||
"Model as Data Generation Java/C# - SummaryModels": [
|
||||
"java/ql/src/utils/model-generator/CaptureSummaryModels.qll",
|
||||
"csharp/ql/src/utils/model-generator/CaptureSummaryModels.qll"
|
||||
],
|
||||
"Sign Java/C#": [
|
||||
"java/ql/lib/semmle/code/java/dataflow/internal/rangeanalysis/Sign.qll",
|
||||
"csharp/ql/lib/semmle/code/csharp/dataflow/internal/rangeanalysis/Sign.qll"
|
||||
@@ -426,7 +434,6 @@
|
||||
"python/ql/src/Lexical/CommentedOutCodeMetricOverview.inc.qhelp"
|
||||
],
|
||||
"FLinesOfDuplicatedCodeCommon.inc.qhelp": [
|
||||
"cpp/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.inc.qhelp",
|
||||
"java/ql/src/Metrics/Files/FLinesOfDuplicatedCodeCommon.inc.qhelp",
|
||||
"javascript/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.inc.qhelp",
|
||||
"python/ql/src/Metrics/FLinesOfDuplicatedCodeCommon.inc.qhelp"
|
||||
@@ -513,4 +520,4 @@
|
||||
"javascript/ql/lib/semmle/javascript/frameworks/data/internal/ApiGraphModels.qll",
|
||||
"ruby/ql/lib/codeql/ruby/frameworks/data/internal/ApiGraphModels.qll"
|
||||
]
|
||||
}
|
||||
}
|
||||
2096
cpp/downgrades/e9a518baf14f4322ac243578a8e1391386ff030f/old.dbscheme
Normal file
2096
cpp/downgrades/e9a518baf14f4322ac243578a8e1391386ff030f/old.dbscheme
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Remove uniqueness constraint from the uuid property
|
||||
compatibility: full
|
||||
@@ -1,5 +1,18 @@
|
||||
## 0.0.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Many queries now support structured bindings, as structured bindings are now handled in the IR translation.
|
||||
|
||||
## 0.0.10
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a `isStructuredBinding` predicate to the `Variable` class which holds when the variable is declared as part of a structured binding declaration.
|
||||
|
||||
## 0.0.9
|
||||
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Deprecated APIs
|
||||
|
||||
@@ -54,11 +54,13 @@ class Options extends string {
|
||||
*
|
||||
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
|
||||
* `longjmp`, `__builtin_unreachable` and any function with a
|
||||
* `noreturn` attribute.
|
||||
* `noreturn` attribute or specifier.
|
||||
*/
|
||||
predicate exits(Function f) {
|
||||
f.getAnAttribute().hasName("noreturn")
|
||||
or
|
||||
f.getASpecifier().hasName("noreturn")
|
||||
or
|
||||
f.hasGlobalOrStdName([
|
||||
"exit", "_exit", "abort", "__assert_fail", "longjmp", "__builtin_unreachable"
|
||||
])
|
||||
|
||||
@@ -39,7 +39,7 @@ class CustomOptions extends Options {
|
||||
*
|
||||
* By default, this holds for `exit`, `_exit`, `abort`, `__assert_fail`,
|
||||
* `longjmp`, `error`, `__builtin_unreachable` and any function with a
|
||||
* `noreturn` attribute.
|
||||
* `noreturn` attribute or specifier.
|
||||
*/
|
||||
override predicate exits(Function f) { Options.super.exits(f) }
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* All deprecated predicates/classes/modules that have been deprecated for over a year have been deleted.
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: deprecated
|
||||
---
|
||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||
The old name still exists as a deprecated alias.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `hasImplicitCopyConstructor` and `hasImplicitCopyAssignmentOperator` now correctly handle implicitly-deleted operators in templates.
|
||||
4
cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md
Normal file
4
cpp/ql/lib/change-notes/2022-03-14-c11-noreturn.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* `DefaultOptions::exits` now holds for C11 functions with the `_Noreturn` or `noreturn` specifier.
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* The flow state variants of `isBarrier` and `isAdditionalFlowStep` are no longer exposed in the taint tracking library. The `isSanitizer` and `isAdditionalTaintStep` predicates should be used instead.
|
||||
@@ -1,4 +1,5 @@
|
||||
---
|
||||
category: feature
|
||||
---
|
||||
## 0.0.10
|
||||
|
||||
### New Features
|
||||
|
||||
* Added a `isStructuredBinding` predicate to the `Variable` class which holds when the variable is declared as part of a structured binding declaration.
|
||||
5
cpp/ql/lib/change-notes/released/0.0.11.md
Normal file
5
cpp/ql/lib/change-notes/released/0.0.11.md
Normal file
@@ -0,0 +1,5 @@
|
||||
## 0.0.11
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Many queries now support structured bindings, as structured bindings are now handled in the IR translation.
|
||||
@@ -1,2 +1,2 @@
|
||||
---
|
||||
lastReleaseVersion: 0.0.9
|
||||
lastReleaseVersion: 0.0.11
|
||||
|
||||
@@ -69,6 +69,4 @@ import semmle.code.cpp.Comments
|
||||
import semmle.code.cpp.Preprocessor
|
||||
import semmle.code.cpp.Iteration
|
||||
import semmle.code.cpp.NameQualifiers
|
||||
import semmle.code.cpp.ObjectiveC
|
||||
import semmle.code.cpp.exprs.ObjectiveC
|
||||
import DefaultOptions
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: codeql/cpp-all
|
||||
version: 0.0.10-dev
|
||||
version: 0.0.12-dev
|
||||
groups: cpp
|
||||
dbscheme: semmlecode.cpp.dbscheme
|
||||
extractor: cpp
|
||||
|
||||
@@ -111,24 +111,6 @@ class Class extends UserType {
|
||||
result = this.getCanonicalMember(index).(TemplateVariable).getAnInstantiation()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getCanonicalMember(int)` or `getAMember(int)` instead.
|
||||
* Gets the `index`th member of this class.
|
||||
*/
|
||||
deprecated Declaration getMember(int index) {
|
||||
member(underlyingElement(this), index, unresolveElement(result))
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: As this includes a somewhat arbitrary number of
|
||||
* template instantiations, it is unlikely to do what
|
||||
* you need.
|
||||
* Gets the number of members that this class has. This includes both
|
||||
* templates that are in this class, and instantiations of those
|
||||
* templates.
|
||||
*/
|
||||
deprecated int getNumMember() { result = count(this.getAMember()) }
|
||||
|
||||
/**
|
||||
* Gets a private member declared in this class, struct or union.
|
||||
* For template members, this may be either the template or an
|
||||
@@ -208,23 +190,6 @@ class Class extends UserType {
|
||||
*/
|
||||
deprecated predicate hasCopyConstructor() { this.getAMemberFunction() instanceof CopyConstructor }
|
||||
|
||||
/**
|
||||
* Holds if this class has a copy assignment operator 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 assignment operator, and we do not want to promote one
|
||||
* particular definition by naming it with this predicate. Having a copy
|
||||
* assignment operator 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 hasCopyAssignmentOperator() {
|
||||
this.getAMemberFunction() instanceof CopyAssignmentOperator
|
||||
}
|
||||
|
||||
/**
|
||||
* Like accessOfBaseMember but returns multiple results if there are multiple
|
||||
* paths to `base` through the inheritance graph.
|
||||
@@ -286,6 +251,16 @@ class Class extends UserType {
|
||||
not this.implicitCopyConstructorDeleted() and
|
||||
forall(CopyConstructor cc | cc = this.getAMemberFunction() |
|
||||
cc.isCompilerGenerated() and not cc.isDeleted()
|
||||
) and
|
||||
(
|
||||
not this instanceof ClassTemplateInstantiation
|
||||
or
|
||||
this.(ClassTemplateInstantiation).getTemplate().hasImplicitCopyConstructor()
|
||||
) and
|
||||
(
|
||||
not this instanceof PartialClassTemplateSpecialization
|
||||
or
|
||||
this.(PartialClassTemplateSpecialization).getPrimaryTemplate().hasImplicitCopyConstructor()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -301,6 +276,18 @@ class Class extends UserType {
|
||||
not this.implicitCopyAssignmentOperatorDeleted() and
|
||||
forall(CopyAssignmentOperator ca | ca = this.getAMemberFunction() |
|
||||
ca.isCompilerGenerated() and not ca.isDeleted()
|
||||
) and
|
||||
(
|
||||
not this instanceof ClassTemplateInstantiation
|
||||
or
|
||||
this.(ClassTemplateInstantiation).getTemplate().hasImplicitCopyAssignmentOperator()
|
||||
) and
|
||||
(
|
||||
not this instanceof PartialClassTemplateSpecialization
|
||||
or
|
||||
this.(PartialClassTemplateSpecialization)
|
||||
.getPrimaryTemplate()
|
||||
.hasImplicitCopyAssignmentOperator()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1070,31 +1057,6 @@ class PartialClassTemplateSpecialization extends ClassTemplateSpecialization {
|
||||
override string getAPrimaryQlClass() { result = "PartialClassTemplateSpecialization" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An "interface" is a class that only contains pure virtual functions (and contains
|
||||
* at least one such function). For example:
|
||||
* ```
|
||||
* class MyInterfaceClass {
|
||||
* public:
|
||||
* virtual void myMethod1() = 0;
|
||||
* virtual void myMethod2() = 0;
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* DEPRECATED: This class is considered to be too specific for general usage.
|
||||
*/
|
||||
deprecated class Interface extends Class {
|
||||
Interface() {
|
||||
forex(Declaration m |
|
||||
m.getDeclaringType() = this.getABaseClass*() and not compgenerated(unresolveElement(m))
|
||||
|
|
||||
m instanceof PureVirtualFunction
|
||||
)
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Interface" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A class/struct derivation that is virtual. For example the derivation in
|
||||
* the following code is a `VirtualClassDerivation`:
|
||||
|
||||
@@ -55,9 +55,6 @@ class ElementBase extends @element {
|
||||
cached
|
||||
string toString() { none() }
|
||||
|
||||
/** DEPRECATED: use `getAPrimaryQlClass` instead. */
|
||||
deprecated string getCanonicalQLClass() { result = this.getAPrimaryQlClass() }
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
|
||||
*/
|
||||
@@ -91,13 +88,6 @@ class Element extends ElementBase {
|
||||
*/
|
||||
predicate fromSource() { this.getFile().fromSource() }
|
||||
|
||||
/**
|
||||
* Holds if this element may be from a library.
|
||||
*
|
||||
* DEPRECATED: always true.
|
||||
*/
|
||||
deprecated predicate fromLibrary() { this.getFile().fromLibrary() }
|
||||
|
||||
/** Gets the primary location of this element. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
|
||||
@@ -196,31 +196,11 @@ class Folder extends Container, @folder {
|
||||
*/
|
||||
deprecated string getName() { folders(underlyingElement(this), result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAbsolutePath` instead.
|
||||
* Holds if this element is named `name`.
|
||||
*/
|
||||
deprecated predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAbsolutePath` instead.
|
||||
* Gets the full name of this folder.
|
||||
*/
|
||||
deprecated string getFullName() { result = this.getName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getBaseName` instead.
|
||||
* Gets the last part of the folder name.
|
||||
*/
|
||||
deprecated string getShortName() { result = this.getBaseName() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getParentContainer` instead.
|
||||
* Gets the parent folder.
|
||||
*/
|
||||
deprecated Folder getParent() {
|
||||
containerparent(unresolveElement(result), underlyingElement(this))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -308,13 +288,6 @@ class File extends Container, @file {
|
||||
*/
|
||||
override predicate fromSource() { numlines(underlyingElement(this), _, _, _) }
|
||||
|
||||
/**
|
||||
* Holds if this file may be from a library.
|
||||
*
|
||||
* DEPRECATED: For historical reasons this is true for any file.
|
||||
*/
|
||||
deprecated override predicate fromLibrary() { any() }
|
||||
|
||||
/** Gets the metric file. */
|
||||
MetricFile getMetrics() { result = this }
|
||||
|
||||
@@ -428,25 +401,3 @@ class CppFile extends File {
|
||||
|
||||
override string getAPrimaryQlClass() { result = "CppFile" }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C source file, as determined by file extension.
|
||||
*
|
||||
* For the related notion of whether a file is compiled as Objective C
|
||||
* code, use `File.compiledAsObjC`.
|
||||
*/
|
||||
deprecated class ObjCFile extends File {
|
||||
ObjCFile() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C++ source file, as determined by file extension.
|
||||
*
|
||||
* For the related notion of whether a file is compiled as Objective C++
|
||||
* code, use `File.compiledAsObjCpp`.
|
||||
*/
|
||||
deprecated class ObjCppFile extends File {
|
||||
ObjCppFile() { none() }
|
||||
}
|
||||
|
||||
@@ -105,25 +105,6 @@ class Location extends @location {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `Location` instead.
|
||||
* A location of an element. Not used for expressions or statements, which
|
||||
* instead use LocationExpr and LocationStmt respectively.
|
||||
*/
|
||||
deprecated library class LocationDefault extends Location, @location_default { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `Location` instead.
|
||||
* A location of a statement.
|
||||
*/
|
||||
deprecated library class LocationStmt extends Location, @location_stmt { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `Location` instead.
|
||||
* A location of an expression.
|
||||
*/
|
||||
deprecated library class LocationExpr extends Location, @location_expr { }
|
||||
|
||||
/**
|
||||
* Gets the length of the longest line in file `f`.
|
||||
*/
|
||||
|
||||
@@ -30,16 +30,6 @@ class Macro extends PreprocessorDirective, @ppd_define {
|
||||
else result = "#define " + this.getHead() + " " + this.getBody()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the body of the macro starts with an unmatched closing
|
||||
* parenthesis. For example:
|
||||
*
|
||||
* #define RPAREN() )
|
||||
*
|
||||
* DEPRECATED: This predicate has a misleading name.
|
||||
*/
|
||||
deprecated predicate isFunctionLike() { this.getBody().regexpMatch("[^(]*\\).*") }
|
||||
|
||||
/**
|
||||
* Gets the name of the macro. For example, `MAX` in
|
||||
* `#define MAX(x,y) (((x)>(y))?(x):(y))`.
|
||||
@@ -261,46 +251,6 @@ class MacroInvocation extends MacroAccess {
|
||||
string getExpandedArgument(int i) { macro_argument_expanded(underlyingElement(this), i, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A top-level expression generated by a macro invocation.
|
||||
*
|
||||
* DEPRECATED: Use `MacroInvocation.getExpr()` directly to get an
|
||||
* expression generated at the top-level of a macro invocation. Use
|
||||
* `MacroInvocation.getAnAffectedElement()` to get any element generated
|
||||
* by a macro invocation.
|
||||
*/
|
||||
deprecated class MacroInvocationExpr extends Expr {
|
||||
MacroInvocationExpr() { exists(MacroInvocation i | this = i.getExpr()) }
|
||||
|
||||
/**
|
||||
* Gets the macro invocation of which this is the top-level expression.
|
||||
*/
|
||||
MacroInvocation getInvocation() { result.getExpr() = this }
|
||||
|
||||
/** Gets the name of the invoked macro. */
|
||||
string getMacroName() { result = this.getInvocation().getMacroName() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A top-level statement generated by a macro invocation.
|
||||
*
|
||||
* DEPRECATED: Use `MacroInvocation.getStmt()` directly to get a
|
||||
* statement generated at the top-level of a macro invocation. Use
|
||||
* `MacroInvocation.getAnAffectedElement()` to get any element generated
|
||||
* by a macro invocation.
|
||||
*/
|
||||
deprecated class MacroInvocationStmt extends Stmt {
|
||||
MacroInvocationStmt() { exists(MacroInvocation i | this = i.getStmt()) }
|
||||
|
||||
/**
|
||||
* Gets the macro invocation of which this is the top-level statement.
|
||||
*/
|
||||
MacroInvocation getInvocation() { result.getStmt() = this }
|
||||
|
||||
/** Gets the name of the invoked macro. */
|
||||
string getMacroName() { result = this.getInvocation().getMacroName() }
|
||||
}
|
||||
|
||||
/** Holds if `l` is the location of a macro. */
|
||||
predicate macroLocation(Location l) { macrolocationbind(_, l) }
|
||||
|
||||
|
||||
@@ -233,40 +233,6 @@ class ImplicitConversionFunction extends MemberFunction {
|
||||
Type getDestType() { none() } // overridden in subclasses
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: as of C++11 this class does not correspond perfectly with the
|
||||
* language definition of a converting constructor.
|
||||
*
|
||||
* A C++ constructor that also defines an implicit conversion. For example the
|
||||
* function `MyClass` in the following code is a `ConversionConstructor`:
|
||||
* ```
|
||||
* class MyClass {
|
||||
* public:
|
||||
* MyClass(const MyOtherClass &from) {
|
||||
* ...
|
||||
* }
|
||||
* };
|
||||
* ```
|
||||
*/
|
||||
deprecated class ConversionConstructor extends Constructor, ImplicitConversionFunction {
|
||||
ConversionConstructor() {
|
||||
strictcount(Parameter p | p = this.getAParameter() and not p.hasInitializer()) = 1 and
|
||||
not this.hasSpecifier("explicit")
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() {
|
||||
not this instanceof CopyConstructor and
|
||||
not this instanceof MoveConstructor and
|
||||
result = "ConversionConstructor"
|
||||
}
|
||||
|
||||
/** Gets the type this `ConversionConstructor` takes as input. */
|
||||
override Type getSourceType() { result = this.getParameter(0).getType() }
|
||||
|
||||
/** Gets the type this `ConversionConstructor` is a constructor of. */
|
||||
override Type getDestType() { result = this.getDeclaringType() }
|
||||
}
|
||||
|
||||
private predicate hasCopySignature(MemberFunction f) {
|
||||
f.getParameter(0).getUnspecifiedType().(LValueReferenceType).getBaseType() = f.getDeclaringType()
|
||||
}
|
||||
|
||||
@@ -86,13 +86,6 @@ class Namespace extends NameQualifyingElement, @namespace {
|
||||
/** Holds if this namespace may be from source. */
|
||||
override predicate fromSource() { this.getADeclaration().fromSource() }
|
||||
|
||||
/**
|
||||
* Holds if this namespace is in a library.
|
||||
*
|
||||
* DEPRECATED: never holds.
|
||||
*/
|
||||
deprecated override predicate fromLibrary() { not this.fromSource() }
|
||||
|
||||
/** Gets the metric namespace. */
|
||||
MetricNamespace getMetrics() { result = this }
|
||||
|
||||
@@ -233,11 +226,6 @@ class GlobalNamespace extends Namespace {
|
||||
|
||||
override Namespace getParentNamespace() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getName()`.
|
||||
*/
|
||||
deprecated string getFullName() { result = this.getName() }
|
||||
|
||||
override string getFriendlyName() { result = "(global namespace)" }
|
||||
}
|
||||
|
||||
|
||||
@@ -1,196 +0,0 @@
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Class
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C class.
|
||||
*/
|
||||
deprecated class ObjectiveClass extends Class {
|
||||
ObjectiveClass() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C protocol.
|
||||
*/
|
||||
deprecated class Protocol extends Class {
|
||||
Protocol() { none() }
|
||||
|
||||
/**
|
||||
* Holds if the type implements the protocol, either because the type
|
||||
* itself does, or because it is a type conforming to the protocol.
|
||||
*/
|
||||
predicate isImplementedBy(Type t) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* A type which conforms to a protocol. Use `getAProtocol` to get a
|
||||
* protocol that this type conforms to.
|
||||
*/
|
||||
deprecated class TypeConformingToProtocol extends DerivedType {
|
||||
TypeConformingToProtocol() { none() }
|
||||
|
||||
/** Gets a protocol that this type conforms to. */
|
||||
Protocol getAProtocol() { none() }
|
||||
|
||||
/** Gets the size of this type. */
|
||||
override int getSize() { none() }
|
||||
|
||||
override int getAlignment() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@autoreleasepool` statement, for example
|
||||
* `@autoreleasepool { int x; int y; }`.
|
||||
*/
|
||||
deprecated class AutoReleasePoolStmt extends Stmt {
|
||||
AutoReleasePoolStmt() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/** Gets the body statement of this `@autoreleasepool` statement. */
|
||||
Stmt getStmt() { none() }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
override predicate mayBeGloballyImpure() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@synchronized statement`, for example
|
||||
* `@synchronized (x) { [x complicationOperation]; }`.
|
||||
*/
|
||||
deprecated class SynchronizedStmt extends Stmt {
|
||||
SynchronizedStmt() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/** Gets the expression which gives the object to be locked. */
|
||||
Expr getLockedObject() { none() }
|
||||
|
||||
/** Gets the body statement of this `@synchronized` statement. */
|
||||
Stmt getStmt() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C for-in statement.
|
||||
*/
|
||||
deprecated class ForInStmt extends Loop {
|
||||
ForInStmt() { none() }
|
||||
|
||||
/**
|
||||
* Gets the condition expression of the `while` statement that the
|
||||
* `for...in` statement desugars into.
|
||||
*/
|
||||
override Expr getCondition() { none() }
|
||||
|
||||
override Expr getControllingExpr() { none() }
|
||||
|
||||
/** Gets the collection that the loop iterates over. */
|
||||
Expr getCollection() { none() }
|
||||
|
||||
/** Gets the body of the loop. */
|
||||
override Stmt getStmt() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C category or class extension.
|
||||
*/
|
||||
deprecated class Category extends Class {
|
||||
Category() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C class extension.
|
||||
*/
|
||||
deprecated class ClassExtension extends Category {
|
||||
ClassExtension() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C try statement.
|
||||
*/
|
||||
deprecated class ObjcTryStmt extends TryStmt {
|
||||
ObjcTryStmt() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/** Gets the finally clause of this try statement, if any. */
|
||||
FinallyBlock getFinallyClause() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@finally` block.
|
||||
*/
|
||||
deprecated class FinallyBlock extends BlockStmt {
|
||||
FinallyBlock() { none() }
|
||||
|
||||
/** Gets the try statement corresponding to this finally block. */
|
||||
ObjcTryStmt getTryStmt() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@property`.
|
||||
*/
|
||||
deprecated class Property extends Declaration {
|
||||
Property() { none() }
|
||||
|
||||
/** Gets the name of this property. */
|
||||
override string getName() { none() }
|
||||
|
||||
/**
|
||||
* Gets nothing (provided for compatibility with Declaration).
|
||||
*
|
||||
* For the attribute list following the `@property` keyword, use
|
||||
* `getAnAttribute()`.
|
||||
*/
|
||||
override Specifier getASpecifier() { none() }
|
||||
|
||||
/**
|
||||
* Gets an attribute of this property (such as `readonly`, `nonatomic`,
|
||||
* or `getter=isEnabled`).
|
||||
*/
|
||||
Attribute getAnAttribute() { none() }
|
||||
|
||||
override Location getADeclarationLocation() { result = getLocation() }
|
||||
|
||||
override Location getDefinitionLocation() { result = getLocation() }
|
||||
|
||||
override Location getLocation() { none() }
|
||||
|
||||
/** Gets the type of this property. */
|
||||
Type getType() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instance method which is called to get the value of this
|
||||
* property.
|
||||
*/
|
||||
MemberFunction getGetter() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instance method which is called to set the value of this
|
||||
* property (if it is a writable property).
|
||||
*/
|
||||
MemberFunction getSetter() { none() }
|
||||
|
||||
/**
|
||||
* Gets the instance variable which stores the property value (if this
|
||||
* property was explicitly or automatically `@synthesize`d).
|
||||
*/
|
||||
MemberVariable getInstanceVariable() { none() }
|
||||
}
|
||||
@@ -95,22 +95,6 @@ class Parameter extends LocalScopeVariable, @parameter {
|
||||
else result = this.getADeclarationEntry()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of this parameter in the given block (which should be
|
||||
* the body of a function with which the parameter is associated).
|
||||
*
|
||||
* DEPRECATED: this method was used in a previous implementation of
|
||||
* getName, but is no longer in use.
|
||||
*/
|
||||
deprecated string getNameInBlock(BlockStmt b) {
|
||||
exists(ParameterDeclarationEntry pde |
|
||||
pde.getFunctionDeclarationEntry().getBlock() = b and
|
||||
this.getFunction().getBlock() = b and
|
||||
pde.getVariable() = this and
|
||||
result = pde.getName()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this parameter has a name.
|
||||
*
|
||||
|
||||
@@ -8,9 +8,9 @@ private import PrintAST
|
||||
private predicate shouldPrintDeclaration(Declaration decl) {
|
||||
not decl instanceof Function
|
||||
or
|
||||
not exists(PrintASTConfiguration c)
|
||||
not exists(PrintAstConfiguration c)
|
||||
or
|
||||
exists(PrintASTConfiguration config | config.shouldPrintFunction(decl))
|
||||
exists(PrintAstConfiguration config | config.shouldPrintFunction(decl))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,7 +12,7 @@ import PrintAST
|
||||
* Temporarily tweak this class or make a copy to control which functions are
|
||||
* printed.
|
||||
*/
|
||||
class Cfg extends PrintASTConfiguration {
|
||||
class Cfg extends PrintAstConfiguration {
|
||||
/**
|
||||
* TWEAK THIS PREDICATE AS NEEDED.
|
||||
* Holds if the AST for `func` should be printed.
|
||||
|
||||
@@ -9,12 +9,12 @@
|
||||
import cpp
|
||||
private import semmle.code.cpp.Print
|
||||
|
||||
private newtype TPrintASTConfiguration = MkPrintASTConfiguration()
|
||||
private newtype TPrintAstConfiguration = MkPrintAstConfiguration()
|
||||
|
||||
/**
|
||||
* The query can extend this class to control which functions are printed.
|
||||
*/
|
||||
class PrintASTConfiguration extends TPrintASTConfiguration {
|
||||
class PrintAstConfiguration extends TPrintAstConfiguration {
|
||||
/**
|
||||
* Gets a textual representation of this `PrintASTConfiguration`.
|
||||
*/
|
||||
@@ -27,8 +27,11 @@ 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))
|
||||
exists(PrintAstConfiguration config | config.shouldPrintFunction(func))
|
||||
}
|
||||
|
||||
bindingset[s]
|
||||
@@ -85,8 +88,8 @@ private Function getEnclosingFunction(Locatable ast) {
|
||||
* Most nodes are just a wrapper around `Locatable`, but we do synthesize new
|
||||
* nodes for things like parameter lists and constructor init lists.
|
||||
*/
|
||||
private newtype TPrintASTNode =
|
||||
TASTNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or
|
||||
private newtype TPrintAstNode =
|
||||
TAstNode(Locatable ast) { shouldPrintFunction(getEnclosingFunction(ast)) } or
|
||||
TDeclarationEntryNode(DeclStmt stmt, DeclarationEntry entry) {
|
||||
// We create a unique node for each pair of (stmt, entry), to avoid having one node with
|
||||
// multiple parents due to extractor bug CPP-413.
|
||||
@@ -106,7 +109,7 @@ private newtype TPrintASTNode =
|
||||
/**
|
||||
* A node in the output tree.
|
||||
*/
|
||||
class PrintASTNode extends TPrintASTNode {
|
||||
class PrintAstNode extends TPrintAstNode {
|
||||
/**
|
||||
* Gets a textual representation of this node in the PrintAST output tree.
|
||||
*/
|
||||
@@ -116,17 +119,17 @@ class PrintASTNode extends TPrintASTNode {
|
||||
* Gets the child node at index `childIndex`. Child indices must be unique,
|
||||
* but need not be contiguous.
|
||||
*/
|
||||
abstract PrintASTNode getChildInternal(int childIndex);
|
||||
abstract PrintAstNode getChildInternal(int childIndex);
|
||||
|
||||
/**
|
||||
* Gets the child node at index `childIndex`.
|
||||
* Adds edges to fully converted expressions, that are not part of the
|
||||
* regular parent/child relation traversal.
|
||||
*/
|
||||
final PrintASTNode getChild(int childIndex) {
|
||||
final PrintAstNode getChild(int childIndex) {
|
||||
// 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 |
|
||||
rank[childIndex](PrintAstNode child, int nonConvertedIndex, boolean isConverted |
|
||||
childAndAccessorPredicate(child, _, nonConvertedIndex, isConverted)
|
||||
|
|
||||
// Unconverted children come first, then sort by original child index within each group.
|
||||
@@ -138,11 +141,11 @@ class PrintASTNode extends TPrintASTNode {
|
||||
* Gets the node for the `.getFullyConverted()` version of the child originally at index
|
||||
* `childIndex`, if that node has any conversions.
|
||||
*/
|
||||
private PrintASTNode getConvertedChild(int childIndex) {
|
||||
private PrintAstNode getConvertedChild(int childIndex) {
|
||||
exists(Expr expr |
|
||||
expr = getChildInternal(childIndex).(ASTNode).getAST() and
|
||||
expr = getChildInternal(childIndex).(AstNode).getAst() and
|
||||
expr.getFullyConverted() instanceof Conversion and
|
||||
result.(ASTNode).getAST() = expr.getFullyConverted() and
|
||||
result.(AstNode).getAst() = expr.getFullyConverted() and
|
||||
not expr instanceof Conversion
|
||||
)
|
||||
}
|
||||
@@ -166,12 +169,12 @@ class PrintASTNode extends TPrintASTNode {
|
||||
/**
|
||||
* Gets the children of this node.
|
||||
*/
|
||||
final PrintASTNode getAChild() { result = getChild(_) }
|
||||
final PrintAstNode getAChild() { result = getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the parent of this node, if any.
|
||||
*/
|
||||
final PrintASTNode getParent() { result.getAChild() = this }
|
||||
final PrintAstNode getParent() { result.getAChild() = this }
|
||||
|
||||
/**
|
||||
* Gets the location of this node in the source code.
|
||||
@@ -196,7 +199,7 @@ class PrintASTNode extends TPrintASTNode {
|
||||
* one result tuple, with `isConverted = false`.
|
||||
*/
|
||||
private predicate childAndAccessorPredicate(
|
||||
PrintASTNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
|
||||
PrintAstNode child, string childPredicate, int nonConvertedIndex, boolean isConverted
|
||||
) {
|
||||
child = getChildInternal(nonConvertedIndex) and
|
||||
childPredicate = getChildAccessorPredicateInternal(nonConvertedIndex) and
|
||||
@@ -234,12 +237,15 @@ class PrintASTNode extends TPrintASTNode {
|
||||
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.
|
||||
*/
|
||||
private class PrintableElement extends Element {
|
||||
PrintableElement() {
|
||||
exists(TASTNode(this))
|
||||
exists(TAstNode(this))
|
||||
or
|
||||
exists(TDeclarationEntryNode(_, this))
|
||||
or
|
||||
@@ -262,7 +268,7 @@ private string qlClass(PrintableElement el) {
|
||||
/**
|
||||
* A node representing an AST node.
|
||||
*/
|
||||
abstract class BaseASTNode extends PrintASTNode {
|
||||
abstract class BaseAstNode extends PrintAstNode {
|
||||
Locatable ast;
|
||||
|
||||
override string toString() { result = qlClass(ast) + ast.toString() }
|
||||
@@ -272,25 +278,34 @@ abstract class BaseASTNode extends PrintASTNode {
|
||||
/**
|
||||
* Gets the AST represented by this node.
|
||||
*/
|
||||
final Locatable getAST() { result = ast }
|
||||
final Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for BaseAstNode */
|
||||
deprecated class BaseASTNode = BaseAstNode;
|
||||
|
||||
/**
|
||||
* A node representing an AST node other than a `DeclarationEntry`.
|
||||
*/
|
||||
abstract class ASTNode extends BaseASTNode, TASTNode {
|
||||
ASTNode() { this = TASTNode(ast) }
|
||||
abstract class AstNode extends BaseAstNode, TAstNode {
|
||||
AstNode() { this = TAstNode(ast) }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AstNode */
|
||||
deprecated class ASTNode = AstNode;
|
||||
|
||||
/**
|
||||
* A node representing an `Expr`.
|
||||
*/
|
||||
class ExprNode extends ASTNode {
|
||||
class ExprNode extends AstNode {
|
||||
Expr expr;
|
||||
|
||||
ExprNode() { expr = ast }
|
||||
|
||||
override ASTNode getChildInternal(int childIndex) { result.getAST() = expr.getChild(childIndex) }
|
||||
override AstNode getChildInternal(int childIndex) { result.getAst() = expr.getChild(childIndex) }
|
||||
|
||||
override string getProperty(string key) {
|
||||
result = super.getProperty(key)
|
||||
@@ -306,7 +321,7 @@ class ExprNode extends ASTNode {
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAST())
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,9 +349,9 @@ class ConversionNode extends ExprNode {
|
||||
|
||||
ConversionNode() { conv = expr }
|
||||
|
||||
override ASTNode getChildInternal(int childIndex) {
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.getAST() = conv.getExpr() and
|
||||
result.getAst() = conv.getExpr() and
|
||||
conv.getExpr() instanceof Conversion
|
||||
}
|
||||
}
|
||||
@@ -363,27 +378,27 @@ class CastNode extends ConversionNode {
|
||||
class StmtExprNode extends ExprNode {
|
||||
override StmtExpr expr;
|
||||
|
||||
override ASTNode getChildInternal(int childIndex) {
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.getAST() = expr.getStmt()
|
||||
result.getAst() = expr.getStmt()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node representing a `DeclarationEntry`.
|
||||
*/
|
||||
class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
|
||||
class DeclarationEntryNode extends BaseAstNode, TDeclarationEntryNode {
|
||||
override DeclarationEntry ast;
|
||||
DeclStmt declStmt;
|
||||
|
||||
DeclarationEntryNode() { this = TDeclarationEntryNode(declStmt, ast) }
|
||||
|
||||
override PrintASTNode getChildInternal(int childIndex) { none() }
|
||||
override PrintAstNode getChildInternal(int childIndex) { none() }
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) { none() }
|
||||
|
||||
override string getProperty(string key) {
|
||||
result = BaseASTNode.super.getProperty(key)
|
||||
result = BaseAstNode.super.getProperty(key)
|
||||
or
|
||||
key = "Type" and
|
||||
result = qlClass(ast.getType()) + ast.getType().toString()
|
||||
@@ -396,9 +411,9 @@ class DeclarationEntryNode extends BaseASTNode, TDeclarationEntryNode {
|
||||
class VariableDeclarationEntryNode extends DeclarationEntryNode {
|
||||
override VariableDeclarationEntry ast;
|
||||
|
||||
override ASTNode getChildInternal(int childIndex) {
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.getAST() = ast.getVariable().getInitializer()
|
||||
result.getAst() = ast.getVariable().getInitializer()
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
@@ -410,23 +425,23 @@ class VariableDeclarationEntryNode extends DeclarationEntryNode {
|
||||
/**
|
||||
* A node representing a `Stmt`.
|
||||
*/
|
||||
class StmtNode extends ASTNode {
|
||||
class StmtNode extends AstNode {
|
||||
Stmt stmt;
|
||||
|
||||
StmtNode() { stmt = ast }
|
||||
|
||||
override BaseASTNode getChildInternal(int childIndex) {
|
||||
override BaseAstNode getChildInternal(int childIndex) {
|
||||
exists(Locatable child |
|
||||
child = stmt.getChild(childIndex) and
|
||||
(
|
||||
result.getAST() = child.(Expr) or
|
||||
result.getAST() = child.(Stmt)
|
||||
result.getAst() = child.(Expr) or
|
||||
result.getAst() = child.(Stmt)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAST())
|
||||
result = getChildAccessorWithoutConversions(ast, getChildInternal(childIndex).getAst())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -449,12 +464,12 @@ class DeclStmtNode extends StmtNode {
|
||||
/**
|
||||
* A node representing a `Parameter`.
|
||||
*/
|
||||
class ParameterNode extends ASTNode {
|
||||
class ParameterNode extends AstNode {
|
||||
Parameter param;
|
||||
|
||||
ParameterNode() { param = ast }
|
||||
|
||||
final override PrintASTNode getChildInternal(int childIndex) { none() }
|
||||
final override PrintAstNode getChildInternal(int childIndex) { none() }
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) { none() }
|
||||
|
||||
@@ -469,14 +484,14 @@ class ParameterNode extends ASTNode {
|
||||
/**
|
||||
* A node representing an `Initializer`.
|
||||
*/
|
||||
class InitializerNode extends ASTNode {
|
||||
class InitializerNode extends AstNode {
|
||||
Initializer init;
|
||||
|
||||
InitializerNode() { init = ast }
|
||||
|
||||
override ASTNode getChildInternal(int childIndex) {
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.getAST() = init.getExpr()
|
||||
result.getAst() = init.getExpr()
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
@@ -488,7 +503,7 @@ class InitializerNode extends ASTNode {
|
||||
/**
|
||||
* A node representing the parameters of a `Function`.
|
||||
*/
|
||||
class ParametersNode extends PrintASTNode, TParametersNode {
|
||||
class ParametersNode extends PrintAstNode, TParametersNode {
|
||||
Function func;
|
||||
|
||||
ParametersNode() { this = TParametersNode(func) }
|
||||
@@ -497,8 +512,8 @@ class ParametersNode extends PrintASTNode, TParametersNode {
|
||||
|
||||
final override Location getLocation() { result = getRepresentativeLocation(func) }
|
||||
|
||||
override ASTNode getChildInternal(int childIndex) {
|
||||
result.getAST() = func.getParameter(childIndex)
|
||||
override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = func.getParameter(childIndex)
|
||||
}
|
||||
|
||||
override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
@@ -515,7 +530,7 @@ class ParametersNode extends PrintASTNode, TParametersNode {
|
||||
/**
|
||||
* A node representing the initializer list of a `Constructor`.
|
||||
*/
|
||||
class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializersNode {
|
||||
class ConstructorInitializersNode extends PrintAstNode, TConstructorInitializersNode {
|
||||
Constructor ctor;
|
||||
|
||||
ConstructorInitializersNode() { this = TConstructorInitializersNode(ctor) }
|
||||
@@ -524,8 +539,8 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
|
||||
|
||||
final override Location getLocation() { result = getRepresentativeLocation(ctor) }
|
||||
|
||||
final override ASTNode getChildInternal(int childIndex) {
|
||||
result.getAST() = ctor.getInitializer(childIndex)
|
||||
final override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = ctor.getInitializer(childIndex)
|
||||
}
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
@@ -542,7 +557,7 @@ class ConstructorInitializersNode extends PrintASTNode, TConstructorInitializers
|
||||
/**
|
||||
* A node representing the destruction list of a `Destructor`.
|
||||
*/
|
||||
class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNode {
|
||||
class DestructorDestructionsNode extends PrintAstNode, TDestructorDestructionsNode {
|
||||
Destructor dtor;
|
||||
|
||||
DestructorDestructionsNode() { this = TDestructorDestructionsNode(dtor) }
|
||||
@@ -551,8 +566,8 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
|
||||
|
||||
final override Location getLocation() { result = getRepresentativeLocation(dtor) }
|
||||
|
||||
final override ASTNode getChildInternal(int childIndex) {
|
||||
result.getAST() = dtor.getDestruction(childIndex)
|
||||
final override AstNode getChildInternal(int childIndex) {
|
||||
result.getAst() = dtor.getDestruction(childIndex)
|
||||
}
|
||||
|
||||
final override string getChildAccessorPredicateInternal(int childIndex) {
|
||||
@@ -569,14 +584,14 @@ class DestructorDestructionsNode extends PrintASTNode, TDestructorDestructionsNo
|
||||
/**
|
||||
* A node representing a `Function`.
|
||||
*/
|
||||
class FunctionNode extends ASTNode {
|
||||
class FunctionNode extends AstNode {
|
||||
Function func;
|
||||
|
||||
FunctionNode() { func = ast }
|
||||
|
||||
override string toString() { result = qlClass(func) + getIdentityString(func) }
|
||||
|
||||
override PrintASTNode getChildInternal(int childIndex) {
|
||||
override PrintAstNode getChildInternal(int childIndex) {
|
||||
childIndex = 0 and
|
||||
result.(ParametersNode).getFunction() = func
|
||||
or
|
||||
@@ -584,7 +599,7 @@ class FunctionNode extends ASTNode {
|
||||
result.(ConstructorInitializersNode).getConstructor() = func
|
||||
or
|
||||
childIndex = 2 and
|
||||
result.(ASTNode).getAST() = func.getEntryPoint()
|
||||
result.(AstNode).getAst() = func.getEntryPoint()
|
||||
or
|
||||
childIndex = 3 and
|
||||
result.(DestructorDestructionsNode).getDestructor() = func
|
||||
@@ -603,7 +618,7 @@ class FunctionNode extends ASTNode {
|
||||
private int getOrder() {
|
||||
this =
|
||||
rank[result](FunctionNode node, Function function, string file, int line, int column |
|
||||
node.getAST() = function and
|
||||
node.getAst() = function and
|
||||
locationSortKeys(function, file, line, column)
|
||||
|
|
||||
node order by file, line, column, getIdentityString(function)
|
||||
@@ -856,7 +871,7 @@ private predicate namedExprChildPredicates(Expr expr, Element ele, string pred)
|
||||
}
|
||||
|
||||
/** Holds if `node` belongs to the output tree, and its property `key` has the given `value`. */
|
||||
query predicate nodes(PrintASTNode node, string key, string value) {
|
||||
query predicate nodes(PrintAstNode node, string key, string value) {
|
||||
node.shouldPrint() and
|
||||
value = node.getProperty(key)
|
||||
}
|
||||
@@ -865,7 +880,7 @@ query predicate nodes(PrintASTNode node, string key, string value) {
|
||||
* Holds if `target` is a child of `source` in the AST, and property `key` of the edge has the
|
||||
* given `value`.
|
||||
*/
|
||||
query predicate edges(PrintASTNode source, PrintASTNode target, string key, string value) {
|
||||
query predicate edges(PrintAstNode source, PrintAstNode target, string key, string value) {
|
||||
exists(int childIndex |
|
||||
source.shouldPrint() and
|
||||
target.shouldPrint() and
|
||||
|
||||
@@ -38,7 +38,7 @@ class FunctionSpecifier extends Specifier {
|
||||
|
||||
/**
|
||||
* A C/C++ storage class specifier: `auto`, `register`, `static`, `extern`,
|
||||
* or `mutable".
|
||||
* or `mutable`.
|
||||
*/
|
||||
class StorageClassSpecifier extends Specifier {
|
||||
StorageClassSpecifier() { this.hasName(["auto", "register", "static", "extern", "mutable"]) }
|
||||
|
||||
@@ -1085,50 +1085,6 @@ class DerivedType extends Type, @derivedtype {
|
||||
override predicate involvesTemplateParameter() { this.getBaseType().involvesTemplateParameter() }
|
||||
|
||||
override Type stripType() { result = this.getBaseType().stripType() }
|
||||
|
||||
/**
|
||||
* Holds if this type has the `__autoreleasing` specifier or if it points to
|
||||
* a type with the `__autoreleasing` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isAutoReleasing() {
|
||||
this.hasSpecifier("__autoreleasing") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__autoreleasing")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this type has the `__strong` specifier or if it points to
|
||||
* a type with the `__strong` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isStrong() {
|
||||
this.hasSpecifier("__strong") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__strong")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this type has the `__unsafe_unretained` specifier or if it points
|
||||
* to a type with the `__unsafe_unretained` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isUnsafeRetained() {
|
||||
this.hasSpecifier("__unsafe_unretained") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__unsafe_unretained")
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this type has the `__weak` specifier or if it points to
|
||||
* a type with the `__weak` specifier.
|
||||
*
|
||||
* DEPRECATED: use `hasSpecifier` directly instead.
|
||||
*/
|
||||
deprecated predicate isWeak() {
|
||||
this.hasSpecifier("__weak") or
|
||||
this.(PointerType).getBaseType().hasSpecifier("__weak")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -106,25 +106,4 @@ class NestedTypedefType extends TypedefType {
|
||||
NestedTypedefType() { this.isMember() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NestedTypedefType" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `.hasSpecifier("private")` instead.
|
||||
*
|
||||
* Holds if this member is private.
|
||||
*/
|
||||
deprecated predicate isPrivate() { this.hasSpecifier("private") }
|
||||
|
||||
/**
|
||||
* DEPRECATED: `.hasSpecifier("protected")` instead.
|
||||
*
|
||||
* Holds if this member is protected.
|
||||
*/
|
||||
deprecated predicate isProtected() { this.hasSpecifier("protected") }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `.hasSpecifier("public")` instead.
|
||||
*
|
||||
* Holds if this member is public.
|
||||
*/
|
||||
deprecated predicate isPublic() { this.hasSpecifier("public") }
|
||||
}
|
||||
|
||||
@@ -556,24 +556,6 @@ class MemberVariable extends Variable, @membervariable {
|
||||
private Type getAType() { membervariables(underlyingElement(this), unresolveElement(result), _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ function pointer variable.
|
||||
*
|
||||
* DEPRECATED: use `Variable.getType() instanceof FunctionPointerType` instead.
|
||||
*/
|
||||
deprecated class FunctionPointerVariable extends Variable {
|
||||
FunctionPointerVariable() { this.getType() instanceof FunctionPointerType }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C/C++ function pointer member variable.
|
||||
*
|
||||
* DEPRECATED: use `MemberVariable.getType() instanceof FunctionPointerType` instead.
|
||||
*/
|
||||
deprecated class FunctionPointerMemberVariable extends MemberVariable {
|
||||
FunctionPointerMemberVariable() { this instanceof FunctionPointerVariable }
|
||||
}
|
||||
|
||||
/**
|
||||
* A C++14 variable template. For example, in the following code the variable
|
||||
* template `v` defines a family of variables:
|
||||
|
||||
@@ -4,21 +4,14 @@
|
||||
|
||||
import semmle.files.FileSystem
|
||||
|
||||
private class TXMLLocatable =
|
||||
private class TXmlLocatable =
|
||||
@xmldtd or @xmlelement or @xmlattribute or @xmlnamespace or @xmlcomment or @xmlcharacters;
|
||||
|
||||
/** An XML element that has a location. */
|
||||
class XMLLocatable extends @xmllocatable, TXMLLocatable {
|
||||
class XMLLocatable extends @xmllocatable, TXmlLocatable {
|
||||
/** Gets the source location for this element. */
|
||||
Location getLocation() { xmllocations(this, result) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLocation()` instead.
|
||||
*
|
||||
* Gets the source location for this element.
|
||||
*/
|
||||
deprecated Location getALocation() { result = this.getLocation() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
@@ -83,21 +76,6 @@ class XMLParent extends @xmlparent {
|
||||
/** Gets the number of places in the body of this XML parent where text occurs. */
|
||||
int getNumberOfCharacterSets() { result = count(int pos | xmlChars(_, _, this, pos, _, _)) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Internal.
|
||||
*
|
||||
* Append the character sequences of this XML parent from left to right, separated by a space,
|
||||
* up to a specified (zero-based) index.
|
||||
*/
|
||||
deprecated string charsSetUpTo(int n) {
|
||||
n = 0 and xmlChars(_, result, this, 0, _, _)
|
||||
or
|
||||
n > 0 and
|
||||
exists(string chars | xmlChars(_, chars, this, n, _, _) |
|
||||
result = this.charsSetUpTo(n - 1) + " " + chars
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the result of appending all the character sequences of this XML parent from
|
||||
* left to right, separated by a space.
|
||||
|
||||
@@ -2,20 +2,6 @@ import cpp
|
||||
import semmle.code.cpp.models.interfaces.Allocation
|
||||
import semmle.code.cpp.models.interfaces.Deallocation
|
||||
|
||||
/**
|
||||
* A library routine that allocates memory.
|
||||
*
|
||||
* DEPRECATED: Use the `AllocationFunction` class instead of this predicate.
|
||||
*/
|
||||
deprecated predicate allocationFunction(Function f) { f instanceof AllocationFunction }
|
||||
|
||||
/**
|
||||
* A call to a library routine that allocates memory.
|
||||
*
|
||||
* DEPRECATED: Use `AllocationExpr` instead (this also includes `new` expressions).
|
||||
*/
|
||||
deprecated predicate allocationCall(FunctionCall fc) { fc instanceof AllocationExpr }
|
||||
|
||||
/**
|
||||
* A library routine that frees memory.
|
||||
*/
|
||||
@@ -33,13 +19,6 @@ predicate freeCall(FunctionCall fc, Expr arg) { arg = fc.(DeallocationExpr).getF
|
||||
*/
|
||||
predicate isMemoryManagementExpr(Expr e) { isAllocationExpr(e) or e instanceof DeallocationExpr }
|
||||
|
||||
/**
|
||||
* Is e an allocation from stdlib.h (`malloc`, `realloc` etc)?
|
||||
*
|
||||
* DEPRECATED: Use `AllocationExpr` instead (this also includes `new` expressions).
|
||||
*/
|
||||
deprecated predicate isStdLibAllocationExpr(Expr e) { allocationCall(e) }
|
||||
|
||||
/**
|
||||
* Is e some kind of allocation (`new`, `alloc`, `realloc` etc)?
|
||||
*/
|
||||
@@ -48,19 +27,3 @@ predicate isAllocationExpr(Expr e) {
|
||||
or
|
||||
e = any(NewOrNewArrayExpr new | not exists(new.getPlacementPointer()))
|
||||
}
|
||||
|
||||
/**
|
||||
* Is e some kind of allocation (`new`, `alloc`, `realloc` etc) with a fixed size?
|
||||
*
|
||||
* DEPRECATED: Use `AllocationExpr.getSizeBytes()` instead.
|
||||
*/
|
||||
deprecated predicate isFixedSizeAllocationExpr(Expr allocExpr, int size) {
|
||||
size = allocExpr.(AllocationExpr).getSizeBytes()
|
||||
}
|
||||
|
||||
/**
|
||||
* Is e some kind of deallocation (`delete`, `free`, `realloc` etc)?
|
||||
*
|
||||
* DEPRECATED: Use `DeallocationExpr` instead.
|
||||
*/
|
||||
deprecated predicate isDeallocationExpr(Expr e) { e instanceof DeallocationExpr }
|
||||
|
||||
@@ -207,26 +207,6 @@ predicate variadicFormatter(Function f, string type, int formatParamIndex, int o
|
||||
callsVariadicFormatter(f, type, formatParamIndex, outputParamIndex)
|
||||
}
|
||||
|
||||
/**
|
||||
* A standard function such as `vprintf` that has a format parameter
|
||||
* and a variable argument list of type `va_arg`.
|
||||
*
|
||||
* DEPRECATED: Use the four argument version instead.
|
||||
*/
|
||||
deprecated predicate primitiveVariadicFormatter(TopLevelFunction f, int formatParamIndex) {
|
||||
primitiveVariadicFormatter(f, _, formatParamIndex, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `f` is a function such as `vprintf` that has a format parameter
|
||||
* (at `formatParamIndex`) and a variable argument list of type `va_arg`.
|
||||
*
|
||||
* DEPRECATED: Use the four argument version instead.
|
||||
*/
|
||||
deprecated predicate variadicFormatter(Function f, int formatParamIndex) {
|
||||
variadicFormatter(f, _, formatParamIndex, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* A function not in the standard library which takes a `printf`-like formatting
|
||||
* string and a variable number of arguments.
|
||||
@@ -428,13 +408,6 @@ class FormatLiteral extends Literal {
|
||||
*/
|
||||
FormattingFunctionCall getUse() { result.getFormat() = this }
|
||||
|
||||
/**
|
||||
* Holds if the default meaning of `%s` is a `wchar_t *`, rather than
|
||||
* a `char *` (either way, `%S` will have the opposite meaning).
|
||||
* DEPRECATED: Use getDefaultCharType() instead.
|
||||
*/
|
||||
deprecated predicate isWideCharDefault() { this.getUse().getTarget().isWideCharDefault() }
|
||||
|
||||
/**
|
||||
* Gets the default character type expected for `%s` by this format literal. Typically
|
||||
* `char` or `wchar_t`.
|
||||
|
||||
@@ -223,20 +223,6 @@ class BasicBlock extends ControlFlowNodeBase {
|
||||
*/
|
||||
predicate inLoop() { this.getASuccessor+() = this }
|
||||
|
||||
/**
|
||||
* DEPRECATED since version 1.11: this predicate does not match the standard
|
||||
* definition of _loop header_.
|
||||
*
|
||||
* Holds if this basic block is in a loop of the control-flow graph and
|
||||
* additionally has an incoming edge that is not part of any loop containing
|
||||
* this basic block. A typical example would be the basic block that computes
|
||||
* `x > 0` in an outermost loop `while (x > 0) { ... }`.
|
||||
*/
|
||||
deprecated predicate isLoopHeader() {
|
||||
this.inLoop() and
|
||||
exists(BasicBlock pred | pred = this.getAPredecessor() and not pred = this.getASuccessor+())
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if control flow may reach this basic block from a function entry
|
||||
* point or any handler of a reachable `try` statement.
|
||||
|
||||
@@ -65,7 +65,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
* taken when this expression is true.
|
||||
*/
|
||||
ControlFlowNode getATrueSuccessor() {
|
||||
qlCFGTrueSuccessor(this, result) and
|
||||
qlCfgTrueSuccessor(this, result) and
|
||||
result = this.getASuccessor()
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class ControlFlowNode extends Locatable, ControlFlowNodeBase {
|
||||
* taken when this expression is false.
|
||||
*/
|
||||
ControlFlowNode getAFalseSuccessor() {
|
||||
qlCFGFalseSuccessor(this, result) and
|
||||
qlCfgFalseSuccessor(this, result) and
|
||||
result = this.getASuccessor()
|
||||
}
|
||||
|
||||
@@ -94,24 +94,6 @@ import ControlFlowGraphPublic
|
||||
*/
|
||||
class ControlFlowNodeBase extends ElementBase, @cfgnode { }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ControlFlowNode.getATrueSuccessor()` instead.
|
||||
* Holds when `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.
|
||||
*/
|
||||
deprecated predicate truecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
|
||||
qlCFGTrueSuccessor(n1, n2)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `ControlFlowNode.getAFalseSuccessor()` instead.
|
||||
* Holds when `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.
|
||||
*/
|
||||
deprecated predicate falsecond_base(ControlFlowNodeBase n1, ControlFlowNodeBase n2) {
|
||||
qlCFGFalseSuccessor(n1, n2)
|
||||
}
|
||||
|
||||
/**
|
||||
* An abstract class that can be extended to add additional edges to the
|
||||
* control-flow graph. Instances of this class correspond to the source nodes
|
||||
@@ -139,7 +121,7 @@ abstract class AdditionalControlFlowEdge extends ControlFlowNodeBase {
|
||||
* `AdditionalControlFlowEdge`. Use this relation instead of `qlCFGSuccessor`.
|
||||
*/
|
||||
predicate successors_extended(ControlFlowNodeBase source, ControlFlowNodeBase target) {
|
||||
qlCFGSuccessor(source, target)
|
||||
qlCfgSuccessor(source, target)
|
||||
or
|
||||
source.(AdditionalControlFlowEdge).getAnEdgeTarget() = target
|
||||
}
|
||||
|
||||
@@ -33,8 +33,8 @@ class GuardCondition extends Expr {
|
||||
or
|
||||
// the IR short-circuits if(!x)
|
||||
// don't produce a guard condition for `y = !x` and other non-short-circuited cases
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and
|
||||
exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAST())
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
|
||||
exists(IRGuardCondition ir | this.(NotExpr).getOperand() = ir.getAst())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -146,8 +146,8 @@ private class GuardConditionFromBinaryLogicalOperator extends GuardCondition {
|
||||
*/
|
||||
private class GuardConditionFromShortCircuitNot extends GuardCondition, NotExpr {
|
||||
GuardConditionFromShortCircuitNot() {
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAST()) and
|
||||
exists(IRGuardCondition ir | this.getOperand() = ir.getAST())
|
||||
not exists(Instruction inst | this.getFullyConverted() = inst.getAst()) and
|
||||
exists(IRGuardCondition ir | this.getOperand() = ir.getAst())
|
||||
}
|
||||
|
||||
override predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
@@ -241,7 +241,7 @@ private class GuardConditionFromIR extends GuardCondition {
|
||||
private predicate controlsBlock(BasicBlock controlled, boolean testIsTrue) {
|
||||
exists(IRBlock irb |
|
||||
forex(IRGuardCondition inst | inst = ir | inst.controls(irb, testIsTrue)) and
|
||||
irb.getAnInstruction().getAST().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
irb.getAnInstruction().getAst().(ControlFlowNode).getBasicBlock() = controlled and
|
||||
not isUnreachedBlock(irb)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,393 +0,0 @@
|
||||
/**
|
||||
* DEPRECATED: Use `StackVariableReachability` instead.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `StackVariableReachability` instead.
|
||||
*
|
||||
* A reachability analysis for control-flow nodes involving stack variables.
|
||||
* This defines sources, sinks, and any other configurable aspect of the
|
||||
* analysis. Multiple analyses can coexist. To create an analysis, extend this
|
||||
* class with a subclass whose characteristic predicate is a unique singleton
|
||||
* string. For example, write
|
||||
*
|
||||
* ```
|
||||
* class MyAnalysisConfiguration extends LocalScopeVariableReachability {
|
||||
* MyAnalysisConfiguration() { this = "MyAnalysisConfiguration" }
|
||||
* // Override `isSource` and `isSink`.
|
||||
* // Override `isBarrier`.
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Then, to query whether there is flow between some source and sink, call the
|
||||
* `reaches` predicate on an instance of `MyAnalysisConfiguration`.
|
||||
*/
|
||||
abstract deprecated class LocalScopeVariableReachability extends string {
|
||||
bindingset[this]
|
||||
LocalScopeVariableReachability() { length() >= 0 }
|
||||
|
||||
/** Holds if `node` is a source for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSource(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/** Holds if `sink` is a (potential) sink for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSink(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/** Holds if `node` is a barrier for the reachability analysis using variable `v`. */
|
||||
abstract predicate isBarrier(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/**
|
||||
* Holds if the source node `source` can reach the sink `sink` without crossing
|
||||
* a barrier. This is (almost) equivalent to the following QL predicate but
|
||||
* uses basic blocks internally for better performance:
|
||||
*
|
||||
* ```
|
||||
* predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
* reachesImpl(source, v, sink)
|
||||
* and
|
||||
* isSink(sink, v)
|
||||
* }
|
||||
*
|
||||
* predicate reachesImpl(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
* sink = source.getASuccessor() and isSource(source, v)
|
||||
* or
|
||||
* exists(ControlFlowNode mid | reachesImpl(source, v, mid) |
|
||||
* not isBarrier(mid, v)
|
||||
* and
|
||||
* sink = mid.getASuccessor()
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In addition to using a better performing implementation, this analysis
|
||||
* accounts for loops where the condition is provably true upon entry.
|
||||
*/
|
||||
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
/*
|
||||
* Implementation detail: the predicates in this class are a generalization of
|
||||
* those in DefinitionsAndUses.qll, and should be kept in sync.
|
||||
*
|
||||
* Unfortunately, caching of abstract predicates does not work well, so the
|
||||
* predicates in DefinitionsAndUses.qll cannot use this library.
|
||||
*/
|
||||
|
||||
exists(BasicBlock bb, int i |
|
||||
this.isSource(source, v) and
|
||||
bb.getNode(i) = source and
|
||||
not bb.isUnreachable()
|
||||
|
|
||||
exists(int j |
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k in [i + 1 .. j - 1])
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(bb.getNode(k), v) | k > i) and
|
||||
this.bbSuccessorEntryReaches(bb, v, sink, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbSuccessorEntryReaches(
|
||||
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
|
||||
boolean skipsFirstLoopAlwaysTrueUponEntry
|
||||
) {
|
||||
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
|
||||
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
|
|
||||
this.bbEntryReachesLocally(succ, v, node) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
or
|
||||
not this.isBarrier(succ.getNode(_), v) and
|
||||
this.bbSuccessorEntryReaches(succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbEntryReachesLocally(
|
||||
BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
|
||||
) {
|
||||
exists(int n |
|
||||
node = bb.getNode(n) and
|
||||
this.isSink(node, v)
|
||||
|
|
||||
not exists(this.firstBarrierIndexIn(bb, v))
|
||||
or
|
||||
n <= this.firstBarrierIndexIn(bb, v)
|
||||
)
|
||||
}
|
||||
|
||||
private int firstBarrierIndexIn(BasicBlock bb, SemanticStackVariable v) {
|
||||
result = min(int m | this.isBarrier(bb.getNode(m), v))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `bb` contains the entry point `loop` for a loop at position `i`.
|
||||
* The condition of that loop is provably true upon entry but not provably
|
||||
* true in general (if it were, the false-successor had already been removed
|
||||
* from the CFG).
|
||||
*
|
||||
* Examples:
|
||||
* ```
|
||||
* for (int i = 0; i < 2; i++) { } // always true upon entry
|
||||
* for (int i = 0; true; i++) { } // always true
|
||||
* ```
|
||||
*/
|
||||
private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, ControlFlowNode loop) {
|
||||
exists(Expr condition |
|
||||
loopConditionAlwaysTrueUponEntry(loop, condition) and
|
||||
not conditionAlwaysTrue(condition) and
|
||||
bb.getNode(i) = loop
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Basic block `pred` contains all or part of the condition belonging to a loop,
|
||||
* and there is an edge from `pred` to `succ` that concludes the condition.
|
||||
* If the edge corrseponds with the loop condition being found to be `true`, then
|
||||
* `skipsLoop` is `false`. Otherwise the edge corresponds with the loop condition
|
||||
* being found to be `false` and `skipsLoop` is `true`. Non-concluding edges
|
||||
* within a complex loop condition are not matched by this predicate.
|
||||
*/
|
||||
private predicate bbLoopConditionAlwaysTrueUponEntrySuccessor(
|
||||
BasicBlock pred, BasicBlock succ, boolean skipsLoop
|
||||
) {
|
||||
exists(Expr cond |
|
||||
loopConditionAlwaysTrueUponEntry(_, cond) and
|
||||
cond.getAChild*() = pred.getEnd() and
|
||||
succ = pred.getASuccessor() and
|
||||
not cond.getAChild*() = succ.getStart() and
|
||||
(
|
||||
succ = pred.getAFalseSuccessor() and
|
||||
skipsLoop = true
|
||||
or
|
||||
succ = pred.getATrueSuccessor() and
|
||||
skipsLoop = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Loop invariant for `bbSuccessorEntryReaches`:
|
||||
*
|
||||
* - `succ` is a successor of `pred`.
|
||||
* - `predSkipsFirstLoopAlwaysTrueUponEntry`: whether the path from
|
||||
* `pred` (via `succ`) skips the first loop where the condition is
|
||||
* provably true upon entry.
|
||||
* - `succSkipsFirstLoopAlwaysTrueUponEntry`: whether the path from
|
||||
* `succ` skips the first loop where the condition is provably true
|
||||
* upon entry.
|
||||
* - If `pred` contains the entry point of a loop where the condition
|
||||
* is provably true upon entry, then `succ` is not allowed to skip
|
||||
* that loop (`succSkipsFirstLoopAlwaysTrueUponEntry = false`).
|
||||
*/
|
||||
predicate bbSuccessorEntryReachesLoopInvariant(
|
||||
BasicBlock pred, BasicBlock succ, boolean predSkipsFirstLoopAlwaysTrueUponEntry,
|
||||
boolean succSkipsFirstLoopAlwaysTrueUponEntry
|
||||
) {
|
||||
succ = pred.getASuccessor() and
|
||||
(succSkipsFirstLoopAlwaysTrueUponEntry = true or succSkipsFirstLoopAlwaysTrueUponEntry = false) and
|
||||
(
|
||||
// The edge from `pred` to `succ` is from a loop condition provably
|
||||
// true upon entry, so the value of `predSkipsFirstLoopAlwaysTrueUponEntry`
|
||||
// is determined by whether the true edge or the false edge is chosen,
|
||||
// regardless of the value of `succSkipsFirstLoopAlwaysTrueUponEntry`.
|
||||
bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, predSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
or
|
||||
// The edge from `pred` to `succ` is _not_ from a loop condition provably
|
||||
// true upon entry, so the values of `predSkipsFirstLoopAlwaysTrueUponEntry`
|
||||
// and `succSkipsFirstLoopAlwaysTrueUponEntry` must be the same.
|
||||
not bbLoopConditionAlwaysTrueUponEntrySuccessor(pred, succ, _) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = predSkipsFirstLoopAlwaysTrueUponEntry and
|
||||
// Moreover, if `pred` contains the entry point of a loop where the
|
||||
// condition is provably true upon entry, then `succ` is not allowed
|
||||
// to skip that loop, and hence `succSkipsFirstLoopAlwaysTrueUponEntry = false`.
|
||||
(
|
||||
bbLoopEntryConditionAlwaysTrueAt(pred, _, _)
|
||||
implies
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `StackVariableReachabilityWithReassignment` instead.
|
||||
*
|
||||
* Reachability analysis for control-flow nodes involving stack variables.
|
||||
* Unlike `LocalScopeVariableReachability`, this analysis takes variable
|
||||
* reassignments into account.
|
||||
*
|
||||
* This class is used like `LocalScopeVariableReachability`, except that
|
||||
* subclasses should override `isSourceActual` and `isSinkActual` instead of
|
||||
* `isSource` and `isSink`, and that there is a `reachesTo` predicate in
|
||||
* addition to `reaches`.
|
||||
*/
|
||||
abstract deprecated class LocalScopeVariableReachabilityWithReassignment extends LocalScopeVariableReachability {
|
||||
bindingset[this]
|
||||
LocalScopeVariableReachabilityWithReassignment() { length() >= 0 }
|
||||
|
||||
/** Override this predicate rather than `isSource` (`isSource` is used internally). */
|
||||
abstract predicate isSourceActual(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/** Override this predicate rather than `isSink` (`isSink` is used internally). */
|
||||
abstract predicate isSinkActual(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/**
|
||||
* Holds if the source node `source` can reach the sink `sink` without crossing
|
||||
* a barrier, taking reassignments into account. This is (almost) equivalent
|
||||
* to the following QL predicate, but uses basic blocks internally for better
|
||||
* performance:
|
||||
*
|
||||
* ```
|
||||
* predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
* reachesImpl(source, v, sink)
|
||||
* and
|
||||
* isSinkActual(sink, v)
|
||||
* }
|
||||
*
|
||||
* predicate reachesImpl(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
* isSourceActual(source, v)
|
||||
* and
|
||||
* (
|
||||
* sink = source.getASuccessor()
|
||||
* or
|
||||
* exists(ControlFlowNode mid, SemanticStackVariable v0 | reachesImpl(source, v0, mid) |
|
||||
* // ordinary successor
|
||||
* not isBarrier(mid, v) and
|
||||
* sink = mid.getASuccessor() and
|
||||
* v = v0
|
||||
* or
|
||||
* // reassigned from v0 to v
|
||||
* exprDefinition(v, mid, v0.getAnAccess()) and
|
||||
* sink = mid.getASuccessor()
|
||||
* )
|
||||
* )
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* In addition to using a better performing implementation, this analysis
|
||||
* accounts for loops where the condition is provably true upon entry.
|
||||
*/
|
||||
override predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
this.reachesTo(source, v, sink, _)
|
||||
}
|
||||
|
||||
/**
|
||||
* As `reaches`, but also specifies the last variable it was reassigned to (`v0`).
|
||||
*/
|
||||
predicate reachesTo(
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink, SemanticStackVariable v0
|
||||
) {
|
||||
exists(ControlFlowNode def |
|
||||
this.actualSourceReaches(source, v, def, v0) and
|
||||
LocalScopeVariableReachability.super.reaches(def, v0, sink) and
|
||||
this.isSinkActual(sink, v0)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate actualSourceReaches(
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
|
||||
) {
|
||||
this.isSourceActual(source, v) and def = source and v0 = v
|
||||
or
|
||||
exists(ControlFlowNode source1, SemanticStackVariable v1 |
|
||||
this.actualSourceReaches(source, v, source1, v1)
|
||||
|
|
||||
this.reassignment(source1, v1, def, v0)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate reassignment(
|
||||
ControlFlowNode source, SemanticStackVariable v, ControlFlowNode def, SemanticStackVariable v0
|
||||
) {
|
||||
LocalScopeVariableReachability.super.reaches(source, v, def) and
|
||||
exprDefinition(v0, def, v.getAnAccess())
|
||||
}
|
||||
|
||||
final override predicate isSource(ControlFlowNode node, LocalScopeVariable v) {
|
||||
this.isSourceActual(node, v)
|
||||
or
|
||||
// Reassignment generates a new (non-actual) source
|
||||
this.reassignment(_, _, node, v)
|
||||
}
|
||||
|
||||
final override predicate isSink(ControlFlowNode node, LocalScopeVariable v) {
|
||||
this.isSinkActual(node, v)
|
||||
or
|
||||
// Reassignment generates a new (non-actual) sink
|
||||
exprDefinition(_, node, v.getAnAccess())
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `StackVariableReachabilityExt` instead.
|
||||
*
|
||||
* Same as `LocalScopeVariableReachability`, but `isBarrier` works on control-flow
|
||||
* edges rather than nodes and is therefore parameterized by the original
|
||||
* source node as well. Otherwise, this class is used like
|
||||
* `LocalScopeVariableReachability`.
|
||||
*/
|
||||
abstract deprecated class LocalScopeVariableReachabilityExt extends string {
|
||||
bindingset[this]
|
||||
LocalScopeVariableReachabilityExt() { length() >= 0 }
|
||||
|
||||
/** `node` is a source for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSource(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/** `sink` is a (potential) sink for the reachability analysis using variable `v`. */
|
||||
abstract predicate isSink(ControlFlowNode node, LocalScopeVariable v);
|
||||
|
||||
/** `node` is a barrier for the reachability analysis using variable `v` and starting from `source`. */
|
||||
abstract predicate isBarrier(
|
||||
ControlFlowNode source, ControlFlowNode node, ControlFlowNode next, LocalScopeVariable v
|
||||
);
|
||||
|
||||
/** See `LocalScopeVariableReachability.reaches`. */
|
||||
predicate reaches(ControlFlowNode source, SemanticStackVariable v, ControlFlowNode sink) {
|
||||
exists(BasicBlock bb, int i |
|
||||
this.isSource(source, v) and
|
||||
bb.getNode(i) = source and
|
||||
not bb.isUnreachable()
|
||||
|
|
||||
exists(int j |
|
||||
j > i and
|
||||
sink = bb.getNode(j) and
|
||||
this.isSink(sink, v) and
|
||||
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) |
|
||||
k in [i .. j - 1]
|
||||
)
|
||||
)
|
||||
or
|
||||
not exists(int k | this.isBarrier(source, bb.getNode(k), bb.getNode(k + 1), v) | k >= i) and
|
||||
this.bbSuccessorEntryReaches(source, bb, v, sink, _)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbSuccessorEntryReaches(
|
||||
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node,
|
||||
boolean skipsFirstLoopAlwaysTrueUponEntry
|
||||
) {
|
||||
exists(BasicBlock succ, boolean succSkipsFirstLoopAlwaysTrueUponEntry |
|
||||
bbSuccessorEntryReachesLoopInvariant(bb, succ, skipsFirstLoopAlwaysTrueUponEntry,
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry) and
|
||||
not this.isBarrier(source, bb.getEnd(), succ.getStart(), v)
|
||||
|
|
||||
this.bbEntryReachesLocally(source, succ, v, node) and
|
||||
succSkipsFirstLoopAlwaysTrueUponEntry = false
|
||||
or
|
||||
not exists(int k | this.isBarrier(source, succ.getNode(k), succ.getNode(k + 1), v)) and
|
||||
this.bbSuccessorEntryReaches(source, succ, v, node, succSkipsFirstLoopAlwaysTrueUponEntry)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate bbEntryReachesLocally(
|
||||
ControlFlowNode source, BasicBlock bb, SemanticStackVariable v, ControlFlowNode node
|
||||
) {
|
||||
this.isSource(source, v) and
|
||||
exists(int n | node = bb.getNode(n) and this.isSink(node, v) |
|
||||
not exists(int m | m < n | this.isBarrier(source, bb.getNode(m), bb.getNode(m + 1), v))
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -156,15 +156,6 @@ class AnalysedExpr extends Expr {
|
||||
this.isValidCheck(v) and result = this.getATrueSuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getNonNullSuccessor` instead, which does the same.
|
||||
*/
|
||||
deprecated ControlFlowNode getValidSuccessor(LocalScopeVariable v) {
|
||||
this.isValidCheck(v) and result = this.getATrueSuccessor()
|
||||
or
|
||||
this.isNullCheck(v) and result = this.getAFalseSuccessor()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a `VariableAccess` of `v` nested inside a condition.
|
||||
*/
|
||||
|
||||
@@ -10,10 +10,13 @@ import SSAUtils
|
||||
* The SSA logic comes in two versions: the standard SSA and range-analysis RangeSSA.
|
||||
* This class provides the standard SSA logic.
|
||||
*/
|
||||
library class StandardSSA extends SSAHelper {
|
||||
StandardSSA() { this = 0 }
|
||||
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
|
||||
@@ -27,22 +30,22 @@ library class StandardSSA extends SSAHelper {
|
||||
* statically seen to be unreachable.
|
||||
*/
|
||||
class SsaDefinition extends ControlFlowNodeBase {
|
||||
SsaDefinition() { exists(StandardSSA x | x.ssa_defn(_, this, _, _)) }
|
||||
SsaDefinition() { exists(StandardSsa x | x.ssa_defn(_, this, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets a variable corresponding to an SSA StackVariable defined by
|
||||
* this definition.
|
||||
*/
|
||||
StackVariable getAVariable() { exists(StandardSSA x | x.ssa_defn(result, this, _, _)) }
|
||||
StackVariable getAVariable() { exists(StandardSsa x | x.ssa_defn(result, this, _, _)) }
|
||||
|
||||
/**
|
||||
* Gets a string representation of the SSA variable represented by the pair
|
||||
* `(this, v)`.
|
||||
*/
|
||||
string toString(StackVariable v) { exists(StandardSSA x | result = x.toString(this, v)) }
|
||||
string toString(StackVariable v) { exists(StandardSsa x | result = x.toString(this, v)) }
|
||||
|
||||
/** Gets a use of the SSA variable represented by the pair `(this, v)`. */
|
||||
VariableAccess getAUse(StackVariable v) { exists(StandardSSA x | result = x.getAUse(this, v)) }
|
||||
VariableAccess getAUse(StackVariable v) { exists(StandardSsa x | result = x.getAUse(this, v)) }
|
||||
|
||||
/**
|
||||
* Gets the control-flow node for this definition. This will usually be the
|
||||
@@ -62,7 +65,7 @@ class SsaDefinition extends ControlFlowNodeBase {
|
||||
BasicBlock getBasicBlock() { result.contains(this.getDefinition()) }
|
||||
|
||||
/** Holds if this definition is a phi node for variable `v`. */
|
||||
predicate isPhiNode(StackVariable v) { exists(StandardSSA x | x.phi_node(v, this)) }
|
||||
predicate isPhiNode(StackVariable v) { exists(StandardSsa x | x.phi_node(v, this)) }
|
||||
|
||||
/** Gets the location of this definition. */
|
||||
Location getLocation() { result = this.(ControlFlowNode).getLocation() }
|
||||
@@ -124,7 +127,7 @@ class SsaDefinition extends ControlFlowNodeBase {
|
||||
|
||||
/** Holds if `(this, v)` reaches the end of basic block `b`. */
|
||||
predicate reachesEndOfBB(StackVariable v, BasicBlock b) {
|
||||
exists(StandardSSA x | x.ssaDefinitionReachesEndOfBB(v, this, b))
|
||||
exists(StandardSsa x | x.ssaDefinitionReachesEndOfBB(v, this, b))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -147,15 +150,4 @@ class SsaDefinition extends ControlFlowNodeBase {
|
||||
Expr getAnUltimateDefiningValue(StackVariable v) {
|
||||
result = this.getAnUltimateSsaDefinition(v).getDefiningValue(v)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: this is the old name for `getAnUltimateDefiningValue`. The
|
||||
* name was confusing as it seemed analogous to `getDefinition` rather than
|
||||
* `getDefiningValue`. The SSA libraries for other languages use the name
|
||||
* `getAnUltimateSsaDefinition` to refer to a predicate named
|
||||
* `getAnUltimateSsaDefinition` in this class.
|
||||
*/
|
||||
deprecated Expr getAnUltimateDefinition(StackVariable v) {
|
||||
result = this.getAnUltimateDefiningValue(v)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,10 +114,10 @@ private predicate live_at_exit_of_bb(StackVariable v, BasicBlock b) {
|
||||
|
||||
/** Common SSA logic for standard SSA and range-analysis SSA. */
|
||||
cached
|
||||
library class SSAHelper extends int {
|
||||
library class SsaHelper extends int {
|
||||
/* 0 = StandardSSA, 1 = RangeSSA */
|
||||
cached
|
||||
SSAHelper() { this in [0 .. 1] }
|
||||
SsaHelper() { this in [0 .. 1] }
|
||||
|
||||
/**
|
||||
* Override to insert a custom phi node for variable `v` at the start of
|
||||
@@ -311,3 +311,6 @@ library class SSAHelper extends int {
|
||||
ssa_use(v, result, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SsaHelper */
|
||||
deprecated class SSAHelper = SsaHelper;
|
||||
|
||||
@@ -447,26 +447,6 @@ private predicate skipInitializer(Initializer init) {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `e` is an expression in a static initializer that must be evaluated
|
||||
* at run time. This predicate computes "is non-const" instead of "is const" in
|
||||
* order to avoid recursion through forall.
|
||||
*/
|
||||
private predicate runtimeExprInStaticInitializer(Expr e) {
|
||||
inStaticInitializer(e) and
|
||||
if e instanceof AggregateLiteral
|
||||
then runtimeExprInStaticInitializer(e.getAChild())
|
||||
else not e.getFullyConverted().isConstant()
|
||||
}
|
||||
|
||||
/** Holds if `e` is part of the initializer of a local static variable. */
|
||||
private predicate inStaticInitializer(Expr e) {
|
||||
exists(LocalVariable local |
|
||||
local.isStatic() and
|
||||
e.getParent+() = local.getInitializer()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th child of `n` in control-flow order, where the `i`-indexes are
|
||||
* contiguous, and the first index is 0.
|
||||
@@ -1379,7 +1359,7 @@ private module Cached {
|
||||
* true-successors and false-successors.
|
||||
*/
|
||||
cached
|
||||
predicate qlCFGSuccessor(Node n1, Node n2) {
|
||||
predicate qlCfgSuccessor(Node n1, Node n2) {
|
||||
exists(Node memberNode, Pos memberPos |
|
||||
subEdgeIncludingDestructors(any(Pos at | at.isAt()), n1, memberNode, memberPos) and
|
||||
normalGroupMember(memberNode, memberPos, n2)
|
||||
@@ -1388,23 +1368,32 @@ 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.
|
||||
*/
|
||||
cached
|
||||
predicate qlCFGTrueSuccessor(Node n1, Node n2) {
|
||||
predicate qlCfgTrueSuccessor(Node n1, Node n2) {
|
||||
conditionalSuccessor(n1, true, n2) and
|
||||
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.
|
||||
*/
|
||||
cached
|
||||
predicate qlCFGFalseSuccessor(Node n1, Node n2) {
|
||||
predicate qlCfgFalseSuccessor(Node n1, Node n2) {
|
||||
conditionalSuccessor(n1, false, n2) and
|
||||
not conditionalSuccessor(n1, true, n2)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for qlCfgFalseSuccessor */
|
||||
deprecated predicate qlCFGFalseSuccessor = qlCfgFalseSuccessor/2;
|
||||
}
|
||||
|
||||
@@ -188,8 +188,8 @@ private predicate nonAnalyzableFunction(Function f) {
|
||||
*/
|
||||
private predicate impossibleFalseEdge(Expr condition, Node succ) {
|
||||
conditionAlwaysTrue(condition) and
|
||||
qlCFGFalseSuccessor(condition, succ) and
|
||||
not qlCFGTrueSuccessor(condition, succ)
|
||||
qlCfgFalseSuccessor(condition, succ) and
|
||||
not qlCfgTrueSuccessor(condition, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,8 +197,8 @@ private predicate impossibleFalseEdge(Expr condition, Node succ) {
|
||||
*/
|
||||
private predicate impossibleTrueEdge(Expr condition, Node succ) {
|
||||
conditionAlwaysFalse(condition) and
|
||||
qlCFGTrueSuccessor(condition, succ) and
|
||||
not qlCFGFalseSuccessor(condition, succ)
|
||||
qlCfgTrueSuccessor(condition, succ) and
|
||||
not qlCfgFalseSuccessor(condition, succ)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -960,9 +960,9 @@ library class ConditionEvaluator extends ExprEvaluator {
|
||||
ConditionEvaluator() { this = 0 }
|
||||
|
||||
override predicate interesting(Expr e) {
|
||||
qlCFGFalseSuccessor(e, _)
|
||||
qlCfgFalseSuccessor(e, _)
|
||||
or
|
||||
qlCFGTrueSuccessor(e, _)
|
||||
qlCfgTrueSuccessor(e, _)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,10 +20,4 @@ import semmle.code.cpp.dataflow.DataFlow2
|
||||
|
||||
module TaintTracking {
|
||||
import semmle.code.cpp.dataflow.internal.tainttracking1.TaintTrackingImpl
|
||||
private import semmle.code.cpp.dataflow.TaintTracking2
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use TaintTracking2::Configuration instead.
|
||||
*/
|
||||
deprecated class Configuration2 = TaintTracking2::Configuration;
|
||||
}
|
||||
|
||||
@@ -113,10 +113,6 @@ private module PartialDefinitions {
|
||||
abstract class PartialDefinition extends Expr {
|
||||
ControlFlowNode node;
|
||||
|
||||
abstract deprecated predicate partiallyDefines(Variable v);
|
||||
|
||||
abstract deprecated predicate partiallyDefinesThis(ThisExpr e);
|
||||
|
||||
/**
|
||||
* Gets the subBasicBlock where this `PartialDefinition` is defined.
|
||||
*/
|
||||
@@ -189,10 +185,6 @@ private module PartialDefinitions {
|
||||
)
|
||||
}
|
||||
|
||||
deprecated override predicate partiallyDefines(Variable v) { v = collection }
|
||||
|
||||
deprecated override predicate partiallyDefinesThis(ThisExpr e) { none() }
|
||||
|
||||
override predicate definesExpressions(Expr inner, Expr outer) {
|
||||
inner = innerDefinedExpr and
|
||||
outer = this
|
||||
@@ -217,12 +209,6 @@ private module PartialDefinitions {
|
||||
|
||||
VariablePartialDefinition() { innerDefinedExpr = getInnerDefinedExpr(this, node) }
|
||||
|
||||
deprecated override predicate partiallyDefines(Variable v) {
|
||||
innerDefinedExpr = v.getAnAccess()
|
||||
}
|
||||
|
||||
deprecated override predicate partiallyDefinesThis(ThisExpr e) { innerDefinedExpr = e }
|
||||
|
||||
/**
|
||||
* Holds if this partial definition may modify `inner` (or what it points
|
||||
* to) through `outer`. These expressions will never be `Conversion`s.
|
||||
|
||||
@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
* Holds if `source` is a relevant taint source with the given initial
|
||||
* `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink accepting `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -79,6 +96,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the node `node` is a taint sanitizer when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizer(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -107,6 +134,25 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis. This step is only applicable
|
||||
* in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
|
||||
@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
* Holds if `source` is a relevant taint source with the given initial
|
||||
* `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink accepting `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -79,6 +96,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the node `node` is a taint sanitizer when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizer(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -107,6 +134,25 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis. This step is only applicable
|
||||
* in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
|
||||
@@ -226,13 +226,6 @@ class AssignPointerSubExpr extends AssignOperation, @assignpsubexpr {
|
||||
* ```
|
||||
*/
|
||||
class ConditionDeclExpr extends Expr, @condition_decl {
|
||||
/**
|
||||
* DEPRECATED: Use `getVariableAccess()` or `getInitializingExpr()` instead.
|
||||
*
|
||||
* Gets the access using the condition for this declaration.
|
||||
*/
|
||||
deprecated Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ConditionDeclExpr" }
|
||||
|
||||
/**
|
||||
|
||||
@@ -118,11 +118,6 @@ class BuiltInNoOp extends BuiltInOperation, @noopexpr {
|
||||
override string getAPrimaryQlClass() { result = "BuiltInNoOp" }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BuiltInOperationBuiltInOffsetOf` instead.
|
||||
*/
|
||||
deprecated class BuiltInOperationOffsetOf = BuiltInOperationBuiltInOffsetOf;
|
||||
|
||||
/**
|
||||
* A C/C++ `__builtin_offsetof` built-in operation (used by some implementations
|
||||
* of `offsetof`). The operation retains its semantics even in the presence
|
||||
@@ -465,11 +460,6 @@ class BuiltInOperationIsUnion extends BuiltInOperation, @isunionexpr {
|
||||
override string getAPrimaryQlClass() { result = "BuiltInOperationIsUnion" }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `BuiltInOperationBuiltInTypesCompatibleP` instead.
|
||||
*/
|
||||
deprecated class BuiltInOperationBuiltInTypes = BuiltInOperationBuiltInTypesCompatibleP;
|
||||
|
||||
/**
|
||||
* A C++ `__builtin_types_compatible_p` built-in operation (used by some
|
||||
* implementations of the `<type_traits>` header).
|
||||
|
||||
@@ -666,13 +666,6 @@ class TypeidOperator extends Expr, @type_id {
|
||||
*/
|
||||
Type getResultType() { typeid_bind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getResultType()` instead.
|
||||
*
|
||||
* Gets the type that is returned by this typeid expression.
|
||||
*/
|
||||
deprecated Type getSpecifiedType() { result = this.getResultType() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TypeidOperator" }
|
||||
|
||||
/**
|
||||
@@ -731,13 +724,6 @@ class SizeofExprOperator extends SizeofOperator {
|
||||
/** Gets the contained expression. */
|
||||
Expr getExprOperand() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getExprOperand()` instead
|
||||
*
|
||||
* Gets the contained expression.
|
||||
*/
|
||||
deprecated Expr getExpr() { result = this.getExprOperand() }
|
||||
|
||||
override string toString() { result = "sizeof(<expr>)" }
|
||||
|
||||
override predicate mayBeImpure() { this.getExprOperand().mayBeImpure() }
|
||||
@@ -759,13 +745,6 @@ class SizeofTypeOperator extends SizeofOperator {
|
||||
/** Gets the contained type. */
|
||||
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getTypeOperand()` instead
|
||||
*
|
||||
* Gets the contained type.
|
||||
*/
|
||||
deprecated Type getSpecifiedType() { result = this.getTypeOperand() }
|
||||
|
||||
override string toString() { result = "sizeof(" + this.getTypeOperand().getName() + ")" }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
@@ -794,11 +773,6 @@ class AlignofExprOperator extends AlignofOperator {
|
||||
*/
|
||||
Expr getExprOperand() { result = this.getChild(0) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getExprOperand()` instead.
|
||||
*/
|
||||
deprecated Expr getExpr() { result = this.getExprOperand() }
|
||||
|
||||
override string toString() { result = "alignof(<expr>)" }
|
||||
}
|
||||
|
||||
@@ -814,11 +788,6 @@ class AlignofTypeOperator extends AlignofOperator {
|
||||
/** Gets the contained type. */
|
||||
Type getTypeOperand() { sizeof_bind(underlyingElement(this), unresolveElement(result)) }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getTypeOperand()` instead.
|
||||
*/
|
||||
deprecated Type getSpecifiedType() { result = this.getTypeOperand() }
|
||||
|
||||
override string toString() { result = "alignof(" + this.getTypeOperand().getName() + ")" }
|
||||
}
|
||||
|
||||
|
||||
@@ -48,16 +48,6 @@ class NEExpr extends EqualityOperation, @neexpr {
|
||||
class RelationalOperation extends ComparisonOperation, @rel_op_expr {
|
||||
override int getPrecedence() { result = 10 }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getGreaterOperand()` instead.
|
||||
*/
|
||||
deprecated Expr getLarge() { result = getGreaterOperand() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getLesserOperand()` instead.
|
||||
*/
|
||||
deprecated Expr getSmall() { result = getLesserOperand() }
|
||||
|
||||
/**
|
||||
* Gets the operand on the "greater" (or "greater-or-equal") side
|
||||
* of this relational expression, that is, the side that is larger
|
||||
|
||||
@@ -114,13 +114,6 @@ class Expr extends StmtParent, @expr {
|
||||
*/
|
||||
Type getUnspecifiedType() { result = this.getType().getUnspecifiedType() }
|
||||
|
||||
/**
|
||||
* Gets an integer indicating the type of expression that this represents.
|
||||
*
|
||||
* DEPRECATED: use the subclasses of `Expr` rather than relying on this predicate.
|
||||
*/
|
||||
deprecated int getKind() { exprs(underlyingElement(this), result, _) }
|
||||
|
||||
/** Gets a textual representation of this expression. */
|
||||
override string toString() { none() }
|
||||
|
||||
|
||||
@@ -164,16 +164,6 @@ class HexLiteral extends Literal {
|
||||
class AggregateLiteral extends Expr, @aggregateliteral {
|
||||
override string getAPrimaryQlClass() { result = "AggregateLiteral" }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use ClassAggregateLiteral.getFieldExpr() instead.
|
||||
*
|
||||
* Gets the expression within the aggregate literal that is used to initialise field `f`,
|
||||
* if this literal is being used to initialise a class/struct instance.
|
||||
*/
|
||||
deprecated Expr getCorrespondingExpr(Field f) {
|
||||
result = this.(ClassAggregateLiteral).getFieldExpr(f)
|
||||
}
|
||||
|
||||
override predicate mayBeImpure() { this.getAChild().mayBeImpure() }
|
||||
|
||||
override predicate mayBeGloballyImpure() { this.getAChild().mayBeGloballyImpure() }
|
||||
|
||||
@@ -1,297 +0,0 @@
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.exprs.Expr
|
||||
import semmle.code.cpp.Class
|
||||
import semmle.code.cpp.ObjectiveC
|
||||
private import semmle.code.cpp.internal.ResolveClass
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C message expression, for example `[myColor changeColorToRed:5.0 green:2.0 blue:6.0]`.
|
||||
*/
|
||||
deprecated class MessageExpr extends Expr, Call {
|
||||
MessageExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets the selector of this message expression, for example `-changeColorToRed:green:blue:`.
|
||||
*/
|
||||
string getSelector() { none() }
|
||||
|
||||
/**
|
||||
* Gets the function invoked by this message expression, as inferred by the compiler.
|
||||
*
|
||||
* If the compiler could infer the type of the receiver, and that type had a method
|
||||
* whose name matched the selector, then the result of this predicate is said method.
|
||||
* Otherwise this predicate has no result.
|
||||
*
|
||||
* In all cases, actual function dispatch isn't performed until runtime, but the
|
||||
* lack of a static target is often cause for concern.
|
||||
*/
|
||||
MemberFunction getStaticTarget() { none() }
|
||||
|
||||
/**
|
||||
* Provided for compatibility with Call. It is the same as the static target.
|
||||
*/
|
||||
override MemberFunction getTarget() { none() }
|
||||
|
||||
/**
|
||||
* Holds if the compiler could infer a function as the target of this message.
|
||||
*
|
||||
* In all cases, actual function dispatch isn't performed until runtime, but the
|
||||
* lack of a static target is often cause for concern.
|
||||
*/
|
||||
predicate hasStaticTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets the number of arguments passed by this message expression.
|
||||
*
|
||||
* In most cases, this equals the number of colons in the selector, but this needn't be the
|
||||
* case for variadic methods like "-initWithFormat:", which can have more than one argument.
|
||||
*/
|
||||
override int getNumberOfArguments() { none() }
|
||||
|
||||
/**
|
||||
* Gets an argument passed by this message expression.
|
||||
*/
|
||||
override Expr getAnArgument() { none() }
|
||||
|
||||
/**
|
||||
* Gets the nth argument passed by this message expression.
|
||||
*
|
||||
* The range of `n` is [`0` .. `getNumberOfArguments()`].
|
||||
*/
|
||||
override Expr getArgument(int n) { none() }
|
||||
|
||||
override int getPrecedence() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C message expression whose receiver is `super`, for example `[super init]`.
|
||||
*/
|
||||
deprecated class SuperMessageExpr extends MessageExpr {
|
||||
SuperMessageExpr() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C message expression whose receiver is the name of a class, and
|
||||
* is therefore calling a class method rather than an instance method. This occurs
|
||||
* most commonly for the "+alloc", "+new", and "+class" selectors.
|
||||
*/
|
||||
deprecated class ClassMessageExpr extends MessageExpr {
|
||||
ClassMessageExpr() { none() }
|
||||
|
||||
/**
|
||||
* Gets the class which is the receiver of this message.
|
||||
*/
|
||||
Type getReceiver() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C message expression whose receiver is an expression (which includes the
|
||||
* common case of the receiver being "self").
|
||||
*/
|
||||
deprecated class ExprMessageExpr extends MessageExpr {
|
||||
ExprMessageExpr() { none() }
|
||||
|
||||
/**
|
||||
* Gets the expression which gives the receiver of this message.
|
||||
*/
|
||||
Expr getReceiver() { none() }
|
||||
|
||||
/**
|
||||
* Gets the Objective C class of which the receiving expression is an instance.
|
||||
*
|
||||
* If the receiving expression has type `id` or type `id<P>` for some protocol `P`,
|
||||
* then there will be no result. If the receiving expression has type `C*` or type
|
||||
* `C<P>*` for some protocol `P`, then the result will be the type `C`.
|
||||
*/
|
||||
ObjectiveClass getReceiverClass() { none() }
|
||||
|
||||
/**
|
||||
* Gets the Objective C classes and/or protocols which are statically implemented
|
||||
* by the receiving expression.
|
||||
*
|
||||
* If the receiving expression has type `id`, then there will be no result.
|
||||
* If the receiving expression has type `id<P>`, then `P` will be the sole result.
|
||||
* If the receiving expression has type `C*`, then `C` will be the sole result.
|
||||
* If the receiving expression has type `C<P>*`, then `C` and `P` will both be results.
|
||||
*/
|
||||
Class getAReceiverClassOrProtocol() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An access to an Objective C property using dot syntax.
|
||||
*
|
||||
* Such accesses are de-sugared into a message expression to the property's getter or setter.
|
||||
*/
|
||||
deprecated class PropertyAccess extends ExprMessageExpr {
|
||||
PropertyAccess() { none() }
|
||||
|
||||
/**
|
||||
* Gets the property being accessed by this expression.
|
||||
*/
|
||||
Property getProperty() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@selector` expression, for example `@selector(driveForDistance:)`.
|
||||
*/
|
||||
deprecated class AtSelectorExpr extends Expr {
|
||||
AtSelectorExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets the selector of this `@selector` expression, for example `driveForDistance:`.
|
||||
*/
|
||||
string getSelector() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@protocol` expression, for example `@protocol(SomeProtocol)`.
|
||||
*/
|
||||
deprecated class AtProtocolExpr extends Expr {
|
||||
AtProtocolExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets the protocol of this `@protocol` expression, for example `SomeProtocol`.
|
||||
*/
|
||||
Protocol getProtocol() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C `@encode` expression, for example `@encode(int *)`.
|
||||
*/
|
||||
deprecated class AtEncodeExpr extends Expr {
|
||||
AtEncodeExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type this `@encode` expression encodes, for example `int *`.
|
||||
*/
|
||||
Type getEncodedType() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C throw expression.
|
||||
*/
|
||||
deprecated class ObjcThrowExpr extends ThrowExpr {
|
||||
ObjcThrowExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C throw expression with no argument (which causes the
|
||||
* current exception to be re-thrown).
|
||||
*/
|
||||
deprecated class ObjcReThrowExpr extends ReThrowExpr, ObjcThrowExpr {
|
||||
ObjcReThrowExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C @ expression which boxes a single value, such as @(22).
|
||||
*/
|
||||
deprecated class AtExpr extends UnaryOperation {
|
||||
AtExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
override string getOperator() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C @[...] literal.
|
||||
*/
|
||||
deprecated class ArrayLiteral extends Expr {
|
||||
ArrayLiteral() { none() }
|
||||
|
||||
/** Gets a textual representation of this array literal. */
|
||||
override string toString() { none() }
|
||||
|
||||
/** An element of the array */
|
||||
Expr getElement(int i) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C @{...} literal.
|
||||
*/
|
||||
deprecated class DictionaryLiteral extends Expr {
|
||||
DictionaryLiteral() { none() }
|
||||
|
||||
/** Gets a textual representation of this dictionary literal. */
|
||||
override string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C @"..." string literal.
|
||||
*/
|
||||
deprecated class ObjCLiteralString extends TextLiteral {
|
||||
ObjCLiteralString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C/C++ overloaded subscripting access expression.
|
||||
*
|
||||
* Either
|
||||
* obj[idx]
|
||||
* or
|
||||
* obj[idx] = expr
|
||||
*/
|
||||
deprecated class SubscriptExpr extends Expr {
|
||||
SubscriptExpr() { none() }
|
||||
|
||||
/**
|
||||
* Gets the object expression being subscripted.
|
||||
*/
|
||||
Expr getSubscriptBase() { none() }
|
||||
|
||||
/**
|
||||
* Gets the expression giving the index into the object.
|
||||
*/
|
||||
Expr getSubscriptIndex() { none() }
|
||||
|
||||
/**
|
||||
* Gets the expression being assigned (if this is an assignment).
|
||||
*/
|
||||
Expr getAssignedExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Objective-C is no longer supported.
|
||||
* An Objective C _cmd expression.
|
||||
*/
|
||||
deprecated class CmdExpr extends Expr {
|
||||
CmdExpr() { none() }
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
override predicate mayBeImpure() { none() }
|
||||
|
||||
override predicate mayBeGloballyImpure() { none() }
|
||||
}
|
||||
@@ -39,19 +39,6 @@ class CorrectIncludeGuard extends IncludeGuardedHeader {
|
||||
PreprocessorEndif getEndif() { correctIncludeGuard(this, _, _, result, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: no longer useful.
|
||||
*/
|
||||
deprecated class NotIncludedGuard extends IncludeGuardedHeader {
|
||||
NotIncludedGuard() { none() }
|
||||
|
||||
/** Gets the `#ifndef` directive used to prevent multiple inclusion of this file. */
|
||||
PreprocessorIfndef getIfndef() { result.getFile() = this }
|
||||
|
||||
/** Gets the `#endif` directive closing this file. */
|
||||
PreprocessorEndif getEndif() { result.getFile() = this }
|
||||
}
|
||||
|
||||
/**
|
||||
* A file with no code in it.
|
||||
*/
|
||||
|
||||
@@ -129,11 +129,11 @@ private class FromGlobalVarTaintTrackingCfg extends TaintTracking2::Configuratio
|
||||
}
|
||||
|
||||
private predicate readsVariable(LoadInstruction load, Variable var) {
|
||||
load.getSourceAddress().(VariableAddressInstruction).getASTVariable() = var
|
||||
load.getSourceAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
|
||||
private predicate writesVariable(StoreInstruction store, Variable var) {
|
||||
store.getDestinationAddress().(VariableAddressInstruction).getASTVariable() = var
|
||||
store.getDestinationAddress().(VariableAddressInstruction).getAstVariable() = var
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,8 +241,8 @@ private module Cached {
|
||||
// For compatibility, send flow from arguments to parameters, even for
|
||||
// functions with no body.
|
||||
exists(FunctionCall call, int i |
|
||||
sink.asExpr() = call.getArgument(i) and
|
||||
result = resolveCall(call).getParameter(i)
|
||||
sink.asExpr() = call.getArgument(pragma[only_bind_into](i)) and
|
||||
result = resolveCall(call).getParameter(pragma[only_bind_into](i))
|
||||
)
|
||||
or
|
||||
// For compatibility, send flow into a `Variable` if there is flow to any
|
||||
@@ -489,9 +489,9 @@ module TaintedWithPath {
|
||||
/** Gets the element that `pathNode` wraps, if any. */
|
||||
Element getElementFromPathNode(PathNode pathNode) {
|
||||
exists(DataFlow::Node node | node = pathNode.(WrapPathNode).inner().getNode() |
|
||||
result = node.asInstruction().getAST()
|
||||
result = node.asInstruction().getAst()
|
||||
or
|
||||
result = node.asOperand().getDef().getAST()
|
||||
result = node.asOperand().getDef().getAst()
|
||||
)
|
||||
or
|
||||
result = pathNode.(EndpointPathNode).inner()
|
||||
|
||||
270
cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll
Normal file
270
cpp/ql/lib/semmle/code/cpp/ir/dataflow/MustFlow.qll
Normal file
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
* This file provides a library for inter-procedural must-flow data flow analysis.
|
||||
* Unlike `DataFlow.qll`, the analysis provided by this file checks whether data _must_ flow
|
||||
* from a source to a _sink_.
|
||||
*/
|
||||
|
||||
private import cpp
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.IR
|
||||
|
||||
/**
|
||||
* A configuration of a data flow analysis that performs must-flow analysis. This is different
|
||||
* from `DataFlow.qll` which performs may-flow analysis (i.e., it finds paths where the source _may_
|
||||
* flow to the sink).
|
||||
*
|
||||
* Like in `DataFlow.qll`, each use of the `MustFlow.qll` library must define its own unique extension
|
||||
* of this abstract class. To create a configuration, extend this class with a subclass whose
|
||||
* characteristic predicate is a unique singleton string and override `isSource`, `isSink` (and
|
||||
* `isAdditionalFlowStep` if additional steps are required).
|
||||
*/
|
||||
abstract class MustFlowConfiguration extends string {
|
||||
bindingset[this]
|
||||
MustFlowConfiguration() { any() }
|
||||
|
||||
/**
|
||||
* Holds if `source` is a relevant data flow source.
|
||||
*/
|
||||
abstract predicate isSource(DataFlow::Node source);
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant data flow sink.
|
||||
*/
|
||||
abstract predicate isSink(DataFlow::Node sink);
|
||||
|
||||
/**
|
||||
* Holds if the additional flow step from `node1` to `node2` must be taken
|
||||
* into account in the analysis.
|
||||
*/
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
/**
|
||||
* Holds if data must flow from `source` to `sink` for this configuration.
|
||||
*
|
||||
* The corresponding paths are generated from the end-points and the graph
|
||||
* included in the module `PathGraph`.
|
||||
*/
|
||||
final predicate hasFlowPath(MustFlowPathNode source, MustFlowPathSink sink) {
|
||||
this.isSource(source.getNode()) and
|
||||
source.getASuccessor+() = sink
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `node` flows from a source. */
|
||||
pragma[nomagic]
|
||||
private predicate flowsFromSource(DataFlow::Node node, MustFlowConfiguration config) {
|
||||
config.isSource(node)
|
||||
or
|
||||
exists(DataFlow::Node mid |
|
||||
step(mid, node, config) and
|
||||
flowsFromSource(mid, pragma[only_bind_into](config))
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if `node` flows to a sink. */
|
||||
pragma[nomagic]
|
||||
private predicate flowsToSink(DataFlow::Node node, MustFlowConfiguration config) {
|
||||
flowsFromSource(node, pragma[only_bind_into](config)) and
|
||||
(
|
||||
config.isSink(node)
|
||||
or
|
||||
exists(DataFlow::Node mid |
|
||||
step(node, mid, config) and
|
||||
flowsToSink(mid, pragma[only_bind_into](config))
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/** Holds if `p` is the `n`'th parameter of the non-virtual function `f`. */
|
||||
private predicate parameterOf(Parameter p, Function f, int n) {
|
||||
not f.isVirtual() and f.getParameter(n) = p
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is the `n`'th argument to a call to the non-virtual function `f`, and
|
||||
* `init` is the corresponding initialization instruction that receives the value of `instr` in `f`.
|
||||
*/
|
||||
private predicate flowIntoParameter(
|
||||
Function f, int n, CallInstruction call, Instruction instr, InitializeParameterInstruction init
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
call.getPositionalArgument(n) = instr and
|
||||
f = call.getStaticCallTarget() and
|
||||
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
|
||||
init.getParameter().getIndex() = pragma[only_bind_into](pragma[only_bind_out](n))
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an argument to a call to the function `f`, and `init` is the
|
||||
* corresponding initialization instruction that receives the value of `instr` in `f`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate getPositionalArgumentInitParam(
|
||||
CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f
|
||||
) {
|
||||
exists(int n |
|
||||
parameterOf(_, f, n) and
|
||||
flowIntoParameter(f, pragma[only_bind_into](pragma[only_bind_out](n)), call, instr, init)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is the qualifier to a call to the non-virtual function `f`, and
|
||||
* `init` is the corresponding initialization instruction that receives the value of
|
||||
* `instr` in `f`.
|
||||
*/
|
||||
pragma[noinline]
|
||||
private predicate getThisArgumentInitParam(
|
||||
CallInstruction call, Instruction instr, InitializeParameterInstruction init, Function f
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
call.getStaticCallTarget() = f and
|
||||
getEnclosingNonVirtualFunctionInitializeParameter(init, f) and
|
||||
call.getThisArgument() = instr and
|
||||
init.getIRVariable() instanceof IRThisVariable
|
||||
}
|
||||
|
||||
/** Holds if `f` is the enclosing non-virtual function of `init`. */
|
||||
private predicate getEnclosingNonVirtualFunctionInitializeParameter(
|
||||
InitializeParameterInstruction init, Function f
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
init.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
/** Holds if `f` is the enclosing non-virtual function of `init`. */
|
||||
private predicate getEnclosingNonVirtualFunctionInitializeIndirection(
|
||||
InitializeIndirectionInstruction init, Function f
|
||||
) {
|
||||
not f.isVirtual() and
|
||||
init.getEnclosingFunction() = f
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `instr` is an argument (or argument indirection) to a call, and
|
||||
* `succ` is the corresponding initialization instruction in the call target.
|
||||
*/
|
||||
private predicate flowThroughCallable(Instruction argument, Instruction parameter) {
|
||||
// Flow from an argument to a parameter
|
||||
exists(CallInstruction call, InitializeParameterInstruction init | init = parameter |
|
||||
getPositionalArgumentInitParam(call, argument, init, call.getStaticCallTarget())
|
||||
or
|
||||
getThisArgumentInitParam(call, argument, init, call.getStaticCallTarget())
|
||||
)
|
||||
or
|
||||
// Flow from argument indirection to parameter indirection
|
||||
exists(
|
||||
CallInstruction call, ReadSideEffectInstruction read, InitializeIndirectionInstruction init
|
||||
|
|
||||
init = parameter and
|
||||
read.getPrimaryInstruction() = call and
|
||||
getEnclosingNonVirtualFunctionInitializeIndirection(init, call.getStaticCallTarget())
|
||||
|
|
||||
exists(int n |
|
||||
read.getSideEffectOperand().getAnyDef() = argument and
|
||||
read.getIndex() = pragma[only_bind_into](n) and
|
||||
init.getParameter().getIndex() = pragma[only_bind_into](n)
|
||||
)
|
||||
or
|
||||
call.getThisArgument() = argument and
|
||||
init.getIRVariable() instanceof IRThisVariable
|
||||
)
|
||||
}
|
||||
|
||||
private predicate instructionToOperandStep(Instruction instr, Operand operand) {
|
||||
operand.getDef() = instr
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if data flows from `operand` to `instr`.
|
||||
*
|
||||
* This predicate ignores flow through `PhiInstruction`s to create a 'must flow' relation.
|
||||
*/
|
||||
private predicate operandToInstructionStep(Operand operand, Instruction instr) {
|
||||
instr.(CopyInstruction).getSourceValueOperand() = operand
|
||||
or
|
||||
instr.(ConvertInstruction).getUnaryOperand() = operand
|
||||
or
|
||||
instr.(CheckedConvertOrNullInstruction).getUnaryOperand() = operand
|
||||
or
|
||||
instr.(InheritanceConversionInstruction).getUnaryOperand() = operand
|
||||
or
|
||||
instr.(ChiInstruction).getTotalOperand() = operand
|
||||
}
|
||||
|
||||
cached
|
||||
predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||
instructionToOperandStep(nodeFrom.asInstruction(), nodeTo.asOperand())
|
||||
or
|
||||
flowThroughCallable(nodeFrom.asInstruction(), nodeTo.asInstruction())
|
||||
or
|
||||
operandToInstructionStep(nodeFrom.asOperand(), nodeTo.asInstruction())
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if `nodeFrom` flows to `nodeTo`. */
|
||||
private predicate step(DataFlow::Node nodeFrom, DataFlow::Node nodeTo, MustFlowConfiguration config) {
|
||||
exists(config) and
|
||||
Cached::step(nodeFrom, nodeTo)
|
||||
or
|
||||
config.isAdditionalFlowStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
private newtype TLocalPathNode =
|
||||
MkLocalPathNode(DataFlow::Node n, MustFlowConfiguration config) {
|
||||
flowsToSink(n, config) and
|
||||
(
|
||||
config.isSource(n)
|
||||
or
|
||||
exists(MustFlowPathNode mid | step(mid.getNode(), n, config))
|
||||
)
|
||||
}
|
||||
|
||||
/** A `Node` that is in a path from a source to a sink. */
|
||||
class MustFlowPathNode extends TLocalPathNode {
|
||||
DataFlow::Node n;
|
||||
|
||||
MustFlowPathNode() { this = MkLocalPathNode(n, _) }
|
||||
|
||||
/** Gets the underlying node. */
|
||||
DataFlow::Node getNode() { result = n }
|
||||
|
||||
/** Gets a textual representation of this node. */
|
||||
string toString() { result = n.toString() }
|
||||
|
||||
/** Gets the location of this element. */
|
||||
Location getLocation() { result = n.getLocation() }
|
||||
|
||||
/** Gets a successor node, if any. */
|
||||
MustFlowPathNode getASuccessor() {
|
||||
step(this.getNode(), result.getNode(), this.getConfiguration())
|
||||
}
|
||||
|
||||
/** Gets the associated configuration. */
|
||||
MustFlowConfiguration getConfiguration() { this = MkLocalPathNode(_, result) }
|
||||
}
|
||||
|
||||
private class MustFlowPathSink extends MustFlowPathNode {
|
||||
MustFlowPathSink() { this.getConfiguration().isSink(this.getNode()) }
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the query predicates needed to include a graph in a path-problem query.
|
||||
*/
|
||||
module PathGraph {
|
||||
private predicate reach(MustFlowPathNode n) {
|
||||
n instanceof MustFlowPathSink or reach(n.getASuccessor())
|
||||
}
|
||||
|
||||
/** Holds if `(a,b)` is an edge in the graph of data flow path explanations. */
|
||||
query predicate edges(MustFlowPathNode a, MustFlowPathNode b) {
|
||||
a.getASuccessor() = b and reach(b)
|
||||
}
|
||||
|
||||
/** Holds if `n` is a node in the graph of data flow path explanations. */
|
||||
query predicate nodes(MustFlowPathNode n, string key, string val) {
|
||||
reach(n) and key = "semmle.label" and val = n.toString()
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ private import semmle.code.cpp.ir.IR
|
||||
*/
|
||||
Function resolveCall(Call call) {
|
||||
exists(CallInstruction callInstruction |
|
||||
callInstruction.getAST() = call and
|
||||
callInstruction.getAst() = call and
|
||||
result = viableCallable(callInstruction)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -20,10 +20,4 @@ import semmle.code.cpp.ir.dataflow.DataFlow2
|
||||
|
||||
module TaintTracking {
|
||||
import semmle.code.cpp.ir.dataflow.internal.tainttracking1.TaintTrackingImpl
|
||||
private import semmle.code.cpp.ir.dataflow.TaintTracking2
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use TaintTracking2::Configuration instead.
|
||||
*/
|
||||
deprecated class Configuration2 = TaintTracking2::Configuration;
|
||||
}
|
||||
|
||||
@@ -116,12 +116,12 @@ private module VirtualDispatch {
|
||||
/** Holds if `addressInstr` is an instruction that produces the address of `var`. */
|
||||
private predicate addressOfGlobal(Instruction addressInstr, GlobalOrNamespaceVariable var) {
|
||||
// Access directly to the global variable
|
||||
addressInstr.(VariableAddressInstruction).getASTVariable() = var
|
||||
addressInstr.(VariableAddressInstruction).getAstVariable() = var
|
||||
or
|
||||
// Access to a field on a global union
|
||||
exists(FieldAddressInstruction fa |
|
||||
fa = addressInstr and
|
||||
fa.getObjectAddress().(VariableAddressInstruction).getASTVariable() = var and
|
||||
fa.getObjectAddress().(VariableAddressInstruction).getAstVariable() = var and
|
||||
fa.getField().getDeclaringType() instanceof Union
|
||||
)
|
||||
}
|
||||
|
||||
@@ -158,14 +158,6 @@ class Node extends TIRDataFlowNode {
|
||||
*/
|
||||
Expr asPartialDefinition() { result = this.(PartialDefinitionNode).getDefinedExpr() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: See UninitializedNode.
|
||||
*
|
||||
* Gets the uninitialized local variable corresponding to this node, if
|
||||
* any.
|
||||
*/
|
||||
deprecated LocalVariable asUninitialized() { none() }
|
||||
|
||||
/**
|
||||
* Gets an upper bound on the type of this node.
|
||||
*/
|
||||
@@ -439,7 +431,7 @@ class SsaPhiNode extends Node, TSsaPhiNode {
|
||||
|
||||
SsaPhiNode() { this = TSsaPhiNode(phi) }
|
||||
|
||||
/* Get the phi node associated with this node. */
|
||||
/** Gets the phi node associated with this node. */
|
||||
Ssa::PhiNode getPhiNode() { result = phi }
|
||||
|
||||
override Declaration getEnclosingCallable() { result = this.getFunction() }
|
||||
@@ -560,22 +552,6 @@ class ParameterIndirectionNode extends ParameterNode {
|
||||
override string toString() { result = "*" + instr.getIRVariable().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Data flow was never an accurate way to determine what
|
||||
* expressions might be uninitialized. It errs on the side of saying that
|
||||
* everything is uninitialized, and this is even worse in the IR because the IR
|
||||
* doesn't use syntactic hints to rule out variables that are definitely
|
||||
* initialized.
|
||||
*
|
||||
* The value of an uninitialized local variable, viewed as a node in a data
|
||||
* flow graph.
|
||||
*/
|
||||
deprecated class UninitializedNode extends Node {
|
||||
UninitializedNode() { none() }
|
||||
|
||||
LocalVariable getLocalVariable() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node associated with an object after an operation that might have
|
||||
* changed its state.
|
||||
@@ -725,14 +701,6 @@ InstructionNode instructionNode(Instruction instr) { result.getInstruction() = i
|
||||
*/
|
||||
OperandNode operandNode(Operand operand) { result.getOperand() = operand }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `definitionByReferenceNodeFromArgument` instead.
|
||||
*
|
||||
* Gets the `Node` corresponding to a definition by reference of the variable
|
||||
* that is passed as `argument` of a call.
|
||||
*/
|
||||
deprecated DefinitionByReferenceNode definitionByReferenceNode(Expr e) { result.getArgument() = e }
|
||||
|
||||
/**
|
||||
* Gets the `Node` corresponding to the value of evaluating `e` or any of its
|
||||
* conversions. There is no result if `e` is a `Conversion`. For data flowing
|
||||
|
||||
@@ -287,20 +287,6 @@ private module SsaDefReaches {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the SSA definition of `v` at `def` reaches uncertain SSA definition
|
||||
* `redef` in the same basic block, without crossing another SSA definition of `v`.
|
||||
*/
|
||||
predicate ssaDefReachesUncertainDefWithinBlock(
|
||||
SourceVariable v, Definition def, UncertainWriteDefinition redef
|
||||
) {
|
||||
exists(BasicBlock bb, int rnk, int i |
|
||||
ssaDefReachesRank(bb, def, rnk, v) and
|
||||
rnk = ssaRefRank(bb, i, v, SsaDef()) - 1 and
|
||||
redef.definesAt(v, bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `ssaRefRank()`, but restricted to a particular SSA definition `def`.
|
||||
*/
|
||||
|
||||
@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
* Holds if `source` is a relevant taint source with the given initial
|
||||
* `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink accepting `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -79,6 +96,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the node `node` is a taint sanitizer when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizer(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -107,6 +134,25 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis. This step is only applicable
|
||||
* in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
|
||||
@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
* Holds if `source` is a relevant taint source with the given initial
|
||||
* `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink accepting `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -79,6 +96,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the node `node` is a taint sanitizer when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizer(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -107,6 +134,25 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis. This step is only applicable
|
||||
* in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
|
||||
@@ -64,13 +64,30 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
override predicate isSource(DataFlow::Node source) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink.
|
||||
* Holds if `source` is a relevant taint source with the given initial
|
||||
* `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSource(DataFlow::Node source, DataFlow::FlowState state) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink) { none() }
|
||||
|
||||
/**
|
||||
* Holds if `sink` is a relevant taint sink accepting `state`.
|
||||
*
|
||||
* The smaller this predicate is, the faster `hasFlow()` will converge.
|
||||
*/
|
||||
// overridden to provide taint-tracking specific qldoc
|
||||
override predicate isSink(DataFlow::Node sink, DataFlow::FlowState state) { none() }
|
||||
|
||||
/** Holds if the node `node` is a taint sanitizer. */
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -79,6 +96,16 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the node `node` is a taint sanitizer when the flow state is
|
||||
* `state`.
|
||||
*/
|
||||
predicate isSanitizer(DataFlow::Node node, DataFlow::FlowState state) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node, DataFlow::FlowState state) {
|
||||
this.isSanitizer(node, state)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
@@ -107,6 +134,25 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
* must be taken into account in the analysis. This step is only applicable
|
||||
* in `state1` and updates the flow state to `state2`.
|
||||
*/
|
||||
predicate isAdditionalTaintStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
none()
|
||||
}
|
||||
|
||||
final override predicate isAdditionalFlowStep(
|
||||
DataFlow::Node node1, DataFlow::FlowState state1, DataFlow::Node node2,
|
||||
DataFlow::FlowState state2
|
||||
) {
|
||||
this.isAdditionalTaintStep(node1, state1, node2, state2)
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::Content c) {
|
||||
(this.isSink(node) or this.isAdditionalTaintStep(node, _)) and
|
||||
defaultImplicitTaintRead(node, c)
|
||||
|
||||
@@ -55,7 +55,10 @@ class IRVariable extends TIRVariable {
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
* variable as part of the AST-to-IR translation.
|
||||
*/
|
||||
Language::AST getAST() { none() }
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -66,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getAST().getLocation() }
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -90,7 +93,10 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
|
||||
final override Language::AST getAST() { result = var }
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
@@ -157,7 +163,10 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() }
|
||||
final string toString() { result = this.getOpcode().toString() + ": " + this.getAst().toString() }
|
||||
|
||||
/**
|
||||
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
|
||||
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
string getResultId() {
|
||||
this.shouldGenerateDumpStrings() and
|
||||
result =
|
||||
this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank()
|
||||
this.getResultPrefix() + this.getAst().getLocation().getStartLine() + "_" + this.getLineRank()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,12 +208,15 @@ class Instruction extends Construction::TStageInstruction {
|
||||
/**
|
||||
* Gets the AST that caused this instruction to be generated.
|
||||
*/
|
||||
final Language::AST getAST() { result = Construction::getInstructionAST(this) }
|
||||
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.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getAST().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
|
||||
@@ -459,7 +462,10 @@ 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() }
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@ private import internal.OperandInternal
|
||||
* of `TOperand` that are used in this stage.
|
||||
*/
|
||||
private class TStageOperand =
|
||||
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
|
||||
TRegisterOperand or TNonSsaMemoryOperand or TPhiOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
|
||||
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
|
||||
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
|
||||
exists(Instruction use, Instruction def | this = registerOperand(use, _, def))
|
||||
or
|
||||
exists(Instruction use | this = nonSSAMemoryOperand(use, _))
|
||||
exists(Instruction use | this = nonSsaMemoryOperand(use, _))
|
||||
or
|
||||
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
|
||||
this = phiOperand(use, def, predecessorBlock, _) or
|
||||
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
|
||||
class MemoryOperand extends Operand {
|
||||
cached
|
||||
MemoryOperand() {
|
||||
this instanceof TNonSSAMemoryOperand or
|
||||
this instanceof TNonSsaMemoryOperand or
|
||||
this instanceof TPhiOperand or
|
||||
this instanceof TChiOperand
|
||||
}
|
||||
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
|
||||
|
||||
NonPhiOperand() {
|
||||
this = registerOperand(useInstr, tag, _) or
|
||||
this = nonSSAMemoryOperand(useInstr, tag) or
|
||||
this = nonSsaMemoryOperand(useInstr, tag) or
|
||||
this = chiOperand(useInstr, tag)
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
|
||||
cached
|
||||
NonPhiMemoryOperand() {
|
||||
this = nonSSAMemoryOperand(useInstr, tag)
|
||||
this = nonSsaMemoryOperand(useInstr, tag)
|
||||
or
|
||||
this = chiOperand(useInstr, tag)
|
||||
}
|
||||
|
||||
@@ -99,13 +99,19 @@ private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
// count rather than strictcount to handle missing AST elements
|
||||
// separate instanceof and inline casts to avoid failed casts with a count of 0
|
||||
instr instanceof VariableAddressInstruction and
|
||||
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
|
||||
count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
|
||||
or
|
||||
instr instanceof ConstantInstruction and
|
||||
count(instr.getResultIRType()) != 1
|
||||
or
|
||||
instr instanceof FieldAddressInstruction and
|
||||
count(instr.(FieldAddressInstruction).getField()) != 1
|
||||
or
|
||||
instr instanceof InheritanceConversionInstruction and
|
||||
(
|
||||
count(instr.(InheritanceConversionInstruction).getBaseClass()) != 1 or
|
||||
count(instr.(InheritanceConversionInstruction).getDerivedClass()) != 1
|
||||
)
|
||||
}
|
||||
|
||||
private predicate variableAddressValueNumber(
|
||||
@@ -115,8 +121,7 @@ private predicate variableAddressValueNumber(
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
instr.getIRVariable().getAST() = ast and
|
||||
strictcount(instr.getIRVariable().getAST()) = 1
|
||||
unique( | | instr.getIRVariable().getAst()) = ast
|
||||
}
|
||||
|
||||
private predicate initializeParameterValueNumber(
|
||||
@@ -126,15 +131,14 @@ private predicate initializeParameterValueNumber(
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
instr.getIRVariable().getAST() = var
|
||||
instr.getIRVariable().getAst() = var
|
||||
}
|
||||
|
||||
private predicate constantValueNumber(
|
||||
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
strictcount(instr.getResultIRType()) = 1 and
|
||||
instr.getResultIRType() = type and
|
||||
unique( | | instr.getResultIRType()) = type and
|
||||
instr.getValue() = value
|
||||
}
|
||||
|
||||
@@ -151,8 +155,7 @@ private predicate fieldAddressValueNumber(
|
||||
TValueNumber objectAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
instr.getField() = field and
|
||||
strictcount(instr.getField()) = 1 and
|
||||
unique( | | instr.getField()) = field and
|
||||
tvalueNumber(instr.getObjectAddress()) = objectAddress
|
||||
}
|
||||
|
||||
@@ -195,9 +198,9 @@ private predicate inheritanceConversionValueNumber(
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getBaseClass() = baseClass and
|
||||
instr.getDerivedClass() = derivedClass and
|
||||
tvalueNumber(instr.getUnary()) = operand
|
||||
tvalueNumber(instr.getUnary()) = operand and
|
||||
unique( | | instr.getBaseClass()) = baseClass and
|
||||
unique( | | instr.getDerivedClass()) = derivedClass
|
||||
}
|
||||
|
||||
private predicate loadTotalOverlapValueNumber(
|
||||
|
||||
@@ -2,12 +2,12 @@ private import AliasConfigurationInternal
|
||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
|
||||
private import cpp
|
||||
private import AliasAnalysis
|
||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SimpleSSA as UnaliasedSSA
|
||||
private import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SimpleSSA as UnaliasedSsa
|
||||
|
||||
private newtype TAllocation =
|
||||
TVariableAllocation(IRVariable var) {
|
||||
// Only model variables that were not already handled in unaliased SSA.
|
||||
not UnaliasedSSA::canReuseSSAForVariable(var)
|
||||
not UnaliasedSsa::canReuseSsaForVariable(var)
|
||||
} or
|
||||
TIndirectParameterAllocation(IRAutomaticVariable var) {
|
||||
exists(InitializeIndirectionInstruction instr | instr.getIRVariable() = var)
|
||||
|
||||
@@ -133,7 +133,10 @@ abstract class MemoryLocation extends TMemoryLocation {
|
||||
*/
|
||||
predicate isAlwaysAllocatedOnStack() { none() }
|
||||
|
||||
final predicate canReuseSSA() { none() }
|
||||
final predicate canReuseSsa() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for canReuseSsa */
|
||||
deprecated predicate canReuseSSA() { canReuseSsa() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -569,13 +572,16 @@ private Overlap getVariableMemoryLocationOverlap(
|
||||
* Holds if the def/use information for the result of `instr` can be reused from the previous
|
||||
* iteration of the IR.
|
||||
*/
|
||||
predicate canReuseSSAForOldResult(Instruction instr) { OldSSA::canReuseSSAForMemoryResult(instr) }
|
||||
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() }
|
||||
|
||||
MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
not canReuseSSAForOldResult(instr) and
|
||||
not canReuseSsaForOldResult(instr) and
|
||||
exists(MemoryAccessKind kind, boolean isMayAccess |
|
||||
kind = instr.getResultMemoryAccess() and
|
||||
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
|
||||
@@ -608,7 +614,7 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
|
||||
}
|
||||
|
||||
MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
|
||||
not canReuseSSAForOldResult(operand.getAnyDef()) and
|
||||
not canReuseSsaForOldResult(operand.getAnyDef()) and
|
||||
exists(MemoryAccessKind kind, boolean isMayAccess |
|
||||
kind = operand.getMemoryAccess() and
|
||||
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
private import semmle.code.cpp.ir.implementation.internal.TOperand
|
||||
import AliasedSSAOperands
|
||||
import AliasedSsaOperands
|
||||
|
||||
@@ -2,7 +2,7 @@ private import SSAConstructionInternal
|
||||
private import OldIR
|
||||
private import Alias
|
||||
private import SSAConstruction
|
||||
private import DebugSSA
|
||||
private import DebugSsa
|
||||
|
||||
bindingset[offset]
|
||||
private string getKeySuffixForOffset(int offset) {
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
private import SSAConstruction as SSA
|
||||
import SSA::SSAConsistency
|
||||
import SSA::SsaConsistency
|
||||
|
||||
@@ -112,7 +112,7 @@ private module Cached {
|
||||
exists(Alias::getResultMemoryLocation(oldInstruction))
|
||||
or
|
||||
// This result was already modeled by a previous iteration of SSA.
|
||||
Alias::canReuseSSAForOldResult(oldInstruction)
|
||||
Alias::canReuseSsaForOldResult(oldInstruction)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -182,7 +182,7 @@ private module Cached {
|
||||
* unreachable, this predicate will recurse through any degenerate `Phi` instructions to find the
|
||||
* true definition.
|
||||
*/
|
||||
private Instruction getNewDefinitionFromOldSSA(OldIR::MemoryOperand oldOperand, Overlap overlap) {
|
||||
private Instruction getNewDefinitionFromOldSsa(OldIR::MemoryOperand oldOperand, Overlap overlap) {
|
||||
exists(Overlap originalOverlap |
|
||||
originalOverlap = oldOperand.getDefinitionOverlap() and
|
||||
(
|
||||
@@ -191,7 +191,7 @@ private module Cached {
|
||||
or
|
||||
exists(OldIR::PhiInputOperand phiOperand, Overlap phiOperandOverlap |
|
||||
phiOperand = getDegeneratePhiOperand(oldOperand.getAnyDef()) and
|
||||
result = getNewDefinitionFromOldSSA(phiOperand, phiOperandOverlap) and
|
||||
result = getNewDefinitionFromOldSsa(phiOperand, phiOperandOverlap) and
|
||||
overlap =
|
||||
combineOverlap(pragma[only_bind_out](phiOperandOverlap),
|
||||
pragma[only_bind_out](originalOverlap))
|
||||
@@ -233,7 +233,7 @@ private module Cached {
|
||||
)
|
||||
or
|
||||
exists(OldIR::NonPhiMemoryOperand oldOperand |
|
||||
result = getNewDefinitionFromOldSSA(oldOperand, overlap) and
|
||||
result = getNewDefinitionFromOldSsa(oldOperand, overlap) and
|
||||
oldOperand.getUse() = instruction and
|
||||
tag = oldOperand.getOperandTag()
|
||||
)
|
||||
@@ -307,13 +307,13 @@ private module Cached {
|
||||
* Gets the new definition instruction for the operand of `instr` that flows from the block
|
||||
* `newPredecessorBlock`, based on that operand's definition in the old IR.
|
||||
*/
|
||||
private Instruction getNewPhiOperandDefinitionFromOldSSA(
|
||||
private Instruction getNewPhiOperandDefinitionFromOldSsa(
|
||||
Instruction instr, IRBlock newPredecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(OldIR::PhiInstruction oldPhi, OldIR::PhiInputOperand oldOperand |
|
||||
oldPhi = getOldInstruction(instr) and
|
||||
oldOperand = oldPhi.getInputOperand(getOldBlock(newPredecessorBlock)) and
|
||||
result = getNewDefinitionFromOldSSA(oldOperand, overlap)
|
||||
result = getNewDefinitionFromOldSsa(oldOperand, overlap)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -333,7 +333,7 @@ private module Cached {
|
||||
overlap = Alias::getOverlap(actualDefLocation, useLocation)
|
||||
)
|
||||
or
|
||||
result = getNewPhiOperandDefinitionFromOldSSA(instr, newPredecessorBlock, overlap)
|
||||
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
|
||||
}
|
||||
|
||||
cached
|
||||
@@ -412,17 +412,17 @@ private module Cached {
|
||||
}
|
||||
|
||||
cached
|
||||
Language::AST getInstructionAST(Instruction instr) {
|
||||
result = getOldInstruction(instr).getAST()
|
||||
Language::AST getInstructionAst(Instruction instr) {
|
||||
result = getOldInstruction(instr).getAst()
|
||||
or
|
||||
exists(RawIR::Instruction blockStartInstr |
|
||||
instr = phiInstruction(blockStartInstr, _) and
|
||||
result = blockStartInstr.getAST()
|
||||
result = blockStartInstr.getAst()
|
||||
)
|
||||
or
|
||||
exists(RawIR::Instruction primaryInstr |
|
||||
instr = chiInstruction(primaryInstr) and
|
||||
result = primaryInstr.getAST()
|
||||
result = primaryInstr.getAst()
|
||||
)
|
||||
or
|
||||
exists(IRFunctionBase irFunc |
|
||||
@@ -430,6 +430,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()
|
||||
@@ -975,35 +981,41 @@ module DefUse {
|
||||
}
|
||||
}
|
||||
|
||||
predicate canReuseSSAForMemoryResult(Instruction instruction) {
|
||||
predicate canReuseSsaForMemoryResult(Instruction instruction) {
|
||||
exists(OldInstruction oldInstruction |
|
||||
oldInstruction = getOldInstruction(instruction) and
|
||||
(
|
||||
// The previous iteration said it was reusable, so we should mark it as reusable as well.
|
||||
Alias::canReuseSSAForOldResult(oldInstruction)
|
||||
Alias::canReuseSsaForOldResult(oldInstruction)
|
||||
or
|
||||
// The current alias analysis says it is reusable.
|
||||
Alias::getResultMemoryLocation(oldInstruction).canReuseSSA()
|
||||
Alias::getResultMemoryLocation(oldInstruction).canReuseSsa()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(Alias::MemoryLocation defLocation |
|
||||
// This is a `Phi` for a reusable location, so the result of the `Phi` is reusable as well.
|
||||
instruction = phiInstruction(_, defLocation) and
|
||||
defLocation.canReuseSSA()
|
||||
defLocation.canReuseSsa()
|
||||
)
|
||||
// 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 publically importing those modules in the
|
||||
* `DebugSSA` module, which is then imported by PrintSSA.
|
||||
*/
|
||||
module DebugSSA {
|
||||
module DebugSsa {
|
||||
import PhiInsertion
|
||||
import DefUse
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for DebugSsa */
|
||||
deprecated module DebugSSA = DebugSsa;
|
||||
|
||||
import CachedForDebugging
|
||||
|
||||
cached
|
||||
@@ -1038,7 +1050,7 @@ private module CachedForDebugging {
|
||||
|
||||
private OldIR::IRTempVariable getOldTempVariable(IRTempVariable var) {
|
||||
result.getEnclosingFunction() = var.getEnclosingFunction() and
|
||||
result.getAST() = var.getAST() and
|
||||
result.getAst() = var.getAst() and
|
||||
result.getTag() = var.getTag()
|
||||
}
|
||||
|
||||
@@ -1061,7 +1073,7 @@ private module CachedForDebugging {
|
||||
int maxValue() { result = 2147483647 }
|
||||
}
|
||||
|
||||
module SSAConsistency {
|
||||
module SsaConsistency {
|
||||
/**
|
||||
* Holds if a `MemoryOperand` has more than one `MemoryLocation` assigned by alias analysis.
|
||||
*/
|
||||
@@ -1114,6 +1126,9 @@ module SSAConsistency {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for SsaConsistency */
|
||||
deprecated module SSAConsistency = SsaConsistency;
|
||||
|
||||
/**
|
||||
* Provides the portion of the parameterized IR interface that is used to construct the SSA stages
|
||||
* of the IR. The raw stage of the IR does not expose these predicates.
|
||||
|
||||
@@ -2,7 +2,7 @@ import semmle.code.cpp.ir.implementation.unaliased_ssa.IR as OldIR
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.ReachableBlock as Reachability
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.reachability.Dominance as Dominance
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.IR as NewIR
|
||||
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSSAInstructions as SSAInstructions
|
||||
import semmle.code.cpp.ir.implementation.internal.TInstruction::AliasedSsaInstructions as SSAInstructions
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import AliasedSSA as Alias
|
||||
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSSAOperands as SSAOperands
|
||||
import semmle.code.cpp.ir.implementation.internal.TOperand::AliasedSsaOperands as SSAOperands
|
||||
|
||||
@@ -19,24 +19,24 @@ newtype TInstruction =
|
||||
) {
|
||||
IRConstruction::Raw::hasInstruction(tag1, tag2)
|
||||
} or
|
||||
TUnaliasedSSAPhiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
TUnaliasedSsaPhiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
UnaliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
UnaliasedSsa::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
} or
|
||||
TUnaliasedSSAChiInstruction(TRawInstruction primaryInstruction) { none() } or
|
||||
TUnaliasedSSAUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
UnaliasedSSA::SSA::hasUnreachedInstruction(irFunc)
|
||||
TUnaliasedSsaChiInstruction(TRawInstruction primaryInstruction) { none() } or
|
||||
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
UnaliasedSsa::SSA::hasUnreachedInstruction(irFunc)
|
||||
} or
|
||||
TAliasedSSAPhiInstruction(
|
||||
TAliasedSsaPhiInstruction(
|
||||
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
AliasedSSA::SSA::hasPhiInstruction(blockStartInstr, memoryLocation)
|
||||
} or
|
||||
TAliasedSSAChiInstruction(TRawInstruction primaryInstruction) {
|
||||
TAliasedSsaChiInstruction(TRawInstruction primaryInstruction) {
|
||||
AliasedSSA::SSA::hasChiInstruction(primaryInstruction)
|
||||
} or
|
||||
TAliasedSSAUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
|
||||
AliasedSSA::SSA::hasUnreachedInstruction(irFunc)
|
||||
}
|
||||
|
||||
@@ -46,58 +46,64 @@ newtype TInstruction =
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
module UnaliasedSSAInstructions {
|
||||
class TPhiInstruction = TUnaliasedSSAPhiInstruction;
|
||||
module UnaliasedSsaInstructions {
|
||||
class TPhiInstruction = TUnaliasedSsaPhiInstruction;
|
||||
|
||||
TPhiInstruction phiInstruction(
|
||||
TRawInstruction blockStartInstr, UnaliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
TRawInstruction blockStartInstr, UnaliasedSsa::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
result = TUnaliasedSSAPhiInstruction(blockStartInstr, memoryLocation)
|
||||
result = TUnaliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
|
||||
}
|
||||
|
||||
TRawInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) { none() }
|
||||
|
||||
class TChiInstruction = TUnaliasedSSAChiInstruction;
|
||||
class TChiInstruction = TUnaliasedSsaChiInstruction;
|
||||
|
||||
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
|
||||
result = TUnaliasedSSAChiInstruction(primaryInstruction)
|
||||
result = TUnaliasedSsaChiInstruction(primaryInstruction)
|
||||
}
|
||||
|
||||
class TUnreachedInstruction = TUnaliasedSSAUnreachedInstruction;
|
||||
class TUnreachedInstruction = TUnaliasedSsaUnreachedInstruction;
|
||||
|
||||
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
|
||||
result = TUnaliasedSSAUnreachedInstruction(irFunc)
|
||||
result = TUnaliasedSsaUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
|
||||
/** 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.
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
module AliasedSSAInstructions {
|
||||
class TPhiInstruction = TAliasedSSAPhiInstruction or TUnaliasedSSAPhiInstruction;
|
||||
module AliasedSsaInstructions {
|
||||
class TPhiInstruction = TAliasedSsaPhiInstruction or TUnaliasedSsaPhiInstruction;
|
||||
|
||||
TPhiInstruction phiInstruction(
|
||||
TRawInstruction blockStartInstr, AliasedSSA::SSA::MemoryLocation memoryLocation
|
||||
) {
|
||||
result = TAliasedSSAPhiInstruction(blockStartInstr, memoryLocation)
|
||||
result = TAliasedSsaPhiInstruction(blockStartInstr, memoryLocation)
|
||||
}
|
||||
|
||||
TPhiInstruction reusedPhiInstruction(TRawInstruction blockStartInstr) {
|
||||
result = TUnaliasedSSAPhiInstruction(blockStartInstr, _)
|
||||
result = TUnaliasedSsaPhiInstruction(blockStartInstr, _)
|
||||
}
|
||||
|
||||
class TChiInstruction = TAliasedSSAChiInstruction;
|
||||
class TChiInstruction = TAliasedSsaChiInstruction;
|
||||
|
||||
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
|
||||
result = TAliasedSSAChiInstruction(primaryInstruction)
|
||||
result = TAliasedSsaChiInstruction(primaryInstruction)
|
||||
}
|
||||
|
||||
class TUnreachedInstruction = TAliasedSSAUnreachedInstruction;
|
||||
class TUnreachedInstruction = TAliasedSsaUnreachedInstruction;
|
||||
|
||||
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
|
||||
result = TAliasedSSAUnreachedInstruction(irFunc)
|
||||
result = TAliasedSsaUnreachedInstruction(irFunc)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaInstructions */
|
||||
deprecated module AliasedSSAInstructions = AliasedSsaInstructions;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import semmle.code.cpp.ir.internal.IRCppLanguage as Language
|
||||
import semmle.code.cpp.ir.implementation.raw.internal.IRConstruction as IRConstruction
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSSA
|
||||
import semmle.code.cpp.ir.implementation.unaliased_ssa.internal.SSAConstruction as UnaliasedSsa
|
||||
import semmle.code.cpp.ir.implementation.aliased_ssa.internal.SSAConstruction as AliasedSSA
|
||||
|
||||
@@ -31,7 +31,7 @@ private module Internal {
|
||||
TNoOperand() { none() } or
|
||||
// Can be "removed" later when there's unreachable code
|
||||
// These operands can be reused across all three stages. They just get different defs.
|
||||
TNonSSAMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) {
|
||||
TNonSsaMemoryOperand(Raw::Instruction useInstr, MemoryOperandTag tag) {
|
||||
// Has no definition in raw but will get definitions later
|
||||
useInstr.getOpcode().hasOperand(tag)
|
||||
} or
|
||||
@@ -49,11 +49,11 @@ private module Internal {
|
||||
// important that we use the same definition of "is variable aliased" across
|
||||
// the phases.
|
||||
TAliasedPhiOperand(
|
||||
TAliasedSSAPhiInstruction useInstr, Aliased::IRBlock predecessorBlock, Overlap overlap
|
||||
TAliasedSsaPhiInstruction useInstr, Aliased::IRBlock predecessorBlock, Overlap overlap
|
||||
) {
|
||||
exists(AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap))
|
||||
} or
|
||||
TAliasedChiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) { any() }
|
||||
TAliasedChiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) { any() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,13 +72,21 @@ private module Shared {
|
||||
result = Internal::TRegisterOperand(useInstr, tag, defInstr)
|
||||
}
|
||||
|
||||
class TNonSSAMemoryOperand = Internal::TNonSSAMemoryOperand;
|
||||
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)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +103,7 @@ module RawOperands {
|
||||
|
||||
class TChiOperand = Internal::TNoOperand;
|
||||
|
||||
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
|
||||
class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* Returns the Phi operand with the specified parameters.
|
||||
@@ -126,14 +134,14 @@ module RawOperands {
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
module UnaliasedSSAOperands {
|
||||
module UnaliasedSsaOperands {
|
||||
import Shared
|
||||
|
||||
class TPhiOperand = Internal::TUnaliasedPhiOperand;
|
||||
|
||||
class TChiOperand = Internal::TNoOperand;
|
||||
|
||||
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
|
||||
class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* Returns the Phi operand with the specified parameters.
|
||||
@@ -159,20 +167,23 @@ 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
|
||||
* asliased SSA stage.
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
module AliasedSSAOperands {
|
||||
module AliasedSsaOperands {
|
||||
import Shared
|
||||
|
||||
class TPhiOperand = Internal::TAliasedPhiOperand or Internal::TUnaliasedPhiOperand;
|
||||
|
||||
class TChiOperand = Internal::TAliasedChiOperand;
|
||||
|
||||
class TNonPhiMemoryOperand = TNonSSAMemoryOperand or TChiOperand;
|
||||
class TNonPhiMemoryOperand = TNonSsaMemoryOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* Returns the Phi operand with the specified parameters.
|
||||
@@ -202,7 +213,10 @@ module AliasedSSAOperands {
|
||||
/**
|
||||
* Returns the Chi operand with the specified parameters.
|
||||
*/
|
||||
TChiOperand chiOperand(TAliasedSSAChiInstruction useInstr, ChiOperandTag tag) {
|
||||
TChiOperand chiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) {
|
||||
result = Internal::TAliasedChiOperand(useInstr, tag)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AliasedSsaOperands */
|
||||
deprecated module AliasedSSAOperands = AliasedSsaOperands;
|
||||
|
||||
@@ -55,7 +55,10 @@ class IRVariable extends TIRVariable {
|
||||
* Gets the AST node that declared this variable, or that introduced this
|
||||
* variable as part of the AST-to-IR translation.
|
||||
*/
|
||||
Language::AST getAST() { none() }
|
||||
Language::AST getAst() { none() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Language::AST getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets an identifier string for the variable. This identifier is unique
|
||||
@@ -66,7 +69,7 @@ class IRVariable extends TIRVariable {
|
||||
/**
|
||||
* Gets the source location of this variable.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getAST().getLocation() }
|
||||
final Language::Location getLocation() { result = getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the IR for the function that references this variable.
|
||||
@@ -90,7 +93,10 @@ class IRUserVariable extends IRVariable, TIRUserVariable {
|
||||
|
||||
final override string toString() { result = getVariable().toString() }
|
||||
|
||||
final override Language::AST getAST() { result = var }
|
||||
final override Language::AST getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
final override string getUniqueId() {
|
||||
result = getVariable().toString() + " " + getVariable().getLocation().toString()
|
||||
@@ -157,7 +163,10 @@ class IRGeneratedVariable extends IRVariable {
|
||||
|
||||
final override Language::LanguageType getLanguageType() { result = type }
|
||||
|
||||
final override Language::AST getAST() { result = ast }
|
||||
final override Language::AST getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Language::AST getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = getBaseString() + getLocationString() }
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
final string toString() { result = this.getOpcode().toString() + ": " + this.getAST().toString() }
|
||||
final string toString() { result = this.getOpcode().toString() + ": " + this.getAst().toString() }
|
||||
|
||||
/**
|
||||
* Gets a string showing the result, opcode, and operands of the instruction, equivalent to what
|
||||
@@ -136,7 +136,7 @@ class Instruction extends Construction::TStageInstruction {
|
||||
string getResultId() {
|
||||
this.shouldGenerateDumpStrings() and
|
||||
result =
|
||||
this.getResultPrefix() + this.getAST().getLocation().getStartLine() + "_" + this.getLineRank()
|
||||
this.getResultPrefix() + this.getAst().getLocation().getStartLine() + "_" + this.getLineRank()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -208,12 +208,15 @@ class Instruction extends Construction::TStageInstruction {
|
||||
/**
|
||||
* Gets the AST that caused this instruction to be generated.
|
||||
*/
|
||||
final Language::AST getAST() { result = Construction::getInstructionAST(this) }
|
||||
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.
|
||||
*/
|
||||
final Language::Location getLocation() { result = this.getAST().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getAst().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the `Expr` whose result is computed by this instruction, if any. The `Expr` may be a
|
||||
@@ -459,7 +462,10 @@ 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() }
|
||||
final Language::Variable getAstVariable() { result = var.(IRUserVariable).getVariable() }
|
||||
|
||||
/** DEPRECATED: Alias for getAstVariable */
|
||||
deprecated Language::Variable getASTVariable() { result = this.getAstVariable() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -18,7 +18,7 @@ private import internal.OperandInternal
|
||||
* of `TOperand` that are used in this stage.
|
||||
*/
|
||||
private class TStageOperand =
|
||||
TRegisterOperand or TNonSSAMemoryOperand or TPhiOperand or TChiOperand;
|
||||
TRegisterOperand or TNonSsaMemoryOperand or TPhiOperand or TChiOperand;
|
||||
|
||||
/**
|
||||
* A known location. Testing `loc instanceof KnownLocation` will account for non existing locations, as
|
||||
@@ -38,7 +38,7 @@ class Operand extends TStageOperand {
|
||||
// Ensure that the operand does not refer to instructions from earlier stages that are unreachable here
|
||||
exists(Instruction use, Instruction def | this = registerOperand(use, _, def))
|
||||
or
|
||||
exists(Instruction use | this = nonSSAMemoryOperand(use, _))
|
||||
exists(Instruction use | this = nonSsaMemoryOperand(use, _))
|
||||
or
|
||||
exists(Instruction use, Instruction def, IRBlock predecessorBlock |
|
||||
this = phiOperand(use, def, predecessorBlock, _) or
|
||||
@@ -209,7 +209,7 @@ class Operand extends TStageOperand {
|
||||
class MemoryOperand extends Operand {
|
||||
cached
|
||||
MemoryOperand() {
|
||||
this instanceof TNonSSAMemoryOperand or
|
||||
this instanceof TNonSsaMemoryOperand or
|
||||
this instanceof TPhiOperand or
|
||||
this instanceof TChiOperand
|
||||
}
|
||||
@@ -249,7 +249,7 @@ class NonPhiOperand extends Operand {
|
||||
|
||||
NonPhiOperand() {
|
||||
this = registerOperand(useInstr, tag, _) or
|
||||
this = nonSSAMemoryOperand(useInstr, tag) or
|
||||
this = nonSsaMemoryOperand(useInstr, tag) or
|
||||
this = chiOperand(useInstr, tag)
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
|
||||
cached
|
||||
NonPhiMemoryOperand() {
|
||||
this = nonSSAMemoryOperand(useInstr, tag)
|
||||
this = nonSsaMemoryOperand(useInstr, tag)
|
||||
or
|
||||
this = chiOperand(useInstr, tag)
|
||||
}
|
||||
|
||||
@@ -99,13 +99,19 @@ private predicate filteredNumberableInstruction(Instruction instr) {
|
||||
// count rather than strictcount to handle missing AST elements
|
||||
// separate instanceof and inline casts to avoid failed casts with a count of 0
|
||||
instr instanceof VariableAddressInstruction and
|
||||
count(instr.(VariableAddressInstruction).getIRVariable().getAST()) != 1
|
||||
count(instr.(VariableAddressInstruction).getIRVariable().getAst()) != 1
|
||||
or
|
||||
instr instanceof ConstantInstruction and
|
||||
count(instr.getResultIRType()) != 1
|
||||
or
|
||||
instr instanceof FieldAddressInstruction and
|
||||
count(instr.(FieldAddressInstruction).getField()) != 1
|
||||
or
|
||||
instr instanceof InheritanceConversionInstruction and
|
||||
(
|
||||
count(instr.(InheritanceConversionInstruction).getBaseClass()) != 1 or
|
||||
count(instr.(InheritanceConversionInstruction).getDerivedClass()) != 1
|
||||
)
|
||||
}
|
||||
|
||||
private predicate variableAddressValueNumber(
|
||||
@@ -115,8 +121,7 @@ private predicate variableAddressValueNumber(
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
instr.getIRVariable().getAST() = ast and
|
||||
strictcount(instr.getIRVariable().getAST()) = 1
|
||||
unique( | | instr.getIRVariable().getAst()) = ast
|
||||
}
|
||||
|
||||
private predicate initializeParameterValueNumber(
|
||||
@@ -126,15 +131,14 @@ private predicate initializeParameterValueNumber(
|
||||
// The underlying AST element is used as value-numbering key instead of the
|
||||
// `IRVariable` to work around a problem where a variable or expression with
|
||||
// multiple types gives rise to multiple `IRVariable`s.
|
||||
instr.getIRVariable().getAST() = var
|
||||
instr.getIRVariable().getAst() = var
|
||||
}
|
||||
|
||||
private predicate constantValueNumber(
|
||||
ConstantInstruction instr, IRFunction irFunc, IRType type, string value
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
strictcount(instr.getResultIRType()) = 1 and
|
||||
instr.getResultIRType() = type and
|
||||
unique( | | instr.getResultIRType()) = type and
|
||||
instr.getValue() = value
|
||||
}
|
||||
|
||||
@@ -151,8 +155,7 @@ private predicate fieldAddressValueNumber(
|
||||
TValueNumber objectAddress
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
instr.getField() = field and
|
||||
strictcount(instr.getField()) = 1 and
|
||||
unique( | | instr.getField()) = field and
|
||||
tvalueNumber(instr.getObjectAddress()) = objectAddress
|
||||
}
|
||||
|
||||
@@ -195,9 +198,9 @@ private predicate inheritanceConversionValueNumber(
|
||||
) {
|
||||
instr.getEnclosingIRFunction() = irFunc and
|
||||
instr.getOpcode() = opcode and
|
||||
instr.getBaseClass() = baseClass and
|
||||
instr.getDerivedClass() = derivedClass and
|
||||
tvalueNumber(instr.getUnary()) = operand
|
||||
tvalueNumber(instr.getUnary()) = operand and
|
||||
unique( | | instr.getBaseClass()) = baseClass and
|
||||
unique( | | instr.getDerivedClass()) = derivedClass
|
||||
}
|
||||
|
||||
private predicate loadTotalOverlapValueNumber(
|
||||
|
||||
@@ -48,7 +48,7 @@ module Raw {
|
||||
cached
|
||||
predicate hasTempVariable(Function func, Locatable ast, TempVariableTag tag, CppType type) {
|
||||
exists(TranslatedElement element |
|
||||
element.getAST() = ast and
|
||||
element.getAst() = ast and
|
||||
func = element.getFunction() and
|
||||
element.hasTempVariable(tag, type)
|
||||
)
|
||||
@@ -75,7 +75,7 @@ module Raw {
|
||||
tag = getInstructionTag(instruction) and
|
||||
(
|
||||
result = element.getInstructionVariable(tag) or
|
||||
result.(IRStringLiteral).getAST() = element.getInstructionStringLiteral(tag)
|
||||
result.(IRStringLiteral).getAst() = element.getInstructionStringLiteral(tag)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -339,7 +339,7 @@ Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind ki
|
||||
// such a `goto` creates a back edge.
|
||||
exists(TranslatedElement s, GotoStmt goto |
|
||||
not isStrictlyForwardGoto(goto) and
|
||||
goto = s.getAST() and
|
||||
goto = s.getAst() and
|
||||
exists(InstructionTag tag |
|
||||
result = s.getInstructionSuccessor(tag, kind) and
|
||||
instruction = s.getInstruction(tag)
|
||||
@@ -352,8 +352,13 @@ private predicate isStrictlyForwardGoto(GotoStmt goto) {
|
||||
goto.getLocation().isBefore(goto.getTarget().getLocation())
|
||||
}
|
||||
|
||||
Locatable getInstructionAST(TStageInstruction instr) {
|
||||
result = getInstructionTranslatedElement(instr).getAST()
|
||||
Locatable getInstructionAst(TStageInstruction instr) {
|
||||
result = getInstructionTranslatedElement(instr).getAst()
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for getInstructionAst */
|
||||
deprecated Locatable getInstructionAST(TStageInstruction instr) {
|
||||
result = getInstructionAst(instr)
|
||||
}
|
||||
|
||||
CppType getInstructionResultType(TStageInstruction instr) {
|
||||
|
||||
@@ -71,7 +71,8 @@ newtype TInstructionTag =
|
||||
AsmTag() or
|
||||
AsmInputTag(int elementIndex) { exists(AsmStmt asm | exists(asm.getChild(elementIndex))) } or
|
||||
ThisAddressTag() or
|
||||
ThisLoadTag()
|
||||
ThisLoadTag() or
|
||||
StructuredBindingAccessTag()
|
||||
|
||||
class InstructionTag extends TInstructionTag {
|
||||
final string toString() { result = "Tag" }
|
||||
@@ -221,4 +222,6 @@ string getInstructionTagId(TInstructionTag tag) {
|
||||
tag = ThisAddressTag() and result = "ThisAddress"
|
||||
or
|
||||
tag = ThisLoadTag() and result = "ThisLoad"
|
||||
or
|
||||
tag = StructuredBindingAccessTag() and result = "StructuredBindingAccess"
|
||||
}
|
||||
|
||||
@@ -175,7 +175,10 @@ abstract class TranslatedSideEffects extends TranslatedElement {
|
||||
/** Gets the expression whose side effects are being modeled. */
|
||||
abstract Expr getExpr();
|
||||
|
||||
final override Locatable getAST() { result = getExpr() }
|
||||
final override Locatable getAst() { result = getExpr() }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = getExpr().getEnclosingFunction() }
|
||||
|
||||
@@ -522,7 +525,10 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
this = TTranslatedArgumentExprSideEffect(call, arg, index, sideEffectOpcode)
|
||||
}
|
||||
|
||||
final override Locatable getAST() { result = arg }
|
||||
final override Locatable getAst() { result = arg }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Type getIndirectionType() {
|
||||
result = arg.getUnspecifiedType().(DerivedType).getBaseType()
|
||||
@@ -553,7 +559,10 @@ class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect
|
||||
index = -1
|
||||
}
|
||||
|
||||
final override Locatable getAST() { result = call }
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Type getIndirectionType() { result = call.getTarget().getDeclaringType() }
|
||||
|
||||
@@ -574,7 +583,10 @@ class TranslatedCallSideEffect extends TranslatedSideEffect, TTranslatedCallSide
|
||||
|
||||
TranslatedCallSideEffect() { this = TTranslatedCallSideEffect(expr, sideEffectOpcode) }
|
||||
|
||||
override Locatable getAST() { result = expr }
|
||||
override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Expr getPrimaryExpr() { result = expr }
|
||||
|
||||
@@ -612,7 +624,10 @@ class TranslatedAllocationSideEffect extends TranslatedSideEffect, TTranslatedAl
|
||||
|
||||
TranslatedAllocationSideEffect() { this = TTranslatedAllocationSideEffect(expr) }
|
||||
|
||||
override Locatable getAST() { result = expr }
|
||||
override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Expr getPrimaryExpr() { result = expr }
|
||||
|
||||
|
||||
@@ -19,7 +19,10 @@ abstract class TranslatedCondition extends TranslatedElement {
|
||||
|
||||
final override string toString() { result = expr.toString() }
|
||||
|
||||
final override Locatable getAST() { result = expr }
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final ConditionContext getConditionContext() { result = getParent() }
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ private import TranslatedInitialization
|
||||
* `entry`.
|
||||
*/
|
||||
TranslatedDeclarationEntry getTranslatedDeclarationEntry(DeclarationEntry entry) {
|
||||
result.getAST() = entry
|
||||
result.getAst() = entry
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -37,7 +37,10 @@ abstract class TranslatedDeclarationEntry extends TranslatedElement, TTranslated
|
||||
|
||||
final override string toString() { result = entry.toString() }
|
||||
|
||||
final override Locatable getAST() { result = entry }
|
||||
final override Locatable getAst() { result = entry }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -223,7 +226,10 @@ class TranslatedStaticLocalVariableInitialization extends TranslatedElement,
|
||||
|
||||
final override string toString() { result = "init: " + entry.toString() }
|
||||
|
||||
final override Locatable getAST() { result = entry }
|
||||
final override Locatable getAst() { result = entry }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override LocalVariable getVariable() { result = var }
|
||||
|
||||
@@ -254,7 +260,10 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
|
||||
|
||||
override string toString() { result = var.toString() }
|
||||
|
||||
override Locatable getAST() { result = var }
|
||||
override Locatable getAst() { result = var }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = forStmt.getEnclosingFunction() }
|
||||
|
||||
@@ -262,7 +271,7 @@ class TranslatedRangeBasedForVariableDeclaration extends TranslatedLocalVariable
|
||||
}
|
||||
|
||||
TranslatedConditionDecl getTranslatedConditionDecl(ConditionDeclExpr expr) {
|
||||
result.getAST() = expr
|
||||
result.getAst() = expr
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -280,7 +289,10 @@ class TranslatedConditionDecl extends TranslatedLocalVariableDeclaration, TTrans
|
||||
|
||||
override string toString() { result = "decl: " + conditionDeclExpr.toString() }
|
||||
|
||||
override Locatable getAST() { result = conditionDeclExpr }
|
||||
override Locatable getAst() { result = conditionDeclExpr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = conditionDeclExpr.getEnclosingFunction() }
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ IRUserVariable getIRUserVariable(Function func, Variable var) {
|
||||
}
|
||||
|
||||
IRTempVariable getIRTempVariable(Locatable ast, TempVariableTag tag) {
|
||||
result.getAST() = ast and
|
||||
result.getAst() = ast and
|
||||
result.getTag() = tag
|
||||
}
|
||||
|
||||
@@ -730,7 +730,10 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
/**
|
||||
* Gets the AST node being translated.
|
||||
*/
|
||||
abstract Locatable getAST();
|
||||
abstract Locatable getAst();
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated Locatable getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Get the first instruction to be executed in the evaluation of this element.
|
||||
@@ -929,16 +932,16 @@ abstract class TranslatedElement extends TTranslatedElement {
|
||||
*/
|
||||
final IRTempVariable getTempVariable(TempVariableTag tag) {
|
||||
exists(Locatable ast |
|
||||
result.getAST() = ast and
|
||||
result.getAst() = ast and
|
||||
result.getTag() = tag and
|
||||
hasTempVariableAndAST(tag, ast)
|
||||
hasTempVariableAndAst(tag, ast)
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasTempVariableAndAST(TempVariableTag tag, Locatable ast) {
|
||||
private predicate hasTempVariableAndAst(TempVariableTag tag, Locatable ast) {
|
||||
hasTempVariable(tag, _) and
|
||||
ast = getAST()
|
||||
ast = getAst()
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,6 +3,7 @@ private import semmle.code.cpp.ir.implementation.IRType
|
||||
private import semmle.code.cpp.ir.implementation.Opcode
|
||||
private import semmle.code.cpp.ir.implementation.internal.OperandTag
|
||||
private import semmle.code.cpp.ir.internal.CppType
|
||||
private import semmle.code.cpp.ir.internal.IRUtilities
|
||||
private import semmle.code.cpp.ir.internal.TempVariableTag
|
||||
private import InstructionTag
|
||||
private import TranslatedCondition
|
||||
@@ -73,7 +74,10 @@ abstract class TranslatedExpr extends TranslatedElement {
|
||||
expr.isGLValueCategory()
|
||||
}
|
||||
|
||||
final override Locatable getAST() { result = expr }
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = this.getAst() }
|
||||
|
||||
final override Function getFunction() { result = expr.getEnclosingFunction() }
|
||||
|
||||
@@ -813,7 +817,9 @@ abstract class TranslatedVariableAccess extends TranslatedNonConstantExpr {
|
||||
}
|
||||
|
||||
class TranslatedNonFieldVariableAccess extends TranslatedVariableAccess {
|
||||
TranslatedNonFieldVariableAccess() { not expr instanceof FieldAccess }
|
||||
TranslatedNonFieldVariableAccess() {
|
||||
not expr instanceof FieldAccess and not isNonReferenceStructuredBinding(expr.getTarget())
|
||||
}
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
if exists(this.getQualifier())
|
||||
@@ -860,6 +866,71 @@ class TranslatedFieldAccess extends TranslatedVariableAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The IR translation of a variable access of a structured binding, where the type
|
||||
* of the structured binding is not of a reference type, e.g., `x0` and `x1`
|
||||
* in `auto [x0, x1] = xs` where `xs` is an array. Although the type of the
|
||||
* structured binding is a non-reference type, the structured binding behaves
|
||||
* like a reference. Hence, the translation requires a `VariableAddress` followed
|
||||
* by a `Load` instead of only a `VariableAddress` as produced by
|
||||
* `TranslatedVariableAccess`.
|
||||
*/
|
||||
class TranslatedStructuredBindingVariableAccess extends TranslatedNonConstantExpr {
|
||||
override VariableAccess expr;
|
||||
|
||||
TranslatedStructuredBindingVariableAccess() { isNonReferenceStructuredBinding(expr.getTarget()) }
|
||||
|
||||
override Instruction getFirstInstruction() {
|
||||
// Structured bindings cannot be qualified.
|
||||
result = this.getInstruction(StructuredBindingAccessTag())
|
||||
}
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
// Structured bindings cannot be qualified.
|
||||
none()
|
||||
}
|
||||
|
||||
override Instruction getResult() { result = this.getInstruction(LoadTag()) }
|
||||
|
||||
override Instruction getInstructionSuccessor(InstructionTag tag, EdgeKind kind) {
|
||||
tag = StructuredBindingAccessTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getInstruction(LoadTag())
|
||||
or
|
||||
tag = LoadTag() and
|
||||
kind instanceof GotoEdge and
|
||||
result = this.getParent().getChildSuccessor(this)
|
||||
}
|
||||
|
||||
override Instruction getChildSuccessor(TranslatedElement child) { none() }
|
||||
|
||||
override predicate hasInstruction(Opcode opcode, InstructionTag tag, CppType resultType) {
|
||||
tag = StructuredBindingAccessTag() and
|
||||
opcode instanceof Opcode::VariableAddress and
|
||||
resultType = getTypeForGLValue(this.getLValueReferenceType())
|
||||
or
|
||||
tag = LoadTag() and
|
||||
opcode instanceof Opcode::Load and
|
||||
resultType = getTypeForPRValue(this.getLValueReferenceType())
|
||||
}
|
||||
|
||||
private LValueReferenceType getLValueReferenceType() {
|
||||
// The extractor ensures `result` exists when `isNonReferenceStructuredBinding(expr.getTarget())` holds.
|
||||
result.getBaseType() = expr.getUnspecifiedType()
|
||||
}
|
||||
|
||||
override Instruction getInstructionRegisterOperand(InstructionTag tag, OperandTag operandTag) {
|
||||
tag = LoadTag() and
|
||||
operandTag instanceof AddressOperandTag and
|
||||
result = this.getInstruction(StructuredBindingAccessTag())
|
||||
}
|
||||
|
||||
override IRVariable getInstructionVariable(InstructionTag tag) {
|
||||
tag = StructuredBindingAccessTag() and
|
||||
result = getIRUserVariable(expr.getEnclosingFunction(), expr.getTarget())
|
||||
}
|
||||
}
|
||||
|
||||
class TranslatedFunctionAccess extends TranslatedNonConstantExpr {
|
||||
override FunctionAccess expr;
|
||||
|
||||
@@ -1641,7 +1712,7 @@ abstract class TranslatedAllocationSize extends TranslatedExpr, TTranslatedAlloc
|
||||
}
|
||||
|
||||
TranslatedAllocationSize getTranslatedAllocationSize(NewOrNewArrayExpr newExpr) {
|
||||
result.getAST() = newExpr
|
||||
result.getAst() = newExpr
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1807,7 +1878,7 @@ class TranslatedAllocatorCall extends TTranslatedAllocatorCall, TranslatedDirect
|
||||
}
|
||||
|
||||
TranslatedAllocatorCall getTranslatedAllocatorCall(NewOrNewArrayExpr newExpr) {
|
||||
result.getAST() = newExpr
|
||||
result.getAst() = newExpr
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,7 +15,7 @@ private import VarArgs
|
||||
/**
|
||||
* Gets the `TranslatedFunction` that represents function `func`.
|
||||
*/
|
||||
TranslatedFunction getTranslatedFunction(Function func) { result.getAST() = func }
|
||||
TranslatedFunction getTranslatedFunction(Function func) { result.getAst() = func }
|
||||
|
||||
/**
|
||||
* Gets the size, in bytes, of the variable used to represent the `...` parameter in a varargs
|
||||
@@ -65,7 +65,10 @@ class TranslatedFunction extends TranslatedElement, TTranslatedFunction {
|
||||
|
||||
final override string toString() { result = func.toString() }
|
||||
|
||||
final override Locatable getAST() { result = func }
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets the function being translated.
|
||||
@@ -344,7 +347,7 @@ TranslatedThisParameter getTranslatedThisParameter(Function func) { result.getFu
|
||||
/**
|
||||
* Gets the `TranslatedPositionalParameter` that represents parameter `param`.
|
||||
*/
|
||||
TranslatedPositionalParameter getTranslatedParameter(Parameter param) { result.getAST() = param }
|
||||
TranslatedPositionalParameter getTranslatedParameter(Parameter param) { result.getAst() = param }
|
||||
|
||||
/**
|
||||
* Gets the `TranslatedEllipsisParameter` for function `func`, if one exists.
|
||||
@@ -457,7 +460,10 @@ class TranslatedThisParameter extends TranslatedParameter, TTranslatedThisParame
|
||||
|
||||
final override string toString() { result = "this" }
|
||||
|
||||
final override Locatable getAST() { result = func }
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
@@ -489,7 +495,10 @@ class TranslatedPositionalParameter extends TranslatedParameter, TTranslatedPara
|
||||
|
||||
final override string toString() { result = param.toString() }
|
||||
|
||||
final override Locatable getAST() { result = param }
|
||||
final override Locatable getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() {
|
||||
result = param.getFunction() or
|
||||
@@ -526,7 +535,10 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
|
||||
|
||||
final override string toString() { result = "..." }
|
||||
|
||||
final override Locatable getAST() { result = func }
|
||||
final override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = func }
|
||||
|
||||
@@ -544,7 +556,7 @@ class TranslatedEllipsisParameter extends TranslatedParameter, TTranslatedEllips
|
||||
}
|
||||
|
||||
private TranslatedConstructorInitList getTranslatedConstructorInitList(Function func) {
|
||||
result.getAST() = func
|
||||
result.getAst() = func
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -561,7 +573,10 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
|
||||
override string toString() { result = "ctor init: " + func.toString() }
|
||||
|
||||
override Locatable getAST() { result = func }
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(ConstructorFieldInit fieldInit |
|
||||
@@ -611,7 +626,7 @@ class TranslatedConstructorInitList extends TranslatedElement, InitializationCon
|
||||
}
|
||||
|
||||
private TranslatedDestructorDestructionList getTranslatedDestructorDestructionList(Function func) {
|
||||
result.getAST() = func
|
||||
result.getAst() = func
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -629,7 +644,10 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
|
||||
override string toString() { result = "dtor destruction: " + func.toString() }
|
||||
|
||||
override Locatable getAST() { result = func }
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override TranslatedElement getChild(int id) {
|
||||
exists(DestructorFieldDestruction fieldDestruction |
|
||||
@@ -667,14 +685,17 @@ class TranslatedDestructorDestructionList extends TranslatedElement,
|
||||
}
|
||||
}
|
||||
|
||||
TranslatedReadEffects getTranslatedReadEffects(Function func) { result.getAST() = func }
|
||||
TranslatedReadEffects getTranslatedReadEffects(Function func) { result.getAst() = func }
|
||||
|
||||
class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
Function func;
|
||||
|
||||
TranslatedReadEffects() { this = TTranslatedReadEffects(func) }
|
||||
|
||||
override Locatable getAST() { result = func }
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
@@ -718,11 +739,11 @@ class TranslatedReadEffects extends TranslatedElement, TTranslatedReadEffects {
|
||||
}
|
||||
|
||||
private TranslatedThisReadEffect getTranslatedThisReadEffect(Function func) {
|
||||
result.getAST() = func
|
||||
result.getAst() = func
|
||||
}
|
||||
|
||||
private TranslatedParameterReadEffect getTranslatedParameterReadEffect(Parameter param) {
|
||||
result.getAST() = param
|
||||
result.getAst() = param
|
||||
}
|
||||
|
||||
abstract class TranslatedReadEffect extends TranslatedElement {
|
||||
@@ -758,7 +779,10 @@ class TranslatedThisReadEffect extends TranslatedReadEffect, TTranslatedThisRead
|
||||
|
||||
TranslatedThisReadEffect() { this = TTranslatedThisReadEffect(func) }
|
||||
|
||||
override Locatable getAST() { result = func }
|
||||
override Locatable getAst() { result = func }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override Function getFunction() { result = func }
|
||||
|
||||
@@ -781,7 +805,10 @@ class TranslatedParameterReadEffect extends TranslatedReadEffect, TTranslatedPar
|
||||
|
||||
TranslatedParameterReadEffect() { this = TTranslatedParameterReadEffect(param) }
|
||||
|
||||
override Locatable getAST() { result = param }
|
||||
override Locatable getAst() { result = param }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
override string toString() { result = "read effect: " + param.toString() }
|
||||
|
||||
|
||||
@@ -139,7 +139,10 @@ abstract class TranslatedInitialization extends TranslatedElement, TTranslatedIn
|
||||
|
||||
final override Function getFunction() { result = expr.getEnclosingFunction() }
|
||||
|
||||
final override Locatable getAST() { result = expr }
|
||||
final override Locatable getAst() { result = expr }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
/**
|
||||
* Gets the expression that is doing the initialization.
|
||||
@@ -461,11 +464,11 @@ class TranslatedConstructorInitialization extends TranslatedDirectInitialization
|
||||
TranslatedFieldInitialization getTranslatedFieldInitialization(
|
||||
ClassAggregateLiteral initList, Field field
|
||||
) {
|
||||
result.getAST() = initList and result.getField() = field
|
||||
result.getAst() = initList and result.getField() = field
|
||||
}
|
||||
|
||||
TranslatedFieldInitialization getTranslatedConstructorFieldInitialization(ConstructorFieldInit init) {
|
||||
result.getAST() = init
|
||||
result.getAst() = init
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -478,7 +481,10 @@ abstract class TranslatedFieldInitialization extends TranslatedElement {
|
||||
|
||||
final override string toString() { result = ast.toString() + "." + field.toString() }
|
||||
|
||||
final override Locatable getAST() { result = ast }
|
||||
final override Locatable getAst() { result = ast }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = ast.getEnclosingFunction() }
|
||||
|
||||
@@ -622,7 +628,10 @@ abstract class TranslatedElementInitialization extends TranslatedElement {
|
||||
result = initList.toString() + "[" + getElementIndex().toString() + "]"
|
||||
}
|
||||
|
||||
final override Locatable getAST() { result = initList }
|
||||
final override Locatable getAst() { result = initList }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = initList.getEnclosingFunction() }
|
||||
|
||||
@@ -802,7 +811,10 @@ class TranslatedElementValueInitialization extends TranslatedElementInitializati
|
||||
abstract class TranslatedStructorCallFromStructor extends TranslatedElement, StructorCallContext {
|
||||
FunctionCall call;
|
||||
|
||||
final override Locatable getAST() { result = call }
|
||||
final override Locatable getAst() { result = call }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override TranslatedElement getChild(int id) {
|
||||
id = 0 and
|
||||
@@ -864,7 +876,7 @@ abstract class TranslatedConstructorCallFromConstructor extends TranslatedStruct
|
||||
}
|
||||
|
||||
TranslatedConstructorCallFromConstructor getTranslatedConstructorBaseInit(ConstructorBaseInit init) {
|
||||
result.getAST() = init
|
||||
result.getAst() = init
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -904,7 +916,7 @@ class TranslatedConstructorBaseInit extends TranslatedConstructorCallFromConstru
|
||||
TranslatedDestructorBaseDestruction getTranslatedDestructorBaseDestruction(
|
||||
DestructorBaseDestruction destruction
|
||||
) {
|
||||
result.getAST() = destruction
|
||||
result.getAst() = destruction
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -928,7 +940,10 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
|
||||
TranslatedConstructorBareInit() { this = TTranslatedConstructorBareInit(init) }
|
||||
|
||||
override Locatable getAST() { result = init }
|
||||
override Locatable getAst() { result = init }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override string toString() { result = "construct base (no constructor)" }
|
||||
|
||||
@@ -948,5 +963,5 @@ class TranslatedConstructorBareInit extends TranslatedElement, TTranslatedConstr
|
||||
}
|
||||
|
||||
TranslatedConstructorBareInit getTranslatedConstructorBareInit(ConstructorInit init) {
|
||||
result.getAST() = init
|
||||
result.getAst() = init
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ private import TranslatedExpr
|
||||
private import TranslatedFunction
|
||||
private import TranslatedInitialization
|
||||
|
||||
TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAST() = stmt }
|
||||
TranslatedStmt getTranslatedStmt(Stmt stmt) { result.getAst() = stmt }
|
||||
|
||||
abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
Stmt stmt;
|
||||
@@ -20,7 +20,10 @@ abstract class TranslatedStmt extends TranslatedElement, TTranslatedStmt {
|
||||
|
||||
final override string toString() { result = stmt.toString() }
|
||||
|
||||
final override Locatable getAST() { result = stmt }
|
||||
final override Locatable getAst() { result = stmt }
|
||||
|
||||
/** DEPRECATED: Alias for getAst */
|
||||
deprecated override Locatable getAST() { result = getAst() }
|
||||
|
||||
final override Function getFunction() { result = stmt.getEnclosingFunction() }
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user