Merge branch 'main' into max-schaefer-patch-1

This commit is contained in:
Owen Mansel-Chan
2024-07-18 10:39:42 +01:00
committed by GitHub
452 changed files with 8230 additions and 24306 deletions

View File

@@ -29,8 +29,6 @@ jobs:
key: all-queries
- name: check formatting
run: find shared */ql -type f \( -name "*.qll" -o -name "*.ql" \) -print0 | xargs -0 -n 3000 -P 10 codeql query format -q --check-only
- name: Omit DatabaseQualityDiagnostics.ql from compile checking # Remove me once CodeQL 2.18.0 is released!
run: mv java/ql/src/Telemetry/DatabaseQualityDiagnostics.ql{,.hidden}
- name: compile queries - check-only
# run with --check-only if running in a PR (github.sha != main)
if : ${{ github.event_name == 'pull_request' }}
@@ -41,6 +39,3 @@ jobs:
if : ${{ github.event_name != 'pull_request' }}
shell: bash
run: codeql query compile -q -j0 */ql/{src,examples} --keep-going --warnings=error --compilation-cache "${{ steps.query-cache.outputs.cache-dir }}" --compilation-cache-size=500
- name: Restore DatabaseQualityDiagnostics.ql after compile checking # Remove me once CodeQL 2.18.0 is released
run: mv java/ql/src/Telemetry/DatabaseQualityDiagnostics.ql{.hidden,}

View File

@@ -112,6 +112,7 @@ use_repo(
"kotlin-compiler-1.9.0-Beta",
"kotlin-compiler-1.9.20-Beta",
"kotlin-compiler-2.0.0-RC1",
"kotlin-compiler-2.0.20-Beta2",
"kotlin-compiler-embeddable-1.5.0",
"kotlin-compiler-embeddable-1.5.10",
"kotlin-compiler-embeddable-1.5.20",
@@ -124,6 +125,7 @@ use_repo(
"kotlin-compiler-embeddable-1.9.0-Beta",
"kotlin-compiler-embeddable-1.9.20-Beta",
"kotlin-compiler-embeddable-2.0.0-RC1",
"kotlin-compiler-embeddable-2.0.20-Beta2",
"kotlin-stdlib-1.5.0",
"kotlin-stdlib-1.5.10",
"kotlin-stdlib-1.5.20",
@@ -136,11 +138,16 @@ use_repo(
"kotlin-stdlib-1.9.0-Beta",
"kotlin-stdlib-1.9.20-Beta",
"kotlin-stdlib-2.0.0-RC1",
"kotlin-stdlib-2.0.20-Beta2",
)
go_sdk = use_extension("@rules_go//go:extensions.bzl", "go_sdk")
go_sdk.download(version = "1.22.2")
go_deps = use_extension("@gazelle//:extensions.bzl", "go_deps")
go_deps.from_file(go_mod = "//go/extractor:go.mod")
use_repo(go_deps, "org_golang_x_mod", "org_golang_x_tools")
lfs_files = use_repo_rule("//misc/bazel:lfs.bzl", "lfs_files")
lfs_files(

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* The class `NewArrayExpr` adds a predicate `getArraySize()` to allow a more convenient way to access the static size of the array when the extent is missing.

View File

@@ -0,0 +1,4 @@
---
category: feature
---
* Models-as-data alert provenance information has been extended to the C/C++ language. Any qltests that include the edges relation in their output (for example, `.qlref`s that reference path-problem queries) will need to be have their expected output updated accordingly.

View File

@@ -146,7 +146,7 @@ predicate summaryModel(string row) { any(SummaryModelCsv s).row(row) }
/** Holds if a source model exists for the given parameters. */
predicate sourceModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string output, string kind, string provenance
string output, string kind, string provenance, string model
) {
exists(string row |
sourceModel(row) and
@@ -160,16 +160,20 @@ predicate sourceModel(
row.splitAt(";", 6) = output and
row.splitAt(";", 7) = kind
) and
provenance = "manual"
provenance = "manual" and
model = ""
or
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance,
_)
exists(QlBuiltins::ExtensionId madId |
Extensions::sourceModel(namespace, type, subtypes, name, signature, ext, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
/** Holds if a sink model exists for the given parameters. */
predicate sinkModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string kind, string provenance
string input, string kind, string provenance, string model
) {
exists(string row |
sinkModel(row) and
@@ -183,9 +187,14 @@ predicate sinkModel(
row.splitAt(";", 6) = input and
row.splitAt(";", 7) = kind
) and
provenance = "manual"
provenance = "manual" and
model = ""
or
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance, _)
exists(QlBuiltins::ExtensionId madId |
Extensions::sinkModel(namespace, type, subtypes, name, signature, ext, input, kind, provenance,
madId) and
model = "MaD:" + madId.toString()
)
}
/**
@@ -195,7 +204,7 @@ predicate sinkModel(
*/
private predicate summaryModel0(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance
string input, string output, string kind, string provenance, string model
) {
exists(string row |
summaryModel(row) and
@@ -210,10 +219,14 @@ private predicate summaryModel0(
row.splitAt(";", 7) = output and
row.splitAt(";", 8) = kind
) and
provenance = "manual"
provenance = "manual" and
model = ""
or
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, _)
exists(QlBuiltins::ExtensionId madId |
Extensions::summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind,
provenance, madId) and
model = "MaD:" + madId.toString()
)
}
/**
@@ -234,19 +247,20 @@ private predicate expandInputAndOutput(
*/
predicate summaryModel(
string namespace, string type, boolean subtypes, string name, string signature, string ext,
string input, string output, string kind, string provenance
string input, string output, string kind, string provenance, string model
) {
exists(string input0, string output0 |
summaryModel0(namespace, type, subtypes, name, signature, ext, input0, output0, kind, provenance) and
summaryModel0(namespace, type, subtypes, name, signature, ext, input0, output0, kind,
provenance, model) and
expandInputAndOutput(input0, input, output0, output,
[0 .. Private::getMaxElementContentIndirectionIndex() - 1])
)
}
private predicate relevantNamespace(string namespace) {
sourceModel(namespace, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _) or
summaryModel(namespace, _, _, _, _, _, _, _, _, _)
sourceModel(namespace, _, _, _, _, _, _, _, _, _) or
sinkModel(namespace, _, _, _, _, _, _, _, _, _) or
summaryModel(namespace, _, _, _, _, _, _, _, _, _, _)
}
private predicate namespaceLink(string shortns, string longns) {
@@ -276,17 +290,17 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
part = "source" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string output, string provenance |
string ext, string output, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance)
sourceModel(subns, type, subtypes, name, signature, ext, output, kind, provenance, model)
)
or
part = "sink" and
n =
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string provenance |
string ext, string input, string provenance, string model |
canonicalNamespaceLink(namespace, subns) and
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance)
sinkModel(subns, type, subtypes, name, signature, ext, input, kind, provenance, model)
)
or
part = "summary" and
@@ -294,7 +308,7 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
strictcount(string subns, string type, boolean subtypes, string name, string signature,
string ext, string input, string output, string provenance |
canonicalNamespaceLink(namespace, subns) and
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance)
summaryModel(subns, type, subtypes, name, signature, ext, input, output, kind, provenance, _)
)
)
}
@@ -303,9 +317,9 @@ predicate modelCoverage(string namespace, int namespaces, string kind, string pa
module CsvValidation {
private string getInvalidModelInput() {
exists(string pred, AccessPath input, string part |
sinkModel(_, _, _, _, _, _, input, _, _) and pred = "sink"
sinkModel(_, _, _, _, _, _, input, _, _, _) and pred = "sink"
or
summaryModel(_, _, _, _, _, _, input, _, _, _) and pred = "summary"
summaryModel(_, _, _, _, _, _, input, _, _, _, _) and pred = "summary"
|
(
invalidSpecComponent(input, part) and
@@ -322,9 +336,9 @@ module CsvValidation {
private string getInvalidModelOutput() {
exists(string pred, string output, string part |
sourceModel(_, _, _, _, _, _, output, _, _) and pred = "source"
sourceModel(_, _, _, _, _, _, output, _, _, _) and pred = "source"
or
summaryModel(_, _, _, _, _, _, _, output, _, _) and pred = "summary"
summaryModel(_, _, _, _, _, _, _, output, _, _, _) and pred = "summary"
|
invalidSpecComponent(output, part) and
not part = "" and
@@ -334,11 +348,11 @@ module CsvValidation {
}
private module KindValConfig implements SharedModelVal::KindValidationConfigSig {
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _) }
predicate summaryKind(string kind) { summaryModel(_, _, _, _, _, _, _, _, kind, _, _) }
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _) }
predicate sinkKind(string kind) { sinkModel(_, _, _, _, _, _, _, kind, _, _) }
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _) }
predicate sourceKind(string kind) { sourceModel(_, _, _, _, _, _, _, kind, _, _) }
}
private module KindVal = SharedModelVal::KindValidation<KindValConfig>;
@@ -379,11 +393,11 @@ module CsvValidation {
private string getInvalidModelSignature() {
exists(string pred, string namespace, string type, string name, string signature, string ext |
sourceModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "source"
sourceModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "source"
or
sinkModel(namespace, type, _, name, signature, ext, _, _, _) and pred = "sink"
sinkModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "sink"
or
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _) and pred = "summary"
summaryModel(namespace, type, _, name, signature, ext, _, _, _, _, _) and pred = "summary"
|
not namespace.regexpMatch("[a-zA-Z0-9_\\.:]*") and
result = "Dubious namespace \"" + namespace + "\" in " + pred + " model."
@@ -415,9 +429,9 @@ module CsvValidation {
private predicate elementSpec(
string namespace, string type, boolean subtypes, string name, string signature, string ext
) {
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _)
sourceModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
sinkModel(namespace, type, subtypes, name, signature, ext, _, _, _, _) or
summaryModel(namespace, type, subtypes, name, signature, ext, _, _, _, _, _)
}
/** Gets the fully templated version of `f`. */
@@ -867,9 +881,9 @@ private module Cached {
* model.
*/
cached
predicate sourceNode(DataFlow::Node node, string kind) {
predicate sourceNode(DataFlow::Node node, string kind, string model) {
exists(SourceSinkInterpretationInput::InterpretNode n |
isSourceNode(n, kind, _) and n.asNode() = node // TODO
isSourceNode(n, kind, model) and n.asNode() = node
)
}
@@ -878,40 +892,57 @@ private module Cached {
* model.
*/
cached
predicate sinkNode(DataFlow::Node node, string kind) {
predicate sinkNode(DataFlow::Node node, string kind, string model) {
exists(SourceSinkInterpretationInput::InterpretNode n |
isSinkNode(n, kind, _) and n.asNode() = node // TODO
isSinkNode(n, kind, model) and n.asNode() = node
)
}
}
import Cached
/**
* Holds if `node` is specified as a source with the given kind in a MaD flow
* model.
*/
predicate sourceNode(DataFlow::Node node, string kind) { sourceNode(node, kind, _) }
/**
* Holds if `node` is specified as a sink with the given kind in a MaD flow
* model.
*/
predicate sinkNode(DataFlow::Node node, string kind) { sinkNode(node, kind, _) }
private predicate interpretSummary(
Function f, string input, string output, string kind, string provenance
Function f, string input, string output, string kind, string provenance, string model
) {
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance) and
summaryModel(namespace, type, subtypes, name, signature, ext, input, output, kind, provenance,
model) and
f = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
// adapter class for converting Mad summaries to `SummarizedCallable`s
private class SummarizedCallableAdapter extends SummarizedCallable {
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _) }
SummarizedCallableAdapter() { interpretSummary(this, _, _, _, _, _) }
private predicate relevantSummaryElementManual(string input, string output, string kind) {
private predicate relevantSummaryElementManual(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance) and
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isManual()
)
}
private predicate relevantSummaryElementGenerated(string input, string output, string kind) {
private predicate relevantSummaryElementGenerated(
string input, string output, string kind, string model
) {
exists(Provenance provenance |
interpretSummary(this, input, output, kind, provenance) and
interpretSummary(this, input, output, kind, provenance, model) and
provenance.isGenerated()
)
}
@@ -920,18 +951,17 @@ private class SummarizedCallableAdapter extends SummarizedCallable {
string input, string output, boolean preservesValue, string model
) {
exists(string kind |
this.relevantSummaryElementManual(input, output, kind)
this.relevantSummaryElementManual(input, output, kind, model)
or
not this.relevantSummaryElementManual(_, _, _) and
this.relevantSummaryElementGenerated(input, output, kind)
not this.relevantSummaryElementManual(_, _, _, _) and
this.relevantSummaryElementGenerated(input, output, kind, model)
|
if kind = "value" then preservesValue = true else preservesValue = false
) and
model = "" // TODO
)
}
override predicate hasProvenance(Provenance provenance) {
interpretSummary(this, _, _, _, provenance)
interpretSummary(this, _, _, _, provenance, _)
}
}

View File

@@ -239,17 +239,7 @@ class CastNode extends Node {
CastNode() { none() } // stub implementation
}
class DataFlowCallable extends Function {
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
c order by file, startline, startcolumn
)
}
}
class DataFlowCallable extends Function { }
class DataFlowExpr = Expr;
@@ -269,24 +259,12 @@ class DataFlowCall extends Expr instanceof Call {
/** Gets the enclosing callable of this call. */
DataFlowCallable getEnclosingCallable() { result = this.getEnclosingFunction() }
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCall c, int startline, int startcolumn |
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
c order by startline, startcolumn
)
}
}
class NodeRegion instanceof Unit {
string toString() { result = "NodeRegion" }
predicate contains(Node n) { none() }
int totalOrder() { result = 1 }
}
predicate isUnreachableInCall(NodeRegion nr, DataFlowCall call) { none() } // stub implementation

View File

@@ -112,9 +112,8 @@ module SourceSinkInterpretationInput implements
exists(
string namespace, string type, boolean subtypes, string name, string signature, string ext
|
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance) and
e = interpretElement(namespace, type, subtypes, name, signature, ext) and
model = "" // TODO
sourceModel(namespace, type, subtypes, name, signature, ext, output, kind, provenance, model) and
e = interpretElement(namespace, type, subtypes, name, signature, ext)
)
}
@@ -128,9 +127,8 @@ module SourceSinkInterpretationInput implements
exists(
string package, string type, boolean subtypes, string name, string signature, string ext
|
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance) and
e = interpretElement(package, type, subtypes, name, signature, ext) and
model = "" // TODO
sinkModel(package, type, subtypes, name, signature, ext, input, kind, provenance, model) and
e = interpretElement(package, type, subtypes, name, signature, ext)
)
}

View File

@@ -949,6 +949,16 @@ class NewArrayExpr extends NewOrNewArrayExpr, @new_array_expr {
* gives nothing, as the 10 is considered part of the type.
*/
Expr getExtent() { result = this.getChild(2) }
/**
* Gets the number of elements in the array, if available.
*
* For example, `new int[]{1,2,3}` has an array size of 3.
*/
int getArraySize() {
result = this.getAllocatedType().(ArrayType).getArraySize() or
result = this.getInitializer().(ArrayAggregateLiteral).getArraySize()
}
}
private class TDeleteOrDeleteArrayExpr = @delete_expr or @delete_array_expr;

View File

@@ -11,6 +11,7 @@ private import Node0ToString
private import ModelUtil
private import semmle.code.cpp.models.interfaces.FunctionInputsAndOutputs as IO
private import semmle.code.cpp.models.interfaces.DataFlow as DF
private import semmle.code.cpp.dataflow.ExternalFlow as External
cached
private module Cached {
@@ -1060,16 +1061,6 @@ class DataFlowCallable extends TDataFlowCallable {
result = this.asSummarizedCallable() or // SummarizedCallable = Function (in CPP)
result = this.asSourceCallable()
}
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCallable c, string file, int startline, int startcolumn |
c.getLocation().hasLocationInfo(file, startline, startcolumn, _, _)
|
c order by file, startline, startcolumn
)
}
}
/**
@@ -1167,16 +1158,6 @@ class DataFlowCall extends TDataFlowCall {
* Gets the location of this call.
*/
Location getLocation() { none() }
/** Gets a best-effort total ordering. */
int totalorder() {
this =
rank[result](DataFlowCall c, int startline, int startcolumn |
c.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
c order by startline, startcolumn
)
}
}
/**
@@ -1269,15 +1250,6 @@ module IsUnreachableInCall {
string toString() { result = "NodeRegion" }
predicate contains(Node n) { this = n.getBasicBlock() }
int totalOrder() {
this =
rank[result](IRBlock b, int startline, int startcolumn |
b.getLocation().hasLocationInfo(_, startline, startcolumn, _, _)
|
b order by startline, startcolumn
)
}
}
predicate isUnreachableInCall(NodeRegion block, DataFlowCall call) {
@@ -1362,9 +1334,9 @@ predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) {
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() }
predicate knownSourceModel(Node source, string model) { none() }
predicate knownSourceModel(Node source, string model) { External::sourceNode(source, _, model) }
predicate knownSinkModel(Node sink, string model) { none() }
predicate knownSinkModel(Node sink, string model) { External::sinkNode(sink, _, model) }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a

View File

@@ -40,7 +40,8 @@ predicate ignoreInstruction(Instruction instr) {
instr instanceof AliasedDefinitionInstruction or
instr instanceof AliasedUseInstruction or
instr instanceof InitializeNonLocalInstruction or
instr instanceof ReturnIndirectionInstruction
instr instanceof ReturnIndirectionInstruction or
instr instanceof UninitializedGroupInstruction
)
}

View File

@@ -13,7 +13,8 @@ private newtype TMemoryAccessKind =
TPhiMemoryAccess() or
TUnmodeledMemoryAccess() or
TChiTotalMemoryAccess() or
TChiPartialMemoryAccess()
TChiPartialMemoryAccess() or
TGroupedMemoryAccess()
/**
* Describes the set of memory locations memory accessed by a memory operand or
@@ -99,3 +100,11 @@ class ChiTotalMemoryAccess extends MemoryAccessKind, TChiTotalMemoryAccess {
class ChiPartialMemoryAccess extends MemoryAccessKind, TChiPartialMemoryAccess {
override string toString() { result = "chi(partial)" }
}
/**
* The result of an `UninitializedGroup` instruction, which initializes a set of
* allocations that are each assigned the same virtual variable.
*/
class GroupedMemoryAccess extends MemoryAccessKind, TGroupedMemoryAccess {
override string toString() { result = "group" }
}

View File

@@ -89,6 +89,7 @@ private newtype TOpcode =
TSizedBufferMayWriteSideEffect() or
TInitializeDynamicAllocation() or
TChi() or
TUninitializedGroup() or
TInlineAsm() or
TUnreached() or
TNewObj()
@@ -1237,6 +1238,17 @@ module Opcode {
}
}
/**
* The `Opcode` for a `UninitializedGroup`.
*
* See the `UninitializedGroupInstruction` documentation for more details.
*/
class UninitializedGroup extends Opcode, TUninitializedGroup {
final override string toString() { result = "UninitializedGroup" }
override GroupedMemoryAccess getWriteMemoryAccess() { any() }
}
/**
* The `Opcode` for an `InlineAsmInstruction`.
*

View File

@@ -2142,6 +2142,47 @@ class ChiInstruction extends Instruction {
final predicate isPartialUpdate() { Construction::chiOnlyPartiallyUpdatesLocation(this) }
}
/**
* An instruction that initializes a set of allocations that are each assigned
* the same "virtual variable".
*
* As an example, consider the following snippet:
* ```
* int a;
* int b;
* int* p;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 5;
* int x = a;
* ```
*
* Since both the address of `a` and `b` reach `p` at `*p = 5` the IR alias
* analysis will create a region that contains both `a` and `b`. The region
* containing both `a` and `b` are initialized by an `UninitializedGroup`
* instruction in the entry block of the enclosing function.
*/
class UninitializedGroupInstruction extends Instruction {
UninitializedGroupInstruction() { this.getOpcode() instanceof Opcode::UninitializedGroup }
/**
* Gets an `IRVariable` whose memory is initialized by this instruction, if any.
* Note: Allocations that are not represented as `IRVariable`s (such as
* dynamic allocations) are not returned by this predicate even if this
* instruction initializes such memory.
*/
final IRVariable getAnIRVariable() {
result = Construction::getAnUninitializedGroupVariable(this)
}
final override string getImmediateString() {
result = strictconcat(this.getAnIRVariable().toString(), ",")
}
}
/**
* An instruction representing unreachable code.
*

View File

@@ -106,8 +106,7 @@ private predicate operandEscapesDomain(Operand operand) {
not isArgumentForParameter(_, operand, _) and
not isOnlyEscapesViaReturnArgument(operand) and
not operand.getUse() instanceof ReturnValueInstruction and
not operand.getUse() instanceof ReturnIndirectionInstruction and
not operand instanceof PhiInputOperand
not operand.getUse() instanceof ReturnIndirectionInstruction
}
/**
@@ -191,6 +190,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset, Instr
// A copy propagates the source value.
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
)
or
operand = instr.(PhiInstruction).getAnInputOperand() and
// Using `unknown` ensures termination since we cannot keep incrementing a bit offset
// through the back edge of a loop (or through recursion).
bitOffset = Ints::unknown()
}
private predicate operandEscapesNonReturn(Operand operand) {
@@ -212,9 +216,6 @@ private predicate operandEscapesNonReturn(Operand operand) {
or
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultEscapesNonReturn(operand.getUse())
or
operandEscapesDomain(operand)
}
@@ -236,9 +237,6 @@ private predicate operandMayReachReturn(Operand operand) {
operand.getUse() instanceof ReturnValueInstruction
or
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultMayReachReturn(operand.getUse())
}
private predicate operandReturned(Operand operand, IntValue bitOffset) {

View File

@@ -101,6 +101,8 @@ class IndirectParameterAllocation extends Allocation, TIndirectParameterAllocati
final override predicate isAlwaysAllocatedOnStack() { none() }
final override predicate alwaysEscapes() { none() }
final IRAutomaticVariable getIRVariable() { result = var }
}
class DynamicAllocation extends Allocation, TDynamicAllocation {

View File

@@ -8,6 +8,7 @@ private import semmle.code.cpp.ir.internal.IntegerConstant as Ints
private import semmle.code.cpp.ir.internal.IntegerInterval as Interval
private import semmle.code.cpp.ir.implementation.internal.OperandTag
private import AliasConfiguration
private import codeql.util.Boolean
private class IntValue = Ints::IntValue;
@@ -16,49 +17,196 @@ private predicate isIndirectOrBufferMemoryAccess(MemoryAccessKind kind) {
kind instanceof BufferMemoryAccess
}
private predicate hasResultMemoryAccess(
Instruction instr, Allocation var, IRType type, Language::LanguageType languageType,
IntValue startBitOffset, IntValue endBitOffset, boolean isMayAccess
private predicate hasMemoryAccess(
AddressOperand addrOperand, Allocation var, IntValue startBitOffset, boolean grouped
) {
exists(AddressOperand addrOperand |
addrOperand = instr.getResultAddressOperand() and
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
languageType = instr.getResultLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(instr.getResultMemoryAccess()) and
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
)
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
if strictcount(Allocation alloc | addressOperandAllocationAndOffset(addrOperand, alloc, _)) > 1
then grouped = true
else grouped = false
}
private predicate hasResultMemoryAccess(
AddressOperand address, Instruction instr, Allocation var, IRType type,
Language::LanguageType languageType, IntValue startBitOffset, IntValue endBitOffset,
boolean isMayAccess, boolean grouped
) {
address = instr.getResultAddressOperand() and
hasMemoryAccess(address, var, startBitOffset, grouped) and
languageType = instr.getResultLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(instr.getResultMemoryAccess()) and
(if instr.hasResultMayMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
}
private predicate hasOperandMemoryAccess(
MemoryOperand operand, Allocation var, IRType type, Language::LanguageType languageType,
IntValue startBitOffset, IntValue endBitOffset, boolean isMayAccess
AddressOperand address, MemoryOperand operand, Allocation var, IRType type,
Language::LanguageType languageType, IntValue startBitOffset, IntValue endBitOffset,
boolean isMayAccess, boolean grouped
) {
exists(AddressOperand addrOperand |
addrOperand = operand.getAddressOperand() and
addressOperandAllocationAndOffset(addrOperand, var, startBitOffset) and
languageType = operand.getLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(operand.getMemoryAccess()) and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
address = operand.getAddressOperand() and
hasMemoryAccess(address, var, startBitOffset, grouped) and
languageType = operand.getLanguageType() and
type = languageType.getIRType() and
isIndirectOrBufferMemoryAccess(operand.getMemoryAccess()) and
(if operand.hasMayReadMemoryAccess() then isMayAccess = true else isMayAccess = false) and
if exists(type.getByteSize())
then endBitOffset = Ints::add(startBitOffset, Ints::mul(type.getByteSize(), 8))
else endBitOffset = Ints::unknown()
}
private Allocation getAnAllocation(AddressOperand address) {
hasResultMemoryAccess(address, _, result, _, _, _, _, _, true) or
hasOperandMemoryAccess(address, _, result, _, _, _, _, _, true)
}
private module AllocationSet0 =
QlBuiltins::InternSets<AddressOperand, Allocation, getAnAllocation/1>;
/**
* A set of allocations containing at least 2 elements.
*/
private class NonSingletonSets extends AllocationSet0::Set {
NonSingletonSets() { strictcount(Allocation var | this.contains(var)) > 1 }
/** Gets an allocation from this set. */
Allocation getAnAllocation() { this.contains(result) }
/** Gets the string representation of this set. */
string toString() { result = "{" + strictconcat(this.getAnAllocation().toString(), ", ") + "}" }
}
/** Holds the instersection of `s1` and `s2` is non-empty. */
private predicate hasOverlappingElement(NonSingletonSets s1, NonSingletonSets s2) {
exists(Allocation var |
s1.contains(var) and
s2.contains(var)
)
}
private module AllocationSet =
QlBuiltins::EquivalenceRelation<NonSingletonSets, hasOverlappingElement/2>;
/**
* Holds if `var` is created by the AST element `e`. Furthermore, the value `d`
* represents which branch of the `Allocation` type `var` is from.
*/
private predicate allocationAst(Allocation var, @element e, int d) {
var.(VariableAllocation).getIRVariable().getAst() = e and d = 0
or
var.(IndirectParameterAllocation).getIRVariable().getAst() = e and d = 1
or
var.(DynamicAllocation).getABaseInstruction().getAst() = e and d = 2
}
/** Holds if `x = y` and `x` is an AST element that creates an `Allocation`. */
private predicate id(@element x, @element y) {
allocationAst(_, x, _) and
x = y
}
private predicate idOf(@element x, int y) = equivalenceRelation(id/2)(x, y)
/** Gets a unique integer representation of `var`. */
private int getUniqueAllocationId(Allocation var) {
exists(int r, @element e, int d |
allocationAst(var, e, d) and
idOf(e, r) and
result = 3 * r + d
)
}
/**
* An equivalence class of a set of allocations.
*
* Any `VariableGroup` will be completely disjunct from any other
* `VariableGroup`.
*/
class VariableGroup extends AllocationSet::EquivalenceClass {
/** Gets the location of this set. */
final Location getLocation() { result = this.getIRFunction().getLocation() }
/** Gets the enclosing `IRFunction` of this set. */
final IRFunction getIRFunction() {
result = unique( | | this.getAnAllocation().getEnclosingIRFunction())
}
/** Gets the type of elements contained in this set. */
final Language::LanguageType getType() {
strictcount(Language::LanguageType langType |
exists(Allocation var | var = this.getAnAllocation() |
hasResultMemoryAccess(_, _, var, _, langType, _, _, _, true) or
hasOperandMemoryAccess(_, _, var, _, langType, _, _, _, true)
)
) = 1 and
exists(Allocation var | var = this.getAnAllocation() |
hasResultMemoryAccess(_, _, var, _, result, _, _, _, true) or
hasOperandMemoryAccess(_, _, var, _, result, _, _, _, true)
)
or
strictcount(Language::LanguageType langType |
exists(Allocation var | var = this.getAnAllocation() |
hasResultMemoryAccess(_, _, var, _, langType, _, _, _, true) or
hasOperandMemoryAccess(_, _, var, _, langType, _, _, _, true)
)
) > 1 and
result = any(IRUnknownType type).getCanonicalLanguageType()
}
/** Gets an allocation of this set. */
final Allocation getAnAllocation() {
exists(AllocationSet0::Set set |
this = AllocationSet::getEquivalenceClass(set) and
set.contains(result)
)
}
/** Gets a unique string representing this set. */
final private string getUniqueId() {
result = strictconcat(getUniqueAllocationId(this.getAnAllocation()).toString(), ",")
}
/**
* Gets the order that this set should be initialized in.
*
* Note: This is _not_ the order in which the _members_ of the set should be
* initialized. Rather, it represents the order in which the set should be
* initialized in relation to other sets. That is, if
* ```
* getInitializationOrder() = 2
* ```
* then this set will be initialized as the second (third) set in the
* enclosing function. In order words, the third `UninitializedGroup`
* instruction in the entry block of the enclosing function will initialize
* this set of allocations.
*/
final int getInitializationOrder() {
exists(IRFunction func |
func = this.getIRFunction() and
this =
rank[result + 1](VariableGroup vg, string uniq |
vg.getIRFunction() = func and uniq = vg.getUniqueId()
|
vg order by uniq
)
)
}
string toString() { result = "{" + strictconcat(this.getAnAllocation().toString(), ", ") + "}" }
}
private newtype TMemoryLocation =
TVariableMemoryLocation(
Allocation var, IRType type, Language::LanguageType languageType, IntValue startBitOffset,
IntValue endBitOffset, boolean isMayAccess
) {
(
hasResultMemoryAccess(_, var, type, _, startBitOffset, endBitOffset, isMayAccess)
hasResultMemoryAccess(_, _, var, type, _, startBitOffset, endBitOffset, isMayAccess, false)
or
hasOperandMemoryAccess(_, var, type, _, startBitOffset, endBitOffset, isMayAccess)
hasOperandMemoryAccess(_, _, var, type, _, startBitOffset, endBitOffset, isMayAccess, false)
or
// For a stack variable, always create a memory location for the entire variable.
var.isAlwaysAllocatedOnStack() and
@@ -69,22 +217,14 @@ private newtype TMemoryLocation =
) and
languageType = type.getCanonicalLanguageType()
} or
TEntireAllocationMemoryLocation(Allocation var, boolean isMayAccess) {
(
var instanceof IndirectParameterAllocation or
var instanceof DynamicAllocation
) and
(isMayAccess = false or isMayAccess = true)
TEntireAllocationMemoryLocation(Allocation var, Boolean isMayAccess) {
var instanceof IndirectParameterAllocation or
var instanceof DynamicAllocation
} or
TUnknownMemoryLocation(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
} or
TAllNonLocalMemory(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
} or
TAllAliasedMemory(IRFunction irFunc, boolean isMayAccess) {
isMayAccess = false or isMayAccess = true
}
TGroupedMemoryLocation(VariableGroup vg, Boolean isMayAccess, Boolean isAll) or
TUnknownMemoryLocation(IRFunction irFunc, Boolean isMayAccess) or
TAllNonLocalMemory(IRFunction irFunc, Boolean isMayAccess) or
TAllAliasedMemory(IRFunction irFunc, Boolean isMayAccess)
/**
* Represents the memory location accessed by a memory operand or memory result. In this implementation, the location is
@@ -116,7 +256,14 @@ abstract class MemoryLocation extends TMemoryLocation {
abstract predicate isMayAccess();
Allocation getAllocation() { none() }
/**
* Gets an allocation associated with this `MemoryLocation`.
*
* This returns zero or one results in all cases except when `this` is an
* instance of `GroupedMemoryLocation`. When `this` is an instance of
* `GroupedMemoryLocation` this predicate always returns two or more results.
*/
Allocation getAnAllocation() { none() }
/**
* Holds if the location cannot be overwritten except by definition of a `MemoryLocation` for
@@ -153,24 +300,29 @@ abstract class AllocationMemoryLocation extends MemoryLocation {
Allocation var;
boolean isMayAccess;
AllocationMemoryLocation() {
this instanceof TMemoryLocation and
isMayAccess = false
or
isMayAccess = true // Just ensures that `isMayAccess` is bound.
}
bindingset[isMayAccess]
AllocationMemoryLocation() { any() }
final override VirtualVariable getVirtualVariable() {
if allocationEscapes(var)
then result = TAllAliasedMemory(var.getEnclosingIRFunction(), false)
else result.(AllocationMemoryLocation).getAllocation() = var
else (
// It may be that the grouped memory location contains an escaping
// allocation. In that case, the virtual variable is still the memory
// location that represents all aliased memory. Thus, we need to
// call `getVirtualVariable` on the grouped memory location.
result = getGroupedMemoryLocation(var, false, false).getVirtualVariable()
or
not exists(getGroupedMemoryLocation(var, false, false)) and
result.(AllocationMemoryLocation).getAnAllocation() = var
)
}
final override IRFunction getIRFunction() { result = var.getEnclosingIRFunction() }
final override Location getLocation() { result = var.getLocation() }
final override Allocation getAllocation() { result = var }
final override Allocation getAnAllocation() { result = var }
final override predicate isMayAccess() { isMayAccess = true }
@@ -211,13 +363,13 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
final override Language::LanguageType getType() {
if
strictcount(Language::LanguageType accessType |
hasResultMemoryAccess(_, var, type, accessType, startBitOffset, endBitOffset, _) or
hasOperandMemoryAccess(_, var, type, accessType, startBitOffset, endBitOffset, _)
hasResultMemoryAccess(_, _, var, type, accessType, startBitOffset, endBitOffset, _, false) or
hasOperandMemoryAccess(_, _, var, type, accessType, startBitOffset, endBitOffset, _, false)
) = 1
then
// All of the accesses have the same `LanguageType`, so just use that.
hasResultMemoryAccess(_, var, type, result, startBitOffset, endBitOffset, _) or
hasOperandMemoryAccess(_, var, type, result, startBitOffset, endBitOffset, _)
hasResultMemoryAccess(_, _, var, type, result, startBitOffset, endBitOffset, _, false) or
hasOperandMemoryAccess(_, _, var, type, result, startBitOffset, endBitOffset, _, false)
else
// There is no single type for all accesses, so just use the canonical one for this `IRType`.
result = type.getCanonicalLanguageType()
@@ -247,6 +399,89 @@ class VariableMemoryLocation extends TVariableMemoryLocation, AllocationMemoryLo
}
}
/**
* A group of allocations represented as a single memory location.
*
* If `isAll()` holds then this memory location represents all the enclosing
* allocations, and if `isSome()` holds then this memory location represents
* one or more of the enclosing allocations.
*
* For example, consider the following snippet:
* ```
* int* p;
* int a, b;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 42;
* ```
*
* The write memory location associated with the write to `*p` writes to a
* grouped memory location representing the _some_ allocation in the set
* `{a, b}`, and the subsequent `Chi` instruction merges the new value of
* `{a, b}` into a memory location that represents _all_ of the allocations
* in the set.
*/
class GroupedMemoryLocation extends TGroupedMemoryLocation, MemoryLocation {
VariableGroup vg;
boolean isMayAccess;
boolean isAll;
GroupedMemoryLocation() { this = TGroupedMemoryLocation(vg, isMayAccess, isAll) }
final override Location getLocation() { result = vg.getLocation() }
final override IRFunction getIRFunction() { result = vg.getIRFunction() }
final override predicate isMayAccess() { isMayAccess = true }
final override string getUniqueId() {
if this.isAll()
then result = "All{" + strictconcat(vg.getAnAllocation().getUniqueId(), ", ") + "}"
else result = "Some{" + strictconcat(vg.getAnAllocation().getUniqueId(), ", ") + "}"
}
final override string toStringInternal() { result = this.getUniqueId() }
final override Language::LanguageType getType() { result = vg.getType() }
final override VirtualVariable getVirtualVariable() {
if allocationEscapes(this.getAnAllocation())
then result = TAllAliasedMemory(vg.getIRFunction(), false)
else result = TGroupedMemoryLocation(vg, false, true)
}
/** Gets an allocation of this memory location. */
override Allocation getAnAllocation() { result = vg.getAnAllocation() }
/** Gets the set of allocations associated with this memory location. */
VariableGroup getGroup() { result = vg }
/** Holds if this memory location represents all the enclosing allocations. */
predicate isAll() { isAll = true }
/** Holds if this memory location represents one or more of the enclosing allocations. */
predicate isSome() { isAll = false }
}
private GroupedMemoryLocation getGroupedMemoryLocation(
Allocation alloc, boolean isMayAccess, boolean isAll
) {
result.getAnAllocation() = alloc and
(
isMayAccess = true and result.isMayAccess()
or
isMayAccess = false and not result.isMayAccess()
) and
(
isAll = true and result.isAll()
or
isAll = false and result.isSome()
)
}
class EntireAllocationMemoryLocation extends TEntireAllocationMemoryLocation,
AllocationMemoryLocation
{
@@ -282,6 +517,14 @@ class VariableVirtualVariable extends VariableMemoryLocation, VirtualVariable {
}
}
class GroupedVirtualVariable extends GroupedMemoryLocation, VirtualVariable {
GroupedVirtualVariable() {
forex(Allocation var | var = this.getAnAllocation() | not allocationEscapes(var)) and
not this.isMayAccess() and
this.isAll()
}
}
/**
* An access to memory that is not known to be confined to a specific `IRVariable`.
*/
@@ -446,7 +689,7 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
result instanceof MustExactlyOverlap
or
not use instanceof EntireAllocationMemoryLocation and
if def.getAllocation() = use.getAllocation()
if def.getAnAllocation() = use.getAnAllocation()
then
// EntireAllocationMemoryLocation totally overlaps any location within
// the same allocation.
@@ -454,11 +697,48 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
else (
// There is no overlap with a location that's known to belong to a
// different allocation, but all other locations may partially overlap.
not exists(use.getAllocation()) and
not exists(use.getAnAllocation()) and
result instanceof MayPartiallyOverlap
)
)
or
exists(GroupedMemoryLocation group |
group = def and
def.getVirtualVariable() = use.getVirtualVariable()
|
(
use instanceof UnknownMemoryLocation or
use instanceof AllAliasedMemory
) and
result instanceof MayPartiallyOverlap
or
group.isAll() and
(
group.getAnAllocation() =
[
use.(EntireAllocationMemoryLocation).getAnAllocation(),
use.(VariableMemoryLocation).getAnAllocation()
]
or
use.(GroupedMemoryLocation).isSome()
) and
result instanceof MustTotallyOverlap
or
group.isAll() and
use.(GroupedMemoryLocation).isAll() and
result instanceof MustExactlyOverlap
or
group.isSome() and
(
use instanceof EntireAllocationMemoryLocation
or
use instanceof VariableMemoryLocation
or
use instanceof GroupedMemoryLocation
) and
result instanceof MayPartiallyOverlap
)
or
exists(VariableMemoryLocation defVariableLocation |
defVariableLocation = def and
(
@@ -468,7 +748,8 @@ private Overlap getExtentOverlap(MemoryLocation def, MemoryLocation use) {
(
use instanceof UnknownMemoryLocation or
use instanceof AllAliasedMemory or
use instanceof EntireAllocationMemoryLocation
use instanceof EntireAllocationMemoryLocation or
use instanceof GroupedMemoryLocation
) and
result instanceof MayPartiallyOverlap
or
@@ -534,7 +815,7 @@ private predicate isCoveredOffset(Allocation var, int offsetRank, VariableMemory
exists(int startRank, int endRank, VirtualVariable vvar |
vml.getStartBitOffset() = rank[startRank](IntValue offset_ | isRelevantOffset(vvar, offset_)) and
vml.getEndBitOffset() = rank[endRank](IntValue offset_ | isRelevantOffset(vvar, offset_)) and
var = vml.getAllocation() and
var = vml.getAnAllocation() and
vvar = vml.getVirtualVariable() and
isRelatableMemoryLocation(vml) and
offsetRank in [startRank .. endRank]
@@ -542,7 +823,7 @@ private predicate isCoveredOffset(Allocation var, int offsetRank, VariableMemory
}
private predicate hasUnknownOffset(Allocation var, VariableMemoryLocation vml) {
vml.getAllocation() = var and
vml.getAnAllocation() = var and
(
vml.getStartBitOffset() = Ints::unknown() or
vml.getEndBitOffset() = Ints::unknown()
@@ -557,9 +838,9 @@ private predicate overlappingIRVariableMemoryLocations(
isCoveredOffset(var, offsetRank, use)
)
or
hasUnknownOffset(use.getAllocation(), def)
hasUnknownOffset(use.getAnAllocation(), def)
or
hasUnknownOffset(def.getAllocation(), use)
hasUnknownOffset(def.getAnAllocation(), use)
}
private Overlap getVariableMemoryLocationOverlap(
@@ -588,13 +869,24 @@ MemoryLocation getResultMemoryLocation(Instruction instr) {
(
(
isIndirectOrBufferMemoryAccess(kind) and
if hasResultMemoryAccess(instr, _, _, _, _, _, _)
if hasResultMemoryAccess(_, instr, _, _, _, _, _, _, _)
then
exists(Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
hasResultMemoryAccess(instr, var, type, _, startBitOffset, endBitOffset, isMayAccess) and
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset,
unbindBool(isMayAccess))
exists(
Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset,
boolean grouped
|
hasResultMemoryAccess(_, instr, var, type, _, startBitOffset, endBitOffset, isMayAccess,
grouped)
|
// If the instruction is only associated with one allocation we assign it a `VariableMemoryLocation`
if grouped = false
then
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset,
unbindBool(isMayAccess))
else
// And otherwise we assign it a memory location that groups all the relevant memory locations into one.
result = getGroupedMemoryLocation(var, unbindBool(isMayAccess), false)
)
else result = TUnknownMemoryLocation(instr.getEnclosingIRFunction(), isMayAccess)
)
@@ -621,12 +913,23 @@ MemoryLocation getOperandMemoryLocation(MemoryOperand operand) {
(
(
isIndirectOrBufferMemoryAccess(kind) and
if hasOperandMemoryAccess(operand, _, _, _, _, _, _)
if hasOperandMemoryAccess(_, operand, _, _, _, _, _, _, _)
then
exists(Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset |
hasOperandMemoryAccess(operand, var, type, _, startBitOffset, endBitOffset, isMayAccess) and
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset, isMayAccess)
exists(
Allocation var, IRType type, IntValue startBitOffset, IntValue endBitOffset,
boolean grouped
|
hasOperandMemoryAccess(_, operand, var, type, _, startBitOffset, endBitOffset,
isMayAccess, grouped)
|
// If the operand is only associated with one memory location we assign it a `VariableMemoryLocation`
if grouped = false
then
result =
TVariableMemoryLocation(var, type, _, startBitOffset, endBitOffset, isMayAccess)
else
// And otherwise we assign it a memory location that groups all relevant memory locations into one.
result = getGroupedMemoryLocation(var, isMayAccess, false)
)
else result = TUnknownMemoryLocation(operand.getEnclosingIRFunction(), isMayAccess)
)

View File

@@ -15,6 +15,51 @@ private class OldInstruction = Reachability::ReachableInstruction;
import Cached
/**
* Holds if `instruction` is the first instruction that may be followed by
* an `UninitializedGroup` instruction, and the enclosing function of
* `instruction` is `func`.
*/
private predicate isFirstInstructionBeforeUninitializedGroup(
Instruction instruction, IRFunction func
) {
instruction = getChi(any(OldIR::InitializeNonLocalInstruction init)) and
func = instruction.getEnclosingIRFunction()
}
/** Gets the `i`'th `UninitializedGroup` instruction in `func`. */
private UninitializedGroupInstruction getInitGroupInstruction(int i, IRFunction func) {
exists(Alias::VariableGroup vg |
vg.getIRFunction() = func and
vg.getInitializationOrder() = i and
result = uninitializedGroup(vg)
)
}
/**
* Holds if `instruction` is the last instruction in the chain of `UninitializedGroup`
* instructions in `func`. The chain of instructions may be empty in which case
* `instruction` satisfies
* ```
* isFirstInstructionBeforeUninitializedGroup(instruction, func)
* ```
*/
predicate isLastInstructionForUninitializedGroups(Instruction instruction, IRFunction func) {
exists(int i |
instruction = getInitGroupInstruction(i, func) and
not exists(getChi(instruction)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
exists(int i |
instruction = getChi(getInitGroupInstruction(i, func)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
not exists(getInitGroupInstruction(0, func))
}
cached
private module Cached {
cached
@@ -32,6 +77,11 @@ private module Cached {
hasChiNode(_, primaryInstruction)
}
cached
predicate hasChiNodeAfterUninitializedGroup(UninitializedGroupInstruction initGroup) {
hasChiNodeAfterUninitializedGroup(_, initGroup)
}
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldIR::Instruction oldInstruction |
@@ -45,7 +95,8 @@ private module Cached {
}
class TStageInstruction =
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction or
TUninitializedGroupInstruction;
/**
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
@@ -78,6 +129,8 @@ private module Cached {
or
instr instanceof TChiInstruction
or
instr instanceof TUninitializedGroupInstruction
or
instr instanceof TUnreachedInstruction
}
@@ -123,7 +176,8 @@ private module Cached {
predicate hasModeledMemoryResult(Instruction instruction) {
canModelResultForOldInstruction(getOldInstruction(instruction)) or
instruction instanceof PhiInstruction or // Phis always have modeled results
instruction instanceof ChiInstruction // Chis always have modeled results
instruction instanceof ChiInstruction or // Chis always have modeled results
instruction instanceof UninitializedGroupInstruction // Group initializers always have modeled results
}
cached
@@ -134,16 +188,23 @@ private module Cached {
or
// Chi instructions track virtual variables, and therefore a chi instruction is
// conflated if it's associated with the aliased virtual variable.
exists(OldInstruction oldInstruction | instruction = getChi(oldInstruction) |
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
exists(Instruction input | instruction = getChi(input) |
Alias::getResultMemoryLocation(input).getVirtualVariable() instanceof
Alias::AliasedVirtualVariable
or
// A chi following an `UninitializedGroupInstruction` only happens when the virtual
// variable of the grouped memory location is `{AllAliasedMemory}`.
exists(Alias::GroupedMemoryLocation gml |
input = uninitializedGroup(gml.getGroup()) and
gml.getVirtualVariable() instanceof Alias::AliasedVirtualVariable
)
)
or
// Phi instructions track locations, and therefore a phi instruction is
// conflated if it's associated with a conflated location.
exists(Alias::MemoryLocation location |
instruction = getPhi(_, location) and
not exists(location.getAllocation())
not exists(location.getAnAllocation())
)
}
@@ -205,7 +266,11 @@ private module Cached {
hasMemoryOperandDefinition(oldInstruction, oldOperand, overlap, result)
)
or
instruction = getChi(getOldInstruction(result)) and
(
instruction = getChi(getOldInstruction(result))
or
instruction = getChi(result.(UninitializedGroupInstruction))
) and
tag instanceof ChiPartialOperandTag and
overlap instanceof MustExactlyOverlap
or
@@ -263,6 +328,14 @@ private module Cached {
)
}
cached
IRVariable getAnUninitializedGroupVariable(UninitializedGroupInstruction init) {
exists(Alias::VariableGroup vg |
init = uninitializedGroup(vg) and
result = vg.getAnAllocation().getABaseInstruction().(VariableInstruction).getIRVariable()
)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
@@ -316,6 +389,19 @@ private module Cached {
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
}
private ChiInstruction getChiAfterUninitializedGroup(int i, IRFunction func) {
result =
rank[i + 1](VariableGroup vg, UninitializedGroupInstruction initGroup, ChiInstruction chi,
int r |
initGroup.getEnclosingIRFunction() = func and
chi = getChi(initGroup) and
initGroup = uninitializedGroup(vg) and
r = vg.getInitializationOrder()
|
chi order by r
)
}
cached
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
exists(
@@ -329,6 +415,19 @@ private module Cached {
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
result = getDefinitionOrChiInstruction(defBlock, defOffset, vvar, _)
)
or
exists(UninitializedGroupInstruction initGroup, IRFunction func |
chiInstr = getChi(initGroup) and
func = initGroup.getEnclosingIRFunction()
|
chiInstr = getChiAfterUninitializedGroup(0, func) and
isFirstInstructionBeforeUninitializedGroup(result, func)
or
exists(int i |
chiInstr = getChiAfterUninitializedGroup(i + 1, func) and
result = getChiAfterUninitializedGroup(i, func)
)
)
}
cached
@@ -344,14 +443,40 @@ private module Cached {
)
}
/*
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction
*/
private UninitializedGroupInstruction firstInstructionToUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
result = getInitGroupInstruction(0, func) and
kind instanceof GotoEdge
)
}
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
private Instruction getNextUninitializedGroupInstruction(Instruction instruction, EdgeKind kind) {
exists(int i, IRFunction func |
func = instruction.getEnclosingIRFunction() and
instruction = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
if hasChiNodeAfterUninitializedGroup(_, instruction)
then result = getChi(instruction)
else result = getInitGroupInstruction(i + 1, func)
)
or
exists(int i, IRFunction func, UninitializedGroupInstruction initGroup |
func = instruction.getEnclosingIRFunction() and
instruction = getChi(initGroup) and
initGroup = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
result = getInitGroupInstruction(i + 1, func)
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup0(
Instruction instruction, EdgeKind kind
) {
if hasChiNode(_, getOldInstruction(instruction))
then
result = getChi(getOldInstruction(instruction)) and
@@ -371,6 +496,107 @@ private module Cached {
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func, Instruction firstBeforeUninitializedGroup |
isLastInstructionForUninitializedGroups(instruction, func) and
isFirstInstructionBeforeUninitializedGroup(firstBeforeUninitializedGroup, func) and
result = getInstructionSuccessorAfterUninitializedGroup0(firstBeforeUninitializedGroup, kind)
)
}
/**
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction.
*
* Furthermore, the entry block is augmented with `UninitializedGroup` instructions and `Chi`
* instructions. For example, consider this example:
* ```cpp
* int x, y;
* int* p;
* if(b) {
* p = &x;
* escape(&x);
* } else {
* p = &y;
* }
* *p = 42;
*
* int z, w;
* int* q;
* if(b) {
* q = &z;
* } else {
* q = &w;
* }
* *q = 43;
* ```
*
* the unaliased IR for the entry block of this snippet is:
* ```
* v1(void) = EnterFunction :
* m1(unknown) = AliasedDefinition :
* m2(unknown) = InitializeNonLocal :
* r1(glval<bool>) = VariableAddress[b] :
* m3(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m4(int) = Uninitialized[x] : &:r2
* r3(glval<int>) = VariableAddress[y] :
* m5(int) = Uninitialized[y] : &:r3
* r4(glval<int *>) = VariableAddress[p] :
* m6(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m3
* v2(void) = ConditionalBranch : r6
* ```
* and we need to transform this to aliased IR by inserting an `UninitializedGroup`
* instruction for every `VariableGroup` memory location in the function. Furthermore,
* if the `VariableGroup` memory location contains an allocation that escapes we need
* to insert a `Chi` that writes the memory produced by `UninitializedGroup` into
* `{AllAliasedMemory}`. For the above snippet we then end up with:
* ```
* v1(void) = EnterFunction :
* m2(unknown) = AliasedDefinition :
* m3(unknown) = InitializeNonLocal :
* m4(unknown) = Chi : total:m2, partial:m3
* m5(int) = UninitializedGroup[x,y] :
* m6(unknown) = Chi : total:m4, partial:m5
* m7(int) = UninitializedGroup[w,z] :
* r1(glval<bool>) = VariableAddress[b] :
* m8(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m10(int) = Uninitialized[x] : &:r2
* m11(unknown) = Chi : total:m6, partial:m10
* r3(glval<int>) = VariableAddress[y] :
* m12(int) = Uninitialized[y] : &:r3
* m13(unknown) = Chi : total:m11, partial:m12
* r4(glval<int *>) = VariableAddress[p] :
* m14(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m8
* v2(void) = ConditionalBranch : r6
* ```
*
* Here, the group `{x, y}` contains an allocation that escapes (`x`), so there
* is a `Chi` after the `UninitializedGroup` that initializes the memory for the
* `VariableGroup` containing `x`. None of the allocations in `{w, z}` escape so
* there is no `Chi` following that the `UninitializedGroup` that initializes the
* memory of `{w, z}`.
*/
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = firstInstructionToUninitializedGroup(instruction, kind)
or
result = getNextUninitializedGroupInstruction(instruction, kind)
or
result = getInstructionSuccessorAfterUninitializedGroup(instruction, kind)
or
not isFirstInstructionBeforeUninitializedGroup(instruction, _) and
result = getInstructionSuccessorAfterUninitializedGroup0(instruction, kind)
}
cached
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
exists(OldInstruction oldInstruction |
@@ -406,6 +632,16 @@ private module Cached {
exists(IRFunctionBase irFunc |
instr = unreachedInstruction(irFunc) and result = irFunc.getFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction().getFunction()
)
or
exists(UninitializedGroupInstruction initGroup |
instr = chiInstruction(initGroup) and
result = getInstructionAst(initGroup)
)
}
cached
@@ -418,9 +654,16 @@ private module Cached {
)
or
exists(Instruction primaryInstr, Alias::VirtualVariable vvar |
instr = chiInstruction(primaryInstr) and
hasChiNode(vvar, primaryInstr) and
result = vvar.getType()
instr = chiInstruction(primaryInstr) and result = vvar.getType()
|
hasChiNode(vvar, primaryInstr)
or
hasChiNodeAfterUninitializedGroup(vvar, primaryInstr)
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getType()
)
or
instr = reusedPhiInstruction(_) and
@@ -448,6 +691,8 @@ private module Cached {
or
instr = chiInstruction(_) and opcode instanceof Opcode::Chi
or
instr = uninitializedGroup(_) and opcode instanceof Opcode::UninitializedGroup
or
instr = unreachedInstruction(_) and opcode instanceof Opcode::Unreached
}
@@ -460,10 +705,15 @@ private module Cached {
result = blockStartInstr.getEnclosingIRFunction()
)
or
exists(OldInstruction primaryInstr |
exists(Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and result = primaryInstr.getEnclosingIRFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction()
)
or
instr = unreachedInstruction(result)
}
@@ -478,6 +728,8 @@ private module Cached {
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction)
)
or
instruction = getChi(result.(UninitializedGroupInstruction))
}
}
@@ -485,7 +737,7 @@ private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(
private OldInstruction getOldInstruction(Instruction instr) { instr = result }
private ChiInstruction getChi(OldInstruction primaryInstr) { result = chiInstruction(primaryInstr) }
private ChiInstruction getChi(Instruction primaryInstr) { result = chiInstruction(primaryInstr) }
private PhiInstruction getPhi(OldBlock defBlock, Alias::MemoryLocation defLocation) {
result = phiInstruction(defBlock.getFirstInstruction(), defLocation)
@@ -506,6 +758,16 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
)
}
private predicate hasChiNodeAfterUninitializedGroup(
Alias::AliasedVirtualVariable vvar, UninitializedGroupInstruction initGroup
) {
exists(Alias::GroupedMemoryLocation defLocation |
initGroup = uninitializedGroup(defLocation.getGroup()) and
defLocation.getVirtualVariable() = vvar and
Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap
)
}
private import PhiInsertion
/**
@@ -668,19 +930,33 @@ private import DefUse
* potentially very sparse.
*/
module DefUse {
bindingset[index, block]
pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) {
exists(IRFunction func | func = block.getEnclosingIRFunction() |
if
getNewBlock(block) = func.getEntryBlock() and
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and
not block.getInstruction(index) instanceof AliasedDefinitionInstruction
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
else result = 2 * index
)
}
bindingset[index, block]
pragma[inline_late]
private int getChiOffset(int index, OldBlock block) { result = getNonChiOffset(index, block) + 1 }
/**
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
*/
Instruction getDefinitionOrChiInstruction(
private Instruction getDefinitionOrChiInstruction0(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(OldInstruction oldInstr, int oldOffset |
oldInstr = defBlock.getInstruction(oldOffset) and
oldOffset >= 0
|
exists(OldInstruction oldInstr, int oldOffset | oldInstr = defBlock.getInstruction(oldOffset) |
// An odd offset corresponds to the `Chi` instruction.
defOffset = oldOffset * 2 + 1 and
defOffset = getChiOffset(oldOffset, defBlock) and
result = getChi(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -689,7 +965,7 @@ module DefUse {
actualDefLocation = defLocation.getVirtualVariable()
or
// An even offset corresponds to the original instruction.
defOffset = oldOffset * 2 and
defOffset = getNonChiOffset(oldOffset, defBlock) and
result = getNewInstruction(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -702,6 +978,54 @@ module DefUse {
hasDefinition(_, defLocation, defBlock, defOffset) and
result = getPhi(defBlock, defLocation) and
actualDefLocation = defLocation
or
exists(
Alias::VariableGroup vg, int index, UninitializedGroupInstruction initGroup,
Alias::GroupedMemoryLocation gml
|
// Add 3 to account for the function prologue:
// v1(void) = EnterFunction
// m1(unknown) = AliasedDefinition
// m2(unknown) = InitializeNonLocal
index = 3 + vg.getInitializationOrder() and
not gml.isMayAccess() and
gml.isSome() and
gml.getGroup() = vg and
vg.getIRFunction().getEntryBlock() = defBlock and
initGroup = uninitializedGroup(vg) and
(defLocation = gml or defLocation = gml.getVirtualVariable())
|
result = initGroup and
defOffset = 2 * index and
actualDefLocation = defLocation
or
result = getChi(initGroup) and
defOffset = 2 * index + 1 and
actualDefLocation = defLocation.getVirtualVariable()
)
}
private ChiInstruction remapGetDefinitionOrChiInstruction(Instruction oldResult) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(oldResult, func) and
isLastInstructionForUninitializedGroups(result, func)
)
}
Instruction getDefinitionOrChiInstruction(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(Instruction oldResult |
oldResult =
getDefinitionOrChiInstruction0(defBlock, defOffset, defLocation, actualDefLocation) and
(
result = remapGetDefinitionOrChiInstruction(oldResult)
or
not exists(remapGetDefinitionOrChiInstruction(oldResult)) and
result = oldResult
)
)
}
/**
@@ -842,8 +1166,20 @@ module DefUse {
block.getInstruction(index) = def and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = index * 2 // The use will be connected to the definition on the original instruction.
then offset = getChiOffset(index, block) // The use will be connected to the definition on the `Chi` instruction.
else offset = getNonChiOffset(index, block) // The use will be connected to the definition on the original instruction.
)
or
exists(UninitializedGroupInstruction initGroup, int index, Overlap overlap, VariableGroup vg |
initGroup.getEnclosingIRFunction().getEntryBlock() = getNewBlock(block) and
vg = defLocation.(Alias::GroupedMemoryLocation).getGroup() and
// EnterFunction + AliasedDefinition + InitializeNonLocal + index
index = 3 + vg.getInitializationOrder() and
initGroup = uninitializedGroup(vg) and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap and hasChiNodeAfterUninitializedGroup(initGroup)
then offset = 2 * index + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = 2 * index // The use will be connected to the definition on the original instruction.
)
}
@@ -904,10 +1240,11 @@ module DefUse {
block.getInstruction(index) = use and
(
// A direct use of the location.
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
offset = getNonChiOffset(index, block)
or
// A `Chi` instruction will include a use of the virtual variable.
hasChiNode(useLocation, use) and offset = (index * 2) + 1
hasChiNode(useLocation, use) and offset = getChiOffset(index, block)
)
)
}
@@ -1057,5 +1394,9 @@ module Ssa {
predicate hasChiInstruction = Cached::hasChiInstructionCached/1;
predicate hasChiNodeAfterUninitializedGroup = Cached::hasChiNodeAfterUninitializedGroup/1;
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
class VariableGroup = Alias::VariableGroup;
}

View File

@@ -31,6 +31,7 @@ newtype TInstruction =
TUnaliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
UnaliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or
TUnaliasedSsaUninitializedGroupInstruction(UnaliasedSsa::Ssa::VariableGroup vg) or
TAliasedSsaPhiInstruction(
TRawInstruction blockStartInstr, AliasedSsa::Ssa::MemoryLocation memoryLocation
) {
@@ -41,6 +42,12 @@ newtype TInstruction =
} or
TAliasedSsaUnreachedInstruction(IRFunctionBase irFunc) {
AliasedSsa::Ssa::hasUnreachedInstruction(irFunc)
} or
TAliasedSsaUninitializedGroupInstruction(AliasedSsa::Ssa::VariableGroup vg) or
TAliasedSsaChiAfterUninitializedGroupInstruction(
TAliasedSsaUninitializedGroupInstruction initGroup
) {
AliasedSsa::Ssa::hasChiNodeAfterUninitializedGroup(initGroup)
}
/**
@@ -62,7 +69,11 @@ module UnaliasedSsaInstructions {
class TChiInstruction = TUnaliasedSsaChiInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
class TUninitializedGroupInstruction = TUnaliasedSsaUninitializedGroupInstruction;
class TRawOrUninitializedGroupInstruction = TRawInstruction or TUninitializedGroupInstruction;
TChiInstruction chiInstruction(TRawOrUninitializedGroupInstruction primaryInstruction) {
result = TUnaliasedSsaChiInstruction(primaryInstruction)
}
@@ -71,6 +82,12 @@ module UnaliasedSsaInstructions {
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
result = TUnaliasedSsaUnreachedInstruction(irFunc)
}
class VariableGroup = UnaliasedSsa::Ssa::VariableGroup;
// This really should just be `TUnaliasedSsaUninitializedGroupInstruction`, but that makes the
// compiler realize that certain expressions in `SSAConstruction` are unsatisfiable.
TRawOrUninitializedGroupInstruction uninitializedGroup(VariableGroup vg) { none() }
}
/**
@@ -92,10 +109,16 @@ module AliasedSsaInstructions {
result = TUnaliasedSsaPhiInstruction(blockStartInstr, _)
}
class TChiInstruction = TAliasedSsaChiInstruction;
class TChiInstruction =
TAliasedSsaChiInstruction or TAliasedSsaChiAfterUninitializedGroupInstruction;
TChiInstruction chiInstruction(TRawInstruction primaryInstruction) {
class TRawOrInitialzieGroupInstruction =
TRawInstruction or TAliasedSsaUninitializedGroupInstruction;
TChiInstruction chiInstruction(TRawOrInitialzieGroupInstruction primaryInstruction) {
result = TAliasedSsaChiInstruction(primaryInstruction)
or
result = TAliasedSsaChiAfterUninitializedGroupInstruction(primaryInstruction)
}
class TUnreachedInstruction = TAliasedSsaUnreachedInstruction;
@@ -103,4 +126,12 @@ module AliasedSsaInstructions {
TUnreachedInstruction unreachedInstruction(IRFunctionBase irFunc) {
result = TAliasedSsaUnreachedInstruction(irFunc)
}
class VariableGroup = AliasedSsa::Ssa::VariableGroup;
class TUninitializedGroupInstruction = TAliasedSsaUninitializedGroupInstruction;
TUninitializedGroupInstruction uninitializedGroup(VariableGroup vg) {
result = TAliasedSsaUninitializedGroupInstruction(vg)
}
}

View File

@@ -12,6 +12,9 @@ private import semmle.code.cpp.ir.internal.Overlap
* Provides the newtype used to represent operands across all phases of the IR.
*/
private module Internal {
private class TAliasedChiInstruction =
TAliasedSsaChiInstruction or TAliasedSsaChiAfterUninitializedGroupInstruction;
/**
* An IR operand. `TOperand` is shared across all phases of the IR. There are branches of this
* type for operands created directly from the AST (`TRegisterOperand` and `TNonSSAMemoryOperand`),
@@ -52,7 +55,7 @@ private module Internal {
) {
exists(AliasedConstruction::getPhiOperandDefinition(useInstr, predecessorBlock, overlap))
} or
TAliasedChiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) { any() }
TAliasedChiOperand(TAliasedChiInstruction useInstr, ChiOperandTag tag) { any() }
}
/**
@@ -198,10 +201,13 @@ module AliasedSsaOperands {
)
}
private class TChiInstruction =
TAliasedSsaChiInstruction or TAliasedSsaChiAfterUninitializedGroupInstruction;
/**
* Returns the Chi operand with the specified parameters.
*/
TChiOperand chiOperand(TAliasedSsaChiInstruction useInstr, ChiOperandTag tag) {
TChiOperand chiOperand(TChiInstruction useInstr, ChiOperandTag tag) {
result = Internal::TAliasedChiOperand(useInstr, tag)
}
}

View File

@@ -2142,6 +2142,47 @@ class ChiInstruction extends Instruction {
final predicate isPartialUpdate() { Construction::chiOnlyPartiallyUpdatesLocation(this) }
}
/**
* An instruction that initializes a set of allocations that are each assigned
* the same "virtual variable".
*
* As an example, consider the following snippet:
* ```
* int a;
* int b;
* int* p;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 5;
* int x = a;
* ```
*
* Since both the address of `a` and `b` reach `p` at `*p = 5` the IR alias
* analysis will create a region that contains both `a` and `b`. The region
* containing both `a` and `b` are initialized by an `UninitializedGroup`
* instruction in the entry block of the enclosing function.
*/
class UninitializedGroupInstruction extends Instruction {
UninitializedGroupInstruction() { this.getOpcode() instanceof Opcode::UninitializedGroup }
/**
* Gets an `IRVariable` whose memory is initialized by this instruction, if any.
* Note: Allocations that are not represented as `IRVariable`s (such as
* dynamic allocations) are not returned by this predicate even if this
* instruction initializes such memory.
*/
final IRVariable getAnIRVariable() {
result = Construction::getAnUninitializedGroupVariable(this)
}
final override string getImmediateString() {
result = strictconcat(this.getAnIRVariable().toString(), ",")
}
}
/**
* An instruction representing unreachable code.
*

View File

@@ -407,6 +407,8 @@ predicate hasUnreachedInstruction(IRFunction func) {
)
}
IRVariable getAnUninitializedGroupVariable(UninitializedGroupInstruction instr) { none() }
import CachedForDebugging
cached

View File

@@ -2142,6 +2142,47 @@ class ChiInstruction extends Instruction {
final predicate isPartialUpdate() { Construction::chiOnlyPartiallyUpdatesLocation(this) }
}
/**
* An instruction that initializes a set of allocations that are each assigned
* the same "virtual variable".
*
* As an example, consider the following snippet:
* ```
* int a;
* int b;
* int* p;
* if(b) {
* p = &a;
* } else {
* p = &b;
* }
* *p = 5;
* int x = a;
* ```
*
* Since both the address of `a` and `b` reach `p` at `*p = 5` the IR alias
* analysis will create a region that contains both `a` and `b`. The region
* containing both `a` and `b` are initialized by an `UninitializedGroup`
* instruction in the entry block of the enclosing function.
*/
class UninitializedGroupInstruction extends Instruction {
UninitializedGroupInstruction() { this.getOpcode() instanceof Opcode::UninitializedGroup }
/**
* Gets an `IRVariable` whose memory is initialized by this instruction, if any.
* Note: Allocations that are not represented as `IRVariable`s (such as
* dynamic allocations) are not returned by this predicate even if this
* instruction initializes such memory.
*/
final IRVariable getAnIRVariable() {
result = Construction::getAnUninitializedGroupVariable(this)
}
final override string getImmediateString() {
result = strictconcat(this.getAnIRVariable().toString(), ",")
}
}
/**
* An instruction representing unreachable code.
*

View File

@@ -106,8 +106,7 @@ private predicate operandEscapesDomain(Operand operand) {
not isArgumentForParameter(_, operand, _) and
not isOnlyEscapesViaReturnArgument(operand) and
not operand.getUse() instanceof ReturnValueInstruction and
not operand.getUse() instanceof ReturnIndirectionInstruction and
not operand instanceof PhiInputOperand
not operand.getUse() instanceof ReturnIndirectionInstruction
}
/**
@@ -191,6 +190,11 @@ private predicate operandIsPropagated(Operand operand, IntValue bitOffset, Instr
// A copy propagates the source value.
operand = instr.(CopyInstruction).getSourceValueOperand() and bitOffset = 0
)
or
operand = instr.(PhiInstruction).getAnInputOperand() and
// Using `unknown` ensures termination since we cannot keep incrementing a bit offset
// through the back edge of a loop (or through recursion).
bitOffset = Ints::unknown()
}
private predicate operandEscapesNonReturn(Operand operand) {
@@ -212,9 +216,6 @@ private predicate operandEscapesNonReturn(Operand operand) {
or
isOnlyEscapesViaReturnArgument(operand) and resultEscapesNonReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultEscapesNonReturn(operand.getUse())
or
operandEscapesDomain(operand)
}
@@ -236,9 +237,6 @@ private predicate operandMayReachReturn(Operand operand) {
operand.getUse() instanceof ReturnValueInstruction
or
isOnlyEscapesViaReturnArgument(operand) and resultMayReachReturn(operand.getUse())
or
operand instanceof PhiInputOperand and
resultMayReachReturn(operand.getUse())
}
private predicate operandReturned(Operand operand, IntValue bitOffset) {

View File

@@ -15,6 +15,51 @@ private class OldInstruction = Reachability::ReachableInstruction;
import Cached
/**
* Holds if `instruction` is the first instruction that may be followed by
* an `UninitializedGroup` instruction, and the enclosing function of
* `instruction` is `func`.
*/
private predicate isFirstInstructionBeforeUninitializedGroup(
Instruction instruction, IRFunction func
) {
instruction = getChi(any(OldIR::InitializeNonLocalInstruction init)) and
func = instruction.getEnclosingIRFunction()
}
/** Gets the `i`'th `UninitializedGroup` instruction in `func`. */
private UninitializedGroupInstruction getInitGroupInstruction(int i, IRFunction func) {
exists(Alias::VariableGroup vg |
vg.getIRFunction() = func and
vg.getInitializationOrder() = i and
result = uninitializedGroup(vg)
)
}
/**
* Holds if `instruction` is the last instruction in the chain of `UninitializedGroup`
* instructions in `func`. The chain of instructions may be empty in which case
* `instruction` satisfies
* ```
* isFirstInstructionBeforeUninitializedGroup(instruction, func)
* ```
*/
predicate isLastInstructionForUninitializedGroups(Instruction instruction, IRFunction func) {
exists(int i |
instruction = getInitGroupInstruction(i, func) and
not exists(getChi(instruction)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
exists(int i |
instruction = getChi(getInitGroupInstruction(i, func)) and
not exists(getInitGroupInstruction(i + 1, func))
)
or
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
not exists(getInitGroupInstruction(0, func))
}
cached
private module Cached {
cached
@@ -32,6 +77,11 @@ private module Cached {
hasChiNode(_, primaryInstruction)
}
cached
predicate hasChiNodeAfterUninitializedGroup(UninitializedGroupInstruction initGroup) {
hasChiNodeAfterUninitializedGroup(_, initGroup)
}
cached
predicate hasUnreachedInstructionCached(IRFunction irFunc) {
exists(OldIR::Instruction oldInstruction |
@@ -45,7 +95,8 @@ private module Cached {
}
class TStageInstruction =
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction;
TRawInstruction or TPhiInstruction or TChiInstruction or TUnreachedInstruction or
TUninitializedGroupInstruction;
/**
* If `oldInstruction` is a `Phi` instruction that has exactly one reachable predecessor block,
@@ -78,6 +129,8 @@ private module Cached {
or
instr instanceof TChiInstruction
or
instr instanceof TUninitializedGroupInstruction
or
instr instanceof TUnreachedInstruction
}
@@ -123,7 +176,8 @@ private module Cached {
predicate hasModeledMemoryResult(Instruction instruction) {
canModelResultForOldInstruction(getOldInstruction(instruction)) or
instruction instanceof PhiInstruction or // Phis always have modeled results
instruction instanceof ChiInstruction // Chis always have modeled results
instruction instanceof ChiInstruction or // Chis always have modeled results
instruction instanceof UninitializedGroupInstruction // Group initializers always have modeled results
}
cached
@@ -134,16 +188,23 @@ private module Cached {
or
// Chi instructions track virtual variables, and therefore a chi instruction is
// conflated if it's associated with the aliased virtual variable.
exists(OldInstruction oldInstruction | instruction = getChi(oldInstruction) |
Alias::getResultMemoryLocation(oldInstruction).getVirtualVariable() instanceof
exists(Instruction input | instruction = getChi(input) |
Alias::getResultMemoryLocation(input).getVirtualVariable() instanceof
Alias::AliasedVirtualVariable
or
// A chi following an `UninitializedGroupInstruction` only happens when the virtual
// variable of the grouped memory location is `{AllAliasedMemory}`.
exists(Alias::GroupedMemoryLocation gml |
input = uninitializedGroup(gml.getGroup()) and
gml.getVirtualVariable() instanceof Alias::AliasedVirtualVariable
)
)
or
// Phi instructions track locations, and therefore a phi instruction is
// conflated if it's associated with a conflated location.
exists(Alias::MemoryLocation location |
instruction = getPhi(_, location) and
not exists(location.getAllocation())
not exists(location.getAnAllocation())
)
}
@@ -205,7 +266,11 @@ private module Cached {
hasMemoryOperandDefinition(oldInstruction, oldOperand, overlap, result)
)
or
instruction = getChi(getOldInstruction(result)) and
(
instruction = getChi(getOldInstruction(result))
or
instruction = getChi(result.(UninitializedGroupInstruction))
) and
tag instanceof ChiPartialOperandTag and
overlap instanceof MustExactlyOverlap
or
@@ -263,6 +328,14 @@ private module Cached {
)
}
cached
IRVariable getAnUninitializedGroupVariable(UninitializedGroupInstruction init) {
exists(Alias::VariableGroup vg |
init = uninitializedGroup(vg) and
result = vg.getAnAllocation().getABaseInstruction().(VariableInstruction).getIRVariable()
)
}
/**
* Holds if `instr` is part of a cycle in the operand graph that doesn't go
* through a phi instruction and therefore should be impossible.
@@ -316,6 +389,19 @@ private module Cached {
result = getNewPhiOperandDefinitionFromOldSsa(instr, newPredecessorBlock, overlap)
}
private ChiInstruction getChiAfterUninitializedGroup(int i, IRFunction func) {
result =
rank[i + 1](VariableGroup vg, UninitializedGroupInstruction initGroup, ChiInstruction chi,
int r |
initGroup.getEnclosingIRFunction() = func and
chi = getChi(initGroup) and
initGroup = uninitializedGroup(vg) and
r = vg.getInitializationOrder()
|
chi order by r
)
}
cached
Instruction getChiInstructionTotalOperand(ChiInstruction chiInstr) {
exists(
@@ -329,6 +415,19 @@ private module Cached {
definitionReachesUse(vvar, defBlock, defRank, useBlock, useRank) and
result = getDefinitionOrChiInstruction(defBlock, defOffset, vvar, _)
)
or
exists(UninitializedGroupInstruction initGroup, IRFunction func |
chiInstr = getChi(initGroup) and
func = initGroup.getEnclosingIRFunction()
|
chiInstr = getChiAfterUninitializedGroup(0, func) and
isFirstInstructionBeforeUninitializedGroup(result, func)
or
exists(int i |
chiInstr = getChiAfterUninitializedGroup(i + 1, func) and
result = getChiAfterUninitializedGroup(i, func)
)
)
}
cached
@@ -344,14 +443,40 @@ private module Cached {
)
}
/*
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction
*/
private UninitializedGroupInstruction firstInstructionToUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(instruction, func) and
result = getInitGroupInstruction(0, func) and
kind instanceof GotoEdge
)
}
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
private Instruction getNextUninitializedGroupInstruction(Instruction instruction, EdgeKind kind) {
exists(int i, IRFunction func |
func = instruction.getEnclosingIRFunction() and
instruction = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
if hasChiNodeAfterUninitializedGroup(_, instruction)
then result = getChi(instruction)
else result = getInitGroupInstruction(i + 1, func)
)
or
exists(int i, IRFunction func, UninitializedGroupInstruction initGroup |
func = instruction.getEnclosingIRFunction() and
instruction = getChi(initGroup) and
initGroup = getInitGroupInstruction(i, func) and
kind instanceof GotoEdge
|
result = getInitGroupInstruction(i + 1, func)
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup0(
Instruction instruction, EdgeKind kind
) {
if hasChiNode(_, getOldInstruction(instruction))
then
result = getChi(getOldInstruction(instruction)) and
@@ -371,6 +496,107 @@ private module Cached {
)
}
private Instruction getInstructionSuccessorAfterUninitializedGroup(
Instruction instruction, EdgeKind kind
) {
exists(IRFunction func, Instruction firstBeforeUninitializedGroup |
isLastInstructionForUninitializedGroups(instruction, func) and
isFirstInstructionBeforeUninitializedGroup(firstBeforeUninitializedGroup, func) and
result = getInstructionSuccessorAfterUninitializedGroup0(firstBeforeUninitializedGroup, kind)
)
}
/**
* This adds Chi nodes to the instruction successor relation; if an instruction has a Chi node,
* that node is its successor in the new successor relation, and the Chi node's successors are
* the new instructions generated from the successors of the old instruction.
*
* Furthermore, the entry block is augmented with `UninitializedGroup` instructions and `Chi`
* instructions. For example, consider this example:
* ```cpp
* int x, y;
* int* p;
* if(b) {
* p = &x;
* escape(&x);
* } else {
* p = &y;
* }
* *p = 42;
*
* int z, w;
* int* q;
* if(b) {
* q = &z;
* } else {
* q = &w;
* }
* *q = 43;
* ```
*
* the unaliased IR for the entry block of this snippet is:
* ```
* v1(void) = EnterFunction :
* m1(unknown) = AliasedDefinition :
* m2(unknown) = InitializeNonLocal :
* r1(glval<bool>) = VariableAddress[b] :
* m3(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m4(int) = Uninitialized[x] : &:r2
* r3(glval<int>) = VariableAddress[y] :
* m5(int) = Uninitialized[y] : &:r3
* r4(glval<int *>) = VariableAddress[p] :
* m6(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m3
* v2(void) = ConditionalBranch : r6
* ```
* and we need to transform this to aliased IR by inserting an `UninitializedGroup`
* instruction for every `VariableGroup` memory location in the function. Furthermore,
* if the `VariableGroup` memory location contains an allocation that escapes we need
* to insert a `Chi` that writes the memory produced by `UninitializedGroup` into
* `{AllAliasedMemory}`. For the above snippet we then end up with:
* ```
* v1(void) = EnterFunction :
* m2(unknown) = AliasedDefinition :
* m3(unknown) = InitializeNonLocal :
* m4(unknown) = Chi : total:m2, partial:m3
* m5(int) = UninitializedGroup[x,y] :
* m6(unknown) = Chi : total:m4, partial:m5
* m7(int) = UninitializedGroup[w,z] :
* r1(glval<bool>) = VariableAddress[b] :
* m8(bool) = InitializeParameter[b] : &:r1
* r2(glval<int>) = VariableAddress[x] :
* m10(int) = Uninitialized[x] : &:r2
* m11(unknown) = Chi : total:m6, partial:m10
* r3(glval<int>) = VariableAddress[y] :
* m12(int) = Uninitialized[y] : &:r3
* m13(unknown) = Chi : total:m11, partial:m12
* r4(glval<int *>) = VariableAddress[p] :
* m14(int *) = Uninitialized[p] : &:r4
* r5(glval<bool>) = VariableAddress[b] :
* r6(bool) = Load[b] : &:r5, m8
* v2(void) = ConditionalBranch : r6
* ```
*
* Here, the group `{x, y}` contains an allocation that escapes (`x`), so there
* is a `Chi` after the `UninitializedGroup` that initializes the memory for the
* `VariableGroup` containing `x`. None of the allocations in `{w, z}` escape so
* there is no `Chi` following that the `UninitializedGroup` that initializes the
* memory of `{w, z}`.
*/
cached
Instruction getInstructionSuccessor(Instruction instruction, EdgeKind kind) {
result = firstInstructionToUninitializedGroup(instruction, kind)
or
result = getNextUninitializedGroupInstruction(instruction, kind)
or
result = getInstructionSuccessorAfterUninitializedGroup(instruction, kind)
or
not isFirstInstructionBeforeUninitializedGroup(instruction, _) and
result = getInstructionSuccessorAfterUninitializedGroup0(instruction, kind)
}
cached
Instruction getInstructionBackEdgeSuccessor(Instruction instruction, EdgeKind kind) {
exists(OldInstruction oldInstruction |
@@ -406,6 +632,16 @@ private module Cached {
exists(IRFunctionBase irFunc |
instr = unreachedInstruction(irFunc) and result = irFunc.getFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction().getFunction()
)
or
exists(UninitializedGroupInstruction initGroup |
instr = chiInstruction(initGroup) and
result = getInstructionAst(initGroup)
)
}
cached
@@ -418,9 +654,16 @@ private module Cached {
)
or
exists(Instruction primaryInstr, Alias::VirtualVariable vvar |
instr = chiInstruction(primaryInstr) and
hasChiNode(vvar, primaryInstr) and
result = vvar.getType()
instr = chiInstruction(primaryInstr) and result = vvar.getType()
|
hasChiNode(vvar, primaryInstr)
or
hasChiNodeAfterUninitializedGroup(vvar, primaryInstr)
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getType()
)
or
instr = reusedPhiInstruction(_) and
@@ -448,6 +691,8 @@ private module Cached {
or
instr = chiInstruction(_) and opcode instanceof Opcode::Chi
or
instr = uninitializedGroup(_) and opcode instanceof Opcode::UninitializedGroup
or
instr = unreachedInstruction(_) and opcode instanceof Opcode::Unreached
}
@@ -460,10 +705,15 @@ private module Cached {
result = blockStartInstr.getEnclosingIRFunction()
)
or
exists(OldInstruction primaryInstr |
exists(Instruction primaryInstr |
instr = chiInstruction(primaryInstr) and result = primaryInstr.getEnclosingIRFunction()
)
or
exists(Alias::VariableGroup vg |
instr = uninitializedGroup(vg) and
result = vg.getIRFunction()
)
or
instr = unreachedInstruction(result)
}
@@ -478,6 +728,8 @@ private module Cached {
instruction = getChi(oldInstruction) and
result = getNewInstruction(oldInstruction)
)
or
instruction = getChi(result.(UninitializedGroupInstruction))
}
}
@@ -485,7 +737,7 @@ private Instruction getNewInstruction(OldInstruction instr) { getOldInstruction(
private OldInstruction getOldInstruction(Instruction instr) { instr = result }
private ChiInstruction getChi(OldInstruction primaryInstr) { result = chiInstruction(primaryInstr) }
private ChiInstruction getChi(Instruction primaryInstr) { result = chiInstruction(primaryInstr) }
private PhiInstruction getPhi(OldBlock defBlock, Alias::MemoryLocation defLocation) {
result = phiInstruction(defBlock.getFirstInstruction(), defLocation)
@@ -506,6 +758,16 @@ private predicate hasChiNode(Alias::VirtualVariable vvar, OldInstruction def) {
)
}
private predicate hasChiNodeAfterUninitializedGroup(
Alias::AliasedVirtualVariable vvar, UninitializedGroupInstruction initGroup
) {
exists(Alias::GroupedMemoryLocation defLocation |
initGroup = uninitializedGroup(defLocation.getGroup()) and
defLocation.getVirtualVariable() = vvar and
Alias::getOverlap(defLocation, vvar) instanceof MayPartiallyOverlap
)
}
private import PhiInsertion
/**
@@ -668,19 +930,33 @@ private import DefUse
* potentially very sparse.
*/
module DefUse {
bindingset[index, block]
pragma[inline_late]
private int getNonChiOffset(int index, OldBlock block) {
exists(IRFunction func | func = block.getEnclosingIRFunction() |
if
getNewBlock(block) = func.getEntryBlock() and
not block.getInstruction(index) instanceof InitializeNonLocalInstruction and
not block.getInstruction(index) instanceof AliasedDefinitionInstruction
then result = 2 * (index + count(VariableGroup vg | vg.getIRFunction() = func))
else result = 2 * index
)
}
bindingset[index, block]
pragma[inline_late]
private int getChiOffset(int index, OldBlock block) { result = getNonChiOffset(index, block) + 1 }
/**
* Gets the `Instruction` for the definition at offset `defOffset` in block `defBlock`.
*/
Instruction getDefinitionOrChiInstruction(
private Instruction getDefinitionOrChiInstruction0(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(OldInstruction oldInstr, int oldOffset |
oldInstr = defBlock.getInstruction(oldOffset) and
oldOffset >= 0
|
exists(OldInstruction oldInstr, int oldOffset | oldInstr = defBlock.getInstruction(oldOffset) |
// An odd offset corresponds to the `Chi` instruction.
defOffset = oldOffset * 2 + 1 and
defOffset = getChiOffset(oldOffset, defBlock) and
result = getChi(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -689,7 +965,7 @@ module DefUse {
actualDefLocation = defLocation.getVirtualVariable()
or
// An even offset corresponds to the original instruction.
defOffset = oldOffset * 2 and
defOffset = getNonChiOffset(oldOffset, defBlock) and
result = getNewInstruction(oldInstr) and
(
defLocation = Alias::getResultMemoryLocation(oldInstr) or
@@ -702,6 +978,54 @@ module DefUse {
hasDefinition(_, defLocation, defBlock, defOffset) and
result = getPhi(defBlock, defLocation) and
actualDefLocation = defLocation
or
exists(
Alias::VariableGroup vg, int index, UninitializedGroupInstruction initGroup,
Alias::GroupedMemoryLocation gml
|
// Add 3 to account for the function prologue:
// v1(void) = EnterFunction
// m1(unknown) = AliasedDefinition
// m2(unknown) = InitializeNonLocal
index = 3 + vg.getInitializationOrder() and
not gml.isMayAccess() and
gml.isSome() and
gml.getGroup() = vg and
vg.getIRFunction().getEntryBlock() = defBlock and
initGroup = uninitializedGroup(vg) and
(defLocation = gml or defLocation = gml.getVirtualVariable())
|
result = initGroup and
defOffset = 2 * index and
actualDefLocation = defLocation
or
result = getChi(initGroup) and
defOffset = 2 * index + 1 and
actualDefLocation = defLocation.getVirtualVariable()
)
}
private ChiInstruction remapGetDefinitionOrChiInstruction(Instruction oldResult) {
exists(IRFunction func |
isFirstInstructionBeforeUninitializedGroup(oldResult, func) and
isLastInstructionForUninitializedGroups(result, func)
)
}
Instruction getDefinitionOrChiInstruction(
OldBlock defBlock, int defOffset, Alias::MemoryLocation defLocation,
Alias::MemoryLocation actualDefLocation
) {
exists(Instruction oldResult |
oldResult =
getDefinitionOrChiInstruction0(defBlock, defOffset, defLocation, actualDefLocation) and
(
result = remapGetDefinitionOrChiInstruction(oldResult)
or
not exists(remapGetDefinitionOrChiInstruction(oldResult)) and
result = oldResult
)
)
}
/**
@@ -842,8 +1166,20 @@ module DefUse {
block.getInstruction(index) = def and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap
then offset = (index * 2) + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = index * 2 // The use will be connected to the definition on the original instruction.
then offset = getChiOffset(index, block) // The use will be connected to the definition on the `Chi` instruction.
else offset = getNonChiOffset(index, block) // The use will be connected to the definition on the original instruction.
)
or
exists(UninitializedGroupInstruction initGroup, int index, Overlap overlap, VariableGroup vg |
initGroup.getEnclosingIRFunction().getEntryBlock() = getNewBlock(block) and
vg = defLocation.(Alias::GroupedMemoryLocation).getGroup() and
// EnterFunction + AliasedDefinition + InitializeNonLocal + index
index = 3 + vg.getInitializationOrder() and
initGroup = uninitializedGroup(vg) and
overlap = Alias::getOverlap(defLocation, useLocation) and
if overlap instanceof MayPartiallyOverlap and hasChiNodeAfterUninitializedGroup(initGroup)
then offset = 2 * index + 1 // The use will be connected to the definition on the `Chi` instruction.
else offset = 2 * index // The use will be connected to the definition on the original instruction.
)
}
@@ -904,10 +1240,11 @@ module DefUse {
block.getInstruction(index) = use and
(
// A direct use of the location.
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and offset = index * 2
useLocation = Alias::getOperandMemoryLocation(use.getAnOperand()) and
offset = getNonChiOffset(index, block)
or
// A `Chi` instruction will include a use of the virtual variable.
hasChiNode(useLocation, use) and offset = (index * 2) + 1
hasChiNode(useLocation, use) and offset = getChiOffset(index, block)
)
)
}
@@ -1057,5 +1394,9 @@ module Ssa {
predicate hasChiInstruction = Cached::hasChiInstructionCached/1;
predicate hasChiNodeAfterUninitializedGroup = Cached::hasChiNodeAfterUninitializedGroup/1;
predicate hasUnreachedInstruction = Cached::hasUnreachedInstructionCached/1;
class VariableGroup = Alias::VariableGroup;
}

View File

@@ -2,6 +2,7 @@ import AliasAnalysis
private import SimpleSSAImports
import SimpleSSAPublicImports
private import AliasConfiguration
private import codeql.util.Unit
private predicate isTotalAccess(Allocation var, AddressOperand addrOperand, IRType type) {
exists(Instruction constantBase, int bitOffset |
@@ -48,7 +49,7 @@ predicate canReuseSsaForVariable(IRAutomaticVariable var) {
private newtype TMemoryLocation = MkMemoryLocation(Allocation var) { isVariableModeled(var) }
private MemoryLocation getMemoryLocation(Allocation var) { result.getAllocation() = var }
private MemoryLocation getMemoryLocation(Allocation var) { result.getAnAllocation() = var }
class MemoryLocation extends TMemoryLocation {
Allocation var;
@@ -57,7 +58,7 @@ class MemoryLocation extends TMemoryLocation {
final string toString() { result = var.getAllocationString() }
final Allocation getAllocation() { result = var }
final Allocation getAnAllocation() { result = var }
final Language::Location getLocation() { result = var.getLocation() }
@@ -77,6 +78,40 @@ class MemoryLocation extends TMemoryLocation {
predicate canReuseSsaForOldResult(Instruction instr) { none() }
abstract class VariableGroup extends Unit {
abstract Allocation getAnAllocation();
string toString() { result = "{" + strictconcat(this.getAnAllocation().toString(), ", ") + "}" }
abstract Language::Location getLocation();
abstract IRFunction getIRFunction();
abstract Language::LanguageType getType();
abstract int getInitializationOrder();
}
class GroupedMemoryLocation extends MemoryLocation {
VariableGroup vg;
GroupedMemoryLocation() { none() }
/** Gets an allocation of this memory location. */
Allocation getAnAllocation() { result = vg.getAnAllocation() }
/** Gets the set of allocations associated with this memory location. */
VariableGroup getGroup() { result = vg }
predicate isMayAccess() { none() }
/** Holds if this memory location represents all the enclosing allocations. */
predicate isAll() { none() }
/** Holds if this memory location represents one or more of the enclosing allocations. */
predicate isSome() { none() }
}
/**
* Represents a set of `MemoryLocation`s that cannot overlap with
* `MemoryLocation`s outside of the set. The `VirtualVariable` will be

View File

@@ -66,7 +66,7 @@ abstract private class StdStringTaintFunction extends TaintFunction {
* Gets the index of a parameter to this function that is an iterator.
*/
final int getAnIteratorParameterIndex() {
this.getParameter(result).getType() instanceof Iterator
this.getParameter(result).getUnspecifiedType() instanceof Iterator
}
}

View File

@@ -172,5 +172,5 @@ where
not arg.isFromUninstantiatedTemplate(_) and
not actual.getUnspecifiedType() instanceof ErroneousType
select arg,
"This argument should be of type '" + expected.getName() + "' but is of type '" +
"This format specifier for type '" + expected.getName() + "' does not match the argument type '" +
actual.getUnspecifiedType().getName() + "'."

View File

@@ -1,7 +0,0 @@
Record* fixRecord(Record* r) {
Record myRecord = *r;
delete r;
myRecord.fix();
return &myRecord; //returns reference to myRecord, which is a stack-allocated object
}

View File

@@ -5,22 +5,23 @@
<overview>
<p>This rule finds return statements that return pointers to an object allocated on the stack.
The lifetime of a stack allocated memory location only lasts until the function returns, and
the contents of that memory become undefined after that. Clearly, using a pointer to stack
<p>This rule finds return statements that return pointers to an object allocated on the stack.
The lifetime of a stack allocated memory location only lasts until the function returns, and
the contents of that memory become undefined after that. Clearly, using a pointer to stack
memory after the function has already returned will have undefined results. </p>
</overview>
<recommendation>
<p>Use the functions of the <tt>malloc</tt> family to dynamically allocate memory on the heap for data that is used across function calls.</p>
<p>Use the functions of the <tt>malloc</tt> family, or <tt>new</tt>, to dynamically allocate memory on the heap for data that is used across function calls.</p>
</recommendation>
<example><sample src="ReturnStackAllocatedMemory.cpp" />
<example>
<p>The following example allocates an object on the stack and returns a pointer to it. This is incorrect because the object is deallocated
when the function returns, and the pointer becomes invalid.</p>
<sample src="ReturnStackAllocatedMemoryBad.cpp" />
<p>To fix this, allocate the object on the heap using <tt>new</tt> and return a pointer to the heap-allocated object.</p>
<sample src="ReturnStackAllocatedMemoryGood.cpp" />
</example>
<references>

View File

@@ -0,0 +1,5 @@
Record *mkRecord(int value) {
Record myRecord(value);
return &myRecord; // BAD: returns a pointer to `myRecord`, which is a stack-allocated object.
}

View File

@@ -0,0 +1,5 @@
Record *mkRecord(int value) {
Record *myRecord = new Record(value);
return myRecord; // GOOD: returns a pointer to a `myRecord`, which is a heap-allocated object.
}

View File

@@ -1,5 +1,14 @@
unsigned limit = get_limit();
unsigned total = 0;
while (limit - total > 0) { // wrong: if `total` is greater than `limit` this will underflow and continue executing the loop.
uint32_t limit = get_limit();
uint32_t total = 0;
while (limit - total > 0) { // BAD: if `total` is greater than `limit` this will underflow and continue executing the loop.
total += get_data();
}
}
while (total < limit) { // GOOD: never underflows here because there is no arithmetic.
total += get_data();
}
while ((int64_t)limit - total > 0) { // GOOD: never underflows here because the result always fits in an `int64_t`.
total += get_data();
}

View File

@@ -17,6 +17,7 @@ import semmle.code.cpp.rangeanalysis.SimpleRangeAnalysis
import semmle.code.cpp.rangeanalysis.RangeAnalysisUtils
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
/**
* Holds if `sub` is guarded by a condition which ensures that
@@ -33,46 +34,109 @@ predicate isGuarded(SubExpr sub, Expr left, Expr right) {
)
}
/**
* Gets an expression that is less than or equal to `sub.getLeftOperand()`.
* These serve as the base cases for `exprIsSubLeftOrLess`.
*/
Expr exprIsLeftOrLessBase(SubExpr sub) {
interestingSubExpr(sub, _) and // Manual magic
exists(Expr e | globalValueNumber(e).getAnExpr() = sub.getLeftOperand() |
// sub = e - x
// result = e
// so:
// result <= e
result = e
or
// sub = e - x
// result = e & y
// so:
// result = e & y <= e
result.(BitwiseAndExpr).getAnOperand() = e
or
exists(SubExpr s |
// sub = e - x
// result = s
// s = e - y
// y >= 0
// so:
// result = e - y <= e
result = s and
s.getLeftOperand() = e and
lowerBound(s.getRightOperand().getFullyConverted()) >= 0
)
or
exists(Expr other |
// sub = e - x
// result = a
// a = e + y
// y <= 0
// so:
// result = e + y <= e + 0 = e
result.(AddExpr).hasOperands(e, other) and
upperBound(other.getFullyConverted()) <= 0
)
or
exists(DivExpr d |
// sub = e - x
// result = d
// d = e / y
// y >= 1
// so:
// result = e / y <= e / 1 = e
result = d and
d.getLeftOperand() = e and
lowerBound(d.getRightOperand().getFullyConverted()) >= 1
)
or
exists(RShiftExpr rs |
// sub = e - x
// result = rs
// rs = e >> y
// so:
// result = e >> y <= e
result = rs and
rs.getLeftOperand() = e
)
)
}
/**
* Holds if `n` is known or suspected to be less than or equal to
* `sub.getLeftOperand()`.
*/
predicate exprIsSubLeftOrLess(SubExpr sub, DataFlow::Node n) {
interestingSubExpr(sub, _) and // Manual magic
(
n.asExpr() = sub.getLeftOperand()
or
exists(DataFlow::Node other |
// dataflow
exprIsSubLeftOrLess(sub, other) and
(
DataFlow::localFlowStep(n, other) or
DataFlow::localFlowStep(other, n)
)
)
or
exists(DataFlow::Node other |
// guard constraining `sub`
exprIsSubLeftOrLess(sub, other) and
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
)
or
exists(DataFlow::Node other, float p, float q |
// linear access of `other`
exprIsSubLeftOrLess(sub, other) and
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
p <= 1 and
q <= 0
)
or
exists(DataFlow::Node other, float p, float q |
// linear access of `n`
exprIsSubLeftOrLess(sub, other) and
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
p >= 1 and
q >= 0
n.asExpr() = exprIsLeftOrLessBase(sub)
or
exists(DataFlow::Node other |
// dataflow
exprIsSubLeftOrLess(sub, other) and
(
DataFlow::localFlowStep(n, other) or
DataFlow::localFlowStep(other, n)
)
)
or
exists(DataFlow::Node other |
// guard constraining `sub`
exprIsSubLeftOrLess(sub, other) and
isGuarded(sub, other.asExpr(), n.asExpr()) // other >= n
)
or
exists(DataFlow::Node other, float p, float q |
// linear access of `other`
exprIsSubLeftOrLess(sub, other) and
linearAccess(n.asExpr(), other.asExpr(), p, q) and // n = p * other + q
p <= 1 and
q <= 0
)
or
exists(DataFlow::Node other, float p, float q |
// linear access of `n`
exprIsSubLeftOrLess(sub, other) and
linearAccess(other.asExpr(), n.asExpr(), p, q) and // other = p * n + q
p >= 1 and
q >= 0
)
}
predicate interestingSubExpr(SubExpr sub, RelationalOperation ro) {

View File

@@ -1,15 +1,17 @@
char *file_name;
FILE *f_ptr;
/* Initialize file_name */
f_ptr = fopen(file_name, "w");
if (f_ptr == NULL) {
/* Handle error */
}
/* ... */
if (chmod(file_name, S_IRUSR) == -1) {
/* Handle error */
}
}
fclose(f_ptr);

View File

@@ -1,8 +1,8 @@
char *file_name;
int fd;
/* Initialize file_name */
fd = open(
file_name,
O_WRONLY | O_CREAT | O_EXCL,
@@ -11,9 +11,11 @@ fd = open(
if (fd == -1) {
/* Handle error */
}
/* ... */
if (fchmod(fd, S_IRUSR) == -1) {
/* Handle error */
}
}
close(fd);

View File

@@ -2,7 +2,7 @@
* @name Iterator to expired container
* @description Using an iterator owned by a container whose lifetime has expired may lead to unexpected behavior.
* @kind problem
* @precision medium
* @precision high
* @id cpp/iterator-to-expired-container
* @problem.severity warning
* @security-severity 8.8

View File

@@ -34,7 +34,7 @@ void good1(std::size_t length) noexcept {
// GOOD: the allocation failure is handled appropriately.
void good2(std::size_t length) noexcept {
int* dest = new int[length];
int* dest = new(std::nothrow) int[length];
if(!dest) {
return;
}

View File

@@ -1,11 +1,38 @@
void write_default_config_bad() {
// BAD - this is world-writable so any user can overwrite the config
int out = creat(OUTFILE, 0666);
dprintf(out, DEFAULT_CONFIG);
if (out < 0) {
// handle error
}
dprintf(out, "%s", DEFAULT_CONFIG);
close(out);
}
void write_default_config_good() {
// GOOD - this allows only the current user to modify the file
int out = creat(OUTFILE, S_IWUSR | S_IRUSR);
dprintf(out, DEFAULT_CONFIG);
if (out < 0) {
// handle error
}
dprintf(out, "%s", DEFAULT_CONFIG);
close(out);
}
void write_default_config_good_2() {
// GOOD - this allows only the current user to modify the file
int out = open(OUTFILE, O_WRONLY | O_CREAT, S_IWUSR | S_IRUSR);
if (out < 0) {
// handle error
}
FILE *fd = fdopen(out, "w");
if (fd == NULL) {
close(out);
// handle error
}
fprintf(fd, "%s", DEFAULT_CONFIG);
fclose(fd);
}

View File

@@ -29,10 +29,11 @@ so it is important that they cannot be controlled by an attacker.
</p>
<p>
The first example creates the default configuration file with the usual "default" Unix permissions, <code>0666</code>. This makes the
The first example creates the default configuration file with the usual "default" Unix permissions, <code>0666</code>. This makes the
file world-writable, so that an attacker could write in their own configuration that would be read by the program. The second example uses
more restrictive permissions: a combination of the standard Unix constants <code>S_IWUSR</code> and <code>S_IRUSR</code> which means that
only the current user will have read and write access to the file.
only the current user will have read and write access to the file. The third example shows another way to create a file with more restrictive
permissions if a <code>FILE *</code> stream pointer is required rather than a file descriptor.
</p>
<sample src="DoNotCreateWorldWritable.c" />

View File

@@ -0,0 +1,4 @@
---
category: queryMetadata
---
* The precision of `cpp/iterator-to-expired-container` ("Iterator to expired container") has been increased to `high`. As a result, it will be run by default as part of the Code Scanning suite.

View File

@@ -0,0 +1,4 @@
---
category: minorAnalysis
---
* The `cpp/unsigned-difference-expression-compared-zero` ("Unsigned difference expression compared to zero") query now produces fewer false positives.

View File

@@ -1,5 +1,11 @@
| file://:0:0:0:0 | char[6] | 6 |
| file://:0:0:0:0 | char[26] | 26 |
| file://:0:0:0:0 | char[] | |
| file://:0:0:0:0 | const char[6] | 6 |
| file://:0:0:0:0 | double[0] | 0 |
| file://:0:0:0:0 | double[3] | 3 |
| file://:0:0:0:0 | double[4] | 4 |
| file://:0:0:0:0 | double[] | |
| file://:0:0:0:0 | int[1] | 1 |
| file://:0:0:0:0 | int[11] | 11 |
| file://:0:0:0:0 | long[] | |

View File

@@ -0,0 +1,10 @@
// semmle-extractor-options: -std=c++20
double a1[]{1,2,3};
double* p1 = new double[]{1,2,3};
double* p2 = new double[0]{};
double* p3 = new double[]{};
char c[]{"Hello"};
char* d = new char[]{"Hello"};
double a2[](1,2,3);
double* p4 = new double[](1,2,3);
double* p5 = new double[4]{1,2}; // Size mismatch

View File

@@ -0,0 +1,6 @@
| implicit_sizes.cpp:3:14:3:32 | new[] | 3 |
| implicit_sizes.cpp:4:14:4:28 | new[] | 0 |
| implicit_sizes.cpp:5:14:5:27 | new[] | 0 |
| implicit_sizes.cpp:7:11:7:29 | new[] | 6 |
| implicit_sizes.cpp:9:14:9:32 | new[] | 3 |
| implicit_sizes.cpp:10:14:10:31 | new[] | 4 |

View File

@@ -0,0 +1,4 @@
import cpp
from NewArrayExpr nae
select nae, nae.getArraySize()

View File

@@ -1,7 +1,5 @@
| (unnamed parameter 0) | __va_list_tag && | rvalue reference to {struct __va_list_tag} |
| (unnamed parameter 0) | atomic_box<int> && | rvalue reference to {struct atomic_box<int>} |
| (unnamed parameter 0) | const __va_list_tag & | reference to {const {struct __va_list_tag}} |
| (unnamed parameter 0) | const atomic_box<int> & | reference to {const {struct atomic_box<int>}} |
| a | _Atomic(int) | atomic {int} |
| b | _Atomic(int) | atomic {int} |
| c | _Atomic(int) * | pointer to {atomic {int}} |

View File

@@ -1,2 +1,46 @@
testFailures
failures
edges
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | provenance | MaD:10 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:91:7:91:17 | recv_buffer | provenance | Src:MaD:2 |
| asio_streams.cpp:87:34:87:44 | read_until output argument | asio_streams.cpp:93:29:93:39 | *recv_buffer | provenance | Src:MaD:2 Sink:MaD:6 |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:98:7:98:14 | send_str | provenance | TaintFunction |
| asio_streams.cpp:97:37:97:44 | call to source | asio_streams.cpp:100:64:100:71 | *send_str | provenance | TaintFunction |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:101:7:101:17 | send_buffer | provenance | |
| asio_streams.cpp:100:44:100:62 | call to buffer | asio_streams.cpp:103:29:103:39 | *send_buffer | provenance | Sink:MaD:6 |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | provenance | |
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:100:44:100:62 | call to buffer | provenance | MaD:10 |
| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | provenance | MaD:2 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:7:10:7:18 | call to ymlSource | provenance | Src:MaD:0 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:11:10:11:10 | x | provenance | Sink:MaD:1 |
| test.cpp:7:10:7:18 | call to ymlSource | test.cpp:13:18:13:18 | x | provenance | |
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:13:10:13:16 | call to ymlStep | provenance | |
| test.cpp:13:10:13:16 | call to ymlStep | test.cpp:15:10:15:10 | y | provenance | Sink:MaD:1 |
| test.cpp:13:18:13:18 | x | test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | provenance | |
| test.cpp:13:18:13:18 | x | test.cpp:13:10:13:16 | call to ymlStep | provenance | MaD:2 |
nodes
| asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | semmle.label | [summary param] *0 in buffer |
| asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | semmle.label | [summary] to write: ReturnValue in buffer |
| asio_streams.cpp:87:34:87:44 | read_until output argument | semmle.label | read_until output argument |
| asio_streams.cpp:91:7:91:17 | recv_buffer | semmle.label | recv_buffer |
| asio_streams.cpp:93:29:93:39 | *recv_buffer | semmle.label | *recv_buffer |
| asio_streams.cpp:97:37:97:44 | call to source | semmle.label | call to source |
| asio_streams.cpp:98:7:98:14 | send_str | semmle.label | send_str |
| asio_streams.cpp:100:44:100:62 | call to buffer | semmle.label | call to buffer |
| asio_streams.cpp:100:44:100:62 | call to buffer | semmle.label | call to buffer |
| asio_streams.cpp:100:64:100:71 | *send_str | semmle.label | *send_str |
| asio_streams.cpp:101:7:101:17 | send_buffer | semmle.label | send_buffer |
| asio_streams.cpp:103:29:103:39 | *send_buffer | semmle.label | *send_buffer |
| test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | semmle.label | [summary param] 0 in ymlStep |
| test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | semmle.label | [summary] to write: ReturnValue in ymlStep |
| test.cpp:7:10:7:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:7:10:7:18 | call to ymlSource | semmle.label | call to ymlSource |
| test.cpp:11:10:11:10 | x | semmle.label | x |
| test.cpp:13:10:13:16 | call to ymlStep | semmle.label | call to ymlStep |
| test.cpp:13:10:13:16 | call to ymlStep | semmle.label | call to ymlStep |
| test.cpp:13:18:13:18 | x | semmle.label | x |
| test.cpp:15:10:15:10 | y | semmle.label | y |
subpaths
| asio_streams.cpp:100:64:100:71 | *send_str | asio_streams.cpp:56:18:56:23 | [summary param] *0 in buffer | asio_streams.cpp:56:18:56:23 | [summary] to write: ReturnValue in buffer | asio_streams.cpp:100:44:100:62 | call to buffer |
| test.cpp:13:18:13:18 | x | test.cpp:4:5:4:11 | [summary param] 0 in ymlStep | test.cpp:4:5:4:11 | [summary] to write: ReturnValue in ymlStep | test.cpp:13:10:13:16 | call to ymlStep |

View File

@@ -1,6 +1,7 @@
import TestUtilities.dataflow.FlowTestCommon
import cpp
import semmle.code.cpp.security.FlowSources
import IRTest::IRFlow::PathGraph
module IRTest {
private import semmle.code.cpp.ir.IR

View File

@@ -301,27 +301,6 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | file://:0:0:0:0 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:75:8:75:8 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:75:8:75:8 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | stl.h:389:9:389:9 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | structlikeclass.cpp:5:7:5:7 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | structlikeclass.cpp:5:7:5:7 | (unnamed parameter 0) | |
| file://:0:0:0:0 | (unnamed parameter 0) | taint.cpp:228:11:228:11 | (unnamed parameter 0) | |
@@ -3599,12 +3578,6 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| standalone_iterators.cpp:128:2:128:3 | it | standalone_iterators.cpp:128:5:128:5 | call to operator+= | TAINT |
| standalone_iterators.cpp:128:2:128:3 | ref arg it | standalone_iterators.cpp:129:7:129:8 | it | |
| standalone_iterators.cpp:128:8:128:13 | call to source | standalone_iterators.cpp:128:2:128:3 | ref arg it | TAINT |
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | constructor init of field container | TAINT |
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
| stl.h:75:8:75:8 | container | stl.h:75:8:75:8 | container | |
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
| stl.h:75:8:75:8 | this | stl.h:75:8:75:8 | constructor init of field container [pre-this] | |
| stl.h:95:69:95:69 | x | stl.h:95:69:95:69 | x | |
| stl.h:95:69:95:69 | x | stl.h:95:69:95:69 | x | |
| stl.h:95:69:95:69 | x | stl.h:95:69:95:69 | x | |
@@ -3620,41 +3593,6 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
| stl.h:292:30:292:40 | call to allocator | stl.h:292:21:292:41 | noexcept(...) | TAINT |
| stl.h:292:53:292:63 | 0 | stl.h:292:46:292:64 | (no string representation) | TAINT |
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [post-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | constructor init of field first [pre-this] | stl.h:389:9:389:9 | constructor init of field second [pre-this] | |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | constructor init of field first | TAINT |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
| stl.h:389:9:389:9 | first | stl.h:389:9:389:9 | first | |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | constructor init of field second | TAINT |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
| stl.h:389:9:389:9 | second | stl.h:389:9:389:9 | second | |
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:389:9:389:9 | this | stl.h:389:9:389:9 | constructor init of field first [pre-this] | |
| stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
| stl.h:396:3:396:3 | this | stl.h:396:36:396:43 | constructor init of field first [pre-this] | |
@@ -4361,6 +4299,8 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| string.cpp:446:17:446:17 | a | string.cpp:446:19:446:23 | call to begin | TAINT |
| string.cpp:446:17:446:17 | ref arg a | string.cpp:446:8:446:8 | a | |
| string.cpp:446:17:446:17 | ref arg a | string.cpp:447:8:447:8 | a | |
| string.cpp:446:17:446:25 | call to iterator | string.cpp:446:8:446:8 | ref arg a | TAINT |
| string.cpp:446:17:446:25 | call to iterator | string.cpp:446:10:446:15 | call to insert | TAINT |
| string.cpp:446:19:446:23 | call to begin | string.cpp:446:17:446:25 | call to iterator | TAINT |
| string.cpp:446:32:446:34 | 120 | string.cpp:446:8:446:8 | ref arg a | TAINT |
| string.cpp:446:32:446:34 | 120 | string.cpp:446:10:446:15 | call to insert | TAINT |
@@ -4369,6 +4309,8 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| string.cpp:449:17:449:17 | b | string.cpp:449:19:449:23 | call to begin | TAINT |
| string.cpp:449:17:449:17 | ref arg b | string.cpp:449:8:449:8 | b | |
| string.cpp:449:17:449:17 | ref arg b | string.cpp:450:8:450:8 | b | |
| string.cpp:449:17:449:25 | call to iterator | string.cpp:449:8:449:8 | ref arg b | TAINT |
| string.cpp:449:17:449:25 | call to iterator | string.cpp:449:10:449:15 | call to insert | TAINT |
| string.cpp:449:19:449:23 | call to begin | string.cpp:449:17:449:25 | call to iterator | TAINT |
| string.cpp:449:32:449:46 | call to source | string.cpp:449:8:449:8 | ref arg b | TAINT |
| string.cpp:449:32:449:46 | call to source | string.cpp:449:10:449:15 | call to insert | TAINT |
@@ -4396,6 +4338,8 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| string.cpp:459:17:459:17 | c | string.cpp:459:19:459:21 | call to end | TAINT |
| string.cpp:459:17:459:17 | ref arg c | string.cpp:459:8:459:8 | c | |
| string.cpp:459:17:459:17 | ref arg c | string.cpp:460:8:460:8 | c | |
| string.cpp:459:17:459:23 | call to iterator | string.cpp:459:8:459:8 | ref arg c | TAINT |
| string.cpp:459:17:459:23 | call to iterator | string.cpp:459:10:459:15 | call to insert | TAINT |
| string.cpp:459:19:459:21 | call to end | string.cpp:459:17:459:23 | call to iterator | TAINT |
| string.cpp:459:26:459:27 | ref arg s1 | string.cpp:459:38:459:39 | s1 | |
| string.cpp:459:26:459:27 | ref arg s1 | string.cpp:465:28:465:29 | s1 | |
@@ -4413,6 +4357,8 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| string.cpp:462:17:462:17 | d | string.cpp:462:19:462:21 | call to end | TAINT |
| string.cpp:462:17:462:17 | ref arg d | string.cpp:462:8:462:8 | d | |
| string.cpp:462:17:462:17 | ref arg d | string.cpp:463:8:463:8 | d | |
| string.cpp:462:17:462:23 | call to iterator | string.cpp:462:8:462:8 | ref arg d | TAINT |
| string.cpp:462:17:462:23 | call to iterator | string.cpp:462:10:462:15 | call to insert | TAINT |
| string.cpp:462:19:462:21 | call to end | string.cpp:462:17:462:23 | call to iterator | TAINT |
| string.cpp:462:26:462:27 | ref arg s2 | string.cpp:462:38:462:39 | s2 | |
| string.cpp:462:26:462:27 | ref arg s2 | string.cpp:465:8:465:9 | s2 | |
@@ -4432,6 +4378,8 @@ WARNING: module 'TaintTracking' has been deprecated and may be removed in future
| string.cpp:465:18:465:19 | ref arg s2 | string.cpp:465:8:465:9 | s2 | |
| string.cpp:465:18:465:19 | ref arg s2 | string.cpp:466:8:466:9 | s2 | |
| string.cpp:465:18:465:19 | s2 | string.cpp:465:21:465:23 | call to end | TAINT |
| string.cpp:465:18:465:25 | call to iterator | string.cpp:465:8:465:9 | ref arg s2 | TAINT |
| string.cpp:465:18:465:25 | call to iterator | string.cpp:465:11:465:16 | call to insert | TAINT |
| string.cpp:465:21:465:23 | call to end | string.cpp:465:18:465:25 | call to iterator | TAINT |
| string.cpp:465:28:465:29 | ref arg s1 | string.cpp:465:40:465:41 | s1 | |
| string.cpp:465:28:465:29 | s1 | string.cpp:465:31:465:35 | call to begin | TAINT |

View File

@@ -377,7 +377,6 @@ getParameterTypeName
| stl.h:88:25:88:33 | operator= | 0 | value_type && |
| stl.h:91:24:91:33 | operator++ | 0 | int |
| stl.h:91:24:91:33 | operator++ | 0 | int |
| stl.h:139:8:139:8 | basic_string | 0 | basic_string & |
| stl.h:148:3:148:14 | basic_string | 0 | const class:2 & |
| stl.h:149:33:149:44 | basic_string | 0 | const class:0 * |
| stl.h:149:33:149:44 | basic_string | 1 | const class:2 & |

View File

@@ -17,10 +17,6 @@
| declaration.cpp:51:7:51:7 | operator= |
| declaration.cpp:52:7:52:14 | myField0 |
| declaration.cpp:53:9:53:17 | myPointer |
| declaration.cpp:62:7:62:7 | operator= |
| declaration.cpp:62:7:62:7 | operator= |
| declaration.cpp:62:7:62:7 | operator= |
| declaration.cpp:62:7:62:7 | operator= |
| declaration.cpp:65:5:65:20 | myMemberVariable |
| declaration.cpp:65:5:65:20 | myMemberVariable |
| declaration.cpp:65:5:65:20 | myMemberVariable |
@@ -36,10 +32,6 @@
| declaration.cpp:105:9:105:21 | myNestedField |
| declaration.cpp:108:3:108:10 | MyClass1 |
| declaration.cpp:110:7:110:17 | getMyField1 |
| declaration.cpp:119:7:119:7 | operator= |
| declaration.cpp:119:7:119:7 | operator= |
| declaration.cpp:119:7:119:7 | operator= |
| declaration.cpp:119:7:119:7 | operator= |
| declaration.cpp:122:5:122:20 | myMemberVariable |
| declaration.cpp:122:5:122:20 | myMemberVariable |
| declaration.cpp:122:5:122:20 | myMemberVariable |

View File

@@ -15,10 +15,6 @@
| declarationEntry.cpp:20:6:20:11 | myEnum | declarationEntry.cpp:18:6:18:11 | declaration of myEnum | 1 | 1 |
| declarationEntry.cpp:20:6:20:11 | myEnum | declarationEntry.cpp:20:6:20:11 | definition of myEnum | 1 | 1 |
| declarationEntry.cpp:27:20:27:20 | T | declarationEntry.cpp:27:20:27:20 | definition of T | 1 | 1 |
| declarationEntry.cpp:28:7:28:7 | operator= | declarationEntry.cpp:28:7:28:7 | declaration of operator= | 1 | 1 |
| declarationEntry.cpp:28:7:28:7 | operator= | declarationEntry.cpp:28:7:28:7 | declaration of operator= | 1 | 1 |
| declarationEntry.cpp:28:7:28:7 | operator= | declarationEntry.cpp:28:7:28:7 | declaration of operator= | 1 | 1 |
| declarationEntry.cpp:28:7:28:7 | operator= | declarationEntry.cpp:28:7:28:7 | declaration of operator= | 1 | 1 |
| declarationEntry.cpp:28:7:28:21 | myTemplateClass<T> | declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass<T> | 1 | 1 |
| declarationEntry.cpp:28:7:28:21 | myTemplateClass<int> | declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass<T> | 1 | 0 |
| declarationEntry.cpp:28:7:28:21 | myTemplateClass<short> | declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass<T> | 1 | 0 |

View File

@@ -6,10 +6,6 @@
| declarationEntry.c:17:6:17:21 | declaration of myFourthFunction | | 1 | c_linkage |
| declarationEntry.cpp:9:6:9:15 | declaration of myFunction | | 0 | |
| declarationEntry.cpp:11:6:11:15 | definition of myFunction | | 0 | |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | |
| declarationEntry.cpp:39:7:39:7 | declaration of operator= | | 0 | |
| macro.c:2:1:2:3 | declaration of foo | | 2 | c_linkage, static |

View File

@@ -15,10 +15,6 @@
| declarationEntry.cpp:18:6:18:11 | declaration of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes |
| declarationEntry.cpp:20:6:20:11 | definition of myEnum | declarationEntry.cpp:20:6:20:11 | myEnum | yes |
| declarationEntry.cpp:27:20:27:20 | definition of T | declarationEntry.cpp:27:20:27:20 | T | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:7 | declaration of operator= | declarationEntry.cpp:28:7:28:7 | operator= | yes |
| declarationEntry.cpp:28:7:28:21 | definition of myTemplateClass<T> | declarationEntry.cpp:28:7:28:21 | myTemplateClass<T> | yes |
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
| declarationEntry.cpp:31:4:31:19 | definition of myMemberVariable | declarationEntry.cpp:31:4:31:19 | myMemberVariable | yes |
@@ -31,10 +27,6 @@
| declarationEntry.cpp:42:6:42:21 | definition of myMemberVariable | declarationEntry.cpp:42:6:42:21 | myMemberVariable | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | declaration of 1st parameter | file://:0:0:0:0 | (unnamed parameter 0) | yes |
| file://:0:0:0:0 | definition of fp_offset | file://:0:0:0:0 | fp_offset | yes |
| file://:0:0:0:0 | definition of gp_offset | file://:0:0:0:0 | gp_offset | yes |
| file://:0:0:0:0 | definition of overflow_arg_area | file://:0:0:0:0 | overflow_arg_area | yes |

View File

@@ -2,10 +2,6 @@
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | declaration of 1st parameter |
| file://:0:0:0:0 | definition of fp_offset |
| file://:0:0:0:0 | definition of gp_offset |
| file://:0:0:0:0 | definition of overflow_arg_area |
@@ -72,12 +68,6 @@
| test.cpp:64:19:64:19 | definition of T |
| test.cpp:65:7:65:27 | declaration of tmplInstantiatedClass<T> |
| test.cpp:66:19:66:19 | definition of T |
| test.cpp:67:7:67:7 | declaration of operator= |
| test.cpp:67:7:67:7 | declaration of operator= |
| test.cpp:67:7:67:7 | declaration of operator= |
| test.cpp:67:7:67:7 | declaration of operator= |
| test.cpp:67:7:67:7 | definition of tmplInstantiatedClass |
| test.cpp:67:7:67:7 | definition of tmplInstantiatedClass |
| test.cpp:67:7:67:27 | definition of tmplInstantiatedClass<T> |
| test.cpp:68:7:68:7 | definition of t |
| test.cpp:68:7:68:7 | definition of t |

View File

@@ -6,8 +6,6 @@
| file://:0:0:0:0 | (unnamed parameter 0) | 0 | 0 |
| file://:0:0:0:0 | (unnamed parameter 0) | 0 | 0 |
| file://:0:0:0:0 | (unnamed parameter 0) | 0 | 0 |
| file://:0:0:0:0 | (unnamed parameter 0) | 0 | 0 |
| file://:0:0:0:0 | (unnamed parameter 0) | 0 | 0 |
| file://:0:0:0:0 | fp_offset | 0 | 0 |
| file://:0:0:0:0 | gp_offset | 0 | 0 |
| file://:0:0:0:0 | overflow_arg_area | 0 | 0 |

View File

@@ -1,11 +1,6 @@
| ODASA-5186.cpp:4:8:4:8 | MyClass | MyClass | | declaration:ODASA-5186.cpp:4:8:4:8, definition:ODASA-5186.cpp:4:8:4:8 |
| ODASA-5186.cpp:4:8:4:8 | operator= | operator= | MyClass<int> && (unnamed parameter 0) | declaration:ODASA-5186.cpp:4:8:4:8 |
| ODASA-5186.cpp:4:8:4:8 | operator= | operator= | const MyClass<int> & (unnamed parameter 0) | declaration:ODASA-5186.cpp:4:8:4:8 |
| ODASA-5186.cpp:5:8:5:8 | operator== | operator== | const MyClass<int> & other | declaration:ODASA-5186.cpp:5:8:5:8, definition:ODASA-5186.cpp:5:8:5:8 |
| ODASA-5186.cpp:5:8:5:17 | operator== | operator== | const MyClass<T> & other | declaration:ODASA-5186.cpp:5:8:5:17, definition:ODASA-5186.cpp:5:8:5:17 |
| ODASA-5186.cpp:8:6:8:9 | test | test | | TopLevelFunction, declaration:ODASA-5186.cpp:8:6:8:9, definition:ODASA-5186.cpp:8:6:8:9, isTopLevel |
| ODASA-5186.hpp:2:8:2:8 | operator= | operator= | NEQ_helper<MyClass<int>> && (unnamed parameter 0) | declaration:ODASA-5186.hpp:2:8:2:8 |
| ODASA-5186.hpp:2:8:2:8 | operator= | operator= | const NEQ_helper<MyClass<int>> & (unnamed parameter 0) | declaration:ODASA-5186.hpp:2:8:2:8 |
| ODASA-5186.hpp:4:18:4:27 | operator!= | operator!= | const MyClass<int> & x, const MyClass<int> & y | TopLevelFunction, declaration:ODASA-5186.hpp:4:18:4:27, definition:ODASA-5186.hpp:4:18:4:27, isTopLevel |
| ODASA-5186.hpp:4:18:4:27 | operator!= | operator!= | const T & x, const T & y | TopLevelFunction, declaration:ODASA-5186.hpp:4:18:4:27, definition:ODASA-5186.hpp:4:18:4:27, isTopLevel |
| functions.cpp:1:6:1:6 | f | f | int a, int b | TopLevelFunction, declaration:functions.cpp:1:6:1:6, definition:functions.cpp:1:6:1:6, isTopLevel |

View File

@@ -1,10 +1,5 @@
| ODASA-5186.cpp:4:8:4:14 | MyClass<T> | Class | ODASA-5186.cpp:5:8:5:17 | operator== | |
| ODASA-5186.cpp:4:8:4:14 | MyClass<int> | Struct | ODASA-5186.cpp:4:8:4:8 | MyClass | Constructor, NoArgConstructor, getAConstructor() |
| ODASA-5186.cpp:4:8:4:14 | MyClass<int> | Struct | ODASA-5186.cpp:4:8:4:8 | operator= | |
| ODASA-5186.cpp:4:8:4:14 | MyClass<int> | Struct | ODASA-5186.cpp:4:8:4:8 | operator= | |
| ODASA-5186.cpp:4:8:4:14 | MyClass<int> | Struct | ODASA-5186.cpp:5:8:5:8 | operator== | |
| ODASA-5186.hpp:2:8:2:17 | NEQ_helper<MyClass<int>> | Struct | ODASA-5186.hpp:2:8:2:8 | operator= | |
| ODASA-5186.hpp:2:8:2:17 | NEQ_helper<MyClass<int>> | Struct | ODASA-5186.hpp:2:8:2:8 | operator= | |
| file://:0:0:0:0 | __va_list_tag | Struct | file://:0:0:0:0 | operator= | |
| file://:0:0:0:0 | __va_list_tag | Struct | file://:0:0:0:0 | operator= | |
| functions.cpp:7:8:7:8 | A | Struct | functions.cpp:7:8:7:8 | operator= | |

View File

@@ -39,8 +39,6 @@
| qualifiedNames.cpp:39:3:39:19 | typedefStructName | typedefStructName | | | typedefStructName | typedefStructName |
| qualifiedNames.cpp:39:23:39:40 | ptypedefStructName | ptypedefStructName | | | ptypedefStructName | ptypedefStructName |
| qualifiedNames.cpp:41:11:41:18 | typedefC | typedefC | | | typedefC | typedefC |
| qualifiedNames.cpp:45:10:45:10 | operator= | templates::TemplateClass<unsigned long>::operator= | templates | TemplateClass | operator= | (not global) |
| qualifiedNames.cpp:45:10:45:10 | operator= | templates::TemplateClass<unsigned long>::operator= | templates | TemplateClass | operator= | (not global) |
| qualifiedNames.cpp:45:10:45:22 | TemplateClass<T> | templates::TemplateClass<T> | templates | | TemplateClass | (not global) |
| qualifiedNames.cpp:45:10:45:22 | TemplateClass<T> | templates::TemplateClass<T> | templates | | TemplateClass | (not global) |
| qualifiedNames.cpp:45:10:45:22 | TemplateClass<unsigned long> | templates::TemplateClass<unsigned long> | templates | | TemplateClass | (not global) |

View File

@@ -25,10 +25,6 @@
| test.cpp:16:7:16:7 | operator= |
| test.cpp:16:32:16:35 | vfun |
| test.cpp:19:7:19:7 | C |
| test.cpp:19:7:19:7 | C |
| test.cpp:19:7:19:7 | C |
| test.cpp:19:7:19:7 | operator= |
| test.cpp:19:7:19:7 | operator= |
| test.cpp:21:18:21:18 | vfun |
| test.cpp:21:18:21:21 | vfun |
| test.cpp:27:6:27:6 | f |

View File

@@ -1729,30 +1729,6 @@ complex.c:
# 144| ValueCategory = prvalue
# 145| getStmt(72): [ReturnStmt] return ...
coroutines.cpp:
# 4| [CopyAssignmentOperator] std::coroutine_traits<co_returnable_value, int>& std::coroutine_traits<co_returnable_value, int>::operator=(std::coroutine_traits<co_returnable_value, int> const&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const coroutine_traits<co_returnable_value, int> &
# 4| [MoveAssignmentOperator] std::coroutine_traits<co_returnable_value, int>& std::coroutine_traits<co_returnable_value, int>::operator=(std::coroutine_traits<co_returnable_value, int>&&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] coroutine_traits<co_returnable_value, int> &&
# 4| [CopyAssignmentOperator] std::coroutine_traits<co_returnable_void, int>& std::coroutine_traits<co_returnable_void, int>::operator=(std::coroutine_traits<co_returnable_void, int> const&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const coroutine_traits<co_returnable_void, int> &
# 4| [MoveAssignmentOperator] std::coroutine_traits<co_returnable_void, int>& std::coroutine_traits<co_returnable_void, int>::operator=(std::coroutine_traits<co_returnable_void, int>&&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] coroutine_traits<co_returnable_void, int> &&
# 4| [CopyAssignmentOperator] std::coroutine_traits<co_returnable_void>& std::coroutine_traits<co_returnable_void>::operator=(std::coroutine_traits<co_returnable_void> const&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const coroutine_traits<co_returnable_void> &
# 4| [MoveAssignmentOperator] std::coroutine_traits<co_returnable_void>& std::coroutine_traits<co_returnable_void>::operator=(std::coroutine_traits<co_returnable_void>&&)
# 4| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] coroutine_traits<co_returnable_void> &&
# 12| [Constructor] void std::coroutine_handle<Promise>::coroutine_handle()
# 12| <params>:
# 13| [Constructor] void std::coroutine_handle<Promise>::coroutine_handle(std::nullptr_t)
@@ -8629,14 +8605,6 @@ ir.cpp:
# 709| getArgument(1): [VariableAccess] y
# 709| Type = [IntType] int
# 709| ValueCategory = prvalue(load)
# 713| [CopyAssignmentOperator] Outer<long>& Outer<long>::operator=(Outer<long> const&)
# 713| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Outer<long> &
# 713| [MoveAssignmentOperator] Outer<long>& Outer<long>::operator=(Outer<long>&&)
# 713| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Outer<long> &&
# 715| [MemberFunction,TemplateFunction] T Outer<T>::Func<U, V>(U, V)
# 715| <params>:
# 715| getParameter(0): [Parameter] x
@@ -11941,22 +11909,6 @@ ir.cpp:
# 1054| getRightOperand().getFullyConverted(): [ReferenceDereferenceExpr] (reference dereference)
# 1054| Type = [IntType] int
# 1054| ValueCategory = prvalue(load)
# 1078| [CopyAssignmentOperator] std::iterator<std::random_access_iterator_tag, ClassWithDestructor, std::ptrdiff_t, ClassWithDestructor*, ClassWithDestructor&>& std::iterator<std::random_access_iterator_tag, ClassWithDestructor, std::ptrdiff_t, ClassWithDestructor*, ClassWithDestructor&>::operator=(std::iterator<std::random_access_iterator_tag, ClassWithDestructor, std::ptrdiff_t, ClassWithDestructor*, ClassWithDestructor&> const&)
# 1078| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const iterator<random_access_iterator_tag, ClassWithDestructor, ptrdiff_t, ClassWithDestructor *, ClassWithDestructor &> &
# 1078| [CopyAssignmentOperator] std::iterator<std::random_access_iterator_tag, String, std::ptrdiff_t, String*, String&>& std::iterator<std::random_access_iterator_tag, String, std::ptrdiff_t, String*, String&>::operator=(std::iterator<std::random_access_iterator_tag, String, std::ptrdiff_t, String*, String&> const&)
# 1078| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const iterator<random_access_iterator_tag, String, ptrdiff_t, String *, String &> &
# 1078| [CopyAssignmentOperator] std::iterator<std::random_access_iterator_tag, char, std::ptrdiff_t, char*, char&>& std::iterator<std::random_access_iterator_tag, char, std::ptrdiff_t, char*, char&>::operator=(std::iterator<std::random_access_iterator_tag, char, std::ptrdiff_t, char*, char&> const&)
# 1078| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const iterator<random_access_iterator_tag, char, ptrdiff_t, char *, char &> &
# 1078| [CopyAssignmentOperator] std::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, int*, int&>& std::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, int*, int&>::operator=(std::iterator<std::random_access_iterator_tag, int, std::ptrdiff_t, int*, int&> const&)
# 1078| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const iterator<random_access_iterator_tag, int, ptrdiff_t, int *, int &> &
# 1081| [Constructor] void std::iterator<Category, value_type, difference_type, pointer_type, reference_type>::iterator()
# 1081| <params>:
# 1082| [Constructor] void std::iterator<Category, value_type, difference_type, pointer_type, reference_type>::iterator(std::iterator<Category, type, std::ptrdiff_t, type*, type&> const&)
@@ -12105,38 +12057,6 @@ ir.cpp:
# 1105| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] output_iterator_tag &&
# 1108| [CopyAssignmentOperator] std::vector<ClassWithDestructor>& std::vector<ClassWithDestructor>::operator=(std::vector<ClassWithDestructor> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<ClassWithDestructor> &
# 1108| [CopyAssignmentOperator] std::vector<String>& std::vector<String>::operator=(std::vector<String> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<String> &
# 1108| [CopyAssignmentOperator] std::vector<char>& std::vector<char>::operator=(std::vector<char> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<char> &
# 1108| [CopyAssignmentOperator] std::vector<int>& std::vector<int>::operator=(std::vector<int> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<int> &
# 1108| [CopyConstructor] void std::vector<ClassWithDestructor>::vector(std::vector<ClassWithDestructor> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<ClassWithDestructor> &
# 1108| [CopyConstructor] void std::vector<String>::vector(std::vector<String> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<String> &
# 1108| [CopyConstructor] void std::vector<char>::vector(std::vector<char> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<char> &
# 1108| [CopyConstructor] void std::vector<int>::vector(std::vector<int> const&)
# 1108| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const vector<int> &
# 1109| [Constructor] void std::vector<ClassWithDestructor>::vector(ClassWithDestructor)
# 1109| <params>:
# 1109| getParameter(0): [Parameter] (unnamed parameter 0)
@@ -17431,14 +17351,6 @@ ir.cpp:
# 1904| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] S &&
# 1908| [CopyAssignmentOperator] missing_declaration_entries::Bar1<int>& missing_declaration_entries::Bar1<int>::operator=(missing_declaration_entries::Bar1<int> const&)
# 1908| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Bar1<int> &
# 1908| [MoveAssignmentOperator] missing_declaration_entries::Bar1<int>& missing_declaration_entries::Bar1<int>::operator=(missing_declaration_entries::Bar1<int>&&)
# 1908| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Bar1<int> &&
# 1911| [MemberFunction] void* missing_declaration_entries::Bar1<T>::missing_type_decl_entry(missing_declaration_entries::Bar1<T>::pointer)
# 1911| <params>:
# 1911| getParameter(0): [Parameter] p
@@ -17494,14 +17406,6 @@ ir.cpp:
# 1919| Value = [CStyleCast] 0
# 1919| ValueCategory = prvalue
# 1920| getStmt(2): [ReturnStmt] return ...
# 1922| [CopyAssignmentOperator] missing_declaration_entries::Bar2<int>& missing_declaration_entries::Bar2<int>::operator=(missing_declaration_entries::Bar2<int> const&)
# 1922| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Bar2<int> &
# 1922| [MoveAssignmentOperator] missing_declaration_entries::Bar2<int>& missing_declaration_entries::Bar2<int>::operator=(missing_declaration_entries::Bar2<int>&&)
# 1922| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Bar2<int> &&
# 1924| [MemberFunction] int missing_declaration_entries::Bar2<T>::two_missing_variable_declaration_entries()
# 1924| <params>:
# 1924| getEntryPoint(): [BlockStmt] { ... }
@@ -17644,14 +17548,6 @@ ir.cpp:
# 1934| Type = [ClassTemplateInstantiation,Struct] Bar2<int>
# 1934| ValueCategory = lvalue
# 1935| getStmt(2): [ReturnStmt] return ...
# 1937| [CopyAssignmentOperator] missing_declaration_entries::Bar3<int>& missing_declaration_entries::Bar3<int>::operator=(missing_declaration_entries::Bar3<int> const&)
# 1937| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Bar3<int> &
# 1937| [MoveAssignmentOperator] missing_declaration_entries::Bar3<int>& missing_declaration_entries::Bar3<int>::operator=(missing_declaration_entries::Bar3<int>&&)
# 1937| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Bar3<int> &&
# 1939| [MemberFunction] int missing_declaration_entries::Bar3<T>::two_more_missing_variable_declaration_entries()
# 1939| <params>:
# 1939| getEntryPoint(): [BlockStmt] { ... }
@@ -22753,6 +22649,616 @@ ir.cpp:
# 2556| Type = [LongType] unsigned long
# 2556| ValueCategory = prvalue(load)
# 2557| getStmt(1): [ReturnStmt] return ...
# 2559| [TopLevelFunction] void p_points_to_x_or_y(int, int)
# 2559| <params>:
# 2559| getParameter(0): [Parameter] a
# 2559| Type = [IntType] int
# 2559| getParameter(1): [Parameter] b
# 2559| Type = [IntType] int
# 2559| getEntryPoint(): [BlockStmt] { ... }
# 2560| getStmt(0): [DeclStmt] declaration
# 2560| getDeclarationEntry(0): [VariableDeclarationEntry] definition of x
# 2560| Type = [IntType] int
# 2561| getStmt(1): [DeclStmt] declaration
# 2561| getDeclarationEntry(0): [VariableDeclarationEntry] definition of y
# 2561| Type = [IntType] int
# 2562| getStmt(2): [DeclStmt] declaration
# 2562| getDeclarationEntry(0): [VariableDeclarationEntry] definition of p
# 2562| Type = [IntPointerType] int *
# 2563| getStmt(3): [IfStmt] if (...) ...
# 2563| getCondition(): [LTExpr] ... < ...
# 2563| Type = [BoolType] bool
# 2563| ValueCategory = prvalue
# 2563| getLesserOperand(): [VariableAccess] a
# 2563| Type = [IntType] int
# 2563| ValueCategory = prvalue(load)
# 2563| getGreaterOperand(): [VariableAccess] b
# 2563| Type = [IntType] int
# 2563| ValueCategory = prvalue(load)
# 2563| getThen(): [BlockStmt] { ... }
# 2564| getStmt(0): [ExprStmt] ExprStmt
# 2564| getExpr(): [AssignExpr] ... = ...
# 2564| Type = [IntPointerType] int *
# 2564| ValueCategory = lvalue
# 2564| getLValue(): [VariableAccess] p
# 2564| Type = [IntPointerType] int *
# 2564| ValueCategory = lvalue
# 2564| getRValue(): [AddressOfExpr] & ...
# 2564| Type = [IntPointerType] int *
# 2564| ValueCategory = prvalue
# 2564| getOperand(): [VariableAccess] x
# 2564| Type = [IntType] int
# 2564| ValueCategory = lvalue
# 2565| getElse(): [BlockStmt] { ... }
# 2566| getStmt(0): [ExprStmt] ExprStmt
# 2566| getExpr(): [AssignExpr] ... = ...
# 2566| Type = [IntPointerType] int *
# 2566| ValueCategory = lvalue
# 2566| getLValue(): [VariableAccess] p
# 2566| Type = [IntPointerType] int *
# 2566| ValueCategory = lvalue
# 2566| getRValue(): [AddressOfExpr] & ...
# 2566| Type = [IntPointerType] int *
# 2566| ValueCategory = prvalue
# 2566| getOperand(): [VariableAccess] y
# 2566| Type = [IntType] int
# 2566| ValueCategory = lvalue
# 2568| getStmt(4): [ExprStmt] ExprStmt
# 2568| getExpr(): [AssignExpr] ... = ...
# 2568| Type = [IntType] int
# 2568| ValueCategory = lvalue
# 2568| getLValue(): [PointerDereferenceExpr] * ...
# 2568| Type = [IntType] int
# 2568| ValueCategory = lvalue
# 2568| getOperand(): [VariableAccess] p
# 2568| Type = [IntPointerType] int *
# 2568| ValueCategory = prvalue(load)
# 2568| getRValue(): [Literal] 5
# 2568| Type = [IntType] int
# 2568| Value = [Literal] 5
# 2568| ValueCategory = prvalue
# 2569| getStmt(5): [DeclStmt] declaration
# 2569| getDeclarationEntry(0): [VariableDeclarationEntry] definition of z
# 2569| Type = [IntType] int
# 2569| getVariable().getInitializer(): [Initializer] initializer for z
# 2569| getExpr(): [VariableAccess] x
# 2569| Type = [IntType] int
# 2569| ValueCategory = prvalue(load)
# 2570| getStmt(6): [DeclStmt] declaration
# 2570| getDeclarationEntry(0): [VariableDeclarationEntry] definition of w
# 2570| Type = [IntType] int
# 2570| getVariable().getInitializer(): [Initializer] initializer for w
# 2570| getExpr(): [VariableAccess] y
# 2570| Type = [IntType] int
# 2570| ValueCategory = prvalue(load)
# 2571| getStmt(7): [ReturnStmt] return ...
# 2573| [TopLevelFunction] int phi_after_while()
# 2573| <params>:
# 2573| getEntryPoint(): [BlockStmt] { ... }
# 2574| getStmt(0): [DeclStmt] declaration
# 2574| getDeclarationEntry(0): [VariableDeclarationEntry] definition of r
# 2574| Type = [IntType] int
# 2575| getStmt(1): [DeclStmt] declaration
# 2575| getDeclarationEntry(0): [VariableDeclarationEntry] definition of rP
# 2575| Type = [IntPointerType] int *
# 2575| getVariable().getInitializer(): [Initializer] initializer for rP
# 2575| getExpr(): [AddressOfExpr] & ...
# 2575| Type = [IntPointerType] int *
# 2575| ValueCategory = prvalue
# 2575| getOperand(): [VariableAccess] r
# 2575| Type = [IntType] int
# 2575| ValueCategory = lvalue
# 2577| getStmt(2): [WhileStmt] while (...) ...
# 2577| getCondition(): [FunctionCall] call to predicateA
# 2577| Type = [BoolType] bool
# 2577| ValueCategory = prvalue
# 2577| getStmt(): [BlockStmt] { ... }
# 2578| getStmt(0): [DeclStmt] declaration
# 2578| getDeclarationEntry(0): [VariableDeclarationEntry] definition of s
# 2578| Type = [IntType] int
# 2578| getVariable().getInitializer(): [Initializer] initializer for s
# 2578| getExpr(): [Literal] 0
# 2578| Type = [IntType] int
# 2578| Value = [Literal] 0
# 2578| ValueCategory = prvalue
# 2579| getStmt(1): [ExprStmt] ExprStmt
# 2579| getExpr(): [AssignExpr] ... = ...
# 2579| Type = [IntType] int
# 2579| ValueCategory = lvalue
# 2579| getLValue(): [PointerDereferenceExpr] * ...
# 2579| Type = [IntType] int
# 2579| ValueCategory = lvalue
# 2579| getOperand(): [VariableAccess] rP
# 2579| Type = [IntPointerType] int *
# 2579| ValueCategory = prvalue(load)
# 2579| getRValue(): [VariableAccess] s
# 2579| Type = [IntType] int
# 2579| ValueCategory = prvalue(load)
# 2580| getStmt(2): [ExprStmt] ExprStmt
# 2580| getExpr(): [AssignExpr] ... = ...
# 2580| Type = [IntPointerType] int *
# 2580| ValueCategory = lvalue
# 2580| getLValue(): [VariableAccess] rP
# 2580| Type = [IntPointerType] int *
# 2580| ValueCategory = lvalue
# 2580| getRValue(): [AddressOfExpr] & ...
# 2580| Type = [IntPointerType] int *
# 2580| ValueCategory = prvalue
# 2580| getOperand(): [VariableAccess] s
# 2580| Type = [IntType] int
# 2580| ValueCategory = lvalue
# 2583| getStmt(3): [ReturnStmt] return ...
# 2583| getExpr(): [VariableAccess] r
# 2583| Type = [IntType] int
# 2583| ValueCategory = prvalue(load)
# 2588| [TopLevelFunction] char* recursive_conditional_call_with_increment(char*, bool)
# 2588| <params>:
# 2588| getParameter(0): [Parameter] d
# 2588| Type = [CharPointerType] char *
# 2588| getParameter(1): [Parameter] b
# 2588| Type = [BoolType] bool
# 2589| getEntryPoint(): [BlockStmt] { ... }
# 2590| getStmt(0): [IfStmt] if (...) ...
# 2590| getCondition(): [VariableAccess] b
# 2590| Type = [BoolType] bool
# 2590| ValueCategory = prvalue(load)
# 2590| getThen(): [BlockStmt] { ... }
# 2591| getStmt(0): [ExprStmt] ExprStmt
# 2591| getExpr(): [AssignExpr] ... = ...
# 2591| Type = [CharPointerType] char *
# 2591| ValueCategory = lvalue
# 2591| getLValue(): [VariableAccess] d
# 2591| Type = [CharPointerType] char *
# 2591| ValueCategory = lvalue
# 2591| getRValue(): [FunctionCall] call to recursive_conditional_call_with_increment
# 2591| Type = [CharPointerType] char *
# 2591| ValueCategory = prvalue
# 2591| getArgument(0): [VariableAccess] d
# 2591| Type = [CharPointerType] char *
# 2591| ValueCategory = prvalue(load)
# 2591| getArgument(1): [VariableAccess] b
# 2591| Type = [BoolType] bool
# 2591| ValueCategory = prvalue(load)
# 2593| getStmt(1): [ExprStmt] ExprStmt
# 2593| getExpr(): [PostfixIncrExpr] ... ++
# 2593| Type = [CharPointerType] char *
# 2593| ValueCategory = prvalue
# 2593| getOperand(): [VariableAccess] d
# 2593| Type = [CharPointerType] char *
# 2593| ValueCategory = lvalue
# 2594| getStmt(2): [ReturnStmt] return ...
# 2594| getExpr(): [VariableAccess] d
# 2594| Type = [CharPointerType] char *
# 2594| ValueCategory = prvalue(load)
# 2597| [CopyAssignmentOperator] Recursive& Recursive::operator=(Recursive const&)
# 2597| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [LValueReferenceType] const Recursive &
# 2597| [MoveAssignmentOperator] Recursive& Recursive::operator=(Recursive&&)
# 2597| <params>:
#-----| getParameter(0): [Parameter] (unnamed parameter 0)
#-----| Type = [RValueReferenceType] Recursive &&
# 2602| [TopLevelFunction] Recursive* merge(Recursive*)
# 2602| <params>:
# 2602| getParameter(0): [Parameter] a
# 2602| Type = [PointerType] Recursive *
# 2603| getEntryPoint(): [BlockStmt] { ... }
# 2604| getStmt(0): [DeclStmt] declaration
# 2604| getDeclarationEntry(0): [VariableDeclarationEntry] definition of b
# 2604| Type = [PointerType] Recursive *
# 2605| getStmt(1): [DeclStmt] declaration
# 2605| getDeclarationEntry(0): [VariableDeclarationEntry] definition of p
# 2605| Type = [PointerType] Recursive **
# 2605| getVariable().getInitializer(): [Initializer] initializer for p
# 2605| getExpr(): [AddressOfExpr] & ...
# 2605| Type = [PointerType] Recursive **
# 2605| ValueCategory = prvalue
# 2605| getOperand(): [VariableAccess] b
# 2605| Type = [PointerType] Recursive *
# 2605| ValueCategory = lvalue
# 2607| getStmt(2): [WhileStmt] while (...) ...
# 2607| getCondition(): [FunctionCall] call to predicateA
# 2607| Type = [BoolType] bool
# 2607| ValueCategory = prvalue
# 2608| getStmt(): [BlockStmt] { ... }
# 2609| getStmt(0): [ExprStmt] ExprStmt
# 2609| getExpr(): [AssignExpr] ... = ...
# 2609| Type = [PointerType] Recursive *
# 2609| ValueCategory = lvalue
# 2609| getLValue(): [PointerDereferenceExpr] * ...
# 2609| Type = [PointerType] Recursive *
# 2609| ValueCategory = lvalue
# 2609| getOperand(): [VariableAccess] p
# 2609| Type = [PointerType] Recursive **
# 2609| ValueCategory = prvalue(load)
# 2609| getRValue(): [VariableAccess] a
# 2609| Type = [PointerType] Recursive *
# 2609| ValueCategory = prvalue(load)
# 2610| getStmt(1): [ExprStmt] ExprStmt
# 2610| getExpr(): [AssignExpr] ... = ...
# 2610| Type = [PointerType] Recursive **
# 2610| ValueCategory = lvalue
# 2610| getLValue(): [VariableAccess] p
# 2610| Type = [PointerType] Recursive **
# 2610| ValueCategory = lvalue
# 2610| getRValue(): [AddressOfExpr] & ...
# 2610| Type = [PointerType] Recursive **
# 2610| ValueCategory = prvalue
# 2610| getOperand(): [PointerFieldAccess] next
# 2610| Type = [PointerType] Recursive *
# 2610| ValueCategory = lvalue
# 2610| getQualifier(): [VariableAccess] a
# 2610| Type = [PointerType] Recursive *
# 2610| ValueCategory = prvalue(load)
# 2613| getStmt(3): [ReturnStmt] return ...
# 2613| getExpr(): [VariableAccess] b
# 2613| Type = [PointerType] Recursive *
# 2613| ValueCategory = prvalue(load)
# 2616| [TopLevelFunction] void use_const_int(int const*)
# 2616| <params>:
# 2616| getParameter(0): [Parameter] (unnamed parameter 0)
# 2616| Type = [PointerType] const int *
# 2618| [TopLevelFunction] void escaping_pointer(bool)
# 2618| <params>:
# 2618| getParameter(0): [Parameter] b
# 2618| Type = [BoolType] bool
# 2619| getEntryPoint(): [BlockStmt] { ... }
# 2620| getStmt(0): [DeclStmt] declaration
# 2620| getDeclarationEntry(0): [VariableDeclarationEntry] definition of data
# 2620| Type = [IntPointerType] int *
# 2621| getStmt(1): [DeclStmt] declaration
# 2621| getDeclarationEntry(0): [VariableDeclarationEntry] definition of l1
# 2621| Type = [IntType] int
# 2621| getDeclarationEntry(1): [VariableDeclarationEntry] definition of l2
# 2621| Type = [IntType] int
# 2622| getStmt(2): [IfStmt] if (...) ...
# 2622| getCondition(): [VariableAccess] b
# 2622| Type = [BoolType] bool
# 2622| ValueCategory = prvalue(load)
# 2623| getThen(): [BlockStmt] { ... }
# 2624| getStmt(0): [ExprStmt] ExprStmt
# 2624| getExpr(): [AssignExpr] ... = ...
# 2624| Type = [IntPointerType] int *
# 2624| ValueCategory = lvalue
# 2624| getLValue(): [VariableAccess] data
# 2624| Type = [IntPointerType] int *
# 2624| ValueCategory = lvalue
# 2624| getRValue(): [AddressOfExpr] & ...
# 2624| Type = [IntPointerType] int *
# 2624| ValueCategory = prvalue
# 2624| getOperand(): [VariableAccess] l1
# 2624| Type = [IntType] int
# 2624| ValueCategory = lvalue
# 2627| getElse(): [BlockStmt] { ... }
# 2628| getStmt(0): [ExprStmt] ExprStmt
# 2628| getExpr(): [AssignExpr] ... = ...
# 2628| Type = [IntPointerType] int *
# 2628| ValueCategory = lvalue
# 2628| getLValue(): [VariableAccess] data
# 2628| Type = [IntPointerType] int *
# 2628| ValueCategory = lvalue
# 2628| getRValue(): [AddressOfExpr] & ...
# 2628| Type = [IntPointerType] int *
# 2628| ValueCategory = prvalue
# 2628| getOperand(): [VariableAccess] l2
# 2628| Type = [IntType] int
# 2628| ValueCategory = lvalue
# 2630| getStmt(3): [ExprStmt] ExprStmt
# 2630| getExpr(): [FunctionCall] call to use_const_int
# 2630| Type = [VoidType] void
# 2630| ValueCategory = prvalue
# 2630| getArgument(0): [VariableAccess] data
# 2630| Type = [IntPointerType] int *
# 2630| ValueCategory = prvalue(load)
# 2630| getArgument(0).getFullyConverted(): [CStyleCast] (const int *)...
# 2630| Conversion = [PointerConversion] pointer conversion
# 2630| Type = [PointerType] const int *
# 2630| ValueCategory = prvalue
# 2631| getStmt(4): [ReturnStmt] return ...
# 2636| [TopLevelFunction] void* malloc(unsigned long)
# 2636| <params>:
# 2636| getParameter(0): [Parameter] (unnamed parameter 0)
# 2636| Type = [LongType] unsigned long
# 2637| [TopLevelFunction] void use_const_void_pointer(void const*)
# 2637| <params>:
# 2637| getParameter(0): [Parameter] (unnamed parameter 0)
# 2637| Type = [PointerType] const void *
# 2639| [TopLevelFunction] void needs_chi_for_initialize_groups()
# 2639| <params>:
# 2640| getEntryPoint(): [BlockStmt] { ... }
# 2641| getStmt(0): [IfStmt] if (...) ...
# 2641| getCondition(): [FunctionCall] call to predicateA
# 2641| Type = [BoolType] bool
# 2641| ValueCategory = prvalue
# 2642| getThen(): [BlockStmt] { ... }
# 2643| getStmt(0): [DeclStmt] declaration
# 2643| getDeclarationEntry(0): [VariableDeclarationEntry] definition of data
# 2643| Type = [PointerType] int64_t *
# 2643| getVariable().getInitializer(): [Initializer] initializer for data
# 2643| getExpr(): [FunctionCall] call to malloc
# 2643| Type = [VoidPointerType] void *
# 2643| ValueCategory = prvalue
# 2643| getArgument(0): [Literal] 100
# 2643| Type = [IntType] int
# 2643| Value = [Literal] 100
# 2643| ValueCategory = prvalue
# 2643| getArgument(0).getFullyConverted(): [CStyleCast] (unsigned long)...
# 2643| Conversion = [IntegralConversion] integral conversion
# 2643| Type = [LongType] unsigned long
# 2643| Value = [CStyleCast] 100
# 2643| ValueCategory = prvalue
# 2643| getExpr().getFullyConverted(): [CStyleCast] (int64_t *)...
# 2643| Conversion = [PointerConversion] pointer conversion
# 2643| Type = [PointerType] int64_t *
# 2643| ValueCategory = prvalue
# 2644| getStmt(1): [IfStmt] if (...) ...
# 2644| getCondition(): [NEExpr] ... != ...
# 2644| Type = [BoolType] bool
# 2644| ValueCategory = prvalue
# 2644| getLeftOperand(): [VariableAccess] data
# 2644| Type = [PointerType] int64_t *
# 2644| ValueCategory = prvalue(load)
# 2644| getRightOperand(): [Literal] 0
# 2644| Type = [IntType] int
# 2644| Value = [Literal] 0
# 2644| ValueCategory = prvalue
# 2644| getLeftOperand().getFullyConverted(): [CStyleCast] (void *)...
# 2644| Conversion = [PointerConversion] pointer conversion
# 2644| Type = [VoidPointerType] void *
# 2644| ValueCategory = prvalue
# 2644| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
# 2644| Type = [VoidPointerType] void *
# 2644| Value = [ParenthesisExpr] 0
# 2644| ValueCategory = prvalue
# 2644| getExpr(): [CStyleCast] (void *)...
# 2644| Conversion = [IntegralToPointerConversion] integral to pointer conversion
# 2644| Type = [VoidPointerType] void *
# 2644| Value = [CStyleCast] 0
# 2644| ValueCategory = prvalue
# 2645| getThen(): [BlockStmt] { ... }
# 2646| getStmt(0): [ExprStmt] ExprStmt
# 2646| getExpr(): [AssignExpr] ... = ...
# 2646| Type = [PointerType] int64_t *
# 2646| ValueCategory = lvalue
# 2646| getLValue(): [VariableAccess] data
# 2646| Type = [PointerType] int64_t *
# 2646| ValueCategory = lvalue
# 2646| getRValue(): [FunctionCall] call to malloc
# 2646| Type = [VoidPointerType] void *
# 2646| ValueCategory = prvalue
# 2646| getArgument(0): [Literal] 100
# 2646| Type = [IntType] int
# 2646| Value = [Literal] 100
# 2646| ValueCategory = prvalue
# 2646| getArgument(0).getFullyConverted(): [CStyleCast] (unsigned long)...
# 2646| Conversion = [IntegralConversion] integral conversion
# 2646| Type = [LongType] unsigned long
# 2646| Value = [CStyleCast] 100
# 2646| ValueCategory = prvalue
# 2646| getRValue().getFullyConverted(): [CStyleCast] (int64_t *)...
# 2646| Conversion = [PointerConversion] pointer conversion
# 2646| Type = [PointerType] int64_t *
# 2646| ValueCategory = prvalue
# 2648| getStmt(2): [ExprStmt] ExprStmt
# 2648| getExpr(): [FunctionCall] call to use_const_void_pointer
# 2648| Type = [VoidType] void
# 2648| ValueCategory = prvalue
# 2648| getArgument(0): [VariableAccess] data
# 2648| Type = [PointerType] int64_t *
# 2648| ValueCategory = prvalue(load)
# 2648| getArgument(0).getFullyConverted(): [CStyleCast] (const void *)...
# 2648| Conversion = [PointerConversion] pointer conversion
# 2648| Type = [PointerType] const void *
# 2648| ValueCategory = prvalue
# 2651| getElse(): [BlockStmt] { ... }
# 2652| getStmt(0): [DeclStmt] declaration
# 2652| getDeclarationEntry(0): [VariableDeclarationEntry] definition of data
# 2652| Type = [PointerType] int64_t *
# 2652| getVariable().getInitializer(): [Initializer] initializer for data
# 2652| getExpr(): [FunctionCall] call to malloc
# 2652| Type = [VoidPointerType] void *
# 2652| ValueCategory = prvalue
# 2652| getArgument(0): [Literal] 100
# 2652| Type = [IntType] int
# 2652| Value = [Literal] 100
# 2652| ValueCategory = prvalue
# 2652| getArgument(0).getFullyConverted(): [CStyleCast] (unsigned long)...
# 2652| Conversion = [IntegralConversion] integral conversion
# 2652| Type = [LongType] unsigned long
# 2652| Value = [CStyleCast] 100
# 2652| ValueCategory = prvalue
# 2652| getExpr().getFullyConverted(): [CStyleCast] (int64_t *)...
# 2652| Conversion = [PointerConversion] pointer conversion
# 2652| Type = [PointerType] int64_t *
# 2652| ValueCategory = prvalue
# 2653| getStmt(1): [IfStmt] if (...) ...
# 2653| getCondition(): [NEExpr] ... != ...
# 2653| Type = [BoolType] bool
# 2653| ValueCategory = prvalue
# 2653| getLeftOperand(): [VariableAccess] data
# 2653| Type = [PointerType] int64_t *
# 2653| ValueCategory = prvalue(load)
# 2653| getRightOperand(): [Literal] 0
# 2653| Type = [IntType] int
# 2653| Value = [Literal] 0
# 2653| ValueCategory = prvalue
# 2653| getLeftOperand().getFullyConverted(): [CStyleCast] (void *)...
# 2653| Conversion = [PointerConversion] pointer conversion
# 2653| Type = [VoidPointerType] void *
# 2653| ValueCategory = prvalue
# 2653| getRightOperand().getFullyConverted(): [ParenthesisExpr] (...)
# 2653| Type = [VoidPointerType] void *
# 2653| Value = [ParenthesisExpr] 0
# 2653| ValueCategory = prvalue
# 2653| getExpr(): [CStyleCast] (void *)...
# 2653| Conversion = [IntegralToPointerConversion] integral to pointer conversion
# 2653| Type = [VoidPointerType] void *
# 2653| Value = [CStyleCast] 0
# 2653| ValueCategory = prvalue
# 2654| getThen(): [BlockStmt] { ... }
# 2655| getStmt(0): [ExprStmt] ExprStmt
# 2655| getExpr(): [AssignExpr] ... = ...
# 2655| Type = [PointerType] int64_t *
# 2655| ValueCategory = lvalue
# 2655| getLValue(): [VariableAccess] data
# 2655| Type = [PointerType] int64_t *
# 2655| ValueCategory = lvalue
# 2655| getRValue(): [FunctionCall] call to malloc
# 2655| Type = [VoidPointerType] void *
# 2655| ValueCategory = prvalue
# 2655| getArgument(0): [Literal] 200
# 2655| Type = [IntType] int
# 2655| Value = [Literal] 200
# 2655| ValueCategory = prvalue
# 2655| getArgument(0).getFullyConverted(): [CStyleCast] (unsigned long)...
# 2655| Conversion = [IntegralConversion] integral conversion
# 2655| Type = [LongType] unsigned long
# 2655| Value = [CStyleCast] 200
# 2655| ValueCategory = prvalue
# 2655| getRValue().getFullyConverted(): [CStyleCast] (int64_t *)...
# 2655| Conversion = [PointerConversion] pointer conversion
# 2655| Type = [PointerType] int64_t *
# 2655| ValueCategory = prvalue
# 2657| getStmt(2): [ExprStmt] ExprStmt
# 2657| getExpr(): [FunctionCall] call to use_const_void_pointer
# 2657| Type = [VoidType] void
# 2657| ValueCategory = prvalue
# 2657| getArgument(0): [VariableAccess] data
# 2657| Type = [PointerType] int64_t *
# 2657| ValueCategory = prvalue(load)
# 2657| getArgument(0).getFullyConverted(): [CStyleCast] (const void *)...
# 2657| Conversion = [PointerConversion] pointer conversion
# 2657| Type = [PointerType] const void *
# 2657| ValueCategory = prvalue
# 2659| getStmt(1): [ReturnStmt] return ...
# 2661| [TopLevelFunction] void use_int(int)
# 2661| <params>:
# 2661| getParameter(0): [Parameter] (unnamed parameter 0)
# 2661| Type = [IntType] int
# 2663| [TopLevelFunction] void phi_with_single_input_at_merge(bool)
# 2663| <params>:
# 2663| getParameter(0): [Parameter] b
# 2663| Type = [BoolType] bool
# 2664| getEntryPoint(): [BlockStmt] { ... }
# 2665| getStmt(0): [DeclStmt] declaration
# 2665| getDeclarationEntry(0): [VariableDeclarationEntry] definition of data
# 2665| Type = [IntPointerType] int *
# 2665| getVariable().getInitializer(): [Initializer] initializer for data
# 2665| getExpr(): [Literal] 0
# 2665| Type = [NullPointerType] decltype(nullptr)
# 2665| Value = [Literal] 0
# 2665| ValueCategory = prvalue
# 2665| getExpr().getFullyConverted(): [CStyleCast] (int *)...
# 2665| Conversion = [PointerConversion] pointer conversion
# 2665| Type = [IntPointerType] int *
# 2665| Value = [CStyleCast] 0
# 2665| ValueCategory = prvalue
# 2666| getStmt(1): [IfStmt] if (...) ...
# 2666| getCondition(): [VariableAccess] b
# 2666| Type = [BoolType] bool
# 2666| ValueCategory = prvalue(load)
# 2666| getThen(): [BlockStmt] { ... }
# 2667| getStmt(0): [DeclStmt] declaration
# 2667| getDeclarationEntry(0): [VariableDeclarationEntry] definition of intBuffer
# 2667| Type = [IntType] int
# 2667| getVariable().getInitializer(): [Initializer] initializer for intBuffer
# 2667| getExpr(): [Literal] 8
# 2667| Type = [IntType] int
# 2667| Value = [Literal] 8
# 2667| ValueCategory = prvalue
# 2668| getStmt(1): [ExprStmt] ExprStmt
# 2668| getExpr(): [AssignExpr] ... = ...
# 2668| Type = [IntPointerType] int *
# 2668| ValueCategory = lvalue
# 2668| getLValue(): [VariableAccess] data
# 2668| Type = [IntPointerType] int *
# 2668| ValueCategory = lvalue
# 2668| getRValue(): [AddressOfExpr] & ...
# 2668| Type = [IntPointerType] int *
# 2668| ValueCategory = prvalue
# 2668| getOperand(): [VariableAccess] intBuffer
# 2668| Type = [IntType] int
# 2668| ValueCategory = lvalue
# 2670| getStmt(2): [ExprStmt] ExprStmt
# 2670| getExpr(): [FunctionCall] call to use_int
# 2670| Type = [VoidType] void
# 2670| ValueCategory = prvalue
# 2670| getArgument(0): [PointerDereferenceExpr] * ...
# 2670| Type = [IntType] int
# 2670| ValueCategory = prvalue(load)
# 2670| getOperand(): [VariableAccess] data
# 2670| Type = [IntPointerType] int *
# 2670| ValueCategory = prvalue(load)
# 2671| getStmt(3): [ReturnStmt] return ...
# 2673| [TopLevelFunction] void use(char const*)
# 2673| <params>:
# 2673| getParameter(0): [Parameter] fmt
# 2673| Type = [PointerType] const char *
# 2684| [TopLevelFunction] void test(bool)
# 2684| <params>:
# 2684| getParameter(0): [Parameter] b
# 2684| Type = [BoolType] bool
# 2685| getEntryPoint(): [BlockStmt] { ... }
# 2686| getStmt(0): [DoStmt] do (...) ...
# 2686| getCondition(): [Literal] 0
# 2686| Type = [IntType] int
# 2686| Value = [Literal] 0
# 2686| ValueCategory = prvalue
# 2686| getStmt(): [BlockStmt] { ... }
# 2686| getStmt(0): [ExprStmt] ExprStmt
# 2686| getExpr(): [FunctionCall] call to use
# 2686| Type = [VoidType] void
# 2686| ValueCategory = prvalue
# 2686| getArgument(0): [ConditionalExpr] ... ? ... : ...
# 2686| Type = [PointerType] const char *
# 2686| ValueCategory = prvalue
# 2686| getCondition(): [VariableAccess] b
# 2686| Type = [BoolType] bool
# 2686| ValueCategory = prvalue(load)
# 2686| getThen():
# 2686| Type = [ArrayType] const char[1]
# 2686| Value = [StringLiteral] ""
# 2686| ValueCategory = lvalue
# 2686| getElse():
# 2686| Type = [ArrayType] const char[1]
# 2686| Value = [StringLiteral] ""
# 2686| ValueCategory = lvalue
# 2686| getThen().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 2686| Type = [PointerType] const char *
# 2686| ValueCategory = prvalue
# 2686| getElse().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 2686| Type = [PointerType] const char *
# 2686| ValueCategory = prvalue
# 2686| getStmt(1): [ExprStmt] ExprStmt
# 2686| getExpr(): [FunctionCall] call to use
# 2686| Type = [VoidType] void
# 2686| ValueCategory = prvalue
# 2686| getArgument(0): [ConditionalExpr] ... ? ... : ...
# 2686| Type = [PointerType] const char *
# 2686| ValueCategory = prvalue
# 2686| getCondition(): [VariableAccess] b
# 2686| Type = [BoolType] bool
# 2686| ValueCategory = prvalue(load)
# 2686| getThen():
# 2686| Type = [ArrayType] const char[1]
# 2686| Value = [StringLiteral] ""
# 2686| ValueCategory = lvalue
# 2686| getElse():
# 2686| Type = [ArrayType] const char[1]
# 2686| Value = [StringLiteral] ""
# 2686| ValueCategory = lvalue
# 2686| getThen().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 2686| Type = [PointerType] const char *
# 2686| ValueCategory = prvalue
# 2686| getElse().getFullyConverted(): [ArrayToPointerConversion] array to pointer conversion
# 2686| Type = [PointerType] const char *
# 2686| ValueCategory = prvalue
# 2686| getCondition().getFullyConverted(): [CStyleCast] (bool)...
# 2686| Conversion = [BoolConversion] conversion to bool
# 2686| Type = [BoolType] bool
# 2686| Value = [CStyleCast] 0
# 2686| ValueCategory = prvalue
# 2687| getStmt(1): [ReturnStmt] return ...
perf-regression.cpp:
# 4| [CopyAssignmentOperator] Big& Big::operator=(Big const&)
# 4| <params>:

View File

@@ -5263,20 +5263,23 @@ ir.cpp:
# 486| void Conditional_LValue(bool)
# 486| Block 0
# 486| v486_1(void) = EnterFunction :
# 486| m486_2(unknown) = AliasedDefinition :
# 486| m486_3(unknown) = InitializeNonLocal :
# 486| m486_4(unknown) = Chi : total:m486_2, partial:m486_3
# 486| r486_5(glval<bool>) = VariableAddress[a] :
# 486| m486_6(bool) = InitializeParameter[a] : &:r486_5
# 487| r487_1(glval<int>) = VariableAddress[x] :
# 487| m487_2(int) = Uninitialized[x] : &:r487_1
# 488| r488_1(glval<int>) = VariableAddress[y] :
# 488| m488_2(int) = Uninitialized[y] : &:r488_1
# 489| r489_1(int) = Constant[5] :
# 489| r489_2(glval<bool>) = VariableAddress[a] :
# 489| r489_3(bool) = Load[a] : &:r489_2, m486_6
# 489| v489_4(void) = ConditionalBranch : r489_3
# 486| v486_1(void) = EnterFunction :
# 486| m486_2(unknown) = AliasedDefinition :
# 486| m486_3(unknown) = InitializeNonLocal :
# 486| m486_4(unknown) = Chi : total:m486_2, partial:m486_3
# 486| m486_5(int) = UninitializedGroup[x,y] :
# 486| r486_6(glval<bool>) = VariableAddress[a] :
# 486| m486_7(bool) = InitializeParameter[a] : &:r486_6
# 487| r487_1(glval<int>) = VariableAddress[x] :
# 487| m487_2(int) = Uninitialized[x] : &:r487_1
# 487| m487_3(int) = Chi : total:m486_5, partial:m487_2
# 488| r488_1(glval<int>) = VariableAddress[y] :
# 488| m488_2(int) = Uninitialized[y] : &:r488_1
# 488| m488_3(int) = Chi : total:m487_3, partial:m488_2
# 489| r489_1(int) = Constant[5] :
# 489| r489_2(glval<bool>) = VariableAddress[a] :
# 489| r489_3(bool) = Load[a] : &:r489_2, m486_7
# 489| v489_4(void) = ConditionalBranch : r489_3
#-----| False -> Block 3
#-----| True -> Block 2
@@ -5285,11 +5288,11 @@ ir.cpp:
# 489| r489_6(glval<unknown>) = VariableAddress[#temp489:6] :
# 489| r489_7(glval<int>) = Load[#temp489:6] : &:r489_6, m489_5
# 489| m489_8(int) = Store[?] : &:r489_7, r489_1
# 489| m489_9(unknown) = Chi : total:m486_4, partial:m489_8
# 489| m489_9(int) = Chi : total:m488_3, partial:m489_8
# 490| v490_1(void) = NoOp :
# 486| v486_7(void) = ReturnVoid :
# 486| v486_8(void) = AliasedUse : ~m489_9
# 486| v486_9(void) = ExitFunction :
# 486| v486_8(void) = ReturnVoid :
# 486| v486_9(void) = AliasedUse : m486_3
# 486| v486_10(void) = ExitFunction :
# 489| Block 2
# 489| r489_10(glval<int>) = VariableAddress[x] :
@@ -14072,21 +14075,24 @@ ir.cpp:
# 2059| void TernaryTestInt(bool, int, int, int)
# 2059| Block 0
# 2059| v2059_1(void) = EnterFunction :
# 2059| m2059_2(unknown) = AliasedDefinition :
# 2059| m2059_3(unknown) = InitializeNonLocal :
# 2059| m2059_4(unknown) = Chi : total:m2059_2, partial:m2059_3
# 2059| r2059_5(glval<bool>) = VariableAddress[a] :
# 2059| m2059_6(bool) = InitializeParameter[a] : &:r2059_5
# 2059| r2059_7(glval<int>) = VariableAddress[x] :
# 2059| m2059_8(int) = InitializeParameter[x] : &:r2059_7
# 2059| r2059_9(glval<int>) = VariableAddress[y] :
# 2059| m2059_10(int) = InitializeParameter[y] : &:r2059_9
# 2059| r2059_11(glval<int>) = VariableAddress[z] :
# 2059| m2059_12(int) = InitializeParameter[z] : &:r2059_11
# 2060| r2060_1(glval<bool>) = VariableAddress[a] :
# 2060| r2060_2(bool) = Load[a] : &:r2060_1, m2059_6
# 2060| v2060_3(void) = ConditionalBranch : r2060_2
# 2059| v2059_1(void) = EnterFunction :
# 2059| m2059_2(unknown) = AliasedDefinition :
# 2059| m2059_3(unknown) = InitializeNonLocal :
# 2059| m2059_4(unknown) = Chi : total:m2059_2, partial:m2059_3
# 2059| m2059_5(int) = UninitializedGroup[x,y] :
# 2059| r2059_6(glval<bool>) = VariableAddress[a] :
# 2059| m2059_7(bool) = InitializeParameter[a] : &:r2059_6
# 2059| r2059_8(glval<int>) = VariableAddress[x] :
# 2059| m2059_9(int) = InitializeParameter[x] : &:r2059_8
# 2059| m2059_10(int) = Chi : total:m2059_5, partial:m2059_9
# 2059| r2059_11(glval<int>) = VariableAddress[y] :
# 2059| m2059_12(int) = InitializeParameter[y] : &:r2059_11
# 2059| m2059_13(int) = Chi : total:m2059_10, partial:m2059_12
# 2059| r2059_14(glval<int>) = VariableAddress[z] :
# 2059| m2059_15(int) = InitializeParameter[z] : &:r2059_14
# 2060| r2060_1(glval<bool>) = VariableAddress[a] :
# 2060| r2060_2(bool) = Load[a] : &:r2060_1, m2059_7
# 2060| v2060_3(void) = ConditionalBranch : r2060_2
#-----| False -> Block 3
#-----| True -> Block 2
@@ -14097,21 +14103,21 @@ ir.cpp:
# 2060| r2060_7(glval<int>) = VariableAddress[z] :
# 2060| m2060_8(int) = Store[z] : &:r2060_7, r2060_6
# 2061| r2061_1(glval<bool>) = VariableAddress[a] :
# 2061| r2061_2(bool) = Load[a] : &:r2061_1, m2059_6
# 2061| r2061_2(bool) = Load[a] : &:r2061_1, m2059_7
# 2061| v2061_3(void) = ConditionalBranch : r2061_2
#-----| False -> Block 6
#-----| True -> Block 5
# 2060| Block 2
# 2060| r2060_9(glval<int>) = VariableAddress[x] :
# 2060| r2060_10(int) = Load[x] : &:r2060_9, m2059_8
# 2060| r2060_10(int) = Load[x] : &:r2060_9, m2059_9
# 2060| r2060_11(glval<int>) = VariableAddress[#temp2060:9] :
# 2060| m2060_12(int) = Store[#temp2060:9] : &:r2060_11, r2060_10
#-----| Goto -> Block 1
# 2060| Block 3
# 2060| r2060_13(glval<int>) = VariableAddress[y] :
# 2060| r2060_14(int) = Load[y] : &:r2060_13, m2059_10
# 2060| r2060_14(int) = Load[y] : &:r2060_13, m2059_12
# 2060| r2060_15(glval<int>) = VariableAddress[#temp2060:9] :
# 2060| m2060_16(int) = Store[#temp2060:9] : &:r2060_15, r2060_14
#-----| Goto -> Block 1
@@ -14123,14 +14129,14 @@ ir.cpp:
# 2061| r2061_7(glval<int>) = VariableAddress[z] :
# 2061| m2061_8(int) = Store[z] : &:r2061_7, r2061_6
# 2062| r2062_1(glval<bool>) = VariableAddress[a] :
# 2062| r2062_2(bool) = Load[a] : &:r2062_1, m2059_6
# 2062| r2062_2(bool) = Load[a] : &:r2062_1, m2059_7
# 2062| v2062_3(void) = ConditionalBranch : r2062_2
#-----| False -> Block 9
#-----| True -> Block 8
# 2061| Block 5
# 2061| r2061_9(glval<int>) = VariableAddress[x] :
# 2061| r2061_10(int) = Load[x] : &:r2061_9, m2059_8
# 2061| r2061_10(int) = Load[x] : &:r2061_9, m2059_9
# 2061| r2061_11(glval<int>) = VariableAddress[#temp2061:9] :
# 2061| m2061_12(int) = Store[#temp2061:9] : &:r2061_11, r2061_10
#-----| Goto -> Block 4
@@ -14149,7 +14155,7 @@ ir.cpp:
# 2062| m2062_8(int) = Store[z] : &:r2062_7, r2062_6
# 2063| r2063_1(int) = Constant[7] :
# 2063| r2063_2(glval<bool>) = VariableAddress[a] :
# 2063| r2063_3(bool) = Load[a] : &:r2063_2, m2059_6
# 2063| r2063_3(bool) = Load[a] : &:r2063_2, m2059_7
# 2063| v2063_4(void) = ConditionalBranch : r2063_3
#-----| False -> Block 12
#-----| True -> Block 11
@@ -14171,11 +14177,11 @@ ir.cpp:
# 2063| r2063_6(glval<unknown>) = VariableAddress[#temp2063:6] :
# 2063| r2063_7(glval<int>) = Load[#temp2063:6] : &:r2063_6, m2063_5
# 2063| m2063_8(int) = Store[?] : &:r2063_7, r2063_1
# 2063| m2063_9(unknown) = Chi : total:m2059_4, partial:m2063_8
# 2063| m2063_9(int) = Chi : total:m2059_13, partial:m2063_8
# 2064| v2064_1(void) = NoOp :
# 2059| v2059_13(void) = ReturnVoid :
# 2059| v2059_14(void) = AliasedUse : ~m2063_9
# 2059| v2059_15(void) = ExitFunction :
# 2059| v2059_16(void) = ReturnVoid :
# 2059| v2059_17(void) = AliasedUse : m2059_3
# 2059| v2059_18(void) = ExitFunction :
# 2063| Block 11
# 2063| r2063_10(glval<int>) = VariableAddress[x] :
@@ -14419,18 +14425,21 @@ ir.cpp:
# 2080| m2080_2(unknown) = AliasedDefinition :
# 2080| m2080_3(unknown) = InitializeNonLocal :
# 2080| m2080_4(unknown) = Chi : total:m2080_2, partial:m2080_3
# 2080| r2080_5(glval<bool>) = VariableAddress[a] :
# 2080| m2080_6(bool) = InitializeParameter[a] : &:r2080_5
# 2080| r2080_7(glval<TernaryNonPodObj>) = VariableAddress[x] :
# 2080| m2080_8(TernaryNonPodObj) = InitializeParameter[x] : &:r2080_7
# 2080| r2080_9(glval<TernaryNonPodObj>) = VariableAddress[y] :
# 2080| m2080_10(TernaryNonPodObj) = InitializeParameter[y] : &:r2080_9
# 2080| r2080_11(glval<TernaryNonPodObj>) = VariableAddress[z] :
# 2080| m2080_12(TernaryNonPodObj) = InitializeParameter[z] : &:r2080_11
# 2080| m2080_5(unknown) = UninitializedGroup[x,y] :
# 2080| r2080_6(glval<bool>) = VariableAddress[a] :
# 2080| m2080_7(bool) = InitializeParameter[a] : &:r2080_6
# 2080| r2080_8(glval<TernaryNonPodObj>) = VariableAddress[x] :
# 2080| m2080_9(TernaryNonPodObj) = InitializeParameter[x] : &:r2080_8
# 2080| m2080_10(unknown) = Chi : total:m2080_5, partial:m2080_9
# 2080| r2080_11(glval<TernaryNonPodObj>) = VariableAddress[y] :
# 2080| m2080_12(TernaryNonPodObj) = InitializeParameter[y] : &:r2080_11
# 2080| m2080_13(unknown) = Chi : total:m2080_10, partial:m2080_12
# 2080| r2080_14(glval<TernaryNonPodObj>) = VariableAddress[z] :
# 2080| m2080_15(TernaryNonPodObj) = InitializeParameter[z] : &:r2080_14
# 2081| r2081_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
# 2081| r2081_2(glval<unknown>) = FunctionAddress[operator=] :
# 2081| r2081_3(glval<bool>) = VariableAddress[a] :
# 2081| r2081_4(bool) = Load[a] : &:r2081_3, m2080_6
# 2081| r2081_4(bool) = Load[a] : &:r2081_3, m2080_7
# 2081| v2081_5(void) = ConditionalBranch : r2081_4
#-----| False -> Block 3
#-----| True -> Block 2
@@ -14444,16 +14453,16 @@ ir.cpp:
# 2081| r2081_11(TernaryNonPodObj &) = Call[operator=] : func:r2081_2, this:r2081_1, 0:r2081_10
# 2081| m2081_12(unknown) = ^CallSideEffect : ~m2080_4
# 2081| m2081_13(unknown) = Chi : total:m2080_4, partial:m2081_12
# 2081| v2081_14(void) = ^IndirectReadSideEffect[-1] : &:r2081_1, m2080_12
# 2081| v2081_15(void) = ^BufferReadSideEffect[0] : &:r2081_10, ~m2081_13
# 2081| v2081_14(void) = ^IndirectReadSideEffect[-1] : &:r2081_1, m2080_15
# 2081| v2081_15(void) = ^BufferReadSideEffect[0] : &:r2081_10, ~m2080_13
# 2081| m2081_16(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2081_1
# 2081| m2081_17(TernaryNonPodObj) = Chi : total:m2080_12, partial:m2081_16
# 2081| m2081_17(TernaryNonPodObj) = Chi : total:m2080_15, partial:m2081_16
# 2081| r2081_18(glval<TernaryNonPodObj>) = CopyValue : r2081_11
# 2082| r2082_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
# 2082| r2082_2(glval<unknown>) = FunctionAddress[operator=] :
# 2082| r2082_3(glval<TernaryNonPodObj>) = VariableAddress[#temp2082:9] :
# 2082| r2082_4(glval<bool>) = VariableAddress[a] :
# 2082| r2082_5(bool) = Load[a] : &:r2082_4, m2080_6
# 2082| r2082_5(bool) = Load[a] : &:r2082_4, m2080_7
# 2082| v2082_6(void) = ConditionalBranch : r2082_5
#-----| False -> Block 6
#-----| True -> Block 5
@@ -14499,7 +14508,7 @@ ir.cpp:
# 2083| r2083_2(glval<unknown>) = FunctionAddress[operator=] :
# 2083| r2083_3(glval<TernaryNonPodObj>) = VariableAddress[#temp2083:9] :
# 2083| r2083_4(glval<bool>) = VariableAddress[a] :
# 2083| r2083_5(bool) = Load[a] : &:r2083_4, m2080_6
# 2083| r2083_5(bool) = Load[a] : &:r2083_4, m2080_7
# 2083| v2083_6(void) = ConditionalBranch : r2083_5
#-----| False -> Block 9
#-----| True -> Block 8
@@ -14514,7 +14523,7 @@ ir.cpp:
# 2082| v2082_37(void) = Call[TernaryNonPodObj] : func:r2082_33, this:r2082_31, 0:r2082_36
# 2082| m2082_38(unknown) = ^CallSideEffect : ~m2081_13
# 2082| m2082_39(unknown) = Chi : total:m2081_13, partial:m2082_38
# 2082| v2082_40(void) = ^BufferReadSideEffect[0] : &:r2082_36, ~m2080_8
# 2082| v2082_40(void) = ^BufferReadSideEffect[0] : &:r2082_36, ~m2080_9
# 2082| m2082_41(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2082_31
# 2082| m2082_42(TernaryNonPodObj) = Chi : total:m2082_32, partial:m2082_41
# 2082| r2082_43(TernaryNonPodObj) = Load[#temp2082:13] : &:r2082_31, m2082_42
@@ -14564,7 +14573,7 @@ ir.cpp:
# 2084| r2084_1(glval<TernaryNonPodObj>) = VariableAddress[z] :
# 2084| r2084_2(glval<unknown>) = FunctionAddress[operator=] :
# 2084| r2084_3(glval<bool>) = VariableAddress[a] :
# 2084| r2084_4(bool) = Load[a] : &:r2084_3, m2080_6
# 2084| r2084_4(bool) = Load[a] : &:r2084_3, m2080_7
# 2084| v2084_5(void) = ConditionalBranch : r2084_4
#-----| False -> Block 12
#-----| True -> Block 11
@@ -14607,7 +14616,7 @@ ir.cpp:
# 2084| m2084_12(unknown) = ^CallSideEffect : ~m2083_29
# 2084| m2084_13(unknown) = Chi : total:m2083_29, partial:m2084_12
# 2084| v2084_14(void) = ^IndirectReadSideEffect[-1] : &:r2084_1, m2083_21
# 2084| v2084_15(void) = ^BufferReadSideEffect[0] : &:r2084_10, ~m2084_13
# 2084| v2084_15(void) = ^BufferReadSideEffect[0] : &:r2084_10, ~m2080_13
# 2084| m2084_16(TernaryNonPodObj) = ^IndirectMayWriteSideEffect[-1] : &:r2084_1
# 2084| m2084_17(TernaryNonPodObj) = Chi : total:m2083_21, partial:m2084_16
# 2084| r2084_18(glval<TernaryNonPodObj>) = CopyValue : r2084_11
@@ -14640,9 +14649,9 @@ ir.cpp:
# 2084| m2084_45(unknown) = Chi : total:m2084_42, partial:m2084_44
# 2084| r2084_46(glval<TernaryNonPodObj>) = CopyValue : r2084_31
# 2085| v2085_1(void) = NoOp :
# 2080| v2080_13(void) = ReturnVoid :
# 2080| v2080_14(void) = AliasedUse : ~m2084_42
# 2080| v2080_15(void) = ExitFunction :
# 2080| v2080_16(void) = ReturnVoid :
# 2080| v2080_17(void) = AliasedUse : ~m2084_42
# 2080| v2080_18(void) = ExitFunction :
# 2084| Block 11
# 2084| r2084_47(glval<TernaryNonPodObj>) = VariableAddress[x] :
@@ -18395,6 +18404,534 @@ ir.cpp:
# 2555| v2555_8(void) = AliasedUse : m2555_3
# 2555| v2555_9(void) = ExitFunction :
# 2559| void p_points_to_x_or_y(int, int)
# 2559| Block 0
# 2559| v2559_1(void) = EnterFunction :
# 2559| m2559_2(unknown) = AliasedDefinition :
# 2559| m2559_3(unknown) = InitializeNonLocal :
# 2559| m2559_4(unknown) = Chi : total:m2559_2, partial:m2559_3
# 2559| m2559_5(int) = UninitializedGroup[x,y] :
# 2559| r2559_6(glval<int>) = VariableAddress[a] :
# 2559| m2559_7(int) = InitializeParameter[a] : &:r2559_6
# 2559| r2559_8(glval<int>) = VariableAddress[b] :
# 2559| m2559_9(int) = InitializeParameter[b] : &:r2559_8
# 2560| r2560_1(glval<int>) = VariableAddress[x] :
# 2560| m2560_2(int) = Uninitialized[x] : &:r2560_1
# 2560| m2560_3(int) = Chi : total:m2559_5, partial:m2560_2
# 2561| r2561_1(glval<int>) = VariableAddress[y] :
# 2561| m2561_2(int) = Uninitialized[y] : &:r2561_1
# 2561| m2561_3(int) = Chi : total:m2560_3, partial:m2561_2
# 2562| r2562_1(glval<int *>) = VariableAddress[p] :
# 2562| m2562_2(int *) = Uninitialized[p] : &:r2562_1
# 2563| r2563_1(glval<int>) = VariableAddress[a] :
# 2563| r2563_2(int) = Load[a] : &:r2563_1, m2559_7
# 2563| r2563_3(glval<int>) = VariableAddress[b] :
# 2563| r2563_4(int) = Load[b] : &:r2563_3, m2559_9
# 2563| r2563_5(bool) = CompareLT : r2563_2, r2563_4
# 2563| v2563_6(void) = ConditionalBranch : r2563_5
#-----| False -> Block 2
#-----| True -> Block 1
# 2564| Block 1
# 2564| r2564_1(glval<int>) = VariableAddress[x] :
# 2564| r2564_2(int *) = CopyValue : r2564_1
# 2564| r2564_3(glval<int *>) = VariableAddress[p] :
# 2564| m2564_4(int *) = Store[p] : &:r2564_3, r2564_2
#-----| Goto -> Block 3
# 2566| Block 2
# 2566| r2566_1(glval<int>) = VariableAddress[y] :
# 2566| r2566_2(int *) = CopyValue : r2566_1
# 2566| r2566_3(glval<int *>) = VariableAddress[p] :
# 2566| m2566_4(int *) = Store[p] : &:r2566_3, r2566_2
#-----| Goto -> Block 3
# 2568| Block 3
# 2568| m2568_1(int *) = Phi : from 1:m2564_4, from 2:m2566_4
# 2568| r2568_2(int) = Constant[5] :
# 2568| r2568_3(glval<int *>) = VariableAddress[p] :
# 2568| r2568_4(int *) = Load[p] : &:r2568_3, m2568_1
# 2568| r2568_5(glval<int>) = CopyValue : r2568_4
# 2568| m2568_6(int) = Store[?] : &:r2568_5, r2568_2
# 2568| m2568_7(int) = Chi : total:m2561_3, partial:m2568_6
# 2569| r2569_1(glval<int>) = VariableAddress[z] :
# 2569| r2569_2(glval<int>) = VariableAddress[x] :
# 2569| r2569_3(int) = Load[x] : &:r2569_2, ~m2568_7
# 2569| m2569_4(int) = Store[z] : &:r2569_1, r2569_3
# 2570| r2570_1(glval<int>) = VariableAddress[w] :
# 2570| r2570_2(glval<int>) = VariableAddress[y] :
# 2570| r2570_3(int) = Load[y] : &:r2570_2, ~m2568_7
# 2570| m2570_4(int) = Store[w] : &:r2570_1, r2570_3
# 2571| v2571_1(void) = NoOp :
# 2559| v2559_10(void) = ReturnVoid :
# 2559| v2559_11(void) = AliasedUse : m2559_3
# 2559| v2559_12(void) = ExitFunction :
# 2573| int phi_after_while()
# 2573| Block 0
# 2573| v2573_1(void) = EnterFunction :
# 2573| m2573_2(unknown) = AliasedDefinition :
# 2573| m2573_3(unknown) = InitializeNonLocal :
# 2573| m2573_4(unknown) = Chi : total:m2573_2, partial:m2573_3
# 2573| m2573_5(int) = UninitializedGroup[r,s] :
# 2574| r2574_1(glval<int>) = VariableAddress[r] :
# 2574| m2574_2(int) = Uninitialized[r] : &:r2574_1
# 2574| m2574_3(int) = Chi : total:m2573_5, partial:m2574_2
# 2575| r2575_1(glval<int *>) = VariableAddress[rP] :
# 2575| r2575_2(glval<int>) = VariableAddress[r] :
# 2575| r2575_3(int *) = CopyValue : r2575_2
# 2575| m2575_4(int *) = Store[rP] : &:r2575_1, r2575_3
#-----| Goto -> Block 1
# 2577| Block 1
# 2577| m2577_1(int) = Phi : from 0:m2574_3, from 2:m2579_7
# 2577| m2577_2(unknown) = Phi : from 0:~m2573_4, from 2:~m2577_7
# 2577| m2577_3(int *) = Phi : from 0:m2575_4, from 2:m2580_4
# 2577| r2577_4(glval<unknown>) = FunctionAddress[predicateA] :
# 2577| r2577_5(bool) = Call[predicateA] : func:r2577_4
# 2577| m2577_6(unknown) = ^CallSideEffect : ~m2577_2
# 2577| m2577_7(unknown) = Chi : total:m2577_2, partial:m2577_6
# 2577| v2577_8(void) = ConditionalBranch : r2577_5
#-----| False -> Block 3
#-----| True -> Block 2
# 2578| Block 2
# 2578| r2578_1(glval<int>) = VariableAddress[s] :
# 2578| r2578_2(int) = Constant[0] :
# 2578| m2578_3(int) = Store[s] : &:r2578_1, r2578_2
# 2578| m2578_4(int) = Chi : total:m2577_1, partial:m2578_3
# 2579| r2579_1(glval<int>) = VariableAddress[s] :
# 2579| r2579_2(int) = Load[s] : &:r2579_1, m2578_3
# 2579| r2579_3(glval<int *>) = VariableAddress[rP] :
# 2579| r2579_4(int *) = Load[rP] : &:r2579_3, m2577_3
# 2579| r2579_5(glval<int>) = CopyValue : r2579_4
# 2579| m2579_6(int) = Store[?] : &:r2579_5, r2579_2
# 2579| m2579_7(int) = Chi : total:m2578_4, partial:m2579_6
# 2580| r2580_1(glval<int>) = VariableAddress[s] :
# 2580| r2580_2(int *) = CopyValue : r2580_1
# 2580| r2580_3(glval<int *>) = VariableAddress[rP] :
# 2580| m2580_4(int *) = Store[rP] : &:r2580_3, r2580_2
#-----| Goto (back edge) -> Block 1
# 2583| Block 3
# 2583| r2583_1(glval<int>) = VariableAddress[#return] :
# 2583| r2583_2(glval<int>) = VariableAddress[r] :
# 2583| r2583_3(int) = Load[r] : &:r2583_2, ~m2577_1
# 2583| m2583_4(int) = Store[#return] : &:r2583_1, r2583_3
# 2573| r2573_6(glval<int>) = VariableAddress[#return] :
# 2573| v2573_7(void) = ReturnValue : &:r2573_6, m2583_4
# 2573| v2573_8(void) = AliasedUse : ~m2577_7
# 2573| v2573_9(void) = ExitFunction :
# 2588| char* recursive_conditional_call_with_increment(char*, bool)
# 2588| Block 0
# 2588| v2588_1(void) = EnterFunction :
# 2588| m2588_2(unknown) = AliasedDefinition :
# 2588| m2588_3(unknown) = InitializeNonLocal :
# 2588| m2588_4(unknown) = Chi : total:m2588_2, partial:m2588_3
# 2588| r2588_5(glval<char *>) = VariableAddress[d] :
# 2588| m2588_6(char *) = InitializeParameter[d] : &:r2588_5
# 2588| r2588_7(char *) = Load[d] : &:r2588_5, m2588_6
# 2588| m2588_8(unknown) = InitializeIndirection[d] : &:r2588_7
# 2588| r2588_9(glval<bool>) = VariableAddress[b] :
# 2588| m2588_10(bool) = InitializeParameter[b] : &:r2588_9
# 2590| r2590_1(glval<bool>) = VariableAddress[b] :
# 2590| r2590_2(bool) = Load[b] : &:r2590_1, m2588_10
# 2590| v2590_3(void) = ConditionalBranch : r2590_2
#-----| False -> Block 2
#-----| True -> Block 1
# 2591| Block 1
# 2591| r2591_1(glval<unknown>) = FunctionAddress[recursive_conditional_call_with_increment] :
# 2591| r2591_2(glval<char *>) = VariableAddress[d] :
# 2591| r2591_3(char *) = Load[d] : &:r2591_2, m2588_6
# 2591| r2591_4(glval<bool>) = VariableAddress[b] :
# 2591| r2591_5(bool) = Load[b] : &:r2591_4, m2588_10
# 2591| r2591_6(char *) = Call[recursive_conditional_call_with_increment] : func:r2591_1, 0:r2591_3, 1:r2591_5
# 2591| m2591_7(unknown) = ^CallSideEffect : ~m2588_4
# 2591| m2591_8(unknown) = Chi : total:m2588_4, partial:m2591_7
# 2591| v2591_9(void) = ^BufferReadSideEffect[0] : &:r2591_3, ~m2588_8
# 2591| m2591_10(unknown) = ^BufferMayWriteSideEffect[0] : &:r2591_3
# 2591| m2591_11(unknown) = Chi : total:m2588_8, partial:m2591_10
# 2591| r2591_12(glval<char *>) = VariableAddress[d] :
# 2591| m2591_13(char *) = Store[d] : &:r2591_12, r2591_6
#-----| Goto -> Block 2
# 2593| Block 2
# 2593| m2593_1(unknown) = Phi : from 0:m2588_8, from 1:m2591_11
# 2593| m2593_2(unknown) = Phi : from 0:~m2588_4, from 1:~m2591_8
# 2593| m2593_3(char *) = Phi : from 0:m2588_6, from 1:m2591_13
# 2593| r2593_4(glval<char *>) = VariableAddress[d] :
# 2593| r2593_5(char *) = Load[d] : &:r2593_4, m2593_3
# 2593| r2593_6(int) = Constant[1] :
# 2593| r2593_7(char *) = PointerAdd[1] : r2593_5, r2593_6
# 2593| m2593_8(char *) = Store[d] : &:r2593_4, r2593_7
# 2594| r2594_1(glval<char *>) = VariableAddress[#return] :
# 2594| r2594_2(glval<char *>) = VariableAddress[d] :
# 2594| r2594_3(char *) = Load[d] : &:r2594_2, m2593_8
# 2594| m2594_4(char *) = Store[#return] : &:r2594_1, r2594_3
# 2588| v2588_11(void) = ReturnIndirection[d] : &:r2588_7, m2593_1
# 2588| r2588_12(glval<char *>) = VariableAddress[#return] :
# 2588| v2588_13(void) = ReturnValue : &:r2588_12, m2594_4
# 2588| v2588_14(void) = AliasedUse : ~m2593_2
# 2588| v2588_15(void) = ExitFunction :
# 2602| Recursive* merge(Recursive*)
# 2602| Block 0
# 2602| v2602_1(void) = EnterFunction :
# 2602| m2602_2(unknown) = AliasedDefinition :
# 2602| m2602_3(unknown) = InitializeNonLocal :
# 2602| m2602_4(unknown) = Chi : total:m2602_2, partial:m2602_3
# 2602| m2602_5(Recursive *) = UninitializedGroup[a,b] :
# 2602| m2602_6(unknown) = Chi : total:m2602_4, partial:m2602_5
# 2602| r2602_7(glval<Recursive *>) = VariableAddress[a] :
# 2602| m2602_8(Recursive *) = InitializeParameter[a] : &:r2602_7
# 2602| r2602_9(Recursive *) = Load[a] : &:r2602_7, m2602_8
# 2602| m2602_10(unknown) = InitializeIndirection[a] : &:r2602_9
# 2602| m2602_11(unknown) = Chi : total:m2602_6, partial:m2602_10
# 2604| r2604_1(glval<Recursive *>) = VariableAddress[b] :
# 2604| m2604_2(Recursive *) = Uninitialized[b] : &:r2604_1
# 2604| m2604_3(unknown) = Chi : total:m2602_11, partial:m2604_2
# 2605| r2605_1(glval<Recursive **>) = VariableAddress[p] :
# 2605| r2605_2(glval<Recursive *>) = VariableAddress[b] :
# 2605| r2605_3(Recursive **) = CopyValue : r2605_2
# 2605| m2605_4(Recursive **) = Store[p] : &:r2605_1, r2605_3
#-----| Goto -> Block 1
# 2607| Block 1
# 2607| m2607_1(unknown) = Phi : from 0:~m2604_3, from 2:~m2609_7
# 2607| m2607_2(Recursive **) = Phi : from 0:m2605_4, from 2:m2610_6
# 2607| r2607_3(glval<unknown>) = FunctionAddress[predicateA] :
# 2607| r2607_4(bool) = Call[predicateA] : func:r2607_3
# 2607| m2607_5(unknown) = ^CallSideEffect : ~m2607_1
# 2607| m2607_6(unknown) = Chi : total:m2607_1, partial:m2607_5
# 2607| v2607_7(void) = ConditionalBranch : r2607_4
#-----| False -> Block 3
#-----| True -> Block 2
# 2609| Block 2
# 2609| r2609_1(glval<Recursive *>) = VariableAddress[a] :
# 2609| r2609_2(Recursive *) = Load[a] : &:r2609_1, m2602_8
# 2609| r2609_3(glval<Recursive **>) = VariableAddress[p] :
# 2609| r2609_4(Recursive **) = Load[p] : &:r2609_3, m2607_2
# 2609| r2609_5(glval<Recursive *>) = CopyValue : r2609_4
# 2609| m2609_6(Recursive *) = Store[?] : &:r2609_5, r2609_2
# 2609| m2609_7(unknown) = Chi : total:m2607_6, partial:m2609_6
# 2610| r2610_1(glval<Recursive *>) = VariableAddress[a] :
# 2610| r2610_2(Recursive *) = Load[a] : &:r2610_1, m2602_8
# 2610| r2610_3(glval<Recursive *>) = FieldAddress[next] : r2610_2
# 2610| r2610_4(Recursive **) = CopyValue : r2610_3
# 2610| r2610_5(glval<Recursive **>) = VariableAddress[p] :
# 2610| m2610_6(Recursive **) = Store[p] : &:r2610_5, r2610_4
#-----| Goto (back edge) -> Block 1
# 2613| Block 3
# 2613| r2613_1(glval<Recursive *>) = VariableAddress[#return] :
# 2613| r2613_2(glval<Recursive *>) = VariableAddress[b] :
# 2613| r2613_3(Recursive *) = Load[b] : &:r2613_2, ~m2607_6
# 2613| m2613_4(Recursive *) = Store[#return] : &:r2613_1, r2613_3
# 2602| v2602_12(void) = ReturnIndirection[a] : &:r2602_9, ~m2607_6
# 2602| r2602_13(glval<Recursive *>) = VariableAddress[#return] :
# 2602| v2602_14(void) = ReturnValue : &:r2602_13, m2613_4
# 2602| v2602_15(void) = AliasedUse : ~m2607_6
# 2602| v2602_16(void) = ExitFunction :
# 2618| void escaping_pointer(bool)
# 2618| Block 0
# 2618| v2618_1(void) = EnterFunction :
# 2618| m2618_2(unknown) = AliasedDefinition :
# 2618| m2618_3(unknown) = InitializeNonLocal :
# 2618| m2618_4(unknown) = Chi : total:m2618_2, partial:m2618_3
# 2618| m2618_5(unknown) = UninitializedGroup[l1,l2] :
# 2618| m2618_6(unknown) = Chi : total:m2618_4, partial:m2618_5
# 2618| r2618_7(glval<bool>) = VariableAddress[b] :
# 2618| m2618_8(bool) = InitializeParameter[b] : &:r2618_7
# 2620| r2620_1(glval<int *>) = VariableAddress[data] :
# 2620| m2620_2(int *) = Uninitialized[data] : &:r2620_1
# 2621| r2621_1(glval<int>) = VariableAddress[l1] :
# 2621| m2621_2(int) = Uninitialized[l1] : &:r2621_1
# 2621| m2621_3(unknown) = Chi : total:m2618_6, partial:m2621_2
# 2621| r2621_4(glval<int>) = VariableAddress[l2] :
# 2621| m2621_5(int) = Uninitialized[l2] : &:r2621_4
# 2621| m2621_6(unknown) = Chi : total:m2621_3, partial:m2621_5
# 2622| r2622_1(glval<bool>) = VariableAddress[b] :
# 2622| r2622_2(bool) = Load[b] : &:r2622_1, m2618_8
# 2622| v2622_3(void) = ConditionalBranch : r2622_2
#-----| False -> Block 2
#-----| True -> Block 1
# 2624| Block 1
# 2624| r2624_1(glval<int>) = VariableAddress[l1] :
# 2624| r2624_2(int *) = CopyValue : r2624_1
# 2624| r2624_3(glval<int *>) = VariableAddress[data] :
# 2624| m2624_4(int *) = Store[data] : &:r2624_3, r2624_2
#-----| Goto -> Block 3
# 2628| Block 2
# 2628| r2628_1(glval<int>) = VariableAddress[l2] :
# 2628| r2628_2(int *) = CopyValue : r2628_1
# 2628| r2628_3(glval<int *>) = VariableAddress[data] :
# 2628| m2628_4(int *) = Store[data] : &:r2628_3, r2628_2
#-----| Goto -> Block 3
# 2630| Block 3
# 2630| m2630_1(int *) = Phi : from 1:m2624_4, from 2:m2628_4
# 2630| r2630_2(glval<unknown>) = FunctionAddress[use_const_int] :
# 2630| r2630_3(glval<int *>) = VariableAddress[data] :
# 2630| r2630_4(int *) = Load[data] : &:r2630_3, m2630_1
# 2630| r2630_5(int *) = Convert : r2630_4
# 2630| v2630_6(void) = Call[use_const_int] : func:r2630_2, 0:r2630_5
# 2630| m2630_7(unknown) = ^CallSideEffect : ~m2621_6
# 2630| m2630_8(unknown) = Chi : total:m2621_6, partial:m2630_7
# 2630| v2630_9(void) = ^BufferReadSideEffect[0] : &:r2630_5, ~m2630_8
# 2631| v2631_1(void) = NoOp :
# 2618| v2618_9(void) = ReturnVoid :
# 2618| v2618_10(void) = AliasedUse : ~m2630_8
# 2618| v2618_11(void) = ExitFunction :
# 2639| void needs_chi_for_initialize_groups()
# 2639| Block 0
# 2639| v2639_1(void) = EnterFunction :
# 2639| m2639_2(unknown) = AliasedDefinition :
# 2639| m2639_3(unknown) = InitializeNonLocal :
# 2639| m2639_4(unknown) = Chi : total:m2639_2, partial:m2639_3
# 2639| m2639_5(unknown) = UninitializedGroup :
# 2639| m2639_6(unknown) = Chi : total:m2639_4, partial:m2639_5
# 2639| m2639_7(unknown) = UninitializedGroup :
# 2639| m2639_8(unknown) = Chi : total:m2639_6, partial:m2639_7
# 2641| r2641_1(glval<unknown>) = FunctionAddress[predicateA] :
# 2641| r2641_2(bool) = Call[predicateA] : func:r2641_1
# 2641| m2641_3(unknown) = ^CallSideEffect : ~m2639_8
# 2641| m2641_4(unknown) = Chi : total:m2639_8, partial:m2641_3
# 2641| v2641_5(void) = ConditionalBranch : r2641_2
#-----| False -> Block 4
#-----| True -> Block 1
# 2643| Block 1
# 2643| r2643_1(glval<long long *>) = VariableAddress[data] :
# 2643| r2643_2(glval<unknown>) = FunctionAddress[malloc] :
# 2643| r2643_3(unsigned long) = Constant[100] :
# 2643| r2643_4(void *) = Call[malloc] : func:r2643_2, 0:r2643_3
# 2643| m2643_5(unknown) = ^CallSideEffect : ~m2641_4
# 2643| m2643_6(unknown) = Chi : total:m2641_4, partial:m2643_5
# 2643| m2643_7(unknown) = ^InitializeDynamicAllocation : &:r2643_4
# 2643| m2643_8(unknown) = Chi : total:m2643_6, partial:m2643_7
# 2643| r2643_9(long long *) = Convert : r2643_4
# 2643| m2643_10(long long *) = Store[data] : &:r2643_1, r2643_9
# 2644| r2644_1(glval<long long *>) = VariableAddress[data] :
# 2644| r2644_2(long long *) = Load[data] : &:r2644_1, m2643_10
# 2644| r2644_3(void *) = Convert : r2644_2
# 2644| r2644_4(void *) = Constant[0] :
# 2644| r2644_5(bool) = CompareNE : r2644_3, r2644_4
# 2644| v2644_6(void) = ConditionalBranch : r2644_5
#-----| False -> Block 3
#-----| True -> Block 2
# 2646| Block 2
# 2646| r2646_1(glval<unknown>) = FunctionAddress[malloc] :
# 2646| r2646_2(unsigned long) = Constant[100] :
# 2646| r2646_3(void *) = Call[malloc] : func:r2646_1, 0:r2646_2
# 2646| m2646_4(unknown) = ^CallSideEffect : ~m2643_8
# 2646| m2646_5(unknown) = Chi : total:m2643_8, partial:m2646_4
# 2646| m2646_6(unknown) = ^InitializeDynamicAllocation : &:r2646_3
# 2646| m2646_7(unknown) = Chi : total:m2646_5, partial:m2646_6
# 2646| r2646_8(long long *) = Convert : r2646_3
# 2646| r2646_9(glval<long long *>) = VariableAddress[data] :
# 2646| m2646_10(long long *) = Store[data] : &:r2646_9, r2646_8
#-----| Goto -> Block 3
# 2648| Block 3
# 2648| m2648_1(unknown) = Phi : from 1:~m2643_8, from 2:~m2646_7
# 2648| m2648_2(long long *) = Phi : from 1:m2643_10, from 2:m2646_10
# 2648| r2648_3(glval<unknown>) = FunctionAddress[use_const_void_pointer] :
# 2648| r2648_4(glval<long long *>) = VariableAddress[data] :
# 2648| r2648_5(long long *) = Load[data] : &:r2648_4, m2648_2
# 2648| r2648_6(void *) = Convert : r2648_5
# 2648| v2648_7(void) = Call[use_const_void_pointer] : func:r2648_3, 0:r2648_6
# 2648| m2648_8(unknown) = ^CallSideEffect : ~m2648_1
# 2648| m2648_9(unknown) = Chi : total:m2648_1, partial:m2648_8
# 2648| v2648_10(void) = ^BufferReadSideEffect[0] : &:r2648_6, ~m2648_9
#-----| Goto -> Block 7
# 2652| Block 4
# 2652| r2652_1(glval<long long *>) = VariableAddress[data] :
# 2652| r2652_2(glval<unknown>) = FunctionAddress[malloc] :
# 2652| r2652_3(unsigned long) = Constant[100] :
# 2652| r2652_4(void *) = Call[malloc] : func:r2652_2, 0:r2652_3
# 2652| m2652_5(unknown) = ^CallSideEffect : ~m2641_4
# 2652| m2652_6(unknown) = Chi : total:m2641_4, partial:m2652_5
# 2652| m2652_7(unknown) = ^InitializeDynamicAllocation : &:r2652_4
# 2652| m2652_8(unknown) = Chi : total:m2652_6, partial:m2652_7
# 2652| r2652_9(long long *) = Convert : r2652_4
# 2652| m2652_10(long long *) = Store[data] : &:r2652_1, r2652_9
# 2653| r2653_1(glval<long long *>) = VariableAddress[data] :
# 2653| r2653_2(long long *) = Load[data] : &:r2653_1, m2652_10
# 2653| r2653_3(void *) = Convert : r2653_2
# 2653| r2653_4(void *) = Constant[0] :
# 2653| r2653_5(bool) = CompareNE : r2653_3, r2653_4
# 2653| v2653_6(void) = ConditionalBranch : r2653_5
#-----| False -> Block 6
#-----| True -> Block 5
# 2655| Block 5
# 2655| r2655_1(glval<unknown>) = FunctionAddress[malloc] :
# 2655| r2655_2(unsigned long) = Constant[200] :
# 2655| r2655_3(void *) = Call[malloc] : func:r2655_1, 0:r2655_2
# 2655| m2655_4(unknown) = ^CallSideEffect : ~m2652_8
# 2655| m2655_5(unknown) = Chi : total:m2652_8, partial:m2655_4
# 2655| m2655_6(unknown) = ^InitializeDynamicAllocation : &:r2655_3
# 2655| m2655_7(unknown) = Chi : total:m2655_5, partial:m2655_6
# 2655| r2655_8(long long *) = Convert : r2655_3
# 2655| r2655_9(glval<long long *>) = VariableAddress[data] :
# 2655| m2655_10(long long *) = Store[data] : &:r2655_9, r2655_8
#-----| Goto -> Block 6
# 2657| Block 6
# 2657| m2657_1(unknown) = Phi : from 4:~m2652_8, from 5:~m2655_7
# 2657| m2657_2(long long *) = Phi : from 4:m2652_10, from 5:m2655_10
# 2657| r2657_3(glval<unknown>) = FunctionAddress[use_const_void_pointer] :
# 2657| r2657_4(glval<long long *>) = VariableAddress[data] :
# 2657| r2657_5(long long *) = Load[data] : &:r2657_4, m2657_2
# 2657| r2657_6(void *) = Convert : r2657_5
# 2657| v2657_7(void) = Call[use_const_void_pointer] : func:r2657_3, 0:r2657_6
# 2657| m2657_8(unknown) = ^CallSideEffect : ~m2657_1
# 2657| m2657_9(unknown) = Chi : total:m2657_1, partial:m2657_8
# 2657| v2657_10(void) = ^BufferReadSideEffect[0] : &:r2657_6, ~m2657_9
#-----| Goto -> Block 7
# 2659| Block 7
# 2659| m2659_1(unknown) = Phi : from 3:~m2648_9, from 6:~m2657_9
# 2659| v2659_2(void) = NoOp :
# 2639| v2639_9(void) = ReturnVoid :
# 2639| v2639_10(void) = AliasedUse : ~m2659_1
# 2639| v2639_11(void) = ExitFunction :
# 2663| void phi_with_single_input_at_merge(bool)
# 2663| Block 0
# 2663| v2663_1(void) = EnterFunction :
# 2663| m2663_2(unknown) = AliasedDefinition :
# 2663| m2663_3(unknown) = InitializeNonLocal :
# 2663| m2663_4(unknown) = Chi : total:m2663_2, partial:m2663_3
# 2663| r2663_5(glval<bool>) = VariableAddress[b] :
# 2663| m2663_6(bool) = InitializeParameter[b] : &:r2663_5
# 2665| r2665_1(glval<int *>) = VariableAddress[data] :
# 2665| r2665_2(int *) = Constant[0] :
# 2665| m2665_3(int *) = Store[data] : &:r2665_1, r2665_2
# 2666| r2666_1(glval<bool>) = VariableAddress[b] :
# 2666| r2666_2(bool) = Load[b] : &:r2666_1, m2663_6
# 2666| v2666_3(void) = ConditionalBranch : r2666_2
#-----| False -> Block 2
#-----| True -> Block 1
# 2667| Block 1
# 2667| r2667_1(glval<int>) = VariableAddress[intBuffer] :
# 2667| r2667_2(int) = Constant[8] :
# 2667| m2667_3(int) = Store[intBuffer] : &:r2667_1, r2667_2
# 2668| r2668_1(glval<int>) = VariableAddress[intBuffer] :
# 2668| r2668_2(int *) = CopyValue : r2668_1
# 2668| r2668_3(glval<int *>) = VariableAddress[data] :
# 2668| m2668_4(int *) = Store[data] : &:r2668_3, r2668_2
#-----| Goto -> Block 2
# 2670| Block 2
# 2670| m2670_1(int) = Phi : from 1:m2667_3
# 2670| m2670_2(int *) = Phi : from 0:m2665_3, from 1:m2668_4
# 2670| r2670_3(glval<unknown>) = FunctionAddress[use_int] :
# 2670| r2670_4(glval<int *>) = VariableAddress[data] :
# 2670| r2670_5(int *) = Load[data] : &:r2670_4, m2670_2
# 2670| r2670_6(int) = Load[?] : &:r2670_5, ~m2670_1
# 2670| v2670_7(void) = Call[use_int] : func:r2670_3, 0:r2670_6
# 2670| m2670_8(unknown) = ^CallSideEffect : ~m2663_4
# 2670| m2670_9(unknown) = Chi : total:m2663_4, partial:m2670_8
# 2671| v2671_1(void) = NoOp :
# 2663| v2663_7(void) = ReturnVoid :
# 2663| v2663_8(void) = AliasedUse : ~m2670_9
# 2663| v2663_9(void) = ExitFunction :
# 2684| void test(bool)
# 2684| Block 0
# 2684| v2684_1(void) = EnterFunction :
# 2684| m2684_2(unknown) = AliasedDefinition :
# 2684| m2684_3(unknown) = InitializeNonLocal :
# 2684| m2684_4(unknown) = Chi : total:m2684_2, partial:m2684_3
# 2684| m2684_5(unknown) = UninitializedGroup[#string2686:22,#string2686:27] :
# 2684| m2684_6(unknown) = Chi : total:m2684_4, partial:m2684_5
# 2684| m2684_7(unknown) = UninitializedGroup[#string2686:22,#string2686:27] :
# 2684| m2684_8(unknown) = Chi : total:m2684_6, partial:m2684_7
# 2684| r2684_9(glval<bool>) = VariableAddress[b] :
# 2684| m2684_10(bool) = InitializeParameter[b] : &:r2684_9
# 2686| r2686_1(glval<unknown>) = FunctionAddress[use] :
# 2686| r2686_2(glval<bool>) = VariableAddress[b] :
# 2686| r2686_3(bool) = Load[b] : &:r2686_2, m2684_10
# 2686| v2686_4(void) = ConditionalBranch : r2686_3
#-----| False -> Block 3
#-----| True -> Block 2
# 2686| Block 1
# 2686| m2686_5(char *) = Phi : from 2:m2686_19, from 3:m2686_23
# 2686| r2686_6(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| r2686_7(char *) = Load[#temp2686:18] : &:r2686_6, m2686_5
# 2686| v2686_8(void) = Call[use] : func:r2686_1, 0:r2686_7
# 2686| m2686_9(unknown) = ^CallSideEffect : ~m2684_8
# 2686| m2686_10(unknown) = Chi : total:m2684_8, partial:m2686_9
# 2686| v2686_11(void) = ^BufferReadSideEffect[0] : &:r2686_7, ~m2686_10
# 2686| r2686_12(glval<unknown>) = FunctionAddress[use] :
# 2686| r2686_13(glval<bool>) = VariableAddress[b] :
# 2686| r2686_14(bool) = Load[b] : &:r2686_13, m2684_10
# 2686| v2686_15(void) = ConditionalBranch : r2686_14
#-----| False -> Block 6
#-----| True -> Block 5
# 2686| Block 2
# 2686| r2686_16(glval<char[1]>) = StringConstant[] :
# 2686| r2686_17(char *) = Convert : r2686_16
# 2686| r2686_18(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| m2686_19(char *) = Store[#temp2686:18] : &:r2686_18, r2686_17
#-----| Goto -> Block 1
# 2686| Block 3
# 2686| r2686_20(glval<char[1]>) = StringConstant[] :
# 2686| r2686_21(char *) = Convert : r2686_20
# 2686| r2686_22(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| m2686_23(char *) = Store[#temp2686:18] : &:r2686_22, r2686_21
#-----| Goto -> Block 1
# 2686| Block 4
# 2686| m2686_24(char *) = Phi : from 5:m2686_36, from 6:m2686_40
# 2686| r2686_25(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| r2686_26(char *) = Load[#temp2686:18] : &:r2686_25, m2686_24
# 2686| v2686_27(void) = Call[use] : func:r2686_12, 0:r2686_26
# 2686| m2686_28(unknown) = ^CallSideEffect : ~m2686_10
# 2686| m2686_29(unknown) = Chi : total:m2686_10, partial:m2686_28
# 2686| v2686_30(void) = ^BufferReadSideEffect[0] : &:r2686_26, ~m2686_29
# 2686| r2686_31(bool) = Constant[0] :
# 2686| v2686_32(void) = ConditionalBranch : r2686_31
#-----| False -> Block 7
#-----| True -> Block 8
# 2686| Block 5
# 2686| r2686_33(glval<char[1]>) = StringConstant[] :
# 2686| r2686_34(char *) = Convert : r2686_33
# 2686| r2686_35(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| m2686_36(char *) = Store[#temp2686:18] : &:r2686_35, r2686_34
#-----| Goto -> Block 4
# 2686| Block 6
# 2686| r2686_37(glval<char[1]>) = StringConstant[] :
# 2686| r2686_38(char *) = Convert : r2686_37
# 2686| r2686_39(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| m2686_40(char *) = Store[#temp2686:18] : &:r2686_39, r2686_38
#-----| Goto -> Block 4
# 2687| Block 7
# 2687| v2687_1(void) = NoOp :
# 2684| v2684_11(void) = ReturnVoid :
# 2684| v2684_12(void) = AliasedUse : ~m2686_29
# 2684| v2684_13(void) = ExitFunction :
# 2684| Block 8
# 2684| v2684_14(void) = Unreached :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -2,6 +2,7 @@ missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary

View File

@@ -2,6 +2,7 @@ missingOperand
unexpectedOperand
duplicateOperand
missingPhiOperand
| ir.cpp:2670:3:2670:9 | Phi: call to use_int | Instruction 'Phi: call to use_int' is missing an operand for predecessor block 'EnterFunction: phi_with_single_input_at_merge' in function '$@'. | ir.cpp:2663:13:2663:42 | void phi_with_single_input_at_merge(bool) | void phi_with_single_input_at_merge(bool) |
missingOperandType
duplicateChiOperand
sideEffectWithoutPrimary

View File

@@ -2556,4 +2556,134 @@ void builtin_bitcast(unsigned long ul) {
double d = __builtin_bit_cast(double, ul);
}
void p_points_to_x_or_y(int a, int b) {
int x;
int y;
int* p;
if (a < b) {
p = &x;
} else {
p = &y;
}
*p = 5;
int z = x;
int w = y;
}
int phi_after_while() {
int r;
int *rP = &r;
while(predicateA()) {
int s = 0;
*rP = s;
rP = &s;
}
return r;
}
// This testcase will loop infinitely if the analysis attempts to propagate
// phi inputs with a non-unknown bit offset.
char *recursive_conditional_call_with_increment(char *d, bool b)
{
if (b) {
d = recursive_conditional_call_with_increment(d, b);
}
d++;
return d;
}
struct Recursive
{
Recursive *next;
};
static Recursive *merge(Recursive *a)
{
Recursive *b;
Recursive **p = &b;
while (predicateA())
{
*p = a;
p = &a->next;
}
return b;
}
void use_const_int(const int*);
void escaping_pointer(bool b)
{
int *data;
int l1, l2;
if (b)
{
data = &l1;
}
else
{
data = &l2;
}
use_const_int(data);
}
using int64_t = long long;
#define NULL ((void *)0)
void *malloc(unsigned long);
void use_const_void_pointer(const void *);
static void needs_chi_for_initialize_groups()
{
if (predicateA())
{
int64_t *data = (int64_t *)malloc(100);
if (data != NULL)
{
data = (int64_t *)malloc(100);
}
use_const_void_pointer(data);
}
else
{
int64_t *data = (int64_t *)malloc(100);
if (data != NULL)
{
data = (int64_t *)malloc(200);
}
use_const_void_pointer(data);
}
}
void use_int(int);
static void phi_with_single_input_at_merge(bool b)
{
int *data = nullptr;
if(b) {
int intBuffer = 8;
data = &intBuffer;
}
use_int(*data);
}
void use(const char *fmt);
#define call_use(format) use(format)
#define twice_call_use(format) \
do \
{ \
call_use(format); \
call_use(format); \
} while (0)
void test(bool b)
{
twice_call_use(b ? "" : "");
}
// semmle-extractor-options: -std=c++20 --clang

View File

@@ -16734,6 +16734,463 @@ ir.cpp:
# 2555| v2555_7(void) = AliasedUse : ~m?
# 2555| v2555_8(void) = ExitFunction :
# 2559| void p_points_to_x_or_y(int, int)
# 2559| Block 0
# 2559| v2559_1(void) = EnterFunction :
# 2559| mu2559_2(unknown) = AliasedDefinition :
# 2559| mu2559_3(unknown) = InitializeNonLocal :
# 2559| r2559_4(glval<int>) = VariableAddress[a] :
# 2559| mu2559_5(int) = InitializeParameter[a] : &:r2559_4
# 2559| r2559_6(glval<int>) = VariableAddress[b] :
# 2559| mu2559_7(int) = InitializeParameter[b] : &:r2559_6
# 2560| r2560_1(glval<int>) = VariableAddress[x] :
# 2560| mu2560_2(int) = Uninitialized[x] : &:r2560_1
# 2561| r2561_1(glval<int>) = VariableAddress[y] :
# 2561| mu2561_2(int) = Uninitialized[y] : &:r2561_1
# 2562| r2562_1(glval<int *>) = VariableAddress[p] :
# 2562| mu2562_2(int *) = Uninitialized[p] : &:r2562_1
# 2563| r2563_1(glval<int>) = VariableAddress[a] :
# 2563| r2563_2(int) = Load[a] : &:r2563_1, ~m?
# 2563| r2563_3(glval<int>) = VariableAddress[b] :
# 2563| r2563_4(int) = Load[b] : &:r2563_3, ~m?
# 2563| r2563_5(bool) = CompareLT : r2563_2, r2563_4
# 2563| v2563_6(void) = ConditionalBranch : r2563_5
#-----| False -> Block 2
#-----| True -> Block 1
# 2564| Block 1
# 2564| r2564_1(glval<int>) = VariableAddress[x] :
# 2564| r2564_2(int *) = CopyValue : r2564_1
# 2564| r2564_3(glval<int *>) = VariableAddress[p] :
# 2564| mu2564_4(int *) = Store[p] : &:r2564_3, r2564_2
#-----| Goto -> Block 3
# 2566| Block 2
# 2566| r2566_1(glval<int>) = VariableAddress[y] :
# 2566| r2566_2(int *) = CopyValue : r2566_1
# 2566| r2566_3(glval<int *>) = VariableAddress[p] :
# 2566| mu2566_4(int *) = Store[p] : &:r2566_3, r2566_2
#-----| Goto -> Block 3
# 2568| Block 3
# 2568| r2568_1(int) = Constant[5] :
# 2568| r2568_2(glval<int *>) = VariableAddress[p] :
# 2568| r2568_3(int *) = Load[p] : &:r2568_2, ~m?
# 2568| r2568_4(glval<int>) = CopyValue : r2568_3
# 2568| mu2568_5(int) = Store[?] : &:r2568_4, r2568_1
# 2569| r2569_1(glval<int>) = VariableAddress[z] :
# 2569| r2569_2(glval<int>) = VariableAddress[x] :
# 2569| r2569_3(int) = Load[x] : &:r2569_2, ~m?
# 2569| mu2569_4(int) = Store[z] : &:r2569_1, r2569_3
# 2570| r2570_1(glval<int>) = VariableAddress[w] :
# 2570| r2570_2(glval<int>) = VariableAddress[y] :
# 2570| r2570_3(int) = Load[y] : &:r2570_2, ~m?
# 2570| mu2570_4(int) = Store[w] : &:r2570_1, r2570_3
# 2571| v2571_1(void) = NoOp :
# 2559| v2559_8(void) = ReturnVoid :
# 2559| v2559_9(void) = AliasedUse : ~m?
# 2559| v2559_10(void) = ExitFunction :
# 2573| int phi_after_while()
# 2573| Block 0
# 2573| v2573_1(void) = EnterFunction :
# 2573| mu2573_2(unknown) = AliasedDefinition :
# 2573| mu2573_3(unknown) = InitializeNonLocal :
# 2574| r2574_1(glval<int>) = VariableAddress[r] :
# 2574| mu2574_2(int) = Uninitialized[r] : &:r2574_1
# 2575| r2575_1(glval<int *>) = VariableAddress[rP] :
# 2575| r2575_2(glval<int>) = VariableAddress[r] :
# 2575| r2575_3(int *) = CopyValue : r2575_2
# 2575| mu2575_4(int *) = Store[rP] : &:r2575_1, r2575_3
#-----| Goto -> Block 1
# 2577| Block 1
# 2577| r2577_1(glval<unknown>) = FunctionAddress[predicateA] :
# 2577| r2577_2(bool) = Call[predicateA] : func:r2577_1
# 2577| mu2577_3(unknown) = ^CallSideEffect : ~m?
# 2577| v2577_4(void) = ConditionalBranch : r2577_2
#-----| False -> Block 3
#-----| True -> Block 2
# 2578| Block 2
# 2578| r2578_1(glval<int>) = VariableAddress[s] :
# 2578| r2578_2(int) = Constant[0] :
# 2578| mu2578_3(int) = Store[s] : &:r2578_1, r2578_2
# 2579| r2579_1(glval<int>) = VariableAddress[s] :
# 2579| r2579_2(int) = Load[s] : &:r2579_1, ~m?
# 2579| r2579_3(glval<int *>) = VariableAddress[rP] :
# 2579| r2579_4(int *) = Load[rP] : &:r2579_3, ~m?
# 2579| r2579_5(glval<int>) = CopyValue : r2579_4
# 2579| mu2579_6(int) = Store[?] : &:r2579_5, r2579_2
# 2580| r2580_1(glval<int>) = VariableAddress[s] :
# 2580| r2580_2(int *) = CopyValue : r2580_1
# 2580| r2580_3(glval<int *>) = VariableAddress[rP] :
# 2580| mu2580_4(int *) = Store[rP] : &:r2580_3, r2580_2
#-----| Goto (back edge) -> Block 1
# 2583| Block 3
# 2583| r2583_1(glval<int>) = VariableAddress[#return] :
# 2583| r2583_2(glval<int>) = VariableAddress[r] :
# 2583| r2583_3(int) = Load[r] : &:r2583_2, ~m?
# 2583| mu2583_4(int) = Store[#return] : &:r2583_1, r2583_3
# 2573| r2573_4(glval<int>) = VariableAddress[#return] :
# 2573| v2573_5(void) = ReturnValue : &:r2573_4, ~m?
# 2573| v2573_6(void) = AliasedUse : ~m?
# 2573| v2573_7(void) = ExitFunction :
# 2588| char* recursive_conditional_call_with_increment(char*, bool)
# 2588| Block 0
# 2588| v2588_1(void) = EnterFunction :
# 2588| mu2588_2(unknown) = AliasedDefinition :
# 2588| mu2588_3(unknown) = InitializeNonLocal :
# 2588| r2588_4(glval<char *>) = VariableAddress[d] :
# 2588| mu2588_5(char *) = InitializeParameter[d] : &:r2588_4
# 2588| r2588_6(char *) = Load[d] : &:r2588_4, ~m?
# 2588| mu2588_7(unknown) = InitializeIndirection[d] : &:r2588_6
# 2588| r2588_8(glval<bool>) = VariableAddress[b] :
# 2588| mu2588_9(bool) = InitializeParameter[b] : &:r2588_8
# 2590| r2590_1(glval<bool>) = VariableAddress[b] :
# 2590| r2590_2(bool) = Load[b] : &:r2590_1, ~m?
# 2590| v2590_3(void) = ConditionalBranch : r2590_2
#-----| False -> Block 2
#-----| True -> Block 1
# 2591| Block 1
# 2591| r2591_1(glval<unknown>) = FunctionAddress[recursive_conditional_call_with_increment] :
# 2591| r2591_2(glval<char *>) = VariableAddress[d] :
# 2591| r2591_3(char *) = Load[d] : &:r2591_2, ~m?
# 2591| r2591_4(glval<bool>) = VariableAddress[b] :
# 2591| r2591_5(bool) = Load[b] : &:r2591_4, ~m?
# 2591| r2591_6(char *) = Call[recursive_conditional_call_with_increment] : func:r2591_1, 0:r2591_3, 1:r2591_5
# 2591| mu2591_7(unknown) = ^CallSideEffect : ~m?
# 2591| v2591_8(void) = ^BufferReadSideEffect[0] : &:r2591_3, ~m?
# 2591| mu2591_9(unknown) = ^BufferMayWriteSideEffect[0] : &:r2591_3
# 2591| r2591_10(glval<char *>) = VariableAddress[d] :
# 2591| mu2591_11(char *) = Store[d] : &:r2591_10, r2591_6
#-----| Goto -> Block 2
# 2593| Block 2
# 2593| r2593_1(glval<char *>) = VariableAddress[d] :
# 2593| r2593_2(char *) = Load[d] : &:r2593_1, ~m?
# 2593| r2593_3(int) = Constant[1] :
# 2593| r2593_4(char *) = PointerAdd[1] : r2593_2, r2593_3
# 2593| mu2593_5(char *) = Store[d] : &:r2593_1, r2593_4
# 2594| r2594_1(glval<char *>) = VariableAddress[#return] :
# 2594| r2594_2(glval<char *>) = VariableAddress[d] :
# 2594| r2594_3(char *) = Load[d] : &:r2594_2, ~m?
# 2594| mu2594_4(char *) = Store[#return] : &:r2594_1, r2594_3
# 2588| v2588_10(void) = ReturnIndirection[d] : &:r2588_6, ~m?
# 2588| r2588_11(glval<char *>) = VariableAddress[#return] :
# 2588| v2588_12(void) = ReturnValue : &:r2588_11, ~m?
# 2588| v2588_13(void) = AliasedUse : ~m?
# 2588| v2588_14(void) = ExitFunction :
# 2602| Recursive* merge(Recursive*)
# 2602| Block 0
# 2602| v2602_1(void) = EnterFunction :
# 2602| mu2602_2(unknown) = AliasedDefinition :
# 2602| mu2602_3(unknown) = InitializeNonLocal :
# 2602| r2602_4(glval<Recursive *>) = VariableAddress[a] :
# 2602| mu2602_5(Recursive *) = InitializeParameter[a] : &:r2602_4
# 2602| r2602_6(Recursive *) = Load[a] : &:r2602_4, ~m?
# 2602| mu2602_7(unknown) = InitializeIndirection[a] : &:r2602_6
# 2604| r2604_1(glval<Recursive *>) = VariableAddress[b] :
# 2604| mu2604_2(Recursive *) = Uninitialized[b] : &:r2604_1
# 2605| r2605_1(glval<Recursive **>) = VariableAddress[p] :
# 2605| r2605_2(glval<Recursive *>) = VariableAddress[b] :
# 2605| r2605_3(Recursive **) = CopyValue : r2605_2
# 2605| mu2605_4(Recursive **) = Store[p] : &:r2605_1, r2605_3
#-----| Goto -> Block 1
# 2607| Block 1
# 2607| r2607_1(glval<unknown>) = FunctionAddress[predicateA] :
# 2607| r2607_2(bool) = Call[predicateA] : func:r2607_1
# 2607| mu2607_3(unknown) = ^CallSideEffect : ~m?
# 2607| v2607_4(void) = ConditionalBranch : r2607_2
#-----| False -> Block 3
#-----| True -> Block 2
# 2609| Block 2
# 2609| r2609_1(glval<Recursive *>) = VariableAddress[a] :
# 2609| r2609_2(Recursive *) = Load[a] : &:r2609_1, ~m?
# 2609| r2609_3(glval<Recursive **>) = VariableAddress[p] :
# 2609| r2609_4(Recursive **) = Load[p] : &:r2609_3, ~m?
# 2609| r2609_5(glval<Recursive *>) = CopyValue : r2609_4
# 2609| mu2609_6(Recursive *) = Store[?] : &:r2609_5, r2609_2
# 2610| r2610_1(glval<Recursive *>) = VariableAddress[a] :
# 2610| r2610_2(Recursive *) = Load[a] : &:r2610_1, ~m?
# 2610| r2610_3(glval<Recursive *>) = FieldAddress[next] : r2610_2
# 2610| r2610_4(Recursive **) = CopyValue : r2610_3
# 2610| r2610_5(glval<Recursive **>) = VariableAddress[p] :
# 2610| mu2610_6(Recursive **) = Store[p] : &:r2610_5, r2610_4
#-----| Goto (back edge) -> Block 1
# 2613| Block 3
# 2613| r2613_1(glval<Recursive *>) = VariableAddress[#return] :
# 2613| r2613_2(glval<Recursive *>) = VariableAddress[b] :
# 2613| r2613_3(Recursive *) = Load[b] : &:r2613_2, ~m?
# 2613| mu2613_4(Recursive *) = Store[#return] : &:r2613_1, r2613_3
# 2602| v2602_8(void) = ReturnIndirection[a] : &:r2602_6, ~m?
# 2602| r2602_9(glval<Recursive *>) = VariableAddress[#return] :
# 2602| v2602_10(void) = ReturnValue : &:r2602_9, ~m?
# 2602| v2602_11(void) = AliasedUse : ~m?
# 2602| v2602_12(void) = ExitFunction :
# 2618| void escaping_pointer(bool)
# 2618| Block 0
# 2618| v2618_1(void) = EnterFunction :
# 2618| mu2618_2(unknown) = AliasedDefinition :
# 2618| mu2618_3(unknown) = InitializeNonLocal :
# 2618| r2618_4(glval<bool>) = VariableAddress[b] :
# 2618| mu2618_5(bool) = InitializeParameter[b] : &:r2618_4
# 2620| r2620_1(glval<int *>) = VariableAddress[data] :
# 2620| mu2620_2(int *) = Uninitialized[data] : &:r2620_1
# 2621| r2621_1(glval<int>) = VariableAddress[l1] :
# 2621| mu2621_2(int) = Uninitialized[l1] : &:r2621_1
# 2621| r2621_3(glval<int>) = VariableAddress[l2] :
# 2621| mu2621_4(int) = Uninitialized[l2] : &:r2621_3
# 2622| r2622_1(glval<bool>) = VariableAddress[b] :
# 2622| r2622_2(bool) = Load[b] : &:r2622_1, ~m?
# 2622| v2622_3(void) = ConditionalBranch : r2622_2
#-----| False -> Block 2
#-----| True -> Block 1
# 2624| Block 1
# 2624| r2624_1(glval<int>) = VariableAddress[l1] :
# 2624| r2624_2(int *) = CopyValue : r2624_1
# 2624| r2624_3(glval<int *>) = VariableAddress[data] :
# 2624| mu2624_4(int *) = Store[data] : &:r2624_3, r2624_2
#-----| Goto -> Block 3
# 2628| Block 2
# 2628| r2628_1(glval<int>) = VariableAddress[l2] :
# 2628| r2628_2(int *) = CopyValue : r2628_1
# 2628| r2628_3(glval<int *>) = VariableAddress[data] :
# 2628| mu2628_4(int *) = Store[data] : &:r2628_3, r2628_2
#-----| Goto -> Block 3
# 2630| Block 3
# 2630| r2630_1(glval<unknown>) = FunctionAddress[use_const_int] :
# 2630| r2630_2(glval<int *>) = VariableAddress[data] :
# 2630| r2630_3(int *) = Load[data] : &:r2630_2, ~m?
# 2630| r2630_4(int *) = Convert : r2630_3
# 2630| v2630_5(void) = Call[use_const_int] : func:r2630_1, 0:r2630_4
# 2630| mu2630_6(unknown) = ^CallSideEffect : ~m?
# 2630| v2630_7(void) = ^BufferReadSideEffect[0] : &:r2630_4, ~m?
# 2631| v2631_1(void) = NoOp :
# 2618| v2618_6(void) = ReturnVoid :
# 2618| v2618_7(void) = AliasedUse : ~m?
# 2618| v2618_8(void) = ExitFunction :
# 2639| void needs_chi_for_initialize_groups()
# 2639| Block 0
# 2639| v2639_1(void) = EnterFunction :
# 2639| mu2639_2(unknown) = AliasedDefinition :
# 2639| mu2639_3(unknown) = InitializeNonLocal :
# 2641| r2641_1(glval<unknown>) = FunctionAddress[predicateA] :
# 2641| r2641_2(bool) = Call[predicateA] : func:r2641_1
# 2641| mu2641_3(unknown) = ^CallSideEffect : ~m?
# 2641| v2641_4(void) = ConditionalBranch : r2641_2
#-----| False -> Block 4
#-----| True -> Block 1
# 2643| Block 1
# 2643| r2643_1(glval<long long *>) = VariableAddress[data] :
# 2643| r2643_2(glval<unknown>) = FunctionAddress[malloc] :
# 2643| r2643_3(unsigned long) = Constant[100] :
# 2643| r2643_4(void *) = Call[malloc] : func:r2643_2, 0:r2643_3
# 2643| mu2643_5(unknown) = ^CallSideEffect : ~m?
# 2643| mu2643_6(unknown) = ^InitializeDynamicAllocation : &:r2643_4
# 2643| r2643_7(long long *) = Convert : r2643_4
# 2643| mu2643_8(long long *) = Store[data] : &:r2643_1, r2643_7
# 2644| r2644_1(glval<long long *>) = VariableAddress[data] :
# 2644| r2644_2(long long *) = Load[data] : &:r2644_1, ~m?
# 2644| r2644_3(void *) = Convert : r2644_2
# 2644| r2644_4(void *) = Constant[0] :
# 2644| r2644_5(bool) = CompareNE : r2644_3, r2644_4
# 2644| v2644_6(void) = ConditionalBranch : r2644_5
#-----| False -> Block 3
#-----| True -> Block 2
# 2646| Block 2
# 2646| r2646_1(glval<unknown>) = FunctionAddress[malloc] :
# 2646| r2646_2(unsigned long) = Constant[100] :
# 2646| r2646_3(void *) = Call[malloc] : func:r2646_1, 0:r2646_2
# 2646| mu2646_4(unknown) = ^CallSideEffect : ~m?
# 2646| mu2646_5(unknown) = ^InitializeDynamicAllocation : &:r2646_3
# 2646| r2646_6(long long *) = Convert : r2646_3
# 2646| r2646_7(glval<long long *>) = VariableAddress[data] :
# 2646| mu2646_8(long long *) = Store[data] : &:r2646_7, r2646_6
#-----| Goto -> Block 3
# 2648| Block 3
# 2648| r2648_1(glval<unknown>) = FunctionAddress[use_const_void_pointer] :
# 2648| r2648_2(glval<long long *>) = VariableAddress[data] :
# 2648| r2648_3(long long *) = Load[data] : &:r2648_2, ~m?
# 2648| r2648_4(void *) = Convert : r2648_3
# 2648| v2648_5(void) = Call[use_const_void_pointer] : func:r2648_1, 0:r2648_4
# 2648| mu2648_6(unknown) = ^CallSideEffect : ~m?
# 2648| v2648_7(void) = ^BufferReadSideEffect[0] : &:r2648_4, ~m?
#-----| Goto -> Block 7
# 2652| Block 4
# 2652| r2652_1(glval<long long *>) = VariableAddress[data] :
# 2652| r2652_2(glval<unknown>) = FunctionAddress[malloc] :
# 2652| r2652_3(unsigned long) = Constant[100] :
# 2652| r2652_4(void *) = Call[malloc] : func:r2652_2, 0:r2652_3
# 2652| mu2652_5(unknown) = ^CallSideEffect : ~m?
# 2652| mu2652_6(unknown) = ^InitializeDynamicAllocation : &:r2652_4
# 2652| r2652_7(long long *) = Convert : r2652_4
# 2652| mu2652_8(long long *) = Store[data] : &:r2652_1, r2652_7
# 2653| r2653_1(glval<long long *>) = VariableAddress[data] :
# 2653| r2653_2(long long *) = Load[data] : &:r2653_1, ~m?
# 2653| r2653_3(void *) = Convert : r2653_2
# 2653| r2653_4(void *) = Constant[0] :
# 2653| r2653_5(bool) = CompareNE : r2653_3, r2653_4
# 2653| v2653_6(void) = ConditionalBranch : r2653_5
#-----| False -> Block 6
#-----| True -> Block 5
# 2655| Block 5
# 2655| r2655_1(glval<unknown>) = FunctionAddress[malloc] :
# 2655| r2655_2(unsigned long) = Constant[200] :
# 2655| r2655_3(void *) = Call[malloc] : func:r2655_1, 0:r2655_2
# 2655| mu2655_4(unknown) = ^CallSideEffect : ~m?
# 2655| mu2655_5(unknown) = ^InitializeDynamicAllocation : &:r2655_3
# 2655| r2655_6(long long *) = Convert : r2655_3
# 2655| r2655_7(glval<long long *>) = VariableAddress[data] :
# 2655| mu2655_8(long long *) = Store[data] : &:r2655_7, r2655_6
#-----| Goto -> Block 6
# 2657| Block 6
# 2657| r2657_1(glval<unknown>) = FunctionAddress[use_const_void_pointer] :
# 2657| r2657_2(glval<long long *>) = VariableAddress[data] :
# 2657| r2657_3(long long *) = Load[data] : &:r2657_2, ~m?
# 2657| r2657_4(void *) = Convert : r2657_3
# 2657| v2657_5(void) = Call[use_const_void_pointer] : func:r2657_1, 0:r2657_4
# 2657| mu2657_6(unknown) = ^CallSideEffect : ~m?
# 2657| v2657_7(void) = ^BufferReadSideEffect[0] : &:r2657_4, ~m?
#-----| Goto -> Block 7
# 2659| Block 7
# 2659| v2659_1(void) = NoOp :
# 2639| v2639_4(void) = ReturnVoid :
# 2639| v2639_5(void) = AliasedUse : ~m?
# 2639| v2639_6(void) = ExitFunction :
# 2663| void phi_with_single_input_at_merge(bool)
# 2663| Block 0
# 2663| v2663_1(void) = EnterFunction :
# 2663| mu2663_2(unknown) = AliasedDefinition :
# 2663| mu2663_3(unknown) = InitializeNonLocal :
# 2663| r2663_4(glval<bool>) = VariableAddress[b] :
# 2663| mu2663_5(bool) = InitializeParameter[b] : &:r2663_4
# 2665| r2665_1(glval<int *>) = VariableAddress[data] :
# 2665| r2665_2(int *) = Constant[0] :
# 2665| mu2665_3(int *) = Store[data] : &:r2665_1, r2665_2
# 2666| r2666_1(glval<bool>) = VariableAddress[b] :
# 2666| r2666_2(bool) = Load[b] : &:r2666_1, ~m?
# 2666| v2666_3(void) = ConditionalBranch : r2666_2
#-----| False -> Block 2
#-----| True -> Block 1
# 2667| Block 1
# 2667| r2667_1(glval<int>) = VariableAddress[intBuffer] :
# 2667| r2667_2(int) = Constant[8] :
# 2667| mu2667_3(int) = Store[intBuffer] : &:r2667_1, r2667_2
# 2668| r2668_1(glval<int>) = VariableAddress[intBuffer] :
# 2668| r2668_2(int *) = CopyValue : r2668_1
# 2668| r2668_3(glval<int *>) = VariableAddress[data] :
# 2668| mu2668_4(int *) = Store[data] : &:r2668_3, r2668_2
#-----| Goto -> Block 2
# 2670| Block 2
# 2670| r2670_1(glval<unknown>) = FunctionAddress[use_int] :
# 2670| r2670_2(glval<int *>) = VariableAddress[data] :
# 2670| r2670_3(int *) = Load[data] : &:r2670_2, ~m?
# 2670| r2670_4(int) = Load[?] : &:r2670_3, ~m?
# 2670| v2670_5(void) = Call[use_int] : func:r2670_1, 0:r2670_4
# 2670| mu2670_6(unknown) = ^CallSideEffect : ~m?
# 2671| v2671_1(void) = NoOp :
# 2663| v2663_6(void) = ReturnVoid :
# 2663| v2663_7(void) = AliasedUse : ~m?
# 2663| v2663_8(void) = ExitFunction :
# 2684| void test(bool)
# 2684| Block 0
# 2684| v2684_1(void) = EnterFunction :
# 2684| mu2684_2(unknown) = AliasedDefinition :
# 2684| mu2684_3(unknown) = InitializeNonLocal :
# 2684| r2684_4(glval<bool>) = VariableAddress[b] :
# 2684| mu2684_5(bool) = InitializeParameter[b] : &:r2684_4
#-----| Goto -> Block 1
# 2686| Block 1
# 2686| r2686_1(glval<unknown>) = FunctionAddress[use] :
# 2686| r2686_2(glval<bool>) = VariableAddress[b] :
# 2686| r2686_3(bool) = Load[b] : &:r2686_2, ~m?
# 2686| v2686_4(void) = ConditionalBranch : r2686_3
#-----| False -> Block 4
#-----| True -> Block 3
# 2686| Block 2
# 2686| r2686_5(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| r2686_6(char *) = Load[#temp2686:18] : &:r2686_5, ~m?
# 2686| v2686_7(void) = Call[use] : func:r2686_1, 0:r2686_6
# 2686| mu2686_8(unknown) = ^CallSideEffect : ~m?
# 2686| v2686_9(void) = ^BufferReadSideEffect[0] : &:r2686_6, ~m?
# 2686| r2686_10(glval<unknown>) = FunctionAddress[use] :
# 2686| r2686_11(glval<bool>) = VariableAddress[b] :
# 2686| r2686_12(bool) = Load[b] : &:r2686_11, ~m?
# 2686| v2686_13(void) = ConditionalBranch : r2686_12
#-----| False -> Block 7
#-----| True -> Block 6
# 2686| Block 3
# 2686| r2686_14(glval<char[1]>) = StringConstant[] :
# 2686| r2686_15(char *) = Convert : r2686_14
# 2686| r2686_16(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| mu2686_17(char *) = Store[#temp2686:18] : &:r2686_16, r2686_15
#-----| Goto -> Block 2
# 2686| Block 4
# 2686| r2686_18(glval<char[1]>) = StringConstant[] :
# 2686| r2686_19(char *) = Convert : r2686_18
# 2686| r2686_20(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| mu2686_21(char *) = Store[#temp2686:18] : &:r2686_20, r2686_19
#-----| Goto -> Block 2
# 2686| Block 5
# 2686| r2686_22(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| r2686_23(char *) = Load[#temp2686:18] : &:r2686_22, ~m?
# 2686| v2686_24(void) = Call[use] : func:r2686_10, 0:r2686_23
# 2686| mu2686_25(unknown) = ^CallSideEffect : ~m?
# 2686| v2686_26(void) = ^BufferReadSideEffect[0] : &:r2686_23, ~m?
# 2686| r2686_27(bool) = Constant[0] :
# 2686| v2686_28(void) = ConditionalBranch : r2686_27
#-----| False -> Block 8
#-----| True (back edge) -> Block 1
# 2686| Block 6
# 2686| r2686_29(glval<char[1]>) = StringConstant[] :
# 2686| r2686_30(char *) = Convert : r2686_29
# 2686| r2686_31(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| mu2686_32(char *) = Store[#temp2686:18] : &:r2686_31, r2686_30
#-----| Goto -> Block 5
# 2686| Block 7
# 2686| r2686_33(glval<char[1]>) = StringConstant[] :
# 2686| r2686_34(char *) = Convert : r2686_33
# 2686| r2686_35(glval<char *>) = VariableAddress[#temp2686:18] :
# 2686| mu2686_36(char *) = Store[#temp2686:18] : &:r2686_35, r2686_34
#-----| Goto -> Block 5
# 2687| Block 8
# 2687| v2687_1(void) = NoOp :
# 2684| v2684_6(void) = ReturnVoid :
# 2684| v2684_7(void) = AliasedUse : ~m?
# 2684| v2684_8(void) = ExitFunction :
perf-regression.cpp:
# 6| void Big::Big()
# 6| Block 0

View File

@@ -1,2 +1 @@
testFailures
failures
ERROR: getAllocation() cannot be resolved for type SimpleSSA::MemoryLocation (points_to.ql:31,42-55)

View File

@@ -56,7 +56,7 @@ module UnaliasedSsa {
not memLocation.getVirtualVariable() instanceof AliasedVirtualVariable and
not memLocation instanceof AllNonLocalMemory and
tag = "ussa" and
not ignoreAllocation(memLocation.getAllocation().getAllocationString()) and
not ignoreAllocation(memLocation.getAnAllocation().getAllocationString()) and
value = memLocation.toString() and
element = instr.toString() and
location = instr.getLocation() and

View File

@@ -381,7 +381,7 @@ ssa.cpp:
#-----| Goto -> Block 1
# 69| Block 1
# 69| m69_1(unknown) = Phi : from 0:~m68_4, from 2:~m70_10
# 69| m69_1(unknown) = Phi : from 0:m68_10, from 2:m70_10
# 69| m69_2(char *) = Phi : from 0:m68_8, from 2:m70_6
# 69| m69_3(int) = Phi : from 0:m68_6, from 2:m69_8
# 69| r69_4(glval<int>) = VariableAddress[n] :
@@ -411,9 +411,9 @@ ssa.cpp:
# 71| Block 3
# 71| v71_1(void) = NoOp :
# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, m68_10
# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, m69_1
# 68| v68_12(void) = ReturnVoid :
# 68| v68_13(void) = AliasedUse : ~m69_1
# 68| v68_13(void) = AliasedUse : m68_3
# 68| v68_14(void) = ExitFunction :
# 75| void ScalarPhi(bool)

View File

@@ -381,7 +381,7 @@ ssa.cpp:
#-----| Goto -> Block 1
# 69| Block 1
# 69| m69_1(unknown) = Phi : from 0:~m68_4, from 2:~m70_10
# 69| m69_1(unknown) = Phi : from 0:m68_10, from 2:m70_10
# 69| m69_2(char *) = Phi : from 0:m68_8, from 2:m70_6
# 69| m69_3(int) = Phi : from 0:m68_6, from 2:m69_8
# 69| r69_4(glval<int>) = VariableAddress[n] :
@@ -411,9 +411,9 @@ ssa.cpp:
# 71| Block 3
# 71| v71_1(void) = NoOp :
# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, m68_10
# 68| v68_11(void) = ReturnIndirection[p] : &:r68_9, m69_1
# 68| v68_12(void) = ReturnVoid :
# 68| v68_13(void) = AliasedUse : ~m69_1
# 68| v68_13(void) = AliasedUse : m68_3
# 68| v68_14(void) = ExitFunction :
# 75| void ScalarPhi(bool)

View File

@@ -19,7 +19,5 @@
| test.cpp:14:7:14:7 | D | test.cpp:23:10:23:12 | f_D | D::f_D() | getAMember(), getAMember(3), getAMemberFunction(), getCanonicalMember(3), getDeclaringType() |
| test.cpp:27:7:27:7 | E<T> | test.cpp:29:10:29:12 | f_E | E<T>::f_E() | getAMember(), getAMember(0), getAMemberFunction(), getCanonicalMember(0), getDeclaringType() |
| test.cpp:27:7:27:7 | E<T> | test.cpp:31:10:31:16 | f_E_arg | E<T>::f_E_arg(E<T>) | getAMember(), getAMember(1), getAMemberFunction(), getCanonicalMember(1), getDeclaringType() |
| test.cpp:27:7:27:7 | E<int> | test.cpp:27:7:27:7 | operator= | E<int>::operator=(E<int> &&) | getAMember(), getAMember(3), getAMemberFunction(), getCanonicalMember(3), getDeclaringType() |
| test.cpp:27:7:27:7 | E<int> | test.cpp:27:7:27:7 | operator= | E<int>::operator=(const E<int> &) | getAMember(), getAMember(2), getAMemberFunction(), getCanonicalMember(2), getDeclaringType() |
| test.cpp:27:7:27:7 | E<int> | test.cpp:29:10:29:10 | f_E | E<int>::f_E() | getAMember(), getAMember(0), getAMemberFunction(), getCanonicalMember(0), getDeclaringType() |
| test.cpp:27:7:27:7 | E<int> | test.cpp:31:10:31:10 | f_E_arg | E<int>::f_E_arg(E<int>) | getAMember(), getAMember(1), getAMemberFunction(), getCanonicalMember(1), getDeclaringType() |

View File

@@ -4,4 +4,7 @@
static void f(void) {
CA::CB<int> x;
CA::CB<float> y;
x.operator=(x);
x.operator=(static_cast<CA::CB<int>&&>(x));
}

View File

@@ -11,9 +11,7 @@
| h.h:2:7:2:8 | CA | 1 CA::operator= |
| h.h:2:7:2:8 | CA | 2 CA::operator= |
| h.h:5:11:5:12 | CB<TB> | <none> |
| h.h:5:11:5:12 | CB<double> | 0 CA::CB<double>::operator= |
| h.h:5:11:5:12 | CB<double> | 1 CA::CB<double>::operator= |
| h.h:5:11:5:12 | CB<float> | 0 CA::CB<float>::operator= |
| h.h:5:11:5:12 | CB<float> | 1 CA::CB<float>::operator= |
| h.h:5:11:5:12 | CB<double> | <none> |
| h.h:5:11:5:12 | CB<float> | <none> |
| h.h:5:11:5:12 | CB<int> | 0 CA::CB<int>::operator= |
| h.h:5:11:5:12 | CB<int> | 1 CA::CB<int>::operator= |

View File

@@ -1,7 +1,3 @@
| copy_from_prototype.cpp:3:7:3:7 | a | void a<int>::a(a<int> const&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:3:7:3:7 | a | void a<int>::a(a<int>&&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:3:7:3:7 | operator= | a<int>& a<int>::operator=(a<int> const&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:3:7:3:7 | operator= | a<int>& a<int>::operator=(a<int>&&) | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:4:26:4:26 | a | void a<(unnamed template parameter)>::a<(unnamed template parameter)>() | copy_from_prototype.cpp:3:7:3:7 | a<<unnamed>> | 123 |
| copy_from_prototype.cpp:4:26:4:26 | a | void a<int>::a<(unnamed template parameter)>() | copy_from_prototype.cpp:3:7:3:7 | a<int> | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | b | void b::b() | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
@@ -9,10 +5,6 @@
| copy_from_prototype.cpp:7:7:7:7 | b | void b::b(b&&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | operator= | b& b::operator=(b const&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:7:7:7:7 | operator= | b& b::operator=(b&&) | copy_from_prototype.cpp:7:7:7:7 | b | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | c | void c<int>::c(c<int> const&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | c | void c<int>::c(c<int>&&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | operator= | c<int>& c<int>::operator=(c<int> const&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:13:7:13:7 | operator= | c<int>& c<int>::operator=(c<int>&&) | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:14:26:14:26 | c | void c<T>::c<(unnamed template parameter)>() | copy_from_prototype.cpp:13:7:13:7 | c<T> | X |
| copy_from_prototype.cpp:14:26:14:26 | c | void c<int>::c<(unnamed template parameter)>() | copy_from_prototype.cpp:13:7:13:7 | c<int> | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | d | void d::d() | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
@@ -20,10 +12,6 @@
| copy_from_prototype.cpp:17:7:17:7 | d | void d::d(d&&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | operator= | d& d::operator=(d const&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:17:7:17:7 | operator= | d& d::operator=(d&&) | copy_from_prototype.cpp:17:7:17:7 | d | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | e | void e<int>::e(e<int> const&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | e | void e<int>::e(e<int>&&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | operator= | e<int>& e<int>::operator=(e<int> const&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:22:8:22:8 | operator= | e<int>& e<int>::operator=(e<int>&&) | copy_from_prototype.cpp:22:8:22:8 | e<int> | <no expr> |
| copy_from_prototype.cpp:23:26:23:26 | e | void e<T>::e<(unnamed template parameter)>() | copy_from_prototype.cpp:22:8:22:8 | e<T> | 456 |
| copy_from_prototype.cpp:26:35:26:43 | e | void e<int>::e<(unnamed template parameter)>() | copy_from_prototype.cpp:22:8:22:8 | e<int> | 456 |
| file://:0:0:0:0 | operator= | __va_list_tag& __va_list_tag::operator=(__va_list_tag const&) | file://:0:0:0:0 | __va_list_tag | <none> |

View File

@@ -1,20 +1,4 @@
| box.cpp:3:6:3:6 | definition of h | -------- | --- |
| box.h:2:8:2:8 | declaration of Box | -------- | --- |
| box.h:2:8:2:8 | declaration of Box | -------- | --- |
| box.h:2:8:2:8 | declaration of Box | -------- | --- |
| box.h:2:8:2:8 | declaration of Box | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | declaration of operator= | -------- | --- |
| box.h:2:8:2:8 | definition of Box | no except | --- |
| box.h:2:8:2:8 | definition of Box | no except | --- |
| box.h:2:8:2:8 | definition of Box | no except | --- |
| box.h:2:8:2:8 | definition of Box | no except | --- |
| box.h:3:3:3:3 | definition of Box | -------- | __has_nothrow_copy |
| box.h:3:3:3:3 | definition of Box | -------- | __has_nothrow_copy |
| box.h:3:3:3:3 | definition of Box | -------- | __has_nothrow_copy |

View File

@@ -63,13 +63,7 @@
| scopes.cpp:74:11:74:13 | One | Namespace | scopes.cpp:95:8:95:8 | I | Class |
| scopes.cpp:77:8:77:8 | H<T> | Class | scopes.cpp:76:18:76:18 | T | |
| scopes.cpp:77:8:77:8 | H<T> | Class | scopes.cpp:79:5:79:5 | t | |
| scopes.cpp:77:8:77:8 | H<long> | Class | scopes.cpp:77:8:77:8 | H | |
| scopes.cpp:77:8:77:8 | H<long> | Class | scopes.cpp:77:8:77:8 | operator= | |
| scopes.cpp:77:8:77:8 | H<long> | Class | scopes.cpp:77:8:77:8 | operator= | |
| scopes.cpp:77:8:77:8 | H<long> | Class | scopes.cpp:79:5:79:5 | t | |
| scopes.cpp:77:8:77:8 | H<short> | Class | scopes.cpp:77:8:77:8 | H | |
| scopes.cpp:77:8:77:8 | H<short> | Class | scopes.cpp:77:8:77:8 | operator= | |
| scopes.cpp:77:8:77:8 | H<short> | Class | scopes.cpp:77:8:77:8 | operator= | |
| scopes.cpp:77:8:77:8 | H<short> | Class | scopes.cpp:79:5:79:5 | t | |
| scopes.cpp:85:12:85:14 | One::Two | Namespace | scopes.cpp:87:8:87:13 | myEnum | |
| scopes.cpp:95:8:95:8 | I | Class | scopes.cpp:95:8:95:8 | operator= | |

View File

@@ -31,11 +31,5 @@
| scopes.cpp:67:3:67:8 | ~Table | | scopes.cpp:62:7:62:11 | Table | 8 |
| scopes.cpp:68:9:68:14 | lookup | | scopes.cpp:62:7:62:11 | Table | 8 |
| scopes.cpp:69:8:69:13 | insert | | scopes.cpp:62:7:62:11 | Table | 8 |
| scopes.cpp:77:8:77:8 | H | Constructor | scopes.cpp:77:8:77:8 | H<long> | 4 |
| scopes.cpp:77:8:77:8 | H | Constructor | scopes.cpp:77:8:77:8 | H<short> | 4 |
| scopes.cpp:77:8:77:8 | operator= | | scopes.cpp:77:8:77:8 | H<long> | 4 |
| scopes.cpp:77:8:77:8 | operator= | | scopes.cpp:77:8:77:8 | H<long> | 4 |
| scopes.cpp:77:8:77:8 | operator= | | scopes.cpp:77:8:77:8 | H<short> | 4 |
| scopes.cpp:77:8:77:8 | operator= | | scopes.cpp:77:8:77:8 | H<short> | 4 |
| scopes.cpp:95:8:95:8 | operator= | | scopes.cpp:95:8:95:8 | I | 3 |
| scopes.cpp:95:8:95:8 | operator= | | scopes.cpp:95:8:95:8 | I | 3 |

View File

@@ -36,11 +36,5 @@
| scopes.cpp:68:9:68:14 | lookup | | 1 | 1 |
| scopes.cpp:69:8:69:13 | insert | | 1 | 1 |
| scopes.cpp:72:16:72:21 | strlen | isTopLevel() | 1 | 1 |
| scopes.cpp:77:8:77:8 | H | | 1 | 0 |
| scopes.cpp:77:8:77:8 | H | | 1 | 0 |
| scopes.cpp:77:8:77:8 | operator= | | 1 | 0 |
| scopes.cpp:77:8:77:8 | operator= | | 1 | 0 |
| scopes.cpp:77:8:77:8 | operator= | | 1 | 0 |
| scopes.cpp:77:8:77:8 | operator= | | 1 | 0 |
| scopes.cpp:95:8:95:8 | operator= | | 1 | 0 |
| scopes.cpp:95:8:95:8 | operator= | | 1 | 0 |

View File

@@ -34,13 +34,6 @@
| copy.cpp:59:9:59:9 | HasArray2D | void private_cc::HasArray2D::HasArray2D(private_cc::HasArray2D&) | deleted | |
| copy.cpp:59:9:59:9 | operator= | private_cc::HasArray2D& private_cc::HasArray2D::operator=(private_cc::HasArray2D const&) | | |
| copy.cpp:59:9:59:9 | operator= | private_cc::HasArray2D& private_cc::HasArray2D::operator=(private_cc::HasArray2D&&) | | |
| copy.cpp:67:9:67:9 | Wrapper | void container::Wrapper<container::Copyable>::Wrapper() | | |
| copy.cpp:67:9:67:9 | Wrapper | void container::Wrapper<container::NotCopyable>::Wrapper() | deleted | |
| copy.cpp:67:9:67:9 | Wrapper | void container::Wrapper<container::NotCopyable>::Wrapper(container::Wrapper<container::NotCopyable> const&) | deleted | |
| copy.cpp:67:9:67:9 | Wrapper | void container::Wrapper<container::NotCopyable>::Wrapper(container::Wrapper<container::NotCopyable>&&) | | |
| copy.cpp:67:9:67:9 | operator= | container::Wrapper<container::Copyable>& container::Wrapper<container::Copyable>::operator=(container::Wrapper<container::Copyable> const&) | | |
| copy.cpp:67:9:67:9 | operator= | container::Wrapper<container::Copyable>& container::Wrapper<container::Copyable>::operator=(container::Wrapper<container::Copyable>&&) | | |
| copy.cpp:67:9:67:9 | operator= | container::Wrapper<container::NotCopyable>& container::Wrapper<container::NotCopyable>::operator=(container::Wrapper<container::NotCopyable> const&) | deleted | |
| copy.cpp:71:9:71:9 | operator= | container::Copyable& container::Copyable::operator=(container::Copyable const&) | | |
| copy.cpp:71:9:71:9 | operator= | container::Copyable& container::Copyable::operator=(container::Copyable&&) | | |
| copy.cpp:72:9:72:9 | NotCopyable | void container::NotCopyable::NotCopyable() | deleted | |
@@ -85,7 +78,6 @@
| copy.cpp:131:9:131:9 | OnlyAssign | void difference::OnlyAssign::OnlyAssign(difference::OnlyAssign const&) | deleted | |
| copy.cpp:131:9:131:9 | operator= | difference::OnlyAssign& difference::OnlyAssign::operator=(difference::OnlyAssign const&) | | |
| copy.cpp:131:9:131:9 | operator= | difference::OnlyAssign& difference::OnlyAssign::operator=(difference::OnlyAssign&&) | | |
| copy.cpp:137:9:137:9 | operator= | instantiated_explicit_ctor::Wrapper<int>& instantiated_explicit_ctor::Wrapper<int>::operator=(instantiated_explicit_ctor::Wrapper<int> const&) | | |
| copy.cpp:139:5:139:11 | Wrapper | void instantiated_explicit_ctor::Wrapper<T>::Wrapper(instantiated_explicit_ctor::Wrapper<T>&) | | |
| copy.cpp:143:5:143:5 | Wrapper | void instantiated_explicit_ctor::Wrapper<int>::Wrapper() | | |
| copy.cpp:143:5:143:11 | Wrapper | void instantiated_explicit_ctor::Wrapper<T>::Wrapper() | | |

View File

@@ -1,7 +1,5 @@
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | __va_list_tag |
| file://:0:0:0:0 | auto |
| file://:0:0:0:0 | fp_offset |
@@ -11,8 +9,6 @@
| file://:0:0:0:0 | overflow_arg_area |
| file://:0:0:0:0 | reg_save_area |
| test.cpp:2:16:2:16 | T |
| test.cpp:3:8:3:8 | operator= |
| test.cpp:3:8:3:8 | operator= |
| test.cpp:3:8:3:10 | Str<T> |
| test.cpp:3:8:3:10 | Str<int> |
| test.cpp:7:16:7:16 | T |

View File

@@ -1,9 +1,5 @@
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | (unnamed parameter 0) |
| file://:0:0:0:0 | C<char>'s friend |
| file://:0:0:0:0 | C<int>'s friend |
| file://:0:0:0:0 | auto |
@@ -24,10 +20,6 @@
| friends.cpp:7:9:7:9 | C<TTT> |
| friends.cpp:7:9:7:9 | C<char> |
| friends.cpp:7:9:7:9 | C<int> |
| friends.cpp:7:9:7:9 | operator= |
| friends.cpp:7:9:7:9 | operator= |
| friends.cpp:7:9:7:9 | operator= |
| friends.cpp:7:9:7:9 | operator= |
| friends.cpp:9:17:9:17 | f |
| friends.cpp:9:17:9:19 | C<TTT>'s friend |
| friends.cpp:9:21:9:26 | (unnamed parameter 0) |

View File

@@ -1,13 +1,5 @@
| h.h:3:7:3:7 | C<T> | h.h:4:10:4:12 | fun | 0 |
| h.h:3:7:3:7 | C<char> | h.h:3:7:3:7 | operator= | 0 |
| h.h:3:7:3:7 | C<char> | h.h:3:7:3:7 | operator= | 0 |
| h.h:3:7:3:7 | C<int> | h.h:3:7:3:7 | operator= | 0 |
| h.h:3:7:3:7 | C<int> | h.h:3:7:3:7 | operator= | 0 |
| h.h:8:7:8:7 | D<T> | h.h:10:10:10:12 | fun | 2 |
| h.h:8:7:8:7 | D<int> | h.h:8:7:8:7 | operator= | 0 |
| h.h:8:7:8:7 | D<int> | h.h:8:7:8:7 | operator= | 0 |
| h.h:8:7:8:7 | D<int> | h.h:10:10:10:10 | fun | 2 |
| h.h:14:7:14:7 | E<T> | h.h:16:10:16:12 | fun | 2 |
| h.h:14:7:14:7 | E<int> | h.h:14:7:14:7 | operator= | 0 |
| h.h:14:7:14:7 | E<int> | h.h:14:7:14:7 | operator= | 0 |
| h.h:14:7:14:7 | E<int> | h.h:16:10:16:10 | fun | 2 |

View File

@@ -45,12 +45,6 @@
| isfromtemplateinstantiation.cpp:38:26:38:26 | definition of a_template_method | isfromtemplateinstantiation.cpp:38:26:38:26 | normal_class::a_template_method<short>() |
| isfromtemplateinstantiation.cpp:39:2:40:2 | { ... } | isfromtemplateinstantiation.cpp:38:26:38:26 | normal_class::a_template_method<short>() |
| isfromtemplateinstantiation.cpp:40:2:40:2 | return ... | isfromtemplateinstantiation.cpp:38:26:38:26 | normal_class::a_template_method<short>() |
| isfromtemplateinstantiation.cpp:44:26:44:26 | declaration of operator= | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:44:26:44:26 | declaration of operator= | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:44:26:44:26 | definition of template_class | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:44:26:44:26 | template_class<char>::operator=(const template_class<char> &) | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:44:26:44:26 | template_class<char>::operator=(template_class<char> &&) | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:44:26:44:26 | template_class<char>::template_class() | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:46:4:46:4 | definition of t | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:46:4:46:4 | t | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:49:7:49:7 | definition of b_method | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
@@ -75,22 +69,6 @@
| isfromtemplateinstantiation.cpp:54:2:55:2 | { ... } | isfromtemplateinstantiation.cpp:53:26:53:26 | template_class<char>::b_template_method<long>(long) |
| isfromtemplateinstantiation.cpp:55:2:55:2 | return ... | isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> |
| isfromtemplateinstantiation.cpp:55:2:55:2 | return ... | isfromtemplateinstantiation.cpp:53:26:53:26 | template_class<char>::b_template_method<long>(long) |
| isfromtemplateinstantiation.cpp:77:26:77:26 | AnotherTemplateClass<int>::operator=(AnotherTemplateClass<int> &&) | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | AnotherTemplateClass<int>::operator=(const AnotherTemplateClass<int> &) | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | AnotherTemplateClass<long *>::operator=(AnotherTemplateClass<long *> &&) | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass<long *> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | AnotherTemplateClass<long *>::operator=(const AnotherTemplateClass<long *> &) | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass<long *> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass<long *> |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass<long *> |
| isfromtemplateinstantiation.cpp:82:9:82:9 | AnotherTemplateClass<int>::MyClassStruct::operator=(MyClassStruct &&) | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:82:9:82:9 | AnotherTemplateClass<int>::MyClassStruct::operator=(MyClassStruct &&) | isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct |
| isfromtemplateinstantiation.cpp:82:9:82:9 | AnotherTemplateClass<int>::MyClassStruct::operator=(const MyClassStruct &) | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:82:9:82:9 | AnotherTemplateClass<int>::MyClassStruct::operator=(const MyClassStruct &) | isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct |
| isfromtemplateinstantiation.cpp:82:9:82:9 | declaration of operator= | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:82:9:82:9 | declaration of operator= | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:82:9:82:9 | declaration of operator= | isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct |
| isfromtemplateinstantiation.cpp:82:9:82:9 | declaration of operator= | isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct |
| isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:84:6:84:10 | definition of value | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:84:6:84:10 | definition of value | isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct |
@@ -126,26 +104,12 @@
| isfromtemplateinstantiation.cpp:99:1:99:1 | return ... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> |
| isfromtemplateinstantiation.cpp:99:1:99:1 | return ... | isfromtemplateinstantiation.cpp:97:52:97:52 | AnotherTemplateClass<int>::myMethod2(MyClassEnum) |
| isfromtemplateinstantiation.cpp:110:3:110:3 | definition of var_template | isfromtemplateinstantiation.cpp:110:3:110:3 | var_template |
| isfromtemplateinstantiation.cpp:134:29:134:29 | Outer<int>::operator=(Outer<int> &&) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
| isfromtemplateinstantiation.cpp:134:29:134:29 | Outer<int>::operator=(const Outer<int> &) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
| isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
| isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<T>::Inner<long>::operator=(Inner<long> &&) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | Outer<T>::Inner<long>::operator=(const Inner<long> &) | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
| isfromtemplateinstantiation.cpp:135:31:135:35 | declaration of Inner<U> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> |
| isfromtemplateinstantiation.cpp:136:7:136:7 | definition of x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:136:7:136:7 | x | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:137:7:137:7 | definition of y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| isfromtemplateinstantiation.cpp:137:7:137:7 | y | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> |
| load.cpp:13:7:13:7 | basic_text_iprimitive<std_istream_mockup>::basic_text_iprimitive(basic_text_iprimitive<std_istream_mockup> &&) | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:13:7:13:7 | basic_text_iprimitive<std_istream_mockup>::basic_text_iprimitive(const basic_text_iprimitive<std_istream_mockup> &) | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:13:7:13:7 | basic_text_iprimitive<std_istream_mockup>::operator=(const basic_text_iprimitive<std_istream_mockup> &) | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:13:7:13:7 | declaration of basic_text_iprimitive | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:13:7:13:7 | declaration of basic_text_iprimitive | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:13:7:13:7 | definition of operator= | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:15:14:15:15 | definition of is | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:15:14:15:15 | is | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |
| load.cpp:22:10:22:13 | basic_text_iprimitive<std_istream_mockup>::load<T>(T &) | load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> |

View File

@@ -1,10 +1,6 @@
isFromUninstantiatedTemplate
| file://:0:0:0:0 | 0 | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
| file://:0:0:0:0 | (int)... | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
| file://:0:0:0:0 | (unnamed parameter 0) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| file://:0:0:0:0 | (unnamed parameter 0) | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| file://:0:0:0:0 | declaration of 1st parameter | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| file://:0:0:0:0 | declaration of 1st parameter | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| file://:0:0:0:0 | initializer for MyClassEnumConst | isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> |
| isfromtemplateinstantiation.cpp:12:24:12:46 | definition of inner_template_function | isfromtemplateinstantiation.cpp:12:24:12:46 | inner_template_function |
| isfromtemplateinstantiation.cpp:12:24:12:46 | inner_template_function | isfromtemplateinstantiation.cpp:12:24:12:46 | inner_template_function |
@@ -141,10 +137,6 @@ isFromUninstantiatedTemplate
| isfromtemplateinstantiation.cpp:129:19:129:19 | 1 | isfromtemplateinstantiation.cpp:129:6:129:6 | f |
| isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:134:29:134:33 | definition of Outer<T> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> |
@@ -358,11 +350,6 @@ isFromUninstantiatedTemplate
| isfromtemplateinstantiation.cpp:39:2:40:2 | { ... } | I | | Stmt | |
| isfromtemplateinstantiation.cpp:40:2:40:2 | return ... | | T | Stmt | |
| isfromtemplateinstantiation.cpp:40:2:40:2 | return ... | I | | Stmt | |
| isfromtemplateinstantiation.cpp:44:26:44:26 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:44:26:44:26 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:44:26:44:26 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:44:26:44:26 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:44:26:44:26 | template_class | I | | Declaration | |
| isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<T> | | T | Declaration | |
| isfromtemplateinstantiation.cpp:44:26:44:39 | template_class<char> | I | | Declaration | |
| isfromtemplateinstantiation.cpp:46:4:46:4 | definition of t | | T | Definition | |
@@ -390,20 +377,8 @@ isFromUninstantiatedTemplate
| isfromtemplateinstantiation.cpp:59:5:59:8 | main | | | Declaration | |
| isfromtemplateinstantiation.cpp:72:30:72:32 | 97 | | | Expr | |
| isfromtemplateinstantiation.cpp:72:30:72:32 | (long)... | | | Expr | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:77:26:77:26 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<T> | | T | Declaration | |
| isfromtemplateinstantiation.cpp:77:26:77:45 | AnotherTemplateClass<int> | I | | Declaration | |
| isfromtemplateinstantiation.cpp:82:9:82:9 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:82:9:82:9 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:82:9:82:9 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:82:9:82:9 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct | | T | Declaration | |
| isfromtemplateinstantiation.cpp:82:9:82:21 | MyClassStruct | I | | Declaration | |
| isfromtemplateinstantiation.cpp:84:6:84:10 | definition of value | | T | Definition | |
@@ -451,16 +426,8 @@ isFromUninstantiatedTemplate
| isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass<T *> | | T | Declaration | |
| isfromtemplateinstantiation.cpp:128:7:128:30 | AnotherTemplateClass<long *> | I | | Declaration | |
| isfromtemplateinstantiation.cpp:129:6:129:6 | f | | T | Declaration | |
| isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:134:29:134:29 | declaration of operator= | I | | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:134:29:134:29 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:134:29:134:29 | operator= | I | | Declaration | |
| isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<T> | | T | Declaration | |
| isfromtemplateinstantiation.cpp:134:29:134:33 | Outer<int> | I | | Declaration | |
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | I | T | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:135:31:135:31 | declaration of operator= | I | T | DeclarationEntry | |
| isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | I | T | Declaration | |
| isfromtemplateinstantiation.cpp:135:31:135:31 | operator= | I | T | Declaration | |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | | T | Declaration | |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<U> | I | T | Declaration | |
| isfromtemplateinstantiation.cpp:135:31:135:35 | Inner<long> | I | T | Declaration | |
@@ -488,11 +455,6 @@ isFromUninstantiatedTemplate
| load.cpp:6:13:6:21 | externInt | | | Expr | Not ref |
| load.cpp:7:16:7:20 | (reference to) | | | Expr | |
| load.cpp:7:16:7:20 | * ... | | | Expr | |
| load.cpp:13:7:13:7 | basic_text_iprimitive | I | | Declaration | |
| load.cpp:13:7:13:7 | basic_text_iprimitive | I | | Declaration | |
| load.cpp:13:7:13:7 | declaration of basic_text_iprimitive | I | | DeclarationEntry | |
| load.cpp:13:7:13:7 | declaration of basic_text_iprimitive | I | | DeclarationEntry | |
| load.cpp:13:7:13:7 | operator= | I | | Declaration | |
| load.cpp:13:7:13:27 | basic_text_iprimitive<IStream> | | T | Declaration | |
| load.cpp:13:7:13:27 | basic_text_iprimitive<std_istream_mockup> | I | | Declaration | |
| load.cpp:15:14:15:15 | definition of is | | T | Definition | |

View File

@@ -4,44 +4,8 @@
| 0 | file://:0:0:0:0 | a[10] | refersTo.cpp:2:7:2:7 | a | direct |
| 0 | file://:0:0:0:0 | const a | refersTo.cpp:2:7:2:7 | a | direct |
| 0 | file://:0:0:0:0 | const a & | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | const container<a> | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | const container<a> | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | const container<a> | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | const container<a> | refersTo.cpp:11:7:11:15 | container<a> | direct |
| 0 | file://:0:0:0:0 | const container<a> & | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | const container<a> & | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | const container<a> & | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | const container<a> & | refersTo.cpp:11:7:11:15 | container<a> | |
| 0 | file://:0:0:0:0 | const container<container<a>> | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | const container<container<a>> | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | const container<container<a>> | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | const container<container<a>> | refersTo.cpp:11:7:11:15 | container<a> | |
| 0 | file://:0:0:0:0 | const container<container<a>> | refersTo.cpp:11:7:11:15 | container<container<a>> | direct |
| 0 | file://:0:0:0:0 | const container<container<a>> & | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | const container<container<a>> & | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | const container<container<a>> & | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | const container<container<a>> & | refersTo.cpp:11:7:11:15 | container<a> | |
| 0 | file://:0:0:0:0 | const container<container<a>> & | refersTo.cpp:11:7:11:15 | container<container<a>> | |
| 0 | file://:0:0:0:0 | const strange | refersTo.cpp:17:7:17:13 | strange | direct |
| 0 | file://:0:0:0:0 | const strange & | refersTo.cpp:17:7:17:13 | strange | |
| 0 | file://:0:0:0:0 | container<a> & | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | container<a> & | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | container<a> & | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | container<a> & | refersTo.cpp:11:7:11:15 | container<a> | direct |
| 0 | file://:0:0:0:0 | container<a> && | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | container<a> && | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | container<a> && | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | container<a> && | refersTo.cpp:11:7:11:15 | container<a> | direct |
| 0 | file://:0:0:0:0 | container<container<a>> & | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | container<container<a>> & | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | container<container<a>> & | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | container<container<a>> & | refersTo.cpp:11:7:11:15 | container<a> | |
| 0 | file://:0:0:0:0 | container<container<a>> & | refersTo.cpp:11:7:11:15 | container<container<a>> | direct |
| 0 | file://:0:0:0:0 | container<container<a>> && | refersTo.cpp:2:7:2:7 | a | |
| 0 | file://:0:0:0:0 | container<container<a>> && | refersTo.cpp:10:16:10:16 | T | |
| 0 | file://:0:0:0:0 | container<container<a>> && | refersTo.cpp:11:7:11:15 | container<T> | |
| 0 | file://:0:0:0:0 | container<container<a>> && | refersTo.cpp:11:7:11:15 | container<a> | |
| 0 | file://:0:0:0:0 | container<container<a>> && | refersTo.cpp:11:7:11:15 | container<container<a>> | direct |
| 0 | file://:0:0:0:0 | strange & | refersTo.cpp:17:7:17:13 | strange | direct |
| 0 | file://:0:0:0:0 | strange && | refersTo.cpp:17:7:17:13 | strange | direct |
| 2 | refersTo.cpp:2:7:2:7 | a | refersTo.cpp:2:7:2:7 | a | |

View File

@@ -468,7 +468,7 @@ test.cpp:
# 56| valnum = r50_1, r55_3, r56_12, r56_19, r56_2, r59_1
# 56| r56_3(char *) = Load[ptr] : &:r56_2, m56_1
# 56| valnum = m56_1, r56_13, r56_20, r56_3, r59_2
# 56| r56_4(char) = Load[?] : &:r56_3, ~m49_4
# 56| r56_4(char) = Load[?] : &:r56_3, ~m49_12
# 56| valnum = r56_14, r56_4, r59_3
# 56| r56_5(int) = Convert : r56_4
# 56| valnum = r56_15, r56_5, r59_4
@@ -491,7 +491,7 @@ test.cpp:
# 56| valnum = r50_1, r55_3, r56_12, r56_19, r56_2, r59_1
# 56| r56_13(char *) = Load[ptr] : &:r56_12, m56_1
# 56| valnum = m56_1, r56_13, r56_20, r56_3, r59_2
# 56| r56_14(char) = Load[?] : &:r56_13, ~m49_4
# 56| r56_14(char) = Load[?] : &:r56_13, ~m49_12
# 56| valnum = r56_14, r56_4, r59_3
# 56| r56_15(int) = Convert : r56_14
# 56| valnum = r56_15, r56_5, r59_4
@@ -521,7 +521,7 @@ test.cpp:
# 59| valnum = r50_1, r55_3, r56_12, r56_19, r56_2, r59_1
# 59| r59_2(char *) = Load[ptr] : &:r59_1, m56_1
# 59| valnum = m56_1, r56_13, r56_20, r56_3, r59_2
# 59| r59_3(char) = Load[?] : &:r59_2, ~m49_4
# 59| r59_3(char) = Load[?] : &:r59_2, ~m49_12
# 59| valnum = r56_14, r56_4, r59_3
# 59| r59_4(int) = Convert : r59_3
# 59| valnum = r56_15, r56_5, r59_4

View File

@@ -1,12 +1,12 @@
| tests.cpp:18:15:18:22 | Hello | This argument should be of type 'char *' but is of type 'char16_t *'. |
| tests.cpp:19:15:19:22 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *'. |
| tests.cpp:21:15:21:21 | Hello | This argument should be of type 'char16_t *' but is of type 'char *'. |
| tests.cpp:21:15:21:21 | Hello | This argument should be of type 'wchar_t *' but is of type 'char *'. |
| tests.cpp:26:17:26:24 | Hello | This argument should be of type 'char *' but is of type 'char16_t *'. |
| tests.cpp:30:17:30:24 | Hello | This argument should be of type 'wchar_t *' but is of type 'char16_t *'. |
| tests.cpp:35:36:35:43 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *'. |
| tests.cpp:39:36:39:43 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *'. |
| tests.cpp:42:37:42:44 | Hello | This argument should be of type 'char *' but is of type 'char16_t *'. |
| tests.cpp:43:37:43:44 | Hello | This argument should be of type 'char *' but is of type 'wchar_t *'. |
| tests.cpp:45:37:45:43 | Hello | This argument should be of type 'char16_t *' but is of type 'char *'. |
| tests.cpp:47:37:47:44 | Hello | This argument should be of type 'char16_t *' but is of type 'wchar_t *'. |
| tests.cpp:18:15:18:22 | Hello | This format specifier for type 'char *' does not match the argument type 'char16_t *'. |
| tests.cpp:19:15:19:22 | Hello | This format specifier for type 'char *' does not match the argument type 'wchar_t *'. |
| tests.cpp:21:15:21:21 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'char *'. |
| tests.cpp:21:15:21:21 | Hello | This format specifier for type 'wchar_t *' does not match the argument type 'char *'. |
| tests.cpp:26:17:26:24 | Hello | This format specifier for type 'char *' does not match the argument type 'char16_t *'. |
| tests.cpp:30:17:30:24 | Hello | This format specifier for type 'wchar_t *' does not match the argument type 'char16_t *'. |
| tests.cpp:35:36:35:43 | Hello | This format specifier for type 'char *' does not match the argument type 'wchar_t *'. |
| tests.cpp:39:36:39:43 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'wchar_t *'. |
| tests.cpp:42:37:42:44 | Hello | This format specifier for type 'char *' does not match the argument type 'char16_t *'. |
| tests.cpp:43:37:43:44 | Hello | This format specifier for type 'char *' does not match the argument type 'wchar_t *'. |
| tests.cpp:45:37:45:43 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'char *'. |
| tests.cpp:47:37:47:44 | Hello | This format specifier for type 'char16_t *' does not match the argument type 'wchar_t *'. |

View File

@@ -1,4 +1,4 @@
| tests_32.cpp:14:16:14:23 | void_ptr | This argument should be of type 'long' but is of type 'void *'. |
| tests_32.cpp:15:15:15:15 | l | This argument should be of type 'void *' but is of type 'long'. |
| tests_64.cpp:14:16:14:23 | void_ptr | This argument should be of type 'long' but is of type 'void *'. |
| tests_64.cpp:15:15:15:15 | l | This argument should be of type 'void *' but is of type 'long'. |
| tests_32.cpp:14:16:14:23 | void_ptr | This format specifier for type 'long' does not match the argument type 'void *'. |
| tests_32.cpp:15:15:15:15 | l | This format specifier for type 'void *' does not match the argument type 'long'. |
| tests_64.cpp:14:16:14:23 | void_ptr | This format specifier for type 'long' does not match the argument type 'void *'. |
| tests_64.cpp:15:15:15:15 | l | This format specifier for type 'void *' does not match the argument type 'long'. |

View File

@@ -1,62 +1,62 @@
| format.h:16:59:16:61 | str | This argument should be of type 'int' but is of type 'char *'. |
| format.h:16:64:16:64 | i | This argument should be of type 'double' but is of type 'int'. |
| format.h:16:67:16:67 | d | This argument should be of type 'char *' but is of type 'double'. |
| linux.cpp:15:24:15:41 | call to get_template_value | This argument should be of type 'int' but is of type 'long'. |
| linux_c.c:11:15:11:18 | str3 | This argument should be of type 'char *' but is of type 'short *'. |
| pri_macros.h:15:35:15:40 | my_u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This argument should be of type 'double' but is of type 'int'. |
| printf1.h:18:18:18:18 | i | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:113:17:113:17 | d | This argument should be of type 'long double' but is of type 'double'. |
| printf1.h:114:18:114:18 | d | This argument should be of type 'long double' but is of type 'double'. |
| printf1.h:147:19:147:19 | i | This argument should be of type 'long long' but is of type 'int'. |
| printf1.h:148:19:148:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int'. |
| printf1.h:160:18:160:18 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:161:21:161:21 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:167:17:167:17 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:168:18:168:18 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:169:19:169:19 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:174:17:174:17 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:175:18:175:18 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:176:19:176:19 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:180:17:180:17 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:181:20:181:20 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:183:18:183:18 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:184:21:184:21 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:186:19:186:19 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:187:22:187:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:189:19:189:19 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:190:22:190:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:192:19:192:19 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:193:22:193:22 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:194:25:194:25 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:198:24:198:24 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:199:21:199:21 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:202:26:202:26 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:203:23:203:23 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:206:25:206:25 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:207:22:207:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:210:26:210:26 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:211:23:211:23 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:214:28:214:28 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:215:28:215:28 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:216:25:216:25 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:221:18:221:18 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:222:20:222:20 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:225:23:225:23 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:228:24:228:24 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:231:25:231:25 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:234:25:234:25 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:235:22:235:22 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:276:32:276:32 | s | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:278:17:278:17 | s | This argument should be of type 'int' but is of type 'char *'. |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This argument should be of type 'short *' but is of type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This argument should be of type 'char' but is of type 'char *'. |
| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. |
| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. |
| linux.cpp:15:24:15:41 | call to get_template_value | This format specifier for type 'int' does not match the argument type 'long'. |
| linux_c.c:11:15:11:18 | str3 | This format specifier for type 'char *' does not match the argument type 'short *'. |
| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:113:17:113:17 | d | This format specifier for type 'long double' does not match the argument type 'double'. |
| printf1.h:114:18:114:18 | d | This format specifier for type 'long double' does not match the argument type 'double'. |
| printf1.h:147:19:147:19 | i | This format specifier for type 'long long' does not match the argument type 'int'. |
| printf1.h:148:19:148:20 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. |
| printf1.h:160:18:160:18 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:161:21:161:21 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:167:17:167:17 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:168:18:168:18 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:169:19:169:19 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:174:17:174:17 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:175:18:175:18 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:176:19:176:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:180:17:180:17 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:181:20:181:20 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:183:18:183:18 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:184:21:184:21 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:186:19:186:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:187:22:187:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:189:19:189:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:190:22:190:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:192:19:192:19 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:193:22:193:22 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:194:25:194:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:198:24:198:24 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:199:21:199:21 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:202:26:202:26 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:203:23:203:23 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:206:25:206:25 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:207:22:207:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:210:26:210:26 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:211:23:211:23 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:214:28:214:28 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:215:28:215:28 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:216:25:216:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:221:18:221:18 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:222:20:222:20 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:225:23:225:23 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:228:24:228:24 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:231:25:231:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:234:25:234:25 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:235:22:235:22 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:276:32:276:32 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:278:17:278:17 | s | This format specifier for type 'int' does not match the argument type 'char *'. |
| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. |

View File

@@ -1,2 +1,2 @@
| printf.cpp:43:29:43:35 | test | This argument should be of type 'char *' but is of type 'char16_t *'. |
| printf.cpp:50:29:50:35 | test | This argument should be of type 'char16_t *' but is of type 'wchar_t *'. |
| printf.cpp:43:29:43:35 | test | This format specifier for type 'char *' does not match the argument type 'char16_t *'. |
| printf.cpp:50:29:50:35 | test | This format specifier for type 'char16_t *' does not match the argument type 'wchar_t *'. |

View File

@@ -1,20 +1,20 @@
| format.h:16:59:16:61 | str | This argument should be of type 'int' but is of type 'char *'. |
| format.h:16:64:16:64 | i | This argument should be of type 'double' but is of type 'int'. |
| format.h:16:67:16:67 | d | This argument should be of type 'char *' but is of type 'double'. |
| pri_macros.h:15:35:15:40 | my_u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This argument should be of type 'double' but is of type 'int'. |
| printf1.h:18:18:18:18 | i | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:168:19:168:19 | i | This argument should be of type 'long long' but is of type 'int'. |
| printf1.h:169:19:169:20 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int'. |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This argument should be of type 'short *' but is of type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This argument should be of type 'char' but is of type 'char *'. |
| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. |
| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. |
| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:130:18:130:18 | 0 | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:168:19:168:19 | i | This format specifier for type 'long long' does not match the argument type 'int'. |
| printf1.h:169:19:169:20 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. |
| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. |

View File

@@ -1,37 +1,37 @@
| format.h:16:59:16:61 | str | This argument should be of type 'int' but is of type 'char *'. |
| format.h:16:64:16:64 | i | This argument should be of type 'double' but is of type 'int'. |
| format.h:16:67:16:67 | d | This argument should be of type 'char *' but is of type 'double'. |
| pri_macros.h:15:35:15:40 | my_u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This argument should be of type 'double' but is of type 'int'. |
| printf1.h:18:18:18:18 | i | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:84:23:84:35 | ... - ... | This argument should be of type 'ssize_t' but is of type 'long long'. |
| printf1.h:116:16:116:24 | myString3 | This argument should be of type '__wchar_t *' but is of type 'int *'. |
| printf1.h:117:16:117:24 | myString4 | This argument should be of type '__wchar_t *' but is of type 'int *'. |
| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:181:21:181:22 | ll | This argument should be of type 'int' but is of type 'long long'. |
| printf1.h:182:21:182:23 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:185:21:185:23 | i64 | This argument should be of type 'int' but is of type 'long long'. |
| printf1.h:186:21:186:23 | u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:188:21:188:21 | i | This argument should be of type 'long long' but is of type 'int'. |
| printf1.h:189:21:189:22 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int'. |
| printf1.h:190:21:190:21 | l | This argument should be of type 'long long' but is of type 'long'. |
| printf1.h:191:21:191:22 | ul | This argument should be of type 'unsigned long long' but is of type 'unsigned long'. |
| printf1.h:194:21:194:23 | i32 | This argument should be of type 'long long' but is of type 'int'. |
| printf1.h:195:21:195:23 | u32 | This argument should be of type 'unsigned long long' but is of type 'unsigned int'. |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This argument should be of type 'short *' but is of type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This argument should be of type 'char' but is of type 'char *'. |
| wide_string.h:29:19:29:22 | c | This argument should be of type 'wchar_t' but is of type '__wchar_t *'. |
| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. |
| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. |
| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:71:19:71:20 | st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:72:19:72:20 | ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:73:19:73:22 | c_st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:74:19:74:22 | C_ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:84:23:84:35 | ... - ... | This format specifier for type 'ssize_t' does not match the argument type 'long long'. |
| printf1.h:116:16:116:24 | myString3 | This format specifier for type '__wchar_t *' does not match the argument type 'int *'. |
| printf1.h:117:16:117:24 | myString4 | This format specifier for type '__wchar_t *' does not match the argument type 'int *'. |
| printf1.h:130:18:130:18 | 0 | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:181:21:181:22 | ll | This format specifier for type 'int' does not match the argument type 'long long'. |
| printf1.h:182:21:182:23 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:185:21:185:23 | i64 | This format specifier for type 'int' does not match the argument type 'long long'. |
| printf1.h:186:21:186:23 | u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:188:21:188:21 | i | This format specifier for type 'long long' does not match the argument type 'int'. |
| printf1.h:189:21:189:22 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. |
| printf1.h:190:21:190:21 | l | This format specifier for type 'long long' does not match the argument type 'long'. |
| printf1.h:191:21:191:22 | ul | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned long'. |
| printf1.h:194:21:194:23 | i32 | This format specifier for type 'long long' does not match the argument type 'int'. |
| printf1.h:195:21:195:23 | u32 | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. |
| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. |
| wide_string.h:29:19:29:22 | c | This format specifier for type 'wchar_t' does not match the argument type '__wchar_t *'. |

View File

@@ -1,35 +1,35 @@
| format.h:16:59:16:61 | str | This argument should be of type 'int' but is of type 'char *'. |
| format.h:16:64:16:64 | i | This argument should be of type 'double' but is of type 'int'. |
| format.h:16:67:16:67 | d | This argument should be of type 'char *' but is of type 'double'. |
| pri_macros.h:15:35:15:40 | my_u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This argument should be of type 'double' but is of type 'int'. |
| printf1.h:18:18:18:18 | i | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:25:22:25:22 | i | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:27:19:27:20 | cs | This argument should be of type 'int' but is of type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This argument should be of type 'char *' but is of type 'int'. |
| printf1.h:44:18:44:20 | ull | This argument should be of type 'int' but is of type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:71:19:71:20 | st | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:72:19:72:20 | ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:73:19:73:22 | c_st | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:74:19:74:22 | C_ST | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This argument should be of type 'ssize_t' but is of type 'unsigned long long'. |
| printf1.h:84:23:84:35 | ... - ... | This argument should be of type 'ssize_t' but is of type 'long long'. |
| printf1.h:130:18:130:18 | 0 | This argument should be of type 'void *' but is of type 'int'. |
| printf1.h:155:21:155:22 | ll | This argument should be of type 'int' but is of type 'long long'. |
| printf1.h:156:21:156:23 | ull | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:159:21:159:23 | i64 | This argument should be of type 'int' but is of type 'long long'. |
| printf1.h:160:21:160:23 | u64 | This argument should be of type 'unsigned int' but is of type 'unsigned long long'. |
| printf1.h:162:21:162:21 | i | This argument should be of type 'long long' but is of type 'int'. |
| printf1.h:163:21:163:22 | ui | This argument should be of type 'unsigned long long' but is of type 'unsigned int'. |
| printf1.h:164:21:164:21 | l | This argument should be of type 'long long' but is of type 'long'. |
| printf1.h:165:21:165:22 | ul | This argument should be of type 'unsigned long long' but is of type 'unsigned long'. |
| printf1.h:168:21:168:23 | i32 | This argument should be of type 'long long' but is of type 'int'. |
| printf1.h:169:21:169:23 | u32 | This argument should be of type 'unsigned long long' but is of type 'unsigned int'. |
| real_world.h:61:21:61:22 | & ... | This argument should be of type 'int *' but is of type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This argument should be of type 'short *' but is of type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This argument should be of type 'short *' but is of type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This argument should be of type 'short *' but is of type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This argument should be of type 'char' but is of type 'char *'. |
| wide_string.h:29:19:29:22 | c | This argument should be of type 'wchar_t' but is of type 'unsigned short *'. |
| format.h:16:59:16:61 | str | This format specifier for type 'int' does not match the argument type 'char *'. |
| format.h:16:64:16:64 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| format.h:16:67:16:67 | d | This format specifier for type 'char *' does not match the argument type 'double'. |
| pri_macros.h:15:35:15:40 | my_u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:12:27:12:27 | i | This format specifier for type 'double' does not match the argument type 'int'. |
| printf1.h:18:18:18:18 | i | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:25:22:25:22 | i | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:27:19:27:20 | cs | This format specifier for type 'int' does not match the argument type 'char *'. |
| printf1.h:38:18:38:30 | MYONETHOUSAND | This format specifier for type 'char *' does not match the argument type 'int'. |
| printf1.h:44:18:44:20 | ull | This format specifier for type 'int' does not match the argument type 'unsigned long long'. |
| printf1.h:45:18:45:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:46:18:46:20 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:71:19:71:20 | st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:72:19:72:20 | ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:73:19:73:22 | c_st | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:74:19:74:22 | C_ST | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:75:19:75:28 | sizeof(<expr>) | This format specifier for type 'ssize_t' does not match the argument type 'unsigned long long'. |
| printf1.h:84:23:84:35 | ... - ... | This format specifier for type 'ssize_t' does not match the argument type 'long long'. |
| printf1.h:130:18:130:18 | 0 | This format specifier for type 'void *' does not match the argument type 'int'. |
| printf1.h:155:21:155:22 | ll | This format specifier for type 'int' does not match the argument type 'long long'. |
| printf1.h:156:21:156:23 | ull | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:159:21:159:23 | i64 | This format specifier for type 'int' does not match the argument type 'long long'. |
| printf1.h:160:21:160:23 | u64 | This format specifier for type 'unsigned int' does not match the argument type 'unsigned long long'. |
| printf1.h:162:21:162:21 | i | This format specifier for type 'long long' does not match the argument type 'int'. |
| printf1.h:163:21:163:22 | ui | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. |
| printf1.h:164:21:164:21 | l | This format specifier for type 'long long' does not match the argument type 'long'. |
| printf1.h:165:21:165:22 | ul | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned long'. |
| printf1.h:168:21:168:23 | i32 | This format specifier for type 'long long' does not match the argument type 'int'. |
| printf1.h:169:21:169:23 | u32 | This format specifier for type 'unsigned long long' does not match the argument type 'unsigned int'. |
| real_world.h:61:21:61:22 | & ... | This format specifier for type 'int *' does not match the argument type 'short *'. |
| real_world.h:62:22:62:23 | & ... | This format specifier for type 'short *' does not match the argument type 'int *'. |
| real_world.h:63:22:63:24 | & ... | This format specifier for type 'short *' does not match the argument type 'unsigned int *'. |
| real_world.h:64:22:64:24 | & ... | This format specifier for type 'short *' does not match the argument type 'signed int *'. |
| wide_string.h:25:18:25:20 | c | This format specifier for type 'char' does not match the argument type 'char *'. |
| wide_string.h:29:19:29:22 | c | This format specifier for type 'wchar_t' does not match the argument type 'unsigned short *'. |

View File

@@ -13,3 +13,5 @@
| test.cpp:266:10:266:24 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:276:11:276:19 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:288:10:288:18 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:312:9:312:25 | ... > ... | Unsigned subtraction can never be negative. |
| test.cpp:362:8:362:16 | ... > ... | Unsigned subtraction can never be negative. |

View File

@@ -43,7 +43,7 @@ void test(unsigned x, unsigned y, bool unknown) {
while(cond()) {
if(unknown) { y--; }
}
if(x - y > 0) { } // GOOD
x = y;
@@ -298,3 +298,80 @@ int test18() {
return (a - b > 0); // GOOD (as b = 0)
}
typedef unsigned int uint32_t;
typedef long long int64_t;
uint32_t get_limit();
uint32_t get_data();
void test19() {
// from the doc:
uint32_t limit = get_limit();
uint32_t total = 0;
while (limit - total > 0) { // BAD: if `total` is greater than `limit` this will underflow and continue executing the loop.
total += get_data();
}
while (total < limit) { // GOOD: never underflows here because there is no arithmetic.
total += get_data();
}
while ((int64_t)limit - total > 0) { // GOOD: never underflows here because the result always fits in an `int64_t`.
total += get_data();
}
}
void test20(int a, bool b, unsigned long c)
{
int x = 0;
if(b) {
x = (a - c) / 2;
} else {
x = a - c;
}
if (a - c - x > 0) // GOOD
{
}
}
uint32_t get_uint32();
int64_t get_int64();
void test21(unsigned long a)
{
{
int b = a & get_int64();
if (a - b > 0) { } // GOOD
}
{
int b = a - get_uint32();
if(a - b > 0) { } // GOOD
}
{
int64_t c = get_int64();
if(c <= 0) {
int64_t b = (int64_t)a + c;
if(a - b > 0) { } // GOOD
}
int64_t b = (int64_t)a + c;
if(a - b > 0) { } // BAD
}
{
unsigned c = get_uint32();
if(c >= 1) {
int b = a / c;
if(a - b > 0) { } // GOOD
}
}
{
int b = a >> get_uint32();
if(a - b > 0) { } // GOOD
}
}

View File

@@ -13,7 +13,6 @@ nodes
| test.cpp:458:6:458:6 | definition of x | semmle.label | definition of x |
| test.cpp:464:6:464:6 | definition of x | semmle.label | definition of x |
| test.cpp:471:6:471:6 | definition of x | semmle.label | definition of x |
| test.cpp:557:15:557:15 | definition of r | semmle.label | definition of r |
#select
| test.cpp:12:6:12:8 | foo | test.cpp:11:6:11:8 | definition of foo | test.cpp:11:6:11:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:11:6:11:8 | foo | foo |
| test.cpp:113:6:113:8 | foo | test.cpp:111:6:111:8 | definition of foo | test.cpp:111:6:111:8 | definition of foo | The variable $@ may not be initialized at this access. | test.cpp:111:6:111:8 | foo | foo |
@@ -28,4 +27,3 @@ nodes
| test.cpp:460:7:460:7 | x | test.cpp:458:6:458:6 | definition of x | test.cpp:458:6:458:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:458:6:458:6 | x | x |
| test.cpp:467:2:467:2 | x | test.cpp:464:6:464:6 | definition of x | test.cpp:464:6:464:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:464:6:464:6 | x | x |
| test.cpp:474:7:474:7 | x | test.cpp:471:6:471:6 | definition of x | test.cpp:471:6:471:6 | definition of x | The variable $@ may not be initialized at this access. | test.cpp:471:6:471:6 | x | x |
| test.cpp:567:7:567:7 | r | test.cpp:557:15:557:15 | definition of r | test.cpp:557:15:557:15 | definition of r | The variable $@ may not be initialized at this access. | test.cpp:557:15:557:15 | r | r |

View File

@@ -564,5 +564,5 @@ void test45() {
}
*rP = NULL;
use(r); // GOOD [FALSE POSITIVE]
use(r); // GOOD
}

View File

@@ -16,3 +16,4 @@
| test.cpp:151:9:151:24 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:152:15:152:18 | { ... } | This catch block |
| test.cpp:199:15:199:35 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:201:16:201:19 | { ... } | This catch block |
| test.cpp:212:14:212:34 | new | This allocation cannot throw. $@ is unnecessary. | test.cpp:213:34:213:36 | { ... } | This catch block |
| test.cpp:246:17:246:31 | new[] | This allocation cannot return null. $@ is unnecessary. | test.cpp:247:8:247:12 | ! ... | This check |

View File

@@ -233,3 +233,54 @@ void test_operator_new_without_exception_spec() {
int* p = new(42, std::nothrow) int; // GOOD
if(p == nullptr) {}
}
namespace std {
void *memset(void *s, int c, size_t n);
}
// from the qhelp:
namespace qhelp {
// BAD: the allocation will throw an unhandled exception
// instead of returning a null pointer.
void bad1(std::size_t length) noexcept {
int* dest = new int[length];
if(!dest) {
return;
}
std::memset(dest, 0, length);
// ...
}
// BAD: the allocation won't throw an exception, but
// instead return a null pointer. [NOT DETECTED]
void bad2(std::size_t length) noexcept {
try {
int* dest = new(std::nothrow) int[length];
std::memset(dest, 0, length);
// ...
} catch(std::bad_alloc&) {
// ...
}
}
// GOOD: the allocation failure is handled appropriately.
void good1(std::size_t length) noexcept {
try {
int* dest = new int[length];
std::memset(dest, 0, length);
// ...
} catch(std::bad_alloc&) {
// ...
}
}
// GOOD: the allocation failure is handled appropriately.
void good2(std::size_t length) noexcept {
int* dest = new(std::nothrow) int[length];
if(!dest) {
return;
}
std::memset(dest, 0, length);
// ...
}
}

View File

@@ -16,10 +16,6 @@
| | forstmt02.cpp:3:6:3:14 | for_loop2 | 0 | 8 | file://:0:0:0:0 | file://:0:0:0:0 | file://:0:0:0:0 | initializer for (__range) | 4: declaration |
| | forstmt02.cpp:3:6:3:14 | for_loop2 | 0 | 12 | file://:0:0:0:0 | file://:0:0:0:0 | file://:0:0:0:0 | initializer for (__begin) | 6: (__range) |
| | forstmt02.cpp:3:6:3:14 | for_loop2 | 0 | 15 | file://:0:0:0:0 | file://:0:0:0:0 | file://:0:0:0:0 | initializer for (__end) | 6: (__end) |
| forstmt | forstmt.h:2:8:2:8 | operator= | 2 | 1 | forstmt.h:2:8:2:8 | forstmt.h:2:8:2:8 | forstmt.h:2:8:2:8 | operator= | <none> |
| forstmt | forstmt.h:2:8:2:8 | operator= | 2 | 1 | forstmt.h:2:8:2:8 | forstmt.h:2:8:2:8 | forstmt.h:2:8:2:8 | operator= | <none> |
| forstmt | forstmt.h:3:12:3:12 | operator= | 3 | 1 | forstmt.h:3:12:3:12 | forstmt.h:3:12:3:12 | forstmt.h:3:12:3:12 | operator= | <none> |
| forstmt | forstmt.h:3:12:3:12 | operator= | 3 | 1 | forstmt.h:3:12:3:12 | forstmt.h:3:12:3:12 | forstmt.h:3:12:3:12 | operator= | <none> |
| forstmt | forstmt.h:4:19:4:28 | operator++ | 4 | 1 | forstmt.h:4:19:4:28 | forstmt.h:4:19:4:28 | forstmt.h:4:19:4:28 | operator++ | <none> |
| forstmt | forstmt.h:4:19:4:28 | operator++ | 4 | 1 | forstmt.h:4:19:4:28 | forstmt.h:4:19:4:28 | forstmt.h:4:19:4:28 | operator++ | <none> |
| forstmt | forstmt.h:5:12:5:20 | operator* | 5 | 1 | forstmt.h:5:12:5:20 | forstmt.h:5:12:5:20 | forstmt.h:5:12:5:20 | operator* | <none> |

Some files were not shown because too many files have changed in this diff Show More