Merge pull request #597 from dave-bartolomeo/dave/IRDataflow

C++: Initial IR-based dataflow implementation
This commit is contained in:
Aditya Sharad
2018-12-11 15:05:58 +00:00
committed by GitHub
38 changed files with 8201 additions and 446 deletions

View File

@@ -1,55 +1,76 @@
{
"C++ IR Instruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll"
],
"C++ IR IRBlock": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRBlock.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll"
],
"C++ IR IRVariable": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll"
],
"C++ IR FunctionIR": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/FunctionIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/FunctionIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/FunctionIR.qll"
],
"C++ IR Operand": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll"
],
"C++ IR IRImpl": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll"
],
"C++ IR IRSanityImpl": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll"
],
"C++ IR PrintIRImpl": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll"
],
"C++ SSA AliasAnalysis": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
],
"C++ SSA SSAConstruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
],
"C++ IR ValueNumber": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll"
]
"DataFlow Java/C++": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl2.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl3.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl4.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImpl5.qll",
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplDepr.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll"
],
"DataFlow Java/C++ Common": [
"java/ql/src/semmle/code/java/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/src/semmle/code/cpp/dataflow/internal/DataFlowImplCommon.qll",
"cpp/ql/src/semmle/code/cpp/ir/dataflow/internal/DataFlowImplCommon.qll"
],
"C++ IR Instruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Instruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Instruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Instruction.qll"
],
"C++ IR IRBlock": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRBlock.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRBlock.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRBlock.qll"
],
"C++ IR IRVariable": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRVariable.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRVariable.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRVariable.qll"
],
"C++ IR FunctionIR": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/FunctionIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/FunctionIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/FunctionIR.qll"
],
"C++ IR Operand": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/Operand.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/Operand.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/Operand.qll"
],
"C++ IR IRImpl": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IR.qll"
],
"C++ IR IRSanityImpl": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/IRSanity.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/IRSanity.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/IRSanity.qll"
],
"C++ IR PrintIRImpl": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/PrintIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/PrintIR.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/PrintIR.qll"
],
"C++ SSA AliasAnalysis": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/AliasAnalysis.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/AliasAnalysis.qll"
],
"C++ SSA SSAConstruction": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/internal/SSAConstruction.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/internal/SSAConstruction.qll"
],
"C++ IR ValueNumber": [
"cpp/ql/src/semmle/code/cpp/ir/implementation/raw/gvn/ValueNumbering.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/unaliased_ssa/gvn/ValueNumbering.qll",
"cpp/ql/src/semmle/code/cpp/ir/implementation/aliased_ssa/gvn/ValueNumbering.qll"
]
}

View File

@@ -14,6 +14,10 @@ import semmle.code.cpp.dataflow.DataFlow2
import semmle.code.cpp.dataflow.DataFlow3
import semmle.code.cpp.dataflow.DataFlow4
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.ir.dataflow.DataFlow
import semmle.code.cpp.ir.dataflow.DataFlow2
import semmle.code.cpp.ir.dataflow.DataFlow3
import semmle.code.cpp.ir.dataflow.DataFlow4
import semmle.code.cpp.valuenumbering.HashCons
from File f, string tag

View File

@@ -0,0 +1,23 @@
/**
* Provides a library for local (intra-procedural) and global (inter-procedural)
* data flow analysis: deciding whether data can flow from a _source_ to a
* _sink_. This library differs from the one in `semmle.code.cpp.dataflow` in that
* this library uses the IR (Intermediate Representation) library, which provides
* a more precise semantic representation of the program, whereas the other dataflow
* library uses the more syntax-oriented ASTs. This library should provide more accurate
* results than the AST-based library in most scenarios.
*
* Unless configured otherwise, _flow_ means that the exact value of
* the source may reach the sink. We do not track flow across pointer
* dereferences or array indexing.
*
* To use global (interprocedural) data flow, extend the class
* `DataFlow::Configuration` as documented on that class. To use local
* (intraprocedural) data flow, invoke `DataFlow::localFlow` or
* `DataFlow::LocalFlowStep` with arguments of type `DataFlow::Node`.
*/
import cpp
module DataFlow {
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl
}

View File

@@ -0,0 +1,38 @@
/**
* Provides a `DataFlow2` module, which is a copy of the `DataFlow` module. Use
* this class when data-flow configurations must depend on each other. Two
* classes extending `DataFlow::Configuration` should never depend on each
* other, but one of them should instead depend on a
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
* `DataFlow4::Configuration`.
*
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
*/
import cpp
module DataFlow2 {
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl2
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
private abstract
class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0
or
strictcount(Node n | this.isSink(n)) < 0
or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0
or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* Provides a `DataFlow3` module, which is a copy of the `DataFlow` module. Use
* this class when data-flow configurations must depend on each other. Two
* classes extending `DataFlow::Configuration` should never depend on each
* other, but one of them should instead depend on a
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
* `DataFlow4::Configuration`.
*
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
*/
import cpp
module DataFlow3 {
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl3
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
private abstract
class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0
or
strictcount(Node n | this.isSink(n)) < 0
or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0
or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,38 @@
/**
* Provides a `DataFlow4` module, which is a copy of the `DataFlow` module. Use
* this class when data-flow configurations must depend on each other. Two
* classes extending `DataFlow::Configuration` should never depend on each
* other, but one of them should instead depend on a
* `DataFlow2::Configuration`, a `DataFlow3::Configuration`, or a
* `DataFlow4::Configuration`.
*
* See `semmle.code.cpp.dataflow.DataFlow` for the full documentation.
*/
import cpp
module DataFlow4 {
import semmle.code.cpp.ir.dataflow.internal.DataFlowImpl4
/**
* This class exists to prevent mutual recursion between the user-overridden
* member predicates of `Configuration` and the rest of the data-flow library.
* Good performance cannot be guaranteed in the presence of such recursion, so
* it should be replaced by using more than one copy of the data flow library.
* Four copies are available: `DataFlow` through `DataFlow4`.
*/
private abstract
class ConfigurationRecursionPrevention extends Configuration {
bindingset[this]
ConfigurationRecursionPrevention() { any() }
override predicate hasFlow(Node source, Node sink) {
strictcount(Node n | this.isSource(n)) < 0
or
strictcount(Node n | this.isSink(n)) < 0
or
strictcount(Node n1, Node n2 | this.isAdditionalFlowStep(n1, n2)) < 0
or
super.hasFlow(source, sink)
}
}
}

View File

@@ -0,0 +1,73 @@
private import cpp
private import DataFlowPrivate
Function viableImpl(MethodAccess ma) {
result = ma.getTarget()
}
Function viableCallable(Call call) {
result = call.getTarget()
}
/**
* Holds if the call context `ctx` reduces the set of viable dispatch
* targets of `ma` in `c`.
*/
predicate reducedViableImplInCallContext(MethodAccess ma, Callable c, Call ctx) {
none()
}
/**
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s for which a context might make a difference.
*/
private Method viableImplInCallContext(MethodAccess ma, Call ctx) {
// stub implementation
result = viableImpl(ma) and
viableCallable(ctx) = ma.getEnclosingFunction()
}
/**
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s for which the context makes a difference.
*/
Method prunedViableImplInCallContext(MethodAccess ma, Call ctx) {
result = viableImplInCallContext(ma, ctx) and
reducedViableImplInCallContext(ma, _, ctx)
}
/**
* Holds if data might flow from `ma` to a return statement in some
* configuration.
*/
private predicate maybeChainedReturn(MethodAccess ma) {
exists(ReturnStmt ret |
exists(ret.getExpr()) and
ret.getEnclosingFunction() = ma.getEnclosingFunction() and
not ma.getParent() instanceof ExprStmt
)
}
/**
* Holds if flow returning from `m` to `ma` might return further and if
* this path restricts the set of call sites that can be returned to.
*/
predicate reducedViableImplInReturn(Method m, MethodAccess ma) {
exists(int tgts, int ctxtgts |
m = viableImpl(ma) and
ctxtgts = count(Call ctx | m = viableImplInCallContext(ma, ctx)) and
tgts = strictcount(Call ctx | viableCallable(ctx) = ma.getEnclosingFunction()) and
ctxtgts < tgts
) and
maybeChainedReturn(ma)
}
/**
* Gets a viable dispatch target of `ma` in the context `ctx`. This is
* restricted to those `ma`s and results for which the return flow from the
* result to `ma` restricts the possible context `ctx`.
*/
Method prunedViableImplInCallContextReverse(MethodAccess ma, Call ctx) {
result = viableImplInCallContext(ma, ctx) and
reducedViableImplInReturn(result, ma)
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,284 @@
import DataFlowUtil
private import DataFlowPrivate
private import DataFlowDispatch
cached
private module ImplCommon {
/**
* Holds if `p` is the `i`th parameter of a viable dispatch target of `call`.
* The instance parameter is considered to have index `-1`.
*/
pragma[nomagic]
private predicate viableParam(Call call, int i, ParameterNode p) {
exists(Callable callable |
callable = viableCallable(call) and
p.isParameterOf(callable, i)
)
}
/**
* Holds if `arg` is a possible argument to `p` taking virtual dispatch into account.
*/
cached
predicate viableParamArg(ParameterNode p, ArgumentNode arg) {
exists(int i, Call call |
viableParam(call, i, p) and
arg.argumentOf(call, i)
)
}
/**
* Holds if `p` can flow to `node` in the same callable using only
* value-preserving steps.
*/
private predicate parameterValueFlow(ParameterNode p, Node node) {
p = node
or
exists(Node mid |
parameterValueFlow(p, mid) and
localFlowStep(mid, node) and
compatibleTypes(p.getType(), node.getType())
)
or
// flow through a callable
exists(Node arg |
parameterValueFlow(p, arg) and
argumentValueFlowsThrough(arg, node) and
compatibleTypes(p.getType(), node.getType())
)
}
/**
* Holds if `p` can flow to a `ReturnNode` in the same callable using only
* value-preserving steps.
*/
cached
predicate parameterValueFlowsThrough(ParameterNode p) {
exists(ReturnNode ret | parameterValueFlow(p, ret))
}
/**
* Holds if `arg` flows through `call` using only value-preserving steps.
*/
cached
predicate argumentValueFlowsThrough(ArgumentNode arg, ExprNode call) {
exists(ParameterNode param |
viableParamArg(param, arg) and
parameterValueFlowsThrough(param) and
arg.argumentOf(call.getExpr(), _) and
compatibleTypes(arg.getType(), call.getType())
)
}
/**
* Holds if `p` can flow to the pre-update node of `n` in the same callable
* using only value-preserving steps.
*/
cached
predicate parameterValueFlowsToUpdate(ParameterNode p, PostUpdateNode n) {
parameterValueFlow(p, n.getPreUpdateNode())
}
/**
* Holds if data can flow from `node1` to `node2` in one local step or a step
* through a value-preserving method.
*/
private predicate localValueStep(Node node1, Node node2) {
localFlowStep(node1, node2) or
argumentValueFlowsThrough(node1, node2)
}
/*
* Calculation of `predicate store(Node node1, Content f, Node node2)`:
* There are three cases:
* - The base case: A direct local assignment given by `storeStep`.
* - A call to a method or constructor with two arguments, `arg1` and `arg2`,
* such the call has the side-effect `arg2.f = arg1`.
* - A call to a method that returns an object in which an argument has been
* stored.
* `storeViaSideEffect` covers the first two cases, and `storeReturn` covers
* the third case.
*/
/**
* Holds if data can flow from `node1` to `node2` via a direct assignment to
* `f` or via a call that acts as a setter.
*/
cached
predicate store(Node node1, Content f, Node node2) {
storeViaSideEffect(node1, f, node2) or
storeReturn(node1, f, node2)
}
private predicate storeViaSideEffect(Node node1, Content f, PostUpdateNode node2) {
storeStep(node1, f, node2) and readStep(_, f, _)
or
exists(Call call, int i1, int i2 |
setterCall(call, i1, i2, f) and
node1.(ArgumentNode).argumentOf(call, i1) and
node2.getPreUpdateNode().(ArgumentNode).argumentOf(call, i2) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
)
}
pragma[nomagic]
private predicate setterInParam(ParameterNode p1, Content f, ParameterNode p2) {
exists(Node n1, PostUpdateNode n2 |
parameterValueFlow(p1, n1) and
storeViaSideEffect(n1, f, n2) and
parameterValueFlow(p2, n2.getPreUpdateNode()) and
p1 != p2
)
}
pragma[nomagic]
private predicate setterCall(Call call, int i1, int i2, Content f) {
exists(Callable callable, ParameterNode p1, ParameterNode p2 |
setterInParam(p1, f, p2) and
callable = viableCallable(call) and
p1.isParameterOf(callable, i1) and
p2.isParameterOf(callable, i2)
)
}
private predicate storeReturn(Node node1, Content f, Node node2) {
exists(ParameterNode p, ArgumentNode arg |
arg = node1 and
viableParamArg(p, arg) and
setterReturn(p, f) and
arg.argumentOf(node2.asExpr(), _) and
compatibleTypes(node1.getTypeBound(), f.getType()) and
compatibleTypes(node2.getTypeBound(), f.getContainerType())
)
}
private predicate setterReturn(ParameterNode p, Content f) {
exists(Node n1, Node n2, ReturnNode ret |
parameterValueFlow(p, n1) and
store(n1, f, n2) and
localValueStep*(n2, ret)
)
}
/**
* Holds if data can flow from `node1` to `node2` via a direct read of `f` or
* via a getter.
*/
cached
predicate read(Node node1, Content f, Node node2) {
readStep(node1, f, node2) and storeStep(_, f, _)
or
exists(ParameterNode p, ArgumentNode arg |
arg = node1 and
viableParamArg(p, arg) and
getter(p, f) and
arg.argumentOf(node2.asExpr(), _) and
compatibleTypes(node1.getTypeBound(), f.getContainerType()) and
compatibleTypes(node2.getTypeBound(), f.getType())
)
}
private predicate getter(ParameterNode p, Content f) {
exists(Node n1, Node n2, ReturnNode ret |
parameterValueFlow(p, n1) and
read(n1, f, n2) and
localValueStep*(n2, ret)
)
}
cached
predicate localStoreReadStep(Node node1, Node node2) {
exists(Node mid1, Node mid2, Content f |
store(node1, f, mid1) and
localValueStep*(mid1, mid2) and
read(mid2, f, node2)
)
}
/**
* Holds if `call` passes an implicit or explicit instance argument, i.e., an
* expression that reaches a `this` parameter.
*/
private predicate callHasInstanceArgument(Call call) {
exists(ArgumentNode arg | arg.argumentOf(call, -1))
}
cached
newtype TCallContext =
TAnyCallContext() or
TSpecificCall(Call call, int i, boolean emptyAp) {
reducedViableImplInCallContext(_, _, call) and
(emptyAp = true or emptyAp = false) and
(
exists(call.getArgument(i))
or
i = -1 and callHasInstanceArgument(call)
)
} or
TSomeCall(ParameterNode p, boolean emptyAp) { emptyAp = true or emptyAp = false } or
TReturn(Method m, MethodAccess ma) { reducedViableImplInReturn(m, ma) }
}
import ImplCommon
/**
* A call context to restrict the targets of virtual dispatch and match the
* call sites of flow into a method with flow out of a method.
*
* There are four cases:
* - `TAnyCallContext()` : No restrictions on method flow.
* - `TSpecificCall(Call call, int i)` : Flow entered through the `i`th
* parameter at the given `call`. This call improves the set of viable
* dispatch targets for at least one method call in the current callable.
* - `TSomeCall(ParameterNode p)` : Flow entered through parameter `p`. The
* originating call does not improve the set of dispatch targets for any
* method call in the current callable and was therefore not recorded.
* - `TReturn(Method m, MethodAccess ma)` : Flow reached `ma` from `m` and
* this dispatch target of `ma` implies a reduced set of dispatch origins
* to which data may flow if it should reach a `return` statement.
*/
abstract class CallContext extends TCallContext { abstract string toString(); }
class CallContextAny extends CallContext, TAnyCallContext {
override string toString() { result = "CcAny" }
}
abstract class CallContextCall extends CallContext { }
class CallContextSpecificCall extends CallContextCall, TSpecificCall {
override string toString() { result = "CcCall" }
}
class CallContextSomeCall extends CallContextCall, TSomeCall {
override string toString() { result = "CcSomeCall" }
}
class CallContextReturn extends CallContext, TReturn {
override string toString() { result = "CcReturn" }
}
bindingset[cc, callable]
predicate resolveReturn(CallContext cc, Callable callable, Call call) {
cc instanceof CallContextAny and callable = viableCallable(call)
or
exists(Method m0, MethodAccess ma0 |
ma0.getEnclosingCallable() = callable and
cc = TReturn(m0, ma0) and
m0 = prunedViableImplInCallContextReverse(ma0, call)
)
}
bindingset[call, cc]
Callable resolveCall(Call call, CallContext cc) {
exists(Call ctx | cc = TSpecificCall(ctx, _, _) |
if reducedViableImplInCallContext(call, _, ctx)
then result = prunedViableImplInCallContext(call, ctx)
else result = viableCallable(call)
)
or
result = viableCallable(call) and cc instanceof CallContextSomeCall
or
result = viableCallable(call) and cc instanceof CallContextAny
or
result = viableCallable(call) and cc instanceof CallContextReturn
}

View File

@@ -0,0 +1,187 @@
private import cpp
private import DataFlowUtil
/**
* A data flow node that occurs as the argument of a call and is passed as-is
* to the callable. Instance arguments (`this` pointer) are also included.
*/
class ArgumentNode extends Node {
ArgumentNode() {
exists(CallInstruction call |
this = call.getAnArgument()
)
}
/**
* Holds if this argument occurs at the given position in the given call.
* The instance argument is considered to have index `-1`.
*/
predicate argumentOf(Call call, int pos) {
exists (CallInstruction callInstr |
callInstr.getAST() = call and
(
this = callInstr.getPositionalArgument(pos) or
this = callInstr.getThisArgument() and pos = -1
)
)
}
}
/** A data flow node that occurs as the result of a `ReturnStmt`. */
class ReturnNode extends Node {
ReturnNode() {
exists(ReturnValueInstruction ret | this = ret.getReturnValue() )
}
}
/**
* Holds if data can flow from `node1` to `node2` in a way that loses the
* calling context. For example, this would happen with flow through a
* global or static variable.
*/
predicate jumpStep(Node n1, Node n2) {
none()
}
/**
* Holds if `call` does not pass an implicit or explicit qualifier, i.e., a
* `this` parameter.
*/
predicate callHasQualifier(Call call) {
call.hasQualifier()
or
call.getTarget() instanceof Destructor
}
private newtype TContent = TFieldContent(Field f) or TCollectionContent() or TArrayContent()
/**
* A reference contained in an object. Examples include instance fields, the
* contents of a collection object, or the contents of an array.
*/
class Content extends TContent {
/** Gets a textual representation of this element. */
abstract string toString();
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
}
/** Gets the type of the object containing this content. */
abstract RefType getContainerType();
/** Gets the type of this content. */
abstract Type getType();
}
private class FieldContent extends Content, TFieldContent {
Field f;
FieldContent() { this = TFieldContent(f) }
Field getField() { result = f }
override string toString() { result = f.toString() }
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
f.getLocation().hasLocationInfo(path, sl, sc, el, ec)
}
override RefType getContainerType() { result = f.getDeclaringType() }
override Type getType() { result = f.getType() }
}
private class CollectionContent extends Content, TCollectionContent {
override string toString() { result = "collection" }
override RefType getContainerType() { none() }
override Type getType() { none() }
}
private class ArrayContent extends Content, TArrayContent {
override string toString() { result = "array" }
override RefType getContainerType() { none() }
override Type getType() { none() }
}
/**
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
* Thus, `node2` references an object with a field `f` that contains the
* value of `node1`.
*/
predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
none() // stub implementation
}
/**
* Holds if data can flow from `node1` to `node2` via a read of `f`.
* Thus, `node1` references an object with a field `f` whose value ends up in
* `node2`.
*/
predicate readStep(Node node1, Content f, Node node2) {
none() // stub implementation
}
/**
* Gets a representative (boxed) type for `t` for the purpose of pruning
* possible flow. A single type is used for all numeric types to account for
* numeric conversions, and otherwise the erasure is used.
*/
RefType getErasedRepr(Type t) {
suppressUnusedType(t) and
result instanceof VoidType // stub implementation
}
/** Gets a string representation of a type returned by `getErasedRepr`. */
string ppReprType(Type t) {
result = t.toString()
}
/**
* Holds if `t1` and `t2` are compatible, that is, whether data can flow from
* a node of type `t1` to a node of type `t2`.
*/
pragma[inline]
predicate compatibleTypes(Type t1, Type t2) {
any() // stub implementation
}
private predicate suppressUnusedType(Type t) { any() }
//////////////////////////////////////////////////////////////////////////////
// Java QL library compatibility wrappers
//////////////////////////////////////////////////////////////////////////////
class RefType extends Type {
}
class CastExpr extends Expr {
CastExpr() { none() } // stub implementation
}
/** An argument to a call. */
class Argument extends Expr {
Call call;
int pos;
Argument() {
call.getArgument(pos) = this
}
/** Gets the call that has this argument. */
Call getCall() { result = call }
/** Gets the position of this argument. */
int getPosition() {
result = pos
}
}
class Callable extends Function { }
/**
* An alias for `Function` in the C++ library. In the Java library, a `Method`
* is any callable except a constructor.
*/
class Method extends Function { }
/**
* An alias for `FunctionCall` in the C++ library. In the Java library, a
* `MethodAccess` is any `Call` that does not call a constructor.
*/
class MethodAccess extends FunctionCall {
/**
* INTERNAL: Do not use. Alternative name for `getEnclosingFunction`.
*/
Callable getEnclosingCallable() {
result = this.getEnclosingFunction()
}
}

View File

@@ -0,0 +1,135 @@
/**
* Provides C++-specific definitions for use in the data flow library.
*/
import cpp
import semmle.code.cpp.ir.IR
/**
* A node in a data flow graph.
*
* A node can be either an expression, a parameter, or an uninitialized local
* variable. Such nodes are created with `DataFlow::exprNode`,
* `DataFlow::parameterNode`, and `DataFlow::uninitializedNode` respectively.
*/
class Node extends Instruction {
/**
* INTERNAL: Do not use. Alternative name for `getFunction`.
*/
Function getEnclosingCallable() {
result = this.getFunction()
}
/** Gets the type of this node. */
Type getType() {
result = this.getResultType()
}
/** Gets the expression corresponding to this node, if any. */
Expr asExpr() { result = this.getConvertedResultExpression() }
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter() { result = this.(InitializeParameterInstruction).getParameter() }
/**
* Gets the uninitialized local variable corresponding to this node, if
* any.
*/
LocalVariable asUninitialized() {
result = this.(UninitializedInstruction).getLocalVariable()
}
/**
* Gets an upper bound on the type of this node.
*/
Type getTypeBound() { result = getType() }
}
/**
* An expression, viewed as a node in a data flow graph.
*/
class ExprNode extends Node {
Expr expr;
ExprNode() { expr = this.asExpr() }
Expr getExpr() { result = expr }
}
/**
* The value of a parameter at function entry, viewed as a node in a data
* flow graph.
*/
class ParameterNode extends Node, InitializeParameterInstruction {
/**
* Holds if this node is the parameter of `c` at the specified (zero-based)
* position. The implicit `this` parameter is considered to have index `-1`.
*/
predicate isParameterOf(Function f, int i) {
f.getParameter(i) = getParameter()
}
}
/**
* The value of an uninitialized local variable, viewed as a node in a data
* flow graph.
*/
class UninitializedNode extends Node, UninitializedInstruction {
}
/**
* A node associated with an object after an operation that might have
* changed its state.
*
* This can be either the argument to a callable after the callable returns
* (which might have mutated the argument), or the qualifier of a field after
* an update to the field.
*
* Nodes corresponding to AST elements, for example `ExprNode`, usually refer
* to the value before the update with the exception of `ClassInstanceExpr`,
* which represents the value after the constructor has run.
*
* This class exists to match the interface used by Java. There are currently no non-abstract
* classes that extend it. When we implement field flow, we can revisit this.
*/
abstract class PostUpdateNode extends Node {
/**
* Gets the node before the state update.
*/
abstract Node getPreUpdateNode();
}
/**
* Gets the `Node` corresponding to `e`.
*/
ExprNode exprNode(Expr e) { result.getExpr() = e }
/**
* Gets the `Node` corresponding to the value of `p` at function entry.
*/
ParameterNode parameterNode(Parameter p) { result.getParameter() = p }
/**
* Gets the `Node` corresponding to the value of an uninitialized local
* variable `v`.
*/
UninitializedNode uninitializedNode(LocalVariable v) {
result.getLocalVariable() = v
}
/**
* Holds if data flows from `nodeFrom` to `nodeTo` in exactly one local
* (intra-procedural) step.
*/
predicate localFlowStep(Node nodeFrom, Node nodeTo) {
nodeTo.(CopyInstruction).getSourceValue() = nodeFrom or
nodeTo.(PhiInstruction).getAnOperand().getDefinitionInstruction() = nodeFrom or
// Treat all conversions as flow, even conversions between different numeric types.
nodeTo.(ConvertInstruction).getOperand() = nodeFrom
}
/**
* Holds if data flows from `source` to `sink` in zero or more local
* (intra-procedural) steps.
*/
predicate localFlow(Node source, Node sink) {
localFlowStep*(source, sink)
}

View File

@@ -595,7 +595,7 @@ class FieldAddressInstruction extends FieldInstruction {
}
}
class UninitializedInstruction extends Instruction {
class UninitializedInstruction extends VariableInstruction {
UninitializedInstruction() {
opcode instanceof Opcode::Uninitialized
}
@@ -603,6 +603,13 @@ class UninitializedInstruction extends Instruction {
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMemoryAccess
}
/**
* Gets the `LocalVariable` that is uninitialized.
*/
final LocalVariable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
class NoOpInstruction extends Instruction {
@@ -1106,9 +1113,39 @@ class CallInstruction extends Instruction {
opcode instanceof Opcode::Call
}
/**
* Gets the `Instruction` that computes the target function of the call. This is usually a
* `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a
* function pointer.
*/
final Instruction getCallTarget() {
result = getAnOperand().(CallTargetOperand).getDefinitionInstruction()
}
/**
* Gets all of the arguments of the call, including the `this` pointer, if any.
*/
final Instruction getAnArgument() {
result = getAnOperand().(ArgumentOperand).getDefinitionInstruction()
}
/**
* Gets the `this` pointer argument of the call, if any.
*/
final Instruction getThisArgument() {
result = getAnOperand().(ThisArgumentOperand).getDefinitionInstruction()
}
/**
* Gets the argument at the specified index.
*/
final Instruction getPositionalArgument(int index) {
exists(PositionalArgumentOperand operand |
operand = getAnOperand() and
operand.getIndex() = index and
result = operand.getDefinitionInstruction()
)
}
}
/**

View File

@@ -304,6 +304,13 @@ class PositionalArgumentOperand extends ArgumentOperand {
override string toString() {
result = "Arg(" + argIndex + ")"
}
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
}
class SideEffectOperand extends NonPhiOperand {

View File

@@ -19,6 +19,10 @@ private VirtualIRVariable getVirtualVariable(IRVariable var) {
result.getIRVariable() = var
}
private UnknownVirtualVariable getUnknownVirtualVariable(FunctionIR f) {
result.getFunctionIR() = f
}
class VirtualVariable extends TVirtualVariable {
string toString() {
none()
@@ -83,10 +87,10 @@ class UnknownVirtualVariable extends VirtualVariable, TUnknownVirtualVariable {
}
private newtype TMemoryAccess =
TVariableMemoryAccess(VirtualIRVariable vvar, IntValue offset, IntValue size) {
TVariableMemoryAccess(IRVariable var, IntValue offset, IntValue size) {
exists(Instruction instr |
exists(MemoryAccessKind mak | instr.getResultMemoryAccess() = mak and not mak instanceof PhiMemoryAccess) and
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), vvar.getIRVariable(), offset) and
resultPointsTo(instr.getAnOperand().(AddressOperand).getDefinitionInstruction(), var, offset) and
if exists(instr.getResultSize())
then instr.getResultSize() = size
else size = Ints::unknown()
@@ -97,7 +101,7 @@ private newtype TMemoryAccess =
TTotalUnknownMemoryAccess(UnknownVirtualVariable uvv)
private VariableMemoryAccess getVariableMemoryAccess(IRVariable var, IntValue offset, IntValue size) {
result.getVirtualVariable() = getVirtualVariable(var) and
result.getVariable() = var and
result.getOffset() = offset and
result.getSize() = size
}
@@ -117,20 +121,21 @@ class MemoryAccess extends TMemoryAccess {
}
class VariableMemoryAccess extends TVariableMemoryAccess, MemoryAccess {
VirtualIRVariable vvar;
IRVariable var;
IntValue offset;
IntValue size;
VariableMemoryAccess() {
this = TVariableMemoryAccess(vvar, offset, size)
this = TVariableMemoryAccess(var, offset, size)
}
override final string toString() {
result = vvar.toString()
result = var.toString() + "[" + offset.toString() + ".." + (offset + size - 1).toString() + "]"
}
final override VirtualVariable getVirtualVariable() {
result = vvar
result = getVirtualVariable(var) or
not exists(getVirtualVariable(var)) and result = getUnknownVirtualVariable(var.getFunctionIR())
}
IntValue getOffset() {
@@ -141,10 +146,15 @@ class VariableMemoryAccess extends TVariableMemoryAccess, MemoryAccess {
result = size
}
final IRVariable getVariable() {
result = var
}
final override predicate isPartialMemoryAccess() {
not exists(getVirtualVariable(var)) or
getOffset() != 0
or
getSize() != vvar.getType().getSize()
getSize() != var.getType().getSize()
}
}
@@ -166,6 +176,7 @@ class UnknownMemoryAccess extends TUnknownMemoryAccess, MemoryAccess {
final override predicate isPartialMemoryAccess() {
any()
}
Type getType() {
result instanceof UnknownType
}

View File

@@ -0,0 +1,12 @@
private import semmle.code.cpp.ir.implementation.unaliased_ssa.IR
private import AliasedSSA
/**
* Property provide that dumps the memory access of each result. Useful for debugging SSA
* construction.
*/
class PropertyProvider extends IRPropertyProvider {
override string getInstructionProperty(Instruction instruction, string key) {
key = "ResultMemoryAccess" and result = getResultMemoryAccess(instruction).toString()
}
}

View File

@@ -595,7 +595,7 @@ class FieldAddressInstruction extends FieldInstruction {
}
}
class UninitializedInstruction extends Instruction {
class UninitializedInstruction extends VariableInstruction {
UninitializedInstruction() {
opcode instanceof Opcode::Uninitialized
}
@@ -603,6 +603,13 @@ class UninitializedInstruction extends Instruction {
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMemoryAccess
}
/**
* Gets the `LocalVariable` that is uninitialized.
*/
final LocalVariable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
class NoOpInstruction extends Instruction {
@@ -1106,9 +1113,39 @@ class CallInstruction extends Instruction {
opcode instanceof Opcode::Call
}
/**
* Gets the `Instruction` that computes the target function of the call. This is usually a
* `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a
* function pointer.
*/
final Instruction getCallTarget() {
result = getAnOperand().(CallTargetOperand).getDefinitionInstruction()
}
/**
* Gets all of the arguments of the call, including the `this` pointer, if any.
*/
final Instruction getAnArgument() {
result = getAnOperand().(ArgumentOperand).getDefinitionInstruction()
}
/**
* Gets the `this` pointer argument of the call, if any.
*/
final Instruction getThisArgument() {
result = getAnOperand().(ThisArgumentOperand).getDefinitionInstruction()
}
/**
* Gets the argument at the specified index.
*/
final Instruction getPositionalArgument(int index) {
exists(PositionalArgumentOperand operand |
operand = getAnOperand() and
operand.getIndex() = index and
result = operand.getDefinitionInstruction()
)
}
}
/**

View File

@@ -304,6 +304,13 @@ class PositionalArgumentOperand extends ArgumentOperand {
override string toString() {
result = "Arg(" + argIndex + ")"
}
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
}
class SideEffectOperand extends NonPhiOperand {

View File

@@ -1,6 +1,7 @@
import cpp
private import semmle.code.cpp.ir.implementation.Opcode
private import semmle.code.cpp.ir.internal.OperandTag
private import semmle.code.cpp.models.interfaces.SideEffect
private import InstructionTag
private import TranslatedElement
private import TranslatedExpr
@@ -37,9 +38,18 @@ abstract class TranslatedCall extends TranslatedExpr {
isGLValue = false
) or
(
hasSideEffect() and
tag = CallSideEffectTag() and
opcode instanceof Opcode::CallSideEffect and
resultType instanceof UnknownType and
(
if hasWriteSideEffect() then (
opcode instanceof Opcode::CallSideEffect and
resultType instanceof UnknownType
)
else (
opcode instanceof Opcode::CallReadSideEffect and
resultType instanceof VoidType
)
) and
isGLValue = false
)
}
@@ -68,9 +78,13 @@ abstract class TranslatedCall extends TranslatedExpr {
(
(
tag = CallTag() and
result = getInstruction(CallSideEffectTag())
if hasSideEffect() then
result = getInstruction(CallSideEffectTag())
else
result = getParent().getChildSuccessor(this)
) or
(
hasSideEffect() and
tag = CallSideEffectTag() and
result = getParent().getChildSuccessor(this)
)
@@ -183,6 +197,18 @@ abstract class TranslatedCall extends TranslatedExpr {
* Holds if the call has any arguments, not counting the `this` argument.
*/
abstract predicate hasArguments();
predicate hasReadSideEffect() {
any()
}
predicate hasWriteSideEffect() {
any()
}
private predicate hasSideEffect() {
hasReadSideEffect() or hasWriteSideEffect()
}
}
/**
@@ -280,6 +306,14 @@ class TranslatedFunctionCall extends TranslatedCallExpr, TranslatedDirectCall {
override Function getInstructionFunction(InstructionTag tag) {
tag = CallTargetTag() and result = funcCall.getTarget()
}
override predicate hasReadSideEffect() {
not funcCall.getTarget().(SideEffectFunction).neverReadsMemory()
}
override predicate hasWriteSideEffect() {
not funcCall.getTarget().(SideEffectFunction).neverWritesMemory()
}
}
/**
@@ -302,4 +336,3 @@ class TranslatedStructorCall extends TranslatedFunctionCall {
any()
}
}

View File

@@ -142,7 +142,10 @@ abstract class TranslatedVariableDeclaration extends TranslatedElement, Initiali
}
override IRVariable getInstructionVariable(InstructionTag tag) {
tag = InitializerVariableAddressTag() and
(
tag = InitializerVariableAddressTag() or
hasUninitializedInstruction() and tag = InitializerStoreTag()
) and
result = getIRUserVariable(getFunction(), getVariable())
}

View File

@@ -595,7 +595,7 @@ class FieldAddressInstruction extends FieldInstruction {
}
}
class UninitializedInstruction extends Instruction {
class UninitializedInstruction extends VariableInstruction {
UninitializedInstruction() {
opcode instanceof Opcode::Uninitialized
}
@@ -603,6 +603,13 @@ class UninitializedInstruction extends Instruction {
override final MemoryAccessKind getResultMemoryAccess() {
result instanceof IndirectMemoryAccess
}
/**
* Gets the `LocalVariable` that is uninitialized.
*/
final LocalVariable getLocalVariable() {
result = var.(IRUserVariable).getVariable()
}
}
class NoOpInstruction extends Instruction {
@@ -1106,9 +1113,39 @@ class CallInstruction extends Instruction {
opcode instanceof Opcode::Call
}
/**
* Gets the `Instruction` that computes the target function of the call. This is usually a
* `FunctionAddress` instruction, but can also be an arbitrary instruction that produces a
* function pointer.
*/
final Instruction getCallTarget() {
result = getAnOperand().(CallTargetOperand).getDefinitionInstruction()
}
/**
* Gets all of the arguments of the call, including the `this` pointer, if any.
*/
final Instruction getAnArgument() {
result = getAnOperand().(ArgumentOperand).getDefinitionInstruction()
}
/**
* Gets the `this` pointer argument of the call, if any.
*/
final Instruction getThisArgument() {
result = getAnOperand().(ThisArgumentOperand).getDefinitionInstruction()
}
/**
* Gets the argument at the specified index.
*/
final Instruction getPositionalArgument(int index) {
exists(PositionalArgumentOperand operand |
operand = getAnOperand() and
operand.getIndex() = index and
result = operand.getDefinitionInstruction()
)
}
}
/**

View File

@@ -304,6 +304,13 @@ class PositionalArgumentOperand extends ArgumentOperand {
override string toString() {
result = "Arg(" + argIndex + ")"
}
/**
* Gets the zero-based index of the argument.
*/
final int getIndex() {
result = argIndex
}
}
class SideEffectOperand extends NonPhiOperand {

View File

@@ -1,3 +1,4 @@
private import implementations.IdentityFunction
private import implementations.Inet
private import implementations.Memcpy
private import implementations.Printf

View File

@@ -0,0 +1,45 @@
import semmle.code.cpp.Function
import semmle.code.cpp.models.interfaces.Alias
import semmle.code.cpp.models.interfaces.DataFlow
import semmle.code.cpp.models.interfaces.SideEffect
/**
* The standard function templates `std::move` and `std::identity`
*/
class IdentityFunction extends DataFlowFunction, SideEffectFunction, AliasFunction {
IdentityFunction() {
this.getNamespace().getParentNamespace() instanceof GlobalNamespace and
this.getNamespace().getName() = "std" and
(
this.getName() = "move" or
this.getName() = "forward"
)
}
override predicate neverReadsMemory() {
any()
}
override predicate neverWritesMemory() {
any()
}
override predicate parameterNeverEscapes(int index) {
none()
}
override predicate parameterEscapesOnlyViaReturn(int index) {
// These functions simply return the argument value.
index = 0
}
override predicate parameterIsAlwaysReturned(int index) {
// These functions simply return the argument value.
index = 0
}
override predicate hasDataFlow(FunctionInput input, FunctionOutput output) {
// These functions simply return the argument value.
input.isInParameter(0) and output.isOutReturnValue()
}
}

View File

@@ -0,0 +1,54 @@
/**
* Provides an abstract class for accurate alias modeling of library
* functions when source code is not available. To use this QL library,
* create a QL class extending `AliasFunction` with a characteristic
* predicate that selects the function or set of functions you are modeling.
* Within that class, override the predicates provided by `AliasFunction`
* to match the flow within that function.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.Models
/**
* Models the aliasing behavior of a library function.
*/
abstract class AliasFunction extends Function {
/**
* Holds if the address passed to the parameter at the specified index is never retained after
* the function returns.
*
* Example:
* ```
* int* g;
* int* func(int* p, int* q, int* r, int* s, int n) {
* *s = 1; // `s` does not escape.
* g = p; // Stored in global. `p` escapes.
* if (rand()) {
* return q; // `q` escapes via the return value.
* }
* else {
* return r + n; // `r` escapes via the return value, even though an offset has been added.
* }
* }
* ```
*
* For the above function, the following terms hold:
* - `parameterEscapesOnlyViaReturn(1)`
* - `parameterEscapesOnlyViaReturn(2)`
* - `parameterNeverEscapes(3)`
*/
abstract predicate parameterNeverEscapes(int index);
/**
* Holds if the address passed to the parameter at the specified index escapes via the return
* value of the function, but does not otherwise escape. See the comment for
* `parameterNeverEscapes` for an example.
*/
abstract predicate parameterEscapesOnlyViaReturn(int index);
/**
* Holds if the function always returns the value of the parameter at the specified index.
*/
abstract predicate parameterIsAlwaysReturned(int index);
}

View File

@@ -1,5 +1,5 @@
/**
* Provides a set of QL clcasses for indicating dataflows through a particular
* Provides a set of QL classes for indicating dataflows through a particular
* parameter, return value, or qualifier, as well as flows at one level of
* pointer indirection.
*/

View File

@@ -0,0 +1,30 @@
/**
* Provides an abstract class for accurate dataflow modeling of library
* functions when source code is not available. To use this QL library,
* create a QL class extending `SideEffectFunction` with a characteristic
* predicate that selects the function or set of functions you are modeling.
* Within that class, override the predicates provided by `SideEffectFunction`
* to match the flow within that function.
*/
import semmle.code.cpp.Function
import semmle.code.cpp.models.Models
/**
* Models the side effects of a library function.
*/
abstract class SideEffectFunction extends Function {
/**
* Holds if the function never reads from memory that was defined before entry to the function.
* This memory could be from global variables, or from other memory that was reachable from a
* pointer that was passed into the function.
*/
abstract predicate neverReadsMemory();
/**
* Holds if the function never writes to memory that remains allocated after the function
* returns. This memory could be from global variables, or from other memory that was reachable
* from a pointer that was passed into the function.
*/
abstract predicate neverWritesMemory();
}

View File

@@ -0,0 +1,29 @@
import cpp
import semmle.code.cpp.ir.dataflow.DataFlow
/** Common data flow configuration to be used by tests. */
class TestAllocationConfig extends DataFlow::Configuration {
TestAllocationConfig() {
this = "TestAllocationConfig"
}
override predicate isSource(DataFlow::Node source) {
source.asExpr().(FunctionCall).getTarget().getName() = "source"
or
source.asParameter().getName().matches("source%")
or
// Track uninitialized variables
exists(source.asUninitialized())
}
override predicate isSink(DataFlow::Node sink) {
exists(FunctionCall call |
call.getTarget().getName() = "sink" and
sink.asExpr() = call.getAnArgument().getFullyConverted()
)
}
override predicate isBarrier(DataFlow::Node barrier) {
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier")
}
}

View File

@@ -0,0 +1,14 @@
| test.cpp:6:12:6:17 | test.cpp:21:8:21:9 | IR only |
| test.cpp:66:30:66:36 | test.cpp:71:8:71:9 | AST only |
| test.cpp:89:28:89:34 | test.cpp:90:8:90:14 | AST only |
| test.cpp:100:13:100:18 | test.cpp:103:10:103:12 | AST only |
| test.cpp:120:9:120:20 | test.cpp:126:8:126:19 | AST only |
| test.cpp:122:18:122:30 | test.cpp:132:22:132:23 | IR only |
| test.cpp:122:18:122:30 | test.cpp:140:22:140:23 | IR only |
| test.cpp:136:27:136:32 | test.cpp:137:27:137:28 | AST only |
| test.cpp:136:27:136:32 | test.cpp:140:22:140:23 | AST only |
| test.cpp:395:17:395:22 | test.cpp:397:10:397:18 | AST only |
| test.cpp:421:13:421:18 | test.cpp:423:10:423:14 | AST only |
| true_upon_entry.cpp:9:11:9:16 | true_upon_entry.cpp:13:8:13:8 | IR only |
| true_upon_entry.cpp:62:11:62:16 | true_upon_entry.cpp:66:8:66:8 | IR only |
| true_upon_entry.cpp:98:11:98:16 | true_upon_entry.cpp:105:8:105:8 | IR only |

View File

@@ -0,0 +1,37 @@
import cpp
import DataflowTestCommon as ASTCommon
import IRDataflowTestCommon as IRCommon
import semmle.code.cpp.dataflow.DataFlow as ASTDataFlow
import semmle.code.cpp.ir.dataflow.DataFlow as IRDataFlow
predicate astFlow(Location sourceLocation, Location sinkLocation) {
exists(ASTDataFlow::DataFlow::Node source, ASTDataFlow::DataFlow::Node sink,
ASTCommon::TestAllocationConfig cfg |
cfg.hasFlow(source, sink) and
sourceLocation = source.getLocation() and
sinkLocation = sink.getLocation()
)
}
predicate irFlow(Location sourceLocation, Location sinkLocation) {
exists(IRDataFlow::DataFlow::Node source, IRDataFlow::DataFlow::Node sink,
IRCommon::TestAllocationConfig cfg |
cfg.hasFlow(source, sink) and
sourceLocation = source.getLocation() and
sinkLocation = sink.getLocation()
)
}
from Location sourceLocation, Location sinkLocation, string note
where
(
astFlow(sourceLocation, sinkLocation) and
not irFlow(sourceLocation, sinkLocation) and
note = "AST only"
) or
(
irFlow(sourceLocation, sinkLocation) and
not astFlow(sourceLocation, sinkLocation) and
note = "IR only"
)
select sourceLocation.toString(), sinkLocation.toString(), note

View File

@@ -0,0 +1,34 @@
| test.cpp:7:8:7:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:9:8:9:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:10:8:10:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:15:8:15:9 | Load: t2 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:21:8:21:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:26:8:26:9 | Load: t1 | test.cpp:6:12:6:17 | Call: call to source |
| test.cpp:30:8:30:8 | Load: t | test.cpp:35:10:35:15 | Call: call to source |
| test.cpp:31:8:31:8 | Load: c | test.cpp:36:13:36:18 | Call: call to source |
| test.cpp:58:10:58:10 | Load: t | test.cpp:50:14:50:19 | Call: call to source |
| test.cpp:76:8:76:9 | Load: u1 | test.cpp:75:7:75:8 | Uninitialized: definition of u1 |
| test.cpp:84:8:84:18 | Load: ... ? ... : ... | test.cpp:83:7:83:8 | Uninitialized: definition of u2 |
| test.cpp:86:8:86:9 | Load: i1 | test.cpp:83:7:83:8 | Uninitialized: definition of u2 |
| test.cpp:132:22:132:23 | Load: m1 | test.cpp:122:18:122:30 | InitializeParameter: sourceStruct1 |
| test.cpp:140:22:140:23 | Load: m1 | test.cpp:122:18:122:30 | InitializeParameter: sourceStruct1 |
| test.cpp:188:8:188:8 | Load: y | test.cpp:186:27:186:32 | Call: call to source |
| test.cpp:192:8:192:8 | Load: s | test.cpp:199:33:199:38 | Call: call to source |
| test.cpp:200:8:200:8 | Load: y | test.cpp:199:33:199:38 | Call: call to source |
| test.cpp:205:8:205:8 | Load: x | test.cpp:212:34:212:39 | Call: call to source |
| test.cpp:213:8:213:8 | Load: y | test.cpp:212:34:212:39 | Call: call to source |
| test.cpp:226:8:226:8 | Load: y | test.cpp:219:11:219:16 | Call: call to source |
| test.cpp:308:12:308:12 | Load: x | test.cpp:293:14:293:19 | Call: call to source |
| test.cpp:314:12:314:12 | Load: x | test.cpp:313:22:313:27 | Call: call to source |
| test.cpp:337:14:337:14 | Load: x | test.cpp:353:17:353:22 | Call: call to source |
| test.cpp:366:7:366:7 | Load: x | test.cpp:362:4:362:9 | Call: call to source |
| true_upon_entry.cpp:13:8:13:8 | Load: x | true_upon_entry.cpp:9:11:9:16 | Call: call to source |
| true_upon_entry.cpp:21:8:21:8 | Load: x | true_upon_entry.cpp:17:11:17:16 | Call: call to source |
| true_upon_entry.cpp:29:8:29:8 | Load: x | true_upon_entry.cpp:27:9:27:14 | Call: call to source |
| true_upon_entry.cpp:39:8:39:8 | Load: x | true_upon_entry.cpp:33:11:33:16 | Call: call to source |
| true_upon_entry.cpp:49:8:49:8 | Load: x | true_upon_entry.cpp:43:11:43:16 | Call: call to source |
| true_upon_entry.cpp:57:8:57:8 | Load: x | true_upon_entry.cpp:54:11:54:16 | Call: call to source |
| true_upon_entry.cpp:66:8:66:8 | Load: x | true_upon_entry.cpp:62:11:62:16 | Call: call to source |
| true_upon_entry.cpp:78:8:78:8 | Load: x | true_upon_entry.cpp:70:11:70:16 | Call: call to source |
| true_upon_entry.cpp:86:8:86:8 | Load: x | true_upon_entry.cpp:83:11:83:16 | Call: call to source |
| true_upon_entry.cpp:105:8:105:8 | Load: x | true_upon_entry.cpp:98:11:98:16 | Call: call to source |

View File

@@ -0,0 +1,5 @@
import IRDataflowTestCommon
from DataFlow::Node sink, DataFlow::Node source, TestAllocationConfig cfg
where cfg.hasFlow(source, sink)
select sink, source

View File

@@ -1,24 +1,26 @@
bad_asts.cpp:
# 14| Bad::CallBadMemberFunction() -> void
# 14| Block 0
# 14| v0_0(void) = EnterFunction :
# 14| m0_1(unknown) = AliasedDefinition :
# 14| mu0_2(unknown) = UnmodeledDefinition :
# 15| r0_3(glval<S>) = VariableAddress[s] :
# 15| mu0_4(S) = Uninitialized : r0_3
# 15| r0_5(glval<int>) = FieldAddress[x] : r0_3
# 15| r0_6(int) = Constant[0] :
# 15| mu0_7(int) = Store : r0_5, r0_6
# 16| r0_8(glval<S>) = VariableAddress[s] :
# 16| r0_9(glval<unknown>) = FunctionAddress[MemberFunction] :
# 16| r0_10(int) = Constant[1] :
# 16| r0_11(int) = Call : r0_9, this:r0_8, r0_10
# 16| m0_12(unknown) = ^CallSideEffect : m0_1
# 16| m0_13(unknown) = Chi : m0_1, m0_12
# 17| v0_14(void) = NoOp :
# 14| v0_15(void) = ReturnVoid :
# 14| v0_16(void) = UnmodeledUse : mu*
# 14| v0_17(void) = ExitFunction :
# 14| v0_0(void) = EnterFunction :
# 14| m0_1(unknown) = AliasedDefinition :
# 14| mu0_2(unknown) = UnmodeledDefinition :
# 15| r0_3(glval<S>) = VariableAddress[s] :
# 15| m0_4(S) = Uninitialized[s] : r0_3
# 15| m0_5(unknown) = Chi : m0_1, m0_4
# 15| r0_6(glval<int>) = FieldAddress[x] : r0_3
# 15| r0_7(int) = Constant[0] :
# 15| m0_8(int) = Store : r0_6, r0_7
# 15| m0_9(unknown) = Chi : m0_5, m0_8
# 16| r0_10(glval<S>) = VariableAddress[s] :
# 16| r0_11(glval<unknown>) = FunctionAddress[MemberFunction] :
# 16| r0_12(int) = Constant[1] :
# 16| r0_13(int) = Call : r0_11, this:r0_10, r0_12
# 16| m0_14(unknown) = ^CallSideEffect : m0_9
# 16| m0_15(unknown) = Chi : m0_9, m0_14
# 17| v0_16(void) = NoOp :
# 14| v0_17(void) = ReturnVoid :
# 14| v0_18(void) = UnmodeledUse : mu*
# 14| v0_19(void) = ExitFunction :
# 22| Bad::Point::Point() -> void
# 22| Block 0
@@ -187,7 +189,7 @@ ir.cpp:
# 50| r0_5(glval<int>) = VariableAddress[y] :
# 50| m0_6(int) = InitializeParameter[y] : r0_5
# 51| r0_7(glval<int>) = VariableAddress[z] :
# 51| m0_8(int) = Uninitialized : r0_7
# 51| m0_8(int) = Uninitialized[z] : r0_7
# 53| r0_9(glval<int>) = VariableAddress[x] :
# 53| r0_10(int) = Load : r0_9, m0_4
# 53| r0_11(glval<int>) = VariableAddress[y] :
@@ -360,7 +362,7 @@ ir.cpp:
# 87| r0_5(glval<int>) = VariableAddress[y] :
# 87| m0_6(int) = InitializeParameter[y] : r0_5
# 88| r0_7(glval<bool>) = VariableAddress[b] :
# 88| m0_8(bool) = Uninitialized : r0_7
# 88| m0_8(bool) = Uninitialized[b] : r0_7
# 90| r0_9(glval<int>) = VariableAddress[x] :
# 90| r0_10(int) = Load : r0_9, m0_4
# 90| r0_11(glval<int>) = VariableAddress[y] :
@@ -416,7 +418,7 @@ ir.cpp:
# 98| r0_3(glval<int>) = VariableAddress[x] :
# 98| m0_4(int) = InitializeParameter[x] : r0_3
# 99| r0_5(glval<int>) = VariableAddress[y] :
# 99| m0_6(int) = Uninitialized : r0_5
# 99| m0_6(int) = Uninitialized[y] : r0_5
# 101| r0_7(glval<int>) = VariableAddress[x] :
# 101| r0_8(int) = Load : r0_7, m0_4
# 101| r0_9(int) = Constant[1] :
@@ -458,7 +460,7 @@ ir.cpp:
# 107| r0_3(glval<int>) = VariableAddress[x] :
# 107| m0_4(int) = InitializeParameter[x] : r0_3
# 108| r0_5(glval<int *>) = VariableAddress[p] :
# 108| m0_6(int *) = Uninitialized : r0_5
# 108| m0_6(int *) = Uninitialized[p] : r0_5
# 110| r0_7(glval<int>) = VariableAddress[x] :
# 110| r0_8(int) = Load : r0_7, mu0_2
# 110| r0_9(int) = Constant[1] :
@@ -488,7 +490,7 @@ ir.cpp:
# 114| r0_5(glval<double>) = VariableAddress[y] :
# 114| m0_6(double) = InitializeParameter[y] : r0_5
# 115| r0_7(glval<double>) = VariableAddress[z] :
# 115| m0_8(double) = Uninitialized : r0_7
# 115| m0_8(double) = Uninitialized[z] : r0_7
# 117| r0_9(glval<double>) = VariableAddress[x] :
# 117| r0_10(double) = Load : r0_9, m0_4
# 117| r0_11(glval<double>) = VariableAddress[y] :
@@ -570,7 +572,7 @@ ir.cpp:
# 133| r0_5(glval<double>) = VariableAddress[y] :
# 133| m0_6(double) = InitializeParameter[y] : r0_5
# 134| r0_7(glval<bool>) = VariableAddress[b] :
# 134| m0_8(bool) = Uninitialized : r0_7
# 134| m0_8(bool) = Uninitialized[b] : r0_7
# 136| r0_9(glval<double>) = VariableAddress[x] :
# 136| r0_10(double) = Load : r0_9, m0_4
# 136| r0_11(glval<double>) = VariableAddress[y] :
@@ -626,7 +628,7 @@ ir.cpp:
# 144| r0_3(glval<float>) = VariableAddress[x] :
# 144| m0_4(float) = InitializeParameter[x] : r0_3
# 145| r0_5(glval<float>) = VariableAddress[y] :
# 145| m0_6(float) = Uninitialized : r0_5
# 145| m0_6(float) = Uninitialized[y] : r0_5
# 147| r0_7(glval<float>) = VariableAddress[x] :
# 147| r0_8(float) = Load : r0_7, m0_4
# 147| r0_9(float) = Constant[1.0] :
@@ -670,9 +672,9 @@ ir.cpp:
# 153| r0_5(glval<int>) = VariableAddress[i] :
# 153| m0_6(int) = InitializeParameter[i] : r0_5
# 154| r0_7(glval<int *>) = VariableAddress[q] :
# 154| m0_8(int *) = Uninitialized : r0_7
# 154| m0_8(int *) = Uninitialized[q] : r0_7
# 155| r0_9(glval<bool>) = VariableAddress[b] :
# 155| m0_10(bool) = Uninitialized : r0_9
# 155| m0_10(bool) = Uninitialized[b] : r0_9
# 157| r0_11(glval<int *>) = VariableAddress[p] :
# 157| r0_12(int *) = Load : r0_11, m0_4
# 157| r0_13(glval<int>) = VariableAddress[i] :
@@ -746,7 +748,7 @@ ir.cpp:
# 171| r0_5(glval<int>) = VariableAddress[i] :
# 171| m0_6(int) = InitializeParameter[i] : r0_5
# 172| r0_7(glval<int>) = VariableAddress[x] :
# 172| m0_8(int) = Uninitialized : r0_7
# 172| m0_8(int) = Uninitialized[x] : r0_7
# 174| r0_9(glval<int *>) = VariableAddress[p] :
# 174| r0_10(int *) = Load : r0_9, m0_4
# 174| r0_11(glval<int>) = VariableAddress[i] :
@@ -782,7 +784,7 @@ ir.cpp:
# 178| m0_41(int) = Store : r0_40, r0_35
# 178| m0_42(unknown) = Chi : m0_33, m0_41
# 180| r0_43(glval<int[10]>) = VariableAddress[a] :
# 180| m0_44(int[10]) = Uninitialized : r0_43
# 180| m0_44(int[10]) = Uninitialized[a] : r0_43
# 181| r0_45(glval<int[10]>) = VariableAddress[a] :
# 181| r0_46(int *) = Convert : r0_45
# 181| r0_47(glval<int>) = VariableAddress[i] :
@@ -865,7 +867,7 @@ ir.cpp:
# 193| r0_5(glval<int *>) = VariableAddress[q] :
# 193| m0_6(int *) = InitializeParameter[q] : r0_5
# 194| r0_7(glval<bool>) = VariableAddress[b] :
# 194| m0_8(bool) = Uninitialized : r0_7
# 194| m0_8(bool) = Uninitialized[b] : r0_7
# 196| r0_9(glval<int *>) = VariableAddress[p] :
# 196| r0_10(int *) = Load : r0_9, m0_4
# 196| r0_11(glval<int *>) = VariableAddress[q] :
@@ -921,7 +923,7 @@ ir.cpp:
# 204| r0_3(glval<int *>) = VariableAddress[p] :
# 204| m0_4(int *) = InitializeParameter[p] : r0_3
# 205| r0_5(glval<int *>) = VariableAddress[q] :
# 205| m0_6(int *) = Uninitialized : r0_5
# 205| m0_6(int *) = Uninitialized[q] : r0_5
# 207| r0_7(glval<int *>) = VariableAddress[p] :
# 207| r0_8(int *) = Load : r0_7, m0_4
# 207| r0_9(int) = Constant[1] :
@@ -1005,7 +1007,7 @@ ir.cpp:
# 230| m0_1(unknown) = AliasedDefinition :
# 230| mu0_2(unknown) = UnmodeledDefinition :
# 231| r0_3(glval<int>) = VariableAddress[x] :
# 231| m0_4(int) = Uninitialized : r0_3
# 231| m0_4(int) = Uninitialized[x] : r0_3
# 232| r0_5(glval<int>) = VariableAddress[y] :
# 232| r0_6(glval<int>) = VariableAddress[x] :
# 232| r0_7(int) = Load : r0_6, m0_4
@@ -1168,7 +1170,7 @@ ir.cpp:
# 265| m0_1(unknown) = AliasedDefinition :
# 265| mu0_2(unknown) = UnmodeledDefinition :
# 266| r0_3(glval<int>) = VariableAddress[j] :
# 266| m0_4(int) = Uninitialized : r0_3
# 266| m0_4(int) = Uninitialized[j] : r0_3
#-----| Goto -> Block 2
# 265| Block 1
@@ -1719,7 +1721,7 @@ ir.cpp:
# 384| r0_3(glval<int>) = VariableAddress[x] :
# 384| m0_4(int) = InitializeParameter[x] : r0_3
# 385| r0_5(glval<int>) = VariableAddress[y] :
# 385| m0_6(int) = Uninitialized : r0_5
# 385| m0_6(int) = Uninitialized[y] : r0_5
# 386| r0_7(glval<int>) = VariableAddress[x] :
# 386| r0_8(int) = Load : r0_7, m0_4
# 386| v0_9(void) = Switch : r0_8
@@ -1814,7 +1816,7 @@ ir.cpp:
# 426| m0_1(unknown) = AliasedDefinition :
# 426| mu0_2(unknown) = UnmodeledDefinition :
# 427| r0_3(glval<Point>) = VariableAddress[pt] :
# 427| m0_4(Point) = Uninitialized : r0_3
# 427| m0_4(Point) = Uninitialized[pt] : r0_3
# 428| r0_5(int) = Constant[5] :
# 428| r0_6(glval<Point>) = VariableAddress[pt] :
# 428| r0_7(glval<int>) = FieldAddress[x] : r0_6
@@ -1846,7 +1848,7 @@ ir.cpp:
# 433| r0_5(glval<bool>) = VariableAddress[b] :
# 433| m0_6(bool) = InitializeParameter[b] : r0_5
# 434| r0_7(glval<int>) = VariableAddress[x] :
# 434| m0_8(int) = Uninitialized : r0_7
# 434| m0_8(int) = Uninitialized[x] : r0_7
# 435| r0_9(glval<bool>) = VariableAddress[a] :
# 435| r0_10(bool) = Load : r0_9, m0_4
# 435| v0_11(void) = ConditionalBranch : r0_10
@@ -1908,7 +1910,7 @@ ir.cpp:
# 447| r0_5(glval<bool>) = VariableAddress[b] :
# 447| m0_6(bool) = InitializeParameter[b] : r0_5
# 448| r0_7(glval<int>) = VariableAddress[x] :
# 448| m0_8(int) = Uninitialized : r0_7
# 448| m0_8(int) = Uninitialized[x] : r0_7
# 449| r0_9(glval<bool>) = VariableAddress[a] :
# 449| r0_10(bool) = Load : r0_9, m0_4
# 449| v0_11(void) = ConditionalBranch : r0_10
@@ -1970,7 +1972,7 @@ ir.cpp:
# 461| r0_5(glval<bool>) = VariableAddress[b] :
# 461| m0_6(bool) = InitializeParameter[b] : r0_5
# 462| r0_7(glval<int>) = VariableAddress[x] :
# 462| m0_8(int) = Uninitialized : r0_7
# 462| m0_8(int) = Uninitialized[x] : r0_7
# 463| r0_9(glval<bool>) = VariableAddress[a] :
# 463| r0_10(bool) = Load : r0_9, m0_4
# 463| v0_11(void) = ConditionalBranch : r0_10
@@ -2025,7 +2027,7 @@ ir.cpp:
# 475| r0_5(glval<bool>) = VariableAddress[b] :
# 475| m0_6(bool) = InitializeParameter[b] : r0_5
# 476| r0_7(glval<bool>) = VariableAddress[x] :
# 476| m0_8(bool) = Uninitialized : r0_7
# 476| m0_8(bool) = Uninitialized[x] : r0_7
# 477| r0_9(glval<bool>) = VariableAddress[a] :
# 477| r0_10(bool) = Load : r0_9, m0_4
# 477| v0_11(void) = ConditionalBranch : r0_10
@@ -2175,13 +2177,15 @@ ir.cpp:
# 486| r0_3(glval<bool>) = VariableAddress[a] :
# 486| m0_4(bool) = InitializeParameter[a] : r0_3
# 487| r0_5(glval<int>) = VariableAddress[x] :
# 487| mu0_6(int) = Uninitialized : r0_5
# 488| r0_7(glval<int>) = VariableAddress[y] :
# 488| mu0_8(int) = Uninitialized : r0_7
# 489| r0_9(int) = Constant[5] :
# 489| r0_10(glval<bool>) = VariableAddress[a] :
# 489| r0_11(bool) = Load : r0_10, m0_4
# 489| v0_12(void) = ConditionalBranch : r0_11
# 487| m0_6(int) = Uninitialized[x] : r0_5
# 487| m0_7(unknown) = Chi : m0_1, m0_6
# 488| r0_8(glval<int>) = VariableAddress[y] :
# 488| m0_9(int) = Uninitialized[y] : r0_8
# 488| m0_10(unknown) = Chi : m0_7, m0_9
# 489| r0_11(int) = Constant[5] :
# 489| r0_12(glval<bool>) = VariableAddress[a] :
# 489| r0_13(bool) = Load : r0_12, m0_4
# 489| v0_14(void) = ConditionalBranch : r0_13
#-----| False -> Block 3
#-----| True -> Block 2
@@ -2189,8 +2193,8 @@ ir.cpp:
# 489| m1_0(int) = Phi : from 2:m2_2, from 3:m3_2
# 489| r1_1(glval<int>) = VariableAddress[#temp489:6] :
# 489| r1_2(glval<int>) = Load : r1_1, m1_0
# 489| m1_3(int) = Store : r1_2, r0_9
# 489| m1_4(unknown) = Chi : m0_1, m1_3
# 489| m1_3(int) = Store : r1_2, r0_11
# 489| m1_4(unknown) = Chi : m0_10, m1_3
# 490| v1_5(void) = NoOp :
# 486| v1_6(void) = ReturnVoid :
# 486| v1_7(void) = UnmodeledUse : mu*
@@ -2273,7 +2277,7 @@ ir.cpp:
# 503| r0_5(glval<float>) = VariableAddress[f] :
# 503| m0_6(float) = InitializeParameter[f] : r0_5
# 504| r0_7(glval<Point>) = VariableAddress[pt1] :
# 504| m0_8(Point) = Uninitialized : r0_7
# 504| m0_8(Point) = Uninitialized[pt1] : r0_7
# 504| r0_9(glval<int>) = FieldAddress[x] : r0_7
# 504| r0_10(glval<int>) = VariableAddress[x] :
# 504| r0_11(int) = Load : r0_10, m0_4
@@ -2286,7 +2290,7 @@ ir.cpp:
# 504| m0_18(int) = Store : r0_14, r0_17
# 504| m0_19(Point) = Chi : m0_13, m0_18
# 505| r0_20(glval<Point>) = VariableAddress[pt2] :
# 505| m0_21(Point) = Uninitialized : r0_20
# 505| m0_21(Point) = Uninitialized[pt2] : r0_20
# 505| r0_22(glval<int>) = FieldAddress[x] : r0_20
# 505| r0_23(glval<int>) = VariableAddress[x] :
# 505| r0_24(int) = Load : r0_23, m0_4
@@ -2297,7 +2301,7 @@ ir.cpp:
# 505| m0_29(int) = Store : r0_27, r0_28
# 505| m0_30(Point) = Chi : m0_26, m0_29
# 506| r0_31(glval<Point>) = VariableAddress[pt3] :
# 506| m0_32(Point) = Uninitialized : r0_31
# 506| m0_32(Point) = Uninitialized[pt3] : r0_31
# 506| r0_33(glval<int>) = FieldAddress[x] : r0_31
# 506| r0_34(int) = Constant[0] :
# 506| m0_35(int) = Store : r0_33, r0_34
@@ -2327,7 +2331,7 @@ ir.cpp:
# 512| r0_5(glval<float>) = VariableAddress[f] :
# 512| m0_6(float) = InitializeParameter[f] : r0_5
# 513| r0_7(glval<Rect>) = VariableAddress[r1] :
# 513| m0_8(Rect) = Uninitialized : r0_7
# 513| m0_8(Rect) = Uninitialized[r1] : r0_7
# 513| r0_9(glval<Point>) = FieldAddress[topLeft] : r0_7
# 513| r0_10(Point) = Constant[0] :
# 513| m0_11(Point) = Store : r0_9, r0_10
@@ -2337,7 +2341,7 @@ ir.cpp:
# 513| m0_15(Point) = Store : r0_13, r0_14
# 513| m0_16(Rect) = Chi : m0_12, m0_15
# 514| r0_17(glval<Rect>) = VariableAddress[r2] :
# 514| m0_18(Rect) = Uninitialized : r0_17
# 514| m0_18(Rect) = Uninitialized[r2] : r0_17
# 514| r0_19(glval<Point>) = FieldAddress[topLeft] : r0_17
# 514| r0_20(glval<int>) = FieldAddress[x] : r0_19
# 514| r0_21(glval<int>) = VariableAddress[x] :
@@ -2355,7 +2359,7 @@ ir.cpp:
# 514| m0_33(Point) = Store : r0_31, r0_32
# 514| m0_34(Rect) = Chi : m0_30, m0_33
# 515| r0_35(glval<Rect>) = VariableAddress[r3] :
# 515| m0_36(Rect) = Uninitialized : r0_35
# 515| m0_36(Rect) = Uninitialized[r3] : r0_35
# 515| r0_37(glval<Point>) = FieldAddress[topLeft] : r0_35
# 515| r0_38(glval<int>) = FieldAddress[x] : r0_37
# 515| r0_39(glval<int>) = VariableAddress[x] :
@@ -2381,7 +2385,7 @@ ir.cpp:
# 515| m0_59(int) = Store : r0_55, r0_58
# 515| m0_60(Rect) = Chi : m0_54, m0_59
# 516| r0_61(glval<Rect>) = VariableAddress[r4] :
# 516| m0_62(Rect) = Uninitialized : r0_61
# 516| m0_62(Rect) = Uninitialized[r4] : r0_61
# 516| r0_63(glval<Point>) = FieldAddress[topLeft] : r0_61
# 516| r0_64(glval<int>) = FieldAddress[x] : r0_63
# 516| r0_65(glval<int>) = VariableAddress[x] :
@@ -2417,49 +2421,52 @@ ir.cpp:
# 519| r0_5(glval<float>) = VariableAddress[f] :
# 519| m0_6(float) = InitializeParameter[f] : r0_5
# 520| r0_7(glval<int[3]>) = VariableAddress[a1] :
# 520| mu0_8(int[3]) = Uninitialized : r0_7
# 520| r0_9(int) = Constant[0] :
# 520| r0_10(glval<int>) = PointerAdd : r0_7, r0_9
# 520| r0_11(unknown[12]) = Constant[0] :
# 520| m0_12(unknown[12]) = Store : r0_10, r0_11
# 520| m0_13(unknown) = Chi : m0_1, m0_12
# 521| r0_14(glval<int[3]>) = VariableAddress[a2] :
# 521| mu0_15(int[3]) = Uninitialized : r0_14
# 521| r0_16(int) = Constant[0] :
# 521| r0_17(glval<int>) = PointerAdd : r0_14, r0_16
# 521| r0_18(glval<int>) = VariableAddress[x] :
# 521| r0_19(int) = Load : r0_18, m0_4
# 521| m0_20(int) = Store : r0_17, r0_19
# 521| m0_21(unknown) = Chi : m0_13, m0_20
# 521| r0_22(int) = Constant[1] :
# 521| r0_23(glval<int>) = PointerAdd : r0_14, r0_22
# 521| r0_24(glval<float>) = VariableAddress[f] :
# 521| r0_25(float) = Load : r0_24, m0_6
# 521| r0_26(int) = Convert : r0_25
# 521| m0_27(int) = Store : r0_23, r0_26
# 521| m0_28(unknown) = Chi : m0_21, m0_27
# 521| r0_29(int) = Constant[2] :
# 521| r0_30(glval<int>) = PointerAdd : r0_14, r0_29
# 521| r0_31(int) = Constant[0] :
# 521| m0_32(int) = Store : r0_30, r0_31
# 521| m0_33(unknown) = Chi : m0_28, m0_32
# 522| r0_34(glval<int[3]>) = VariableAddress[a3] :
# 522| mu0_35(int[3]) = Uninitialized : r0_34
# 522| r0_36(int) = Constant[0] :
# 522| r0_37(glval<int>) = PointerAdd : r0_34, r0_36
# 522| r0_38(glval<int>) = VariableAddress[x] :
# 522| r0_39(int) = Load : r0_38, m0_4
# 522| m0_40(int) = Store : r0_37, r0_39
# 522| m0_41(unknown) = Chi : m0_33, m0_40
# 522| r0_42(int) = Constant[1] :
# 522| r0_43(glval<int>) = PointerAdd : r0_34, r0_42
# 522| r0_44(unknown[8]) = Constant[0] :
# 522| m0_45(unknown[8]) = Store : r0_43, r0_44
# 522| m0_46(unknown) = Chi : m0_41, m0_45
# 523| v0_47(void) = NoOp :
# 519| v0_48(void) = ReturnVoid :
# 519| v0_49(void) = UnmodeledUse : mu*
# 519| v0_50(void) = ExitFunction :
# 520| m0_8(int[3]) = Uninitialized[a1] : r0_7
# 520| m0_9(unknown) = Chi : m0_1, m0_8
# 520| r0_10(int) = Constant[0] :
# 520| r0_11(glval<int>) = PointerAdd : r0_7, r0_10
# 520| r0_12(unknown[12]) = Constant[0] :
# 520| m0_13(unknown[12]) = Store : r0_11, r0_12
# 520| m0_14(unknown) = Chi : m0_9, m0_13
# 521| r0_15(glval<int[3]>) = VariableAddress[a2] :
# 521| m0_16(int[3]) = Uninitialized[a2] : r0_15
# 521| m0_17(unknown) = Chi : m0_14, m0_16
# 521| r0_18(int) = Constant[0] :
# 521| r0_19(glval<int>) = PointerAdd : r0_15, r0_18
# 521| r0_20(glval<int>) = VariableAddress[x] :
# 521| r0_21(int) = Load : r0_20, m0_4
# 521| m0_22(int) = Store : r0_19, r0_21
# 521| m0_23(unknown) = Chi : m0_17, m0_22
# 521| r0_24(int) = Constant[1] :
# 521| r0_25(glval<int>) = PointerAdd : r0_15, r0_24
# 521| r0_26(glval<float>) = VariableAddress[f] :
# 521| r0_27(float) = Load : r0_26, m0_6
# 521| r0_28(int) = Convert : r0_27
# 521| m0_29(int) = Store : r0_25, r0_28
# 521| m0_30(unknown) = Chi : m0_23, m0_29
# 521| r0_31(int) = Constant[2] :
# 521| r0_32(glval<int>) = PointerAdd : r0_15, r0_31
# 521| r0_33(int) = Constant[0] :
# 521| m0_34(int) = Store : r0_32, r0_33
# 521| m0_35(unknown) = Chi : m0_30, m0_34
# 522| r0_36(glval<int[3]>) = VariableAddress[a3] :
# 522| m0_37(int[3]) = Uninitialized[a3] : r0_36
# 522| m0_38(unknown) = Chi : m0_35, m0_37
# 522| r0_39(int) = Constant[0] :
# 522| r0_40(glval<int>) = PointerAdd : r0_36, r0_39
# 522| r0_41(glval<int>) = VariableAddress[x] :
# 522| r0_42(int) = Load : r0_41, m0_4
# 522| m0_43(int) = Store : r0_40, r0_42
# 522| m0_44(unknown) = Chi : m0_38, m0_43
# 522| r0_45(int) = Constant[1] :
# 522| r0_46(glval<int>) = PointerAdd : r0_36, r0_45
# 522| r0_47(unknown[8]) = Constant[0] :
# 522| m0_48(unknown[8]) = Store : r0_46, r0_47
# 522| m0_49(unknown) = Chi : m0_44, m0_48
# 523| v0_50(void) = NoOp :
# 519| v0_51(void) = ReturnVoid :
# 519| v0_52(void) = UnmodeledUse : mu*
# 519| v0_53(void) = ExitFunction :
# 530| UnionInit(int, float) -> void
# 530| Block 0
@@ -2471,7 +2478,7 @@ ir.cpp:
# 530| r0_5(glval<float>) = VariableAddress[f] :
# 530| m0_6(float) = InitializeParameter[f] : r0_5
# 531| r0_7(glval<U>) = VariableAddress[u1] :
# 531| m0_8(U) = Uninitialized : r0_7
# 531| m0_8(U) = Uninitialized[u1] : r0_7
# 531| r0_9(glval<double>) = FieldAddress[d] : r0_7
# 531| r0_10(glval<float>) = VariableAddress[f] :
# 531| r0_11(float) = Load : r0_10, m0_6
@@ -2630,69 +2637,74 @@ ir.cpp:
# 572| r0_3(glval<char[32]>) = VariableAddress[a_pad] :
# 572| r0_4(glval<char[1]>) = StringConstant[""] :
# 572| r0_5(char[1]) = Load : r0_4, m0_1
# 572| mu0_6(char[1]) = Store : r0_3, r0_5
# 572| r0_7(unknown[31]) = Constant[0] :
# 572| r0_8(int) = Constant[1] :
# 572| r0_9(glval<char>) = PointerAdd : r0_3, r0_8
# 572| m0_10(unknown[31]) = Store : r0_9, r0_7
# 572| m0_11(unknown) = Chi : m0_1, m0_10
# 573| r0_12(glval<char[4]>) = VariableAddress[a_nopad] :
# 573| r0_13(glval<char[4]>) = StringConstant["foo"] :
# 573| r0_14(char[4]) = Load : r0_13, m0_11
# 573| m0_15(char[4]) = Store : r0_12, r0_14
# 574| r0_16(glval<char[]>) = VariableAddress[a_infer] :
# 574| r0_17(glval<char[5]>) = StringConstant["blah"] :
# 574| r0_18(char[5]) = Load : r0_17, m0_11
# 574| m0_19(char[5]) = Store : r0_16, r0_18
# 575| r0_20(glval<char[2]>) = VariableAddress[b] :
# 575| m0_21(char[2]) = Uninitialized : r0_20
# 576| r0_22(glval<char[2]>) = VariableAddress[c] :
# 576| mu0_23(char[2]) = Uninitialized : r0_22
# 576| r0_24(int) = Constant[0] :
# 576| r0_25(glval<char>) = PointerAdd : r0_22, r0_24
# 576| r0_26(unknown[2]) = Constant[0] :
# 576| m0_27(unknown[2]) = Store : r0_25, r0_26
# 576| m0_28(unknown) = Chi : m0_11, m0_27
# 577| r0_29(glval<char[2]>) = VariableAddress[d] :
# 577| mu0_30(char[2]) = Uninitialized : r0_29
# 577| r0_31(int) = Constant[0] :
# 577| r0_32(glval<char>) = PointerAdd : r0_29, r0_31
# 577| r0_33(char) = Constant[0] :
# 577| m0_34(char) = Store : r0_32, r0_33
# 577| m0_35(unknown) = Chi : m0_28, m0_34
# 577| r0_36(int) = Constant[1] :
# 577| r0_37(glval<char>) = PointerAdd : r0_29, r0_36
# 577| r0_38(char) = Constant[0] :
# 577| m0_39(char) = Store : r0_37, r0_38
# 577| m0_40(unknown) = Chi : m0_35, m0_39
# 578| r0_41(glval<char[2]>) = VariableAddress[e] :
# 578| mu0_42(char[2]) = Uninitialized : r0_41
# 578| r0_43(int) = Constant[0] :
# 578| r0_44(glval<char>) = PointerAdd : r0_41, r0_43
# 578| r0_45(char) = Constant[0] :
# 578| m0_46(char) = Store : r0_44, r0_45
# 578| m0_47(unknown) = Chi : m0_40, m0_46
# 578| r0_48(int) = Constant[1] :
# 578| r0_49(glval<char>) = PointerAdd : r0_41, r0_48
# 578| r0_50(char) = Constant[1] :
# 578| m0_51(char) = Store : r0_49, r0_50
# 578| m0_52(unknown) = Chi : m0_47, m0_51
# 579| r0_53(glval<char[3]>) = VariableAddress[f] :
# 579| mu0_54(char[3]) = Uninitialized : r0_53
# 579| r0_55(int) = Constant[0] :
# 579| r0_56(glval<char>) = PointerAdd : r0_53, r0_55
# 579| r0_57(char) = Constant[0] :
# 579| m0_58(char) = Store : r0_56, r0_57
# 579| m0_59(unknown) = Chi : m0_52, m0_58
# 579| r0_60(int) = Constant[1] :
# 579| r0_61(glval<char>) = PointerAdd : r0_53, r0_60
# 579| r0_62(unknown[2]) = Constant[0] :
# 579| m0_63(unknown[2]) = Store : r0_61, r0_62
# 572| m0_6(char[1]) = Store : r0_3, r0_5
# 572| m0_7(unknown) = Chi : m0_1, m0_6
# 572| r0_8(unknown[31]) = Constant[0] :
# 572| r0_9(int) = Constant[1] :
# 572| r0_10(glval<char>) = PointerAdd : r0_3, r0_9
# 572| m0_11(unknown[31]) = Store : r0_10, r0_8
# 572| m0_12(unknown) = Chi : m0_7, m0_11
# 573| r0_13(glval<char[4]>) = VariableAddress[a_nopad] :
# 573| r0_14(glval<char[4]>) = StringConstant["foo"] :
# 573| r0_15(char[4]) = Load : r0_14, m0_12
# 573| m0_16(char[4]) = Store : r0_13, r0_15
# 574| r0_17(glval<char[]>) = VariableAddress[a_infer] :
# 574| r0_18(glval<char[5]>) = StringConstant["blah"] :
# 574| r0_19(char[5]) = Load : r0_18, m0_12
# 574| m0_20(char[5]) = Store : r0_17, r0_19
# 575| r0_21(glval<char[2]>) = VariableAddress[b] :
# 575| m0_22(char[2]) = Uninitialized[b] : r0_21
# 576| r0_23(glval<char[2]>) = VariableAddress[c] :
# 576| m0_24(char[2]) = Uninitialized[c] : r0_23
# 576| m0_25(unknown) = Chi : m0_12, m0_24
# 576| r0_26(int) = Constant[0] :
# 576| r0_27(glval<char>) = PointerAdd : r0_23, r0_26
# 576| r0_28(unknown[2]) = Constant[0] :
# 576| m0_29(unknown[2]) = Store : r0_27, r0_28
# 576| m0_30(unknown) = Chi : m0_25, m0_29
# 577| r0_31(glval<char[2]>) = VariableAddress[d] :
# 577| m0_32(char[2]) = Uninitialized[d] : r0_31
# 577| m0_33(unknown) = Chi : m0_30, m0_32
# 577| r0_34(int) = Constant[0] :
# 577| r0_35(glval<char>) = PointerAdd : r0_31, r0_34
# 577| r0_36(char) = Constant[0] :
# 577| m0_37(char) = Store : r0_35, r0_36
# 577| m0_38(unknown) = Chi : m0_33, m0_37
# 577| r0_39(int) = Constant[1] :
# 577| r0_40(glval<char>) = PointerAdd : r0_31, r0_39
# 577| r0_41(char) = Constant[0] :
# 577| m0_42(char) = Store : r0_40, r0_41
# 577| m0_43(unknown) = Chi : m0_38, m0_42
# 578| r0_44(glval<char[2]>) = VariableAddress[e] :
# 578| m0_45(char[2]) = Uninitialized[e] : r0_44
# 578| m0_46(unknown) = Chi : m0_43, m0_45
# 578| r0_47(int) = Constant[0] :
# 578| r0_48(glval<char>) = PointerAdd : r0_44, r0_47
# 578| r0_49(char) = Constant[0] :
# 578| m0_50(char) = Store : r0_48, r0_49
# 578| m0_51(unknown) = Chi : m0_46, m0_50
# 578| r0_52(int) = Constant[1] :
# 578| r0_53(glval<char>) = PointerAdd : r0_44, r0_52
# 578| r0_54(char) = Constant[1] :
# 578| m0_55(char) = Store : r0_53, r0_54
# 578| m0_56(unknown) = Chi : m0_51, m0_55
# 579| r0_57(glval<char[3]>) = VariableAddress[f] :
# 579| m0_58(char[3]) = Uninitialized[f] : r0_57
# 579| m0_59(unknown) = Chi : m0_56, m0_58
# 579| r0_60(int) = Constant[0] :
# 579| r0_61(glval<char>) = PointerAdd : r0_57, r0_60
# 579| r0_62(char) = Constant[0] :
# 579| m0_63(char) = Store : r0_61, r0_62
# 579| m0_64(unknown) = Chi : m0_59, m0_63
# 580| v0_65(void) = NoOp :
# 571| v0_66(void) = ReturnVoid :
# 571| v0_67(void) = UnmodeledUse : mu*
# 571| v0_68(void) = ExitFunction :
# 579| r0_65(int) = Constant[1] :
# 579| r0_66(glval<char>) = PointerAdd : r0_57, r0_65
# 579| r0_67(unknown[2]) = Constant[0] :
# 579| m0_68(unknown[2]) = Store : r0_66, r0_67
# 579| m0_69(unknown) = Chi : m0_64, m0_68
# 580| v0_70(void) = NoOp :
# 571| v0_71(void) = ReturnVoid :
# 571| v0_72(void) = UnmodeledUse : mu*
# 571| v0_73(void) = ExitFunction :
# 584| VarArgs() -> void
# 584| Block 0
@@ -2780,31 +2792,32 @@ ir.cpp:
# 622| r0_5(glval<String *>) = VariableAddress[p] :
# 622| m0_6(String *) = InitializeParameter[p] : r0_5
# 622| r0_7(glval<String>) = VariableAddress[s] :
# 622| mu0_8(String) = InitializeParameter[s] : r0_7
# 623| r0_9(glval<String &>) = VariableAddress[r] :
# 623| r0_10(String &) = Load : r0_9, m0_4
# 623| r0_11(glval<String>) = Convert : r0_10
# 623| r0_12(glval<unknown>) = FunctionAddress[c_str] :
# 623| r0_13(char *) = Call : r0_12, this:r0_11
# 623| m0_14(unknown) = ^CallSideEffect : m0_1
# 623| m0_15(unknown) = Chi : m0_1, m0_14
# 624| r0_16(glval<String *>) = VariableAddress[p] :
# 624| r0_17(String *) = Load : r0_16, m0_6
# 624| r0_18(String *) = Convert : r0_17
# 624| r0_19(glval<unknown>) = FunctionAddress[c_str] :
# 624| r0_20(char *) = Call : r0_19, this:r0_18
# 624| m0_21(unknown) = ^CallSideEffect : m0_15
# 624| m0_22(unknown) = Chi : m0_15, m0_21
# 625| r0_23(glval<String>) = VariableAddress[s] :
# 625| r0_24(glval<String>) = Convert : r0_23
# 625| r0_25(glval<unknown>) = FunctionAddress[c_str] :
# 625| r0_26(char *) = Call : r0_25, this:r0_24
# 625| m0_27(unknown) = ^CallSideEffect : m0_22
# 625| m0_28(unknown) = Chi : m0_22, m0_27
# 626| v0_29(void) = NoOp :
# 622| v0_30(void) = ReturnVoid :
# 622| v0_31(void) = UnmodeledUse : mu*
# 622| v0_32(void) = ExitFunction :
# 622| m0_8(String) = InitializeParameter[s] : r0_7
# 622| m0_9(unknown) = Chi : m0_1, m0_8
# 623| r0_10(glval<String &>) = VariableAddress[r] :
# 623| r0_11(String &) = Load : r0_10, m0_4
# 623| r0_12(glval<String>) = Convert : r0_11
# 623| r0_13(glval<unknown>) = FunctionAddress[c_str] :
# 623| r0_14(char *) = Call : r0_13, this:r0_12
# 623| m0_15(unknown) = ^CallSideEffect : m0_9
# 623| m0_16(unknown) = Chi : m0_9, m0_15
# 624| r0_17(glval<String *>) = VariableAddress[p] :
# 624| r0_18(String *) = Load : r0_17, m0_6
# 624| r0_19(String *) = Convert : r0_18
# 624| r0_20(glval<unknown>) = FunctionAddress[c_str] :
# 624| r0_21(char *) = Call : r0_20, this:r0_19
# 624| m0_22(unknown) = ^CallSideEffect : m0_16
# 624| m0_23(unknown) = Chi : m0_16, m0_22
# 625| r0_24(glval<String>) = VariableAddress[s] :
# 625| r0_25(glval<String>) = Convert : r0_24
# 625| r0_26(glval<unknown>) = FunctionAddress[c_str] :
# 625| r0_27(char *) = Call : r0_26, this:r0_25
# 625| m0_28(unknown) = ^CallSideEffect : m0_23
# 625| m0_29(unknown) = Chi : m0_23, m0_28
# 626| v0_30(void) = NoOp :
# 622| v0_31(void) = ReturnVoid :
# 622| v0_32(void) = UnmodeledUse : mu*
# 622| v0_33(void) = ExitFunction :
# 630| C::StaticMemberFunction(int) -> int
# 630| Block 0
@@ -2878,7 +2891,7 @@ ir.cpp:
# 645| m0_17(int) = Store : r0_16, r0_14
# 645| m0_18(unknown) = Chi : m0_13, m0_17
# 646| r0_19(glval<int>) = VariableAddress[x] :
# 646| m0_20(int) = Uninitialized : r0_19
# 646| m0_20(int) = Uninitialized[x] : r0_19
# 647| r0_21(C *) = CopyValue : r0_3
# 647| r0_22(glval<int>) = FieldAddress[m_a] : r0_21
# 647| r0_23(int) = Load : r0_22, m0_18
@@ -3025,7 +3038,7 @@ ir.cpp:
# 691| m0_1(unknown) = AliasedDefinition :
# 691| mu0_2(unknown) = UnmodeledDefinition :
# 692| r0_3(glval<int[10]>) = VariableAddress[a] :
# 692| m0_4(int[10]) = Uninitialized : r0_3
# 692| m0_4(int[10]) = Uninitialized[a] : r0_3
# 693| r0_5(glval<int(&)[10]>) = VariableAddress[ra] :
# 693| r0_6(glval<int[10]>) = VariableAddress[a] :
# 693| m0_7(int(&)[10]) = Store : r0_5, r0_6
@@ -4000,7 +4013,7 @@ ir.cpp:
# 871| m0_1(unknown) = AliasedDefinition :
# 871| mu0_2(unknown) = UnmodeledDefinition :
# 872| r0_3(glval<char[5]>) = VariableAddress[a] :
# 872| m0_4(char[5]) = Uninitialized : r0_3
# 872| m0_4(char[5]) = Uninitialized[a] : r0_3
# 873| r0_5(glval<char *>) = VariableAddress[p] :
# 873| r0_6(glval<char[5]>) = VariableAddress[a] :
# 873| r0_7(char *) = Convert : r0_6
@@ -4071,43 +4084,46 @@ ir.cpp:
# 888| m0_1(unknown) = AliasedDefinition :
# 888| mu0_2(unknown) = UnmodeledDefinition :
# 888| r0_3(glval<int>) = VariableAddress[x] :
# 888| mu0_4(int) = InitializeParameter[x] : r0_3
# 889| r0_5(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 889| mu0_6(__va_list_tag[1]) = Uninitialized : r0_5
# 891| r0_7(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 891| r0_8(__va_list_tag *) = Convert : r0_7
# 891| r0_9(glval<int>) = VariableAddress[x] :
# 891| v0_10(void) = VarArgsStart : r0_8, r0_9
# 892| r0_11(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 892| mu0_12(__va_list_tag[1]) = Uninitialized : r0_11
# 893| r0_13(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 893| r0_14(__va_list_tag *) = Convert : r0_13
# 893| r0_15(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 893| r0_16(__va_list_tag *) = Convert : r0_15
# 893| v0_17(void) = VarArgsStart : r0_14, r0_16
# 894| r0_18(glval<double>) = VariableAddress[d] :
# 894| r0_19(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 894| r0_20(__va_list_tag *) = Convert : r0_19
# 894| r0_21(glval<double>) = VarArg : r0_20
# 894| r0_22(double) = Load : r0_21, m0_1
# 894| m0_23(double) = Store : r0_18, r0_22
# 895| r0_24(glval<float>) = VariableAddress[f] :
# 895| r0_25(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 895| r0_26(__va_list_tag *) = Convert : r0_25
# 895| r0_27(glval<double>) = VarArg : r0_26
# 895| r0_28(double) = Load : r0_27, m0_1
# 895| r0_29(float) = Convert : r0_28
# 895| m0_30(float) = Store : r0_24, r0_29
# 896| r0_31(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 896| r0_32(__va_list_tag *) = Convert : r0_31
# 896| v0_33(void) = VarArgsEnd : r0_32
# 897| r0_34(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 897| r0_35(__va_list_tag *) = Convert : r0_34
# 897| v0_36(void) = VarArgsEnd : r0_35
# 898| v0_37(void) = NoOp :
# 888| v0_38(void) = ReturnVoid :
# 888| v0_39(void) = UnmodeledUse : mu*
# 888| v0_40(void) = ExitFunction :
# 888| m0_4(int) = InitializeParameter[x] : r0_3
# 888| m0_5(unknown) = Chi : m0_1, m0_4
# 889| r0_6(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 889| m0_7(__va_list_tag[1]) = Uninitialized[args] : r0_6
# 889| m0_8(unknown) = Chi : m0_5, m0_7
# 891| r0_9(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 891| r0_10(__va_list_tag *) = Convert : r0_9
# 891| r0_11(glval<int>) = VariableAddress[x] :
# 891| v0_12(void) = VarArgsStart : r0_10, r0_11
# 892| r0_13(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 892| m0_14(__va_list_tag[1]) = Uninitialized[args2] : r0_13
# 892| m0_15(unknown) = Chi : m0_8, m0_14
# 893| r0_16(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 893| r0_17(__va_list_tag *) = Convert : r0_16
# 893| r0_18(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 893| r0_19(__va_list_tag *) = Convert : r0_18
# 893| v0_20(void) = VarArgsStart : r0_17, r0_19
# 894| r0_21(glval<double>) = VariableAddress[d] :
# 894| r0_22(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 894| r0_23(__va_list_tag *) = Convert : r0_22
# 894| r0_24(glval<double>) = VarArg : r0_23
# 894| r0_25(double) = Load : r0_24, m0_15
# 894| m0_26(double) = Store : r0_21, r0_25
# 895| r0_27(glval<float>) = VariableAddress[f] :
# 895| r0_28(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 895| r0_29(__va_list_tag *) = Convert : r0_28
# 895| r0_30(glval<double>) = VarArg : r0_29
# 895| r0_31(double) = Load : r0_30, m0_15
# 895| r0_32(float) = Convert : r0_31
# 895| m0_33(float) = Store : r0_27, r0_32
# 896| r0_34(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 896| r0_35(__va_list_tag *) = Convert : r0_34
# 896| v0_36(void) = VarArgsEnd : r0_35
# 897| r0_37(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 897| r0_38(__va_list_tag *) = Convert : r0_37
# 897| v0_39(void) = VarArgsEnd : r0_38
# 898| v0_40(void) = NoOp :
# 888| v0_41(void) = ReturnVoid :
# 888| v0_42(void) = UnmodeledUse : mu*
# 888| v0_43(void) = ExitFunction :
# 900| CastToVoid(int) -> void
# 900| Block 0
@@ -4115,13 +4131,14 @@ ir.cpp:
# 900| m0_1(unknown) = AliasedDefinition :
# 900| mu0_2(unknown) = UnmodeledDefinition :
# 900| r0_3(glval<int>) = VariableAddress[x] :
# 900| mu0_4(int) = InitializeParameter[x] : r0_3
# 901| r0_5(glval<int>) = VariableAddress[x] :
# 901| v0_6(void) = Convert : r0_5
# 902| v0_7(void) = NoOp :
# 900| v0_8(void) = ReturnVoid :
# 900| v0_9(void) = UnmodeledUse : mu*
# 900| v0_10(void) = ExitFunction :
# 900| m0_4(int) = InitializeParameter[x] : r0_3
# 900| m0_5(unknown) = Chi : m0_1, m0_4
# 901| r0_6(glval<int>) = VariableAddress[x] :
# 901| v0_7(void) = Convert : r0_6
# 902| v0_8(void) = NoOp :
# 900| v0_9(void) = ReturnVoid :
# 900| v0_10(void) = UnmodeledUse : mu*
# 900| v0_11(void) = ExitFunction :
# 904| ConstantConditions(int) -> void
# 904| Block 0
@@ -4330,43 +4347,44 @@ ir.cpp:
# 961| m0_1(unknown) = AliasedDefinition :
# 961| mu0_2(unknown) = UnmodeledDefinition :
# 962| r0_3(glval<int[1000]>) = VariableAddress[a1] :
# 962| mu0_4(int[1000]) = Uninitialized : r0_3
# 962| r0_5(int) = Constant[0] :
# 962| r0_6(glval<int>) = PointerAdd : r0_3, r0_5
# 962| r0_7(unknown[8]) = Constant[0] :
# 962| m0_8(unknown[8]) = Store : r0_6, r0_7
# 962| m0_9(unknown) = Chi : m0_1, m0_8
# 962| r0_10(int) = Constant[2] :
# 962| r0_11(glval<int>) = PointerAdd : r0_3, r0_10
# 962| r0_12(int) = Constant[10002] :
# 962| m0_13(int) = Store : r0_11, r0_12
# 962| m0_14(unknown) = Chi : m0_9, m0_13
# 962| r0_15(int) = Constant[3] :
# 962| r0_16(glval<int>) = PointerAdd : r0_3, r0_15
# 962| r0_17(unknown[3588]) = Constant[0] :
# 962| m0_18(unknown[3588]) = Store : r0_16, r0_17
# 962| m0_19(unknown) = Chi : m0_14, m0_18
# 962| r0_20(int) = Constant[900] :
# 962| r0_21(glval<int>) = PointerAdd : r0_3, r0_20
# 962| r0_22(int) = Constant[10900] :
# 962| m0_23(int) = Store : r0_21, r0_22
# 962| m0_24(unknown) = Chi : m0_19, m0_23
# 962| r0_25(int) = Constant[901] :
# 962| r0_26(glval<int>) = PointerAdd : r0_3, r0_25
# 962| r0_27(unknown[396]) = Constant[0] :
# 962| m0_28(unknown[396]) = Store : r0_26, r0_27
# 962| m0_29(unknown) = Chi : m0_24, m0_28
# 963| r0_30(glval<int>) = VariableAddress[#return] :
# 963| r0_31(glval<int[1000]>) = VariableAddress[a1] :
# 963| r0_32(int *) = Convert : r0_31
# 963| r0_33(int) = Constant[900] :
# 963| r0_34(int *) = PointerAdd[4] : r0_32, r0_33
# 963| r0_35(int) = Load : r0_34, mu0_2
# 963| m0_36(int) = Store : r0_30, r0_35
# 961| r0_37(glval<int>) = VariableAddress[#return] :
# 961| v0_38(void) = ReturnValue : r0_37, m0_36
# 961| v0_39(void) = UnmodeledUse : mu*
# 961| v0_40(void) = ExitFunction :
# 962| m0_4(int[1000]) = Uninitialized[a1] : r0_3
# 962| m0_5(unknown) = Chi : m0_1, m0_4
# 962| r0_6(int) = Constant[0] :
# 962| r0_7(glval<int>) = PointerAdd : r0_3, r0_6
# 962| r0_8(unknown[8]) = Constant[0] :
# 962| m0_9(unknown[8]) = Store : r0_7, r0_8
# 962| m0_10(unknown) = Chi : m0_5, m0_9
# 962| r0_11(int) = Constant[2] :
# 962| r0_12(glval<int>) = PointerAdd : r0_3, r0_11
# 962| r0_13(int) = Constant[10002] :
# 962| m0_14(int) = Store : r0_12, r0_13
# 962| m0_15(unknown) = Chi : m0_10, m0_14
# 962| r0_16(int) = Constant[3] :
# 962| r0_17(glval<int>) = PointerAdd : r0_3, r0_16
# 962| r0_18(unknown[3588]) = Constant[0] :
# 962| m0_19(unknown[3588]) = Store : r0_17, r0_18
# 962| m0_20(unknown) = Chi : m0_15, m0_19
# 962| r0_21(int) = Constant[900] :
# 962| r0_22(glval<int>) = PointerAdd : r0_3, r0_21
# 962| r0_23(int) = Constant[10900] :
# 962| m0_24(int) = Store : r0_22, r0_23
# 962| m0_25(unknown) = Chi : m0_20, m0_24
# 962| r0_26(int) = Constant[901] :
# 962| r0_27(glval<int>) = PointerAdd : r0_3, r0_26
# 962| r0_28(unknown[396]) = Constant[0] :
# 962| m0_29(unknown[396]) = Store : r0_27, r0_28
# 962| m0_30(unknown) = Chi : m0_25, m0_29
# 963| r0_31(glval<int>) = VariableAddress[#return] :
# 963| r0_32(glval<int[1000]>) = VariableAddress[a1] :
# 963| r0_33(int *) = Convert : r0_32
# 963| r0_34(int) = Constant[900] :
# 963| r0_35(int *) = PointerAdd[4] : r0_33, r0_34
# 963| r0_36(int) = Load : r0_35, mu0_2
# 963| m0_37(int) = Store : r0_31, r0_36
# 961| r0_38(glval<int>) = VariableAddress[#return] :
# 961| v0_39(void) = ReturnValue : r0_38, m0_37
# 961| v0_40(void) = UnmodeledUse : mu*
# 961| v0_41(void) = ExitFunction :
# 966| IfStmtWithDeclaration(int, int) -> void
# 966| Block 0

View File

@@ -5,7 +5,7 @@ bad_asts.cpp:
# 14| mu0_1(unknown) = AliasedDefinition :
# 14| mu0_2(unknown) = UnmodeledDefinition :
# 15| r0_3(glval<S>) = VariableAddress[s] :
# 15| mu0_4(S) = Uninitialized : r0_3
# 15| mu0_4(S) = Uninitialized[s] : r0_3
# 15| r0_5(glval<int>) = FieldAddress[x] : r0_3
# 15| r0_6(int) = Constant[0] :
# 15| mu0_7(int) = Store : r0_5, r0_6
@@ -186,7 +186,7 @@ ir.cpp:
# 50| r0_5(glval<int>) = VariableAddress[y] :
# 50| mu0_6(int) = InitializeParameter[y] : r0_5
# 51| r0_7(glval<int>) = VariableAddress[z] :
# 51| mu0_8(int) = Uninitialized : r0_7
# 51| mu0_8(int) = Uninitialized[z] : r0_7
# 53| r0_9(glval<int>) = VariableAddress[x] :
# 53| r0_10(int) = Load : r0_9, mu0_2
# 53| r0_11(glval<int>) = VariableAddress[y] :
@@ -359,7 +359,7 @@ ir.cpp:
# 87| r0_5(glval<int>) = VariableAddress[y] :
# 87| mu0_6(int) = InitializeParameter[y] : r0_5
# 88| r0_7(glval<bool>) = VariableAddress[b] :
# 88| mu0_8(bool) = Uninitialized : r0_7
# 88| mu0_8(bool) = Uninitialized[b] : r0_7
# 90| r0_9(glval<int>) = VariableAddress[x] :
# 90| r0_10(int) = Load : r0_9, mu0_2
# 90| r0_11(glval<int>) = VariableAddress[y] :
@@ -415,7 +415,7 @@ ir.cpp:
# 98| r0_3(glval<int>) = VariableAddress[x] :
# 98| mu0_4(int) = InitializeParameter[x] : r0_3
# 99| r0_5(glval<int>) = VariableAddress[y] :
# 99| mu0_6(int) = Uninitialized : r0_5
# 99| mu0_6(int) = Uninitialized[y] : r0_5
# 101| r0_7(glval<int>) = VariableAddress[x] :
# 101| r0_8(int) = Load : r0_7, mu0_2
# 101| r0_9(int) = Constant[1] :
@@ -457,7 +457,7 @@ ir.cpp:
# 107| r0_3(glval<int>) = VariableAddress[x] :
# 107| mu0_4(int) = InitializeParameter[x] : r0_3
# 108| r0_5(glval<int *>) = VariableAddress[p] :
# 108| mu0_6(int *) = Uninitialized : r0_5
# 108| mu0_6(int *) = Uninitialized[p] : r0_5
# 110| r0_7(glval<int>) = VariableAddress[x] :
# 110| r0_8(int) = Load : r0_7, mu0_2
# 110| r0_9(int) = Constant[1] :
@@ -487,7 +487,7 @@ ir.cpp:
# 114| r0_5(glval<double>) = VariableAddress[y] :
# 114| mu0_6(double) = InitializeParameter[y] : r0_5
# 115| r0_7(glval<double>) = VariableAddress[z] :
# 115| mu0_8(double) = Uninitialized : r0_7
# 115| mu0_8(double) = Uninitialized[z] : r0_7
# 117| r0_9(glval<double>) = VariableAddress[x] :
# 117| r0_10(double) = Load : r0_9, mu0_2
# 117| r0_11(glval<double>) = VariableAddress[y] :
@@ -569,7 +569,7 @@ ir.cpp:
# 133| r0_5(glval<double>) = VariableAddress[y] :
# 133| mu0_6(double) = InitializeParameter[y] : r0_5
# 134| r0_7(glval<bool>) = VariableAddress[b] :
# 134| mu0_8(bool) = Uninitialized : r0_7
# 134| mu0_8(bool) = Uninitialized[b] : r0_7
# 136| r0_9(glval<double>) = VariableAddress[x] :
# 136| r0_10(double) = Load : r0_9, mu0_2
# 136| r0_11(glval<double>) = VariableAddress[y] :
@@ -625,7 +625,7 @@ ir.cpp:
# 144| r0_3(glval<float>) = VariableAddress[x] :
# 144| mu0_4(float) = InitializeParameter[x] : r0_3
# 145| r0_5(glval<float>) = VariableAddress[y] :
# 145| mu0_6(float) = Uninitialized : r0_5
# 145| mu0_6(float) = Uninitialized[y] : r0_5
# 147| r0_7(glval<float>) = VariableAddress[x] :
# 147| r0_8(float) = Load : r0_7, mu0_2
# 147| r0_9(float) = Constant[1.0] :
@@ -669,9 +669,9 @@ ir.cpp:
# 153| r0_5(glval<int>) = VariableAddress[i] :
# 153| mu0_6(int) = InitializeParameter[i] : r0_5
# 154| r0_7(glval<int *>) = VariableAddress[q] :
# 154| mu0_8(int *) = Uninitialized : r0_7
# 154| mu0_8(int *) = Uninitialized[q] : r0_7
# 155| r0_9(glval<bool>) = VariableAddress[b] :
# 155| mu0_10(bool) = Uninitialized : r0_9
# 155| mu0_10(bool) = Uninitialized[b] : r0_9
# 157| r0_11(glval<int *>) = VariableAddress[p] :
# 157| r0_12(int *) = Load : r0_11, mu0_2
# 157| r0_13(glval<int>) = VariableAddress[i] :
@@ -745,7 +745,7 @@ ir.cpp:
# 171| r0_5(glval<int>) = VariableAddress[i] :
# 171| mu0_6(int) = InitializeParameter[i] : r0_5
# 172| r0_7(glval<int>) = VariableAddress[x] :
# 172| mu0_8(int) = Uninitialized : r0_7
# 172| mu0_8(int) = Uninitialized[x] : r0_7
# 174| r0_9(glval<int *>) = VariableAddress[p] :
# 174| r0_10(int *) = Load : r0_9, mu0_2
# 174| r0_11(glval<int>) = VariableAddress[i] :
@@ -779,7 +779,7 @@ ir.cpp:
# 178| r0_39(int *) = PointerAdd[4] : r0_36, r0_38
# 178| mu0_40(int) = Store : r0_39, r0_34
# 180| r0_41(glval<int[10]>) = VariableAddress[a] :
# 180| mu0_42(int[10]) = Uninitialized : r0_41
# 180| mu0_42(int[10]) = Uninitialized[a] : r0_41
# 181| r0_43(glval<int[10]>) = VariableAddress[a] :
# 181| r0_44(int *) = Convert : r0_43
# 181| r0_45(glval<int>) = VariableAddress[i] :
@@ -860,7 +860,7 @@ ir.cpp:
# 193| r0_5(glval<int *>) = VariableAddress[q] :
# 193| mu0_6(int *) = InitializeParameter[q] : r0_5
# 194| r0_7(glval<bool>) = VariableAddress[b] :
# 194| mu0_8(bool) = Uninitialized : r0_7
# 194| mu0_8(bool) = Uninitialized[b] : r0_7
# 196| r0_9(glval<int *>) = VariableAddress[p] :
# 196| r0_10(int *) = Load : r0_9, mu0_2
# 196| r0_11(glval<int *>) = VariableAddress[q] :
@@ -916,7 +916,7 @@ ir.cpp:
# 204| r0_3(glval<int *>) = VariableAddress[p] :
# 204| mu0_4(int *) = InitializeParameter[p] : r0_3
# 205| r0_5(glval<int *>) = VariableAddress[q] :
# 205| mu0_6(int *) = Uninitialized : r0_5
# 205| mu0_6(int *) = Uninitialized[q] : r0_5
# 207| r0_7(glval<int *>) = VariableAddress[p] :
# 207| r0_8(int *) = Load : r0_7, mu0_2
# 207| r0_9(int) = Constant[1] :
@@ -1000,7 +1000,7 @@ ir.cpp:
# 230| mu0_1(unknown) = AliasedDefinition :
# 230| mu0_2(unknown) = UnmodeledDefinition :
# 231| r0_3(glval<int>) = VariableAddress[x] :
# 231| mu0_4(int) = Uninitialized : r0_3
# 231| mu0_4(int) = Uninitialized[x] : r0_3
# 232| r0_5(glval<int>) = VariableAddress[y] :
# 232| r0_6(glval<int>) = VariableAddress[x] :
# 232| r0_7(int) = Load : r0_6, mu0_2
@@ -1160,7 +1160,7 @@ ir.cpp:
# 265| mu0_1(unknown) = AliasedDefinition :
# 265| mu0_2(unknown) = UnmodeledDefinition :
# 266| r0_3(glval<int>) = VariableAddress[j] :
# 266| mu0_4(int) = Uninitialized : r0_3
# 266| mu0_4(int) = Uninitialized[j] : r0_3
#-----| Goto -> Block 2
# 265| Block 1
@@ -1697,7 +1697,7 @@ ir.cpp:
# 384| r0_3(glval<int>) = VariableAddress[x] :
# 384| mu0_4(int) = InitializeParameter[x] : r0_3
# 385| r0_5(glval<int>) = VariableAddress[y] :
# 385| mu0_6(int) = Uninitialized : r0_5
# 385| mu0_6(int) = Uninitialized[y] : r0_5
# 386| r0_7(glval<int>) = VariableAddress[x] :
# 386| r0_8(int) = Load : r0_7, mu0_2
# 386| v0_9(void) = Switch : r0_8
@@ -1792,7 +1792,7 @@ ir.cpp:
# 426| mu0_1(unknown) = AliasedDefinition :
# 426| mu0_2(unknown) = UnmodeledDefinition :
# 427| r0_3(glval<Point>) = VariableAddress[pt] :
# 427| mu0_4(Point) = Uninitialized : r0_3
# 427| mu0_4(Point) = Uninitialized[pt] : r0_3
# 428| r0_5(int) = Constant[5] :
# 428| r0_6(glval<Point>) = VariableAddress[pt] :
# 428| r0_7(glval<int>) = FieldAddress[x] : r0_6
@@ -1822,7 +1822,7 @@ ir.cpp:
# 433| r0_5(glval<bool>) = VariableAddress[b] :
# 433| mu0_6(bool) = InitializeParameter[b] : r0_5
# 434| r0_7(glval<int>) = VariableAddress[x] :
# 434| mu0_8(int) = Uninitialized : r0_7
# 434| mu0_8(int) = Uninitialized[x] : r0_7
# 435| r0_9(glval<bool>) = VariableAddress[a] :
# 435| r0_10(bool) = Load : r0_9, mu0_2
# 435| v0_11(void) = ConditionalBranch : r0_10
@@ -1884,7 +1884,7 @@ ir.cpp:
# 447| r0_5(glval<bool>) = VariableAddress[b] :
# 447| mu0_6(bool) = InitializeParameter[b] : r0_5
# 448| r0_7(glval<int>) = VariableAddress[x] :
# 448| mu0_8(int) = Uninitialized : r0_7
# 448| mu0_8(int) = Uninitialized[x] : r0_7
# 449| r0_9(glval<bool>) = VariableAddress[a] :
# 449| r0_10(bool) = Load : r0_9, mu0_2
# 449| v0_11(void) = ConditionalBranch : r0_10
@@ -1946,7 +1946,7 @@ ir.cpp:
# 461| r0_5(glval<bool>) = VariableAddress[b] :
# 461| mu0_6(bool) = InitializeParameter[b] : r0_5
# 462| r0_7(glval<int>) = VariableAddress[x] :
# 462| mu0_8(int) = Uninitialized : r0_7
# 462| mu0_8(int) = Uninitialized[x] : r0_7
# 463| r0_9(glval<bool>) = VariableAddress[a] :
# 463| r0_10(bool) = Load : r0_9, mu0_2
# 463| v0_11(void) = ConditionalBranch : r0_10
@@ -2001,7 +2001,7 @@ ir.cpp:
# 475| r0_5(glval<bool>) = VariableAddress[b] :
# 475| mu0_6(bool) = InitializeParameter[b] : r0_5
# 476| r0_7(glval<bool>) = VariableAddress[x] :
# 476| mu0_8(bool) = Uninitialized : r0_7
# 476| mu0_8(bool) = Uninitialized[x] : r0_7
# 477| r0_9(glval<bool>) = VariableAddress[a] :
# 477| r0_10(bool) = Load : r0_9, mu0_2
# 477| v0_11(void) = ConditionalBranch : r0_10
@@ -2147,9 +2147,9 @@ ir.cpp:
# 486| r0_3(glval<bool>) = VariableAddress[a] :
# 486| mu0_4(bool) = InitializeParameter[a] : r0_3
# 487| r0_5(glval<int>) = VariableAddress[x] :
# 487| mu0_6(int) = Uninitialized : r0_5
# 487| mu0_6(int) = Uninitialized[x] : r0_5
# 488| r0_7(glval<int>) = VariableAddress[y] :
# 488| mu0_8(int) = Uninitialized : r0_7
# 488| mu0_8(int) = Uninitialized[y] : r0_7
# 489| r0_9(int) = Constant[5] :
# 489| r0_10(glval<bool>) = VariableAddress[a] :
# 489| r0_11(bool) = Load : r0_10, mu0_2
@@ -2241,7 +2241,7 @@ ir.cpp:
# 503| r0_5(glval<float>) = VariableAddress[f] :
# 503| mu0_6(float) = InitializeParameter[f] : r0_5
# 504| r0_7(glval<Point>) = VariableAddress[pt1] :
# 504| mu0_8(Point) = Uninitialized : r0_7
# 504| mu0_8(Point) = Uninitialized[pt1] : r0_7
# 504| r0_9(glval<int>) = FieldAddress[x] : r0_7
# 504| r0_10(glval<int>) = VariableAddress[x] :
# 504| r0_11(int) = Load : r0_10, mu0_2
@@ -2252,7 +2252,7 @@ ir.cpp:
# 504| r0_16(int) = Convert : r0_15
# 504| mu0_17(int) = Store : r0_13, r0_16
# 505| r0_18(glval<Point>) = VariableAddress[pt2] :
# 505| mu0_19(Point) = Uninitialized : r0_18
# 505| mu0_19(Point) = Uninitialized[pt2] : r0_18
# 505| r0_20(glval<int>) = FieldAddress[x] : r0_18
# 505| r0_21(glval<int>) = VariableAddress[x] :
# 505| r0_22(int) = Load : r0_21, mu0_2
@@ -2261,7 +2261,7 @@ ir.cpp:
# 505| r0_25(int) = Constant[0] :
# 505| mu0_26(int) = Store : r0_24, r0_25
# 506| r0_27(glval<Point>) = VariableAddress[pt3] :
# 506| mu0_28(Point) = Uninitialized : r0_27
# 506| mu0_28(Point) = Uninitialized[pt3] : r0_27
# 506| r0_29(glval<int>) = FieldAddress[x] : r0_27
# 506| r0_30(int) = Constant[0] :
# 506| mu0_31(int) = Store : r0_29, r0_30
@@ -2289,7 +2289,7 @@ ir.cpp:
# 512| r0_5(glval<float>) = VariableAddress[f] :
# 512| mu0_6(float) = InitializeParameter[f] : r0_5
# 513| r0_7(glval<Rect>) = VariableAddress[r1] :
# 513| mu0_8(Rect) = Uninitialized : r0_7
# 513| mu0_8(Rect) = Uninitialized[r1] : r0_7
# 513| r0_9(glval<Point>) = FieldAddress[topLeft] : r0_7
# 513| r0_10(Point) = Constant[0] :
# 513| mu0_11(Point) = Store : r0_9, r0_10
@@ -2297,7 +2297,7 @@ ir.cpp:
# 513| r0_13(Point) = Constant[0] :
# 513| mu0_14(Point) = Store : r0_12, r0_13
# 514| r0_15(glval<Rect>) = VariableAddress[r2] :
# 514| mu0_16(Rect) = Uninitialized : r0_15
# 514| mu0_16(Rect) = Uninitialized[r2] : r0_15
# 514| r0_17(glval<Point>) = FieldAddress[topLeft] : r0_15
# 514| r0_18(glval<int>) = FieldAddress[x] : r0_17
# 514| r0_19(glval<int>) = VariableAddress[x] :
@@ -2312,7 +2312,7 @@ ir.cpp:
# 514| r0_28(Point) = Constant[0] :
# 514| mu0_29(Point) = Store : r0_27, r0_28
# 515| r0_30(glval<Rect>) = VariableAddress[r3] :
# 515| mu0_31(Rect) = Uninitialized : r0_30
# 515| mu0_31(Rect) = Uninitialized[r3] : r0_30
# 515| r0_32(glval<Point>) = FieldAddress[topLeft] : r0_30
# 515| r0_33(glval<int>) = FieldAddress[x] : r0_32
# 515| r0_34(glval<int>) = VariableAddress[x] :
@@ -2334,7 +2334,7 @@ ir.cpp:
# 515| r0_50(int) = Convert : r0_49
# 515| mu0_51(int) = Store : r0_47, r0_50
# 516| r0_52(glval<Rect>) = VariableAddress[r4] :
# 516| mu0_53(Rect) = Uninitialized : r0_52
# 516| mu0_53(Rect) = Uninitialized[r4] : r0_52
# 516| r0_54(glval<Point>) = FieldAddress[topLeft] : r0_52
# 516| r0_55(glval<int>) = FieldAddress[x] : r0_54
# 516| r0_56(glval<int>) = VariableAddress[x] :
@@ -2366,13 +2366,13 @@ ir.cpp:
# 519| r0_5(glval<float>) = VariableAddress[f] :
# 519| mu0_6(float) = InitializeParameter[f] : r0_5
# 520| r0_7(glval<int[3]>) = VariableAddress[a1] :
# 520| mu0_8(int[3]) = Uninitialized : r0_7
# 520| mu0_8(int[3]) = Uninitialized[a1] : r0_7
# 520| r0_9(int) = Constant[0] :
# 520| r0_10(glval<int>) = PointerAdd : r0_7, r0_9
# 520| r0_11(unknown[12]) = Constant[0] :
# 520| mu0_12(unknown[12]) = Store : r0_10, r0_11
# 521| r0_13(glval<int[3]>) = VariableAddress[a2] :
# 521| mu0_14(int[3]) = Uninitialized : r0_13
# 521| mu0_14(int[3]) = Uninitialized[a2] : r0_13
# 521| r0_15(int) = Constant[0] :
# 521| r0_16(glval<int>) = PointerAdd : r0_13, r0_15
# 521| r0_17(glval<int>) = VariableAddress[x] :
@@ -2389,7 +2389,7 @@ ir.cpp:
# 521| r0_28(int) = Constant[0] :
# 521| mu0_29(int) = Store : r0_27, r0_28
# 522| r0_30(glval<int[3]>) = VariableAddress[a3] :
# 522| mu0_31(int[3]) = Uninitialized : r0_30
# 522| mu0_31(int[3]) = Uninitialized[a3] : r0_30
# 522| r0_32(int) = Constant[0] :
# 522| r0_33(glval<int>) = PointerAdd : r0_30, r0_32
# 522| r0_34(glval<int>) = VariableAddress[x] :
@@ -2414,7 +2414,7 @@ ir.cpp:
# 530| r0_5(glval<float>) = VariableAddress[f] :
# 530| mu0_6(float) = InitializeParameter[f] : r0_5
# 531| r0_7(glval<U>) = VariableAddress[u1] :
# 531| mu0_8(U) = Uninitialized : r0_7
# 531| mu0_8(U) = Uninitialized[u1] : r0_7
# 531| r0_9(glval<double>) = FieldAddress[d] : r0_7
# 531| r0_10(glval<float>) = VariableAddress[f] :
# 531| r0_11(float) = Load : r0_10, mu0_2
@@ -2584,15 +2584,15 @@ ir.cpp:
# 574| r0_17(char[5]) = Load : r0_16, mu0_2
# 574| mu0_18(char[5]) = Store : r0_15, r0_17
# 575| r0_19(glval<char[2]>) = VariableAddress[b] :
# 575| mu0_20(char[2]) = Uninitialized : r0_19
# 575| mu0_20(char[2]) = Uninitialized[b] : r0_19
# 576| r0_21(glval<char[2]>) = VariableAddress[c] :
# 576| mu0_22(char[2]) = Uninitialized : r0_21
# 576| mu0_22(char[2]) = Uninitialized[c] : r0_21
# 576| r0_23(int) = Constant[0] :
# 576| r0_24(glval<char>) = PointerAdd : r0_21, r0_23
# 576| r0_25(unknown[2]) = Constant[0] :
# 576| mu0_26(unknown[2]) = Store : r0_24, r0_25
# 577| r0_27(glval<char[2]>) = VariableAddress[d] :
# 577| mu0_28(char[2]) = Uninitialized : r0_27
# 577| mu0_28(char[2]) = Uninitialized[d] : r0_27
# 577| r0_29(int) = Constant[0] :
# 577| r0_30(glval<char>) = PointerAdd : r0_27, r0_29
# 577| r0_31(char) = Constant[0] :
@@ -2602,7 +2602,7 @@ ir.cpp:
# 577| r0_35(char) = Constant[0] :
# 577| mu0_36(char) = Store : r0_34, r0_35
# 578| r0_37(glval<char[2]>) = VariableAddress[e] :
# 578| mu0_38(char[2]) = Uninitialized : r0_37
# 578| mu0_38(char[2]) = Uninitialized[e] : r0_37
# 578| r0_39(int) = Constant[0] :
# 578| r0_40(glval<char>) = PointerAdd : r0_37, r0_39
# 578| r0_41(char) = Constant[0] :
@@ -2612,7 +2612,7 @@ ir.cpp:
# 578| r0_45(char) = Constant[1] :
# 578| mu0_46(char) = Store : r0_44, r0_45
# 579| r0_47(glval<char[3]>) = VariableAddress[f] :
# 579| mu0_48(char[3]) = Uninitialized : r0_47
# 579| mu0_48(char[3]) = Uninitialized[f] : r0_47
# 579| r0_49(int) = Constant[0] :
# 579| r0_50(glval<char>) = PointerAdd : r0_47, r0_49
# 579| r0_51(char) = Constant[0] :
@@ -2799,7 +2799,7 @@ ir.cpp:
# 645| r0_14(glval<int>) = FieldAddress[m_a] : r0_13
# 645| mu0_15(int) = Store : r0_14, r0_12
# 646| r0_16(glval<int>) = VariableAddress[x] :
# 646| mu0_17(int) = Uninitialized : r0_16
# 646| mu0_17(int) = Uninitialized[x] : r0_16
# 647| r0_18(C *) = CopyValue : r0_3
# 647| r0_19(glval<int>) = FieldAddress[m_a] : r0_18
# 647| r0_20(int) = Load : r0_19, mu0_2
@@ -2937,7 +2937,7 @@ ir.cpp:
# 691| mu0_1(unknown) = AliasedDefinition :
# 691| mu0_2(unknown) = UnmodeledDefinition :
# 692| r0_3(glval<int[10]>) = VariableAddress[a] :
# 692| mu0_4(int[10]) = Uninitialized : r0_3
# 692| mu0_4(int[10]) = Uninitialized[a] : r0_3
# 693| r0_5(glval<int(&)[10]>) = VariableAddress[ra] :
# 693| r0_6(glval<int[10]>) = VariableAddress[a] :
# 693| mu0_7(int(&)[10]) = Store : r0_5, r0_6
@@ -3851,7 +3851,7 @@ ir.cpp:
# 871| mu0_1(unknown) = AliasedDefinition :
# 871| mu0_2(unknown) = UnmodeledDefinition :
# 872| r0_3(glval<char[5]>) = VariableAddress[a] :
# 872| mu0_4(char[5]) = Uninitialized : r0_3
# 872| mu0_4(char[5]) = Uninitialized[a] : r0_3
# 873| r0_5(glval<char *>) = VariableAddress[p] :
# 873| r0_6(glval<char[5]>) = VariableAddress[a] :
# 873| r0_7(char *) = Convert : r0_6
@@ -3924,13 +3924,13 @@ ir.cpp:
# 888| r0_3(glval<int>) = VariableAddress[x] :
# 888| mu0_4(int) = InitializeParameter[x] : r0_3
# 889| r0_5(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 889| mu0_6(__va_list_tag[1]) = Uninitialized : r0_5
# 889| mu0_6(__va_list_tag[1]) = Uninitialized[args] : r0_5
# 891| r0_7(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 891| r0_8(__va_list_tag *) = Convert : r0_7
# 891| r0_9(glval<int>) = VariableAddress[x] :
# 891| v0_10(void) = VarArgsStart : r0_8, r0_9
# 892| r0_11(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 892| mu0_12(__va_list_tag[1]) = Uninitialized : r0_11
# 892| mu0_12(__va_list_tag[1]) = Uninitialized[args2] : r0_11
# 893| r0_13(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 893| r0_14(__va_list_tag *) = Convert : r0_13
# 893| r0_15(glval<__va_list_tag[1]>) = VariableAddress[args] :
@@ -4161,7 +4161,7 @@ ir.cpp:
# 961| mu0_1(unknown) = AliasedDefinition :
# 961| mu0_2(unknown) = UnmodeledDefinition :
# 962| r0_3(glval<int[1000]>) = VariableAddress[a1] :
# 962| mu0_4(int[1000]) = Uninitialized : r0_3
# 962| mu0_4(int[1000]) = Uninitialized[a1] : r0_3
# 962| r0_5(int) = Constant[0] :
# 962| r0_6(glval<int>) = PointerAdd : r0_3, r0_5
# 962| r0_7(unknown[8]) = Constant[0] :

View File

@@ -5,7 +5,7 @@ bad_asts.cpp:
# 14| mu0_1(unknown) = AliasedDefinition :
# 14| mu0_2(unknown) = UnmodeledDefinition :
# 15| r0_3(glval<S>) = VariableAddress[s] :
# 15| mu0_4(S) = Uninitialized : r0_3
# 15| mu0_4(S) = Uninitialized[s] : r0_3
# 15| r0_5(glval<int>) = FieldAddress[x] : r0_3
# 15| r0_6(int) = Constant[0] :
# 15| mu0_7(int) = Store : r0_5, r0_6
@@ -186,7 +186,7 @@ ir.cpp:
# 50| r0_5(glval<int>) = VariableAddress[y] :
# 50| m0_6(int) = InitializeParameter[y] : r0_5
# 51| r0_7(glval<int>) = VariableAddress[z] :
# 51| m0_8(int) = Uninitialized : r0_7
# 51| m0_8(int) = Uninitialized[z] : r0_7
# 53| r0_9(glval<int>) = VariableAddress[x] :
# 53| r0_10(int) = Load : r0_9, m0_4
# 53| r0_11(glval<int>) = VariableAddress[y] :
@@ -359,7 +359,7 @@ ir.cpp:
# 87| r0_5(glval<int>) = VariableAddress[y] :
# 87| m0_6(int) = InitializeParameter[y] : r0_5
# 88| r0_7(glval<bool>) = VariableAddress[b] :
# 88| m0_8(bool) = Uninitialized : r0_7
# 88| m0_8(bool) = Uninitialized[b] : r0_7
# 90| r0_9(glval<int>) = VariableAddress[x] :
# 90| r0_10(int) = Load : r0_9, m0_4
# 90| r0_11(glval<int>) = VariableAddress[y] :
@@ -415,7 +415,7 @@ ir.cpp:
# 98| r0_3(glval<int>) = VariableAddress[x] :
# 98| m0_4(int) = InitializeParameter[x] : r0_3
# 99| r0_5(glval<int>) = VariableAddress[y] :
# 99| m0_6(int) = Uninitialized : r0_5
# 99| m0_6(int) = Uninitialized[y] : r0_5
# 101| r0_7(glval<int>) = VariableAddress[x] :
# 101| r0_8(int) = Load : r0_7, m0_4
# 101| r0_9(int) = Constant[1] :
@@ -457,7 +457,7 @@ ir.cpp:
# 107| r0_3(glval<int>) = VariableAddress[x] :
# 107| mu0_4(int) = InitializeParameter[x] : r0_3
# 108| r0_5(glval<int *>) = VariableAddress[p] :
# 108| m0_6(int *) = Uninitialized : r0_5
# 108| m0_6(int *) = Uninitialized[p] : r0_5
# 110| r0_7(glval<int>) = VariableAddress[x] :
# 110| r0_8(int) = Load : r0_7, mu0_2
# 110| r0_9(int) = Constant[1] :
@@ -487,7 +487,7 @@ ir.cpp:
# 114| r0_5(glval<double>) = VariableAddress[y] :
# 114| m0_6(double) = InitializeParameter[y] : r0_5
# 115| r0_7(glval<double>) = VariableAddress[z] :
# 115| m0_8(double) = Uninitialized : r0_7
# 115| m0_8(double) = Uninitialized[z] : r0_7
# 117| r0_9(glval<double>) = VariableAddress[x] :
# 117| r0_10(double) = Load : r0_9, m0_4
# 117| r0_11(glval<double>) = VariableAddress[y] :
@@ -569,7 +569,7 @@ ir.cpp:
# 133| r0_5(glval<double>) = VariableAddress[y] :
# 133| m0_6(double) = InitializeParameter[y] : r0_5
# 134| r0_7(glval<bool>) = VariableAddress[b] :
# 134| m0_8(bool) = Uninitialized : r0_7
# 134| m0_8(bool) = Uninitialized[b] : r0_7
# 136| r0_9(glval<double>) = VariableAddress[x] :
# 136| r0_10(double) = Load : r0_9, m0_4
# 136| r0_11(glval<double>) = VariableAddress[y] :
@@ -625,7 +625,7 @@ ir.cpp:
# 144| r0_3(glval<float>) = VariableAddress[x] :
# 144| m0_4(float) = InitializeParameter[x] : r0_3
# 145| r0_5(glval<float>) = VariableAddress[y] :
# 145| m0_6(float) = Uninitialized : r0_5
# 145| m0_6(float) = Uninitialized[y] : r0_5
# 147| r0_7(glval<float>) = VariableAddress[x] :
# 147| r0_8(float) = Load : r0_7, m0_4
# 147| r0_9(float) = Constant[1.0] :
@@ -669,9 +669,9 @@ ir.cpp:
# 153| r0_5(glval<int>) = VariableAddress[i] :
# 153| m0_6(int) = InitializeParameter[i] : r0_5
# 154| r0_7(glval<int *>) = VariableAddress[q] :
# 154| m0_8(int *) = Uninitialized : r0_7
# 154| m0_8(int *) = Uninitialized[q] : r0_7
# 155| r0_9(glval<bool>) = VariableAddress[b] :
# 155| m0_10(bool) = Uninitialized : r0_9
# 155| m0_10(bool) = Uninitialized[b] : r0_9
# 157| r0_11(glval<int *>) = VariableAddress[p] :
# 157| r0_12(int *) = Load : r0_11, m0_4
# 157| r0_13(glval<int>) = VariableAddress[i] :
@@ -745,7 +745,7 @@ ir.cpp:
# 171| r0_5(glval<int>) = VariableAddress[i] :
# 171| m0_6(int) = InitializeParameter[i] : r0_5
# 172| r0_7(glval<int>) = VariableAddress[x] :
# 172| m0_8(int) = Uninitialized : r0_7
# 172| m0_8(int) = Uninitialized[x] : r0_7
# 174| r0_9(glval<int *>) = VariableAddress[p] :
# 174| r0_10(int *) = Load : r0_9, m0_4
# 174| r0_11(glval<int>) = VariableAddress[i] :
@@ -779,7 +779,7 @@ ir.cpp:
# 178| r0_39(int *) = PointerAdd[4] : r0_36, r0_38
# 178| mu0_40(int) = Store : r0_39, r0_34
# 180| r0_41(glval<int[10]>) = VariableAddress[a] :
# 180| m0_42(int[10]) = Uninitialized : r0_41
# 180| m0_42(int[10]) = Uninitialized[a] : r0_41
# 181| r0_43(glval<int[10]>) = VariableAddress[a] :
# 181| r0_44(int *) = Convert : r0_43
# 181| r0_45(glval<int>) = VariableAddress[i] :
@@ -860,7 +860,7 @@ ir.cpp:
# 193| r0_5(glval<int *>) = VariableAddress[q] :
# 193| m0_6(int *) = InitializeParameter[q] : r0_5
# 194| r0_7(glval<bool>) = VariableAddress[b] :
# 194| m0_8(bool) = Uninitialized : r0_7
# 194| m0_8(bool) = Uninitialized[b] : r0_7
# 196| r0_9(glval<int *>) = VariableAddress[p] :
# 196| r0_10(int *) = Load : r0_9, m0_4
# 196| r0_11(glval<int *>) = VariableAddress[q] :
@@ -916,7 +916,7 @@ ir.cpp:
# 204| r0_3(glval<int *>) = VariableAddress[p] :
# 204| m0_4(int *) = InitializeParameter[p] : r0_3
# 205| r0_5(glval<int *>) = VariableAddress[q] :
# 205| m0_6(int *) = Uninitialized : r0_5
# 205| m0_6(int *) = Uninitialized[q] : r0_5
# 207| r0_7(glval<int *>) = VariableAddress[p] :
# 207| r0_8(int *) = Load : r0_7, m0_4
# 207| r0_9(int) = Constant[1] :
@@ -1000,7 +1000,7 @@ ir.cpp:
# 230| mu0_1(unknown) = AliasedDefinition :
# 230| mu0_2(unknown) = UnmodeledDefinition :
# 231| r0_3(glval<int>) = VariableAddress[x] :
# 231| m0_4(int) = Uninitialized : r0_3
# 231| m0_4(int) = Uninitialized[x] : r0_3
# 232| r0_5(glval<int>) = VariableAddress[y] :
# 232| r0_6(glval<int>) = VariableAddress[x] :
# 232| r0_7(int) = Load : r0_6, m0_4
@@ -1163,7 +1163,7 @@ ir.cpp:
# 265| mu0_1(unknown) = AliasedDefinition :
# 265| mu0_2(unknown) = UnmodeledDefinition :
# 266| r0_3(glval<int>) = VariableAddress[j] :
# 266| m0_4(int) = Uninitialized : r0_3
# 266| m0_4(int) = Uninitialized[j] : r0_3
#-----| Goto -> Block 2
# 265| Block 1
@@ -1709,7 +1709,7 @@ ir.cpp:
# 384| r0_3(glval<int>) = VariableAddress[x] :
# 384| m0_4(int) = InitializeParameter[x] : r0_3
# 385| r0_5(glval<int>) = VariableAddress[y] :
# 385| m0_6(int) = Uninitialized : r0_5
# 385| m0_6(int) = Uninitialized[y] : r0_5
# 386| r0_7(glval<int>) = VariableAddress[x] :
# 386| r0_8(int) = Load : r0_7, m0_4
# 386| v0_9(void) = Switch : r0_8
@@ -1804,7 +1804,7 @@ ir.cpp:
# 426| mu0_1(unknown) = AliasedDefinition :
# 426| mu0_2(unknown) = UnmodeledDefinition :
# 427| r0_3(glval<Point>) = VariableAddress[pt] :
# 427| mu0_4(Point) = Uninitialized : r0_3
# 427| mu0_4(Point) = Uninitialized[pt] : r0_3
# 428| r0_5(int) = Constant[5] :
# 428| r0_6(glval<Point>) = VariableAddress[pt] :
# 428| r0_7(glval<int>) = FieldAddress[x] : r0_6
@@ -1834,7 +1834,7 @@ ir.cpp:
# 433| r0_5(glval<bool>) = VariableAddress[b] :
# 433| m0_6(bool) = InitializeParameter[b] : r0_5
# 434| r0_7(glval<int>) = VariableAddress[x] :
# 434| m0_8(int) = Uninitialized : r0_7
# 434| m0_8(int) = Uninitialized[x] : r0_7
# 435| r0_9(glval<bool>) = VariableAddress[a] :
# 435| r0_10(bool) = Load : r0_9, m0_4
# 435| v0_11(void) = ConditionalBranch : r0_10
@@ -1896,7 +1896,7 @@ ir.cpp:
# 447| r0_5(glval<bool>) = VariableAddress[b] :
# 447| m0_6(bool) = InitializeParameter[b] : r0_5
# 448| r0_7(glval<int>) = VariableAddress[x] :
# 448| m0_8(int) = Uninitialized : r0_7
# 448| m0_8(int) = Uninitialized[x] : r0_7
# 449| r0_9(glval<bool>) = VariableAddress[a] :
# 449| r0_10(bool) = Load : r0_9, m0_4
# 449| v0_11(void) = ConditionalBranch : r0_10
@@ -1958,7 +1958,7 @@ ir.cpp:
# 461| r0_5(glval<bool>) = VariableAddress[b] :
# 461| m0_6(bool) = InitializeParameter[b] : r0_5
# 462| r0_7(glval<int>) = VariableAddress[x] :
# 462| m0_8(int) = Uninitialized : r0_7
# 462| m0_8(int) = Uninitialized[x] : r0_7
# 463| r0_9(glval<bool>) = VariableAddress[a] :
# 463| r0_10(bool) = Load : r0_9, m0_4
# 463| v0_11(void) = ConditionalBranch : r0_10
@@ -2013,7 +2013,7 @@ ir.cpp:
# 475| r0_5(glval<bool>) = VariableAddress[b] :
# 475| m0_6(bool) = InitializeParameter[b] : r0_5
# 476| r0_7(glval<bool>) = VariableAddress[x] :
# 476| m0_8(bool) = Uninitialized : r0_7
# 476| m0_8(bool) = Uninitialized[x] : r0_7
# 477| r0_9(glval<bool>) = VariableAddress[a] :
# 477| r0_10(bool) = Load : r0_9, m0_4
# 477| v0_11(void) = ConditionalBranch : r0_10
@@ -2163,9 +2163,9 @@ ir.cpp:
# 486| r0_3(glval<bool>) = VariableAddress[a] :
# 486| m0_4(bool) = InitializeParameter[a] : r0_3
# 487| r0_5(glval<int>) = VariableAddress[x] :
# 487| mu0_6(int) = Uninitialized : r0_5
# 487| mu0_6(int) = Uninitialized[x] : r0_5
# 488| r0_7(glval<int>) = VariableAddress[y] :
# 488| mu0_8(int) = Uninitialized : r0_7
# 488| mu0_8(int) = Uninitialized[y] : r0_7
# 489| r0_9(int) = Constant[5] :
# 489| r0_10(glval<bool>) = VariableAddress[a] :
# 489| r0_11(bool) = Load : r0_10, m0_4
@@ -2258,7 +2258,7 @@ ir.cpp:
# 503| r0_5(glval<float>) = VariableAddress[f] :
# 503| m0_6(float) = InitializeParameter[f] : r0_5
# 504| r0_7(glval<Point>) = VariableAddress[pt1] :
# 504| m0_8(Point) = Uninitialized : r0_7
# 504| m0_8(Point) = Uninitialized[pt1] : r0_7
# 504| r0_9(glval<int>) = FieldAddress[x] : r0_7
# 504| r0_10(glval<int>) = VariableAddress[x] :
# 504| r0_11(int) = Load : r0_10, m0_4
@@ -2269,7 +2269,7 @@ ir.cpp:
# 504| r0_16(int) = Convert : r0_15
# 504| mu0_17(int) = Store : r0_13, r0_16
# 505| r0_18(glval<Point>) = VariableAddress[pt2] :
# 505| m0_19(Point) = Uninitialized : r0_18
# 505| m0_19(Point) = Uninitialized[pt2] : r0_18
# 505| r0_20(glval<int>) = FieldAddress[x] : r0_18
# 505| r0_21(glval<int>) = VariableAddress[x] :
# 505| r0_22(int) = Load : r0_21, m0_4
@@ -2278,7 +2278,7 @@ ir.cpp:
# 505| r0_25(int) = Constant[0] :
# 505| mu0_26(int) = Store : r0_24, r0_25
# 506| r0_27(glval<Point>) = VariableAddress[pt3] :
# 506| m0_28(Point) = Uninitialized : r0_27
# 506| m0_28(Point) = Uninitialized[pt3] : r0_27
# 506| r0_29(glval<int>) = FieldAddress[x] : r0_27
# 506| r0_30(int) = Constant[0] :
# 506| m0_31(int) = Store : r0_29, r0_30
@@ -2306,7 +2306,7 @@ ir.cpp:
# 512| r0_5(glval<float>) = VariableAddress[f] :
# 512| m0_6(float) = InitializeParameter[f] : r0_5
# 513| r0_7(glval<Rect>) = VariableAddress[r1] :
# 513| m0_8(Rect) = Uninitialized : r0_7
# 513| m0_8(Rect) = Uninitialized[r1] : r0_7
# 513| r0_9(glval<Point>) = FieldAddress[topLeft] : r0_7
# 513| r0_10(Point) = Constant[0] :
# 513| m0_11(Point) = Store : r0_9, r0_10
@@ -2314,7 +2314,7 @@ ir.cpp:
# 513| r0_13(Point) = Constant[0] :
# 513| mu0_14(Point) = Store : r0_12, r0_13
# 514| r0_15(glval<Rect>) = VariableAddress[r2] :
# 514| m0_16(Rect) = Uninitialized : r0_15
# 514| m0_16(Rect) = Uninitialized[r2] : r0_15
# 514| r0_17(glval<Point>) = FieldAddress[topLeft] : r0_15
# 514| r0_18(glval<int>) = FieldAddress[x] : r0_17
# 514| r0_19(glval<int>) = VariableAddress[x] :
@@ -2329,7 +2329,7 @@ ir.cpp:
# 514| r0_28(Point) = Constant[0] :
# 514| mu0_29(Point) = Store : r0_27, r0_28
# 515| r0_30(glval<Rect>) = VariableAddress[r3] :
# 515| m0_31(Rect) = Uninitialized : r0_30
# 515| m0_31(Rect) = Uninitialized[r3] : r0_30
# 515| r0_32(glval<Point>) = FieldAddress[topLeft] : r0_30
# 515| r0_33(glval<int>) = FieldAddress[x] : r0_32
# 515| r0_34(glval<int>) = VariableAddress[x] :
@@ -2351,7 +2351,7 @@ ir.cpp:
# 515| r0_50(int) = Convert : r0_49
# 515| mu0_51(int) = Store : r0_47, r0_50
# 516| r0_52(glval<Rect>) = VariableAddress[r4] :
# 516| m0_53(Rect) = Uninitialized : r0_52
# 516| m0_53(Rect) = Uninitialized[r4] : r0_52
# 516| r0_54(glval<Point>) = FieldAddress[topLeft] : r0_52
# 516| r0_55(glval<int>) = FieldAddress[x] : r0_54
# 516| r0_56(glval<int>) = VariableAddress[x] :
@@ -2383,13 +2383,13 @@ ir.cpp:
# 519| r0_5(glval<float>) = VariableAddress[f] :
# 519| m0_6(float) = InitializeParameter[f] : r0_5
# 520| r0_7(glval<int[3]>) = VariableAddress[a1] :
# 520| mu0_8(int[3]) = Uninitialized : r0_7
# 520| mu0_8(int[3]) = Uninitialized[a1] : r0_7
# 520| r0_9(int) = Constant[0] :
# 520| r0_10(glval<int>) = PointerAdd : r0_7, r0_9
# 520| r0_11(unknown[12]) = Constant[0] :
# 520| mu0_12(unknown[12]) = Store : r0_10, r0_11
# 521| r0_13(glval<int[3]>) = VariableAddress[a2] :
# 521| mu0_14(int[3]) = Uninitialized : r0_13
# 521| mu0_14(int[3]) = Uninitialized[a2] : r0_13
# 521| r0_15(int) = Constant[0] :
# 521| r0_16(glval<int>) = PointerAdd : r0_13, r0_15
# 521| r0_17(glval<int>) = VariableAddress[x] :
@@ -2406,7 +2406,7 @@ ir.cpp:
# 521| r0_28(int) = Constant[0] :
# 521| mu0_29(int) = Store : r0_27, r0_28
# 522| r0_30(glval<int[3]>) = VariableAddress[a3] :
# 522| mu0_31(int[3]) = Uninitialized : r0_30
# 522| mu0_31(int[3]) = Uninitialized[a3] : r0_30
# 522| r0_32(int) = Constant[0] :
# 522| r0_33(glval<int>) = PointerAdd : r0_30, r0_32
# 522| r0_34(glval<int>) = VariableAddress[x] :
@@ -2431,7 +2431,7 @@ ir.cpp:
# 530| r0_5(glval<float>) = VariableAddress[f] :
# 530| m0_6(float) = InitializeParameter[f] : r0_5
# 531| r0_7(glval<U>) = VariableAddress[u1] :
# 531| m0_8(U) = Uninitialized : r0_7
# 531| m0_8(U) = Uninitialized[u1] : r0_7
# 531| r0_9(glval<double>) = FieldAddress[d] : r0_7
# 531| r0_10(glval<float>) = VariableAddress[f] :
# 531| r0_11(float) = Load : r0_10, m0_6
@@ -2603,15 +2603,15 @@ ir.cpp:
# 574| r0_17(char[5]) = Load : r0_16, mu0_2
# 574| m0_18(char[5]) = Store : r0_15, r0_17
# 575| r0_19(glval<char[2]>) = VariableAddress[b] :
# 575| m0_20(char[2]) = Uninitialized : r0_19
# 575| m0_20(char[2]) = Uninitialized[b] : r0_19
# 576| r0_21(glval<char[2]>) = VariableAddress[c] :
# 576| mu0_22(char[2]) = Uninitialized : r0_21
# 576| mu0_22(char[2]) = Uninitialized[c] : r0_21
# 576| r0_23(int) = Constant[0] :
# 576| r0_24(glval<char>) = PointerAdd : r0_21, r0_23
# 576| r0_25(unknown[2]) = Constant[0] :
# 576| mu0_26(unknown[2]) = Store : r0_24, r0_25
# 577| r0_27(glval<char[2]>) = VariableAddress[d] :
# 577| mu0_28(char[2]) = Uninitialized : r0_27
# 577| mu0_28(char[2]) = Uninitialized[d] : r0_27
# 577| r0_29(int) = Constant[0] :
# 577| r0_30(glval<char>) = PointerAdd : r0_27, r0_29
# 577| r0_31(char) = Constant[0] :
@@ -2621,7 +2621,7 @@ ir.cpp:
# 577| r0_35(char) = Constant[0] :
# 577| mu0_36(char) = Store : r0_34, r0_35
# 578| r0_37(glval<char[2]>) = VariableAddress[e] :
# 578| mu0_38(char[2]) = Uninitialized : r0_37
# 578| mu0_38(char[2]) = Uninitialized[e] : r0_37
# 578| r0_39(int) = Constant[0] :
# 578| r0_40(glval<char>) = PointerAdd : r0_37, r0_39
# 578| r0_41(char) = Constant[0] :
@@ -2631,7 +2631,7 @@ ir.cpp:
# 578| r0_45(char) = Constant[1] :
# 578| mu0_46(char) = Store : r0_44, r0_45
# 579| r0_47(glval<char[3]>) = VariableAddress[f] :
# 579| mu0_48(char[3]) = Uninitialized : r0_47
# 579| mu0_48(char[3]) = Uninitialized[f] : r0_47
# 579| r0_49(int) = Constant[0] :
# 579| r0_50(glval<char>) = PointerAdd : r0_47, r0_49
# 579| r0_51(char) = Constant[0] :
@@ -2818,7 +2818,7 @@ ir.cpp:
# 645| r0_14(glval<int>) = FieldAddress[m_a] : r0_13
# 645| mu0_15(int) = Store : r0_14, r0_12
# 646| r0_16(glval<int>) = VariableAddress[x] :
# 646| m0_17(int) = Uninitialized : r0_16
# 646| m0_17(int) = Uninitialized[x] : r0_16
# 647| r0_18(C *) = CopyValue : r0_3
# 647| r0_19(glval<int>) = FieldAddress[m_a] : r0_18
# 647| r0_20(int) = Load : r0_19, mu0_2
@@ -2956,7 +2956,7 @@ ir.cpp:
# 691| mu0_1(unknown) = AliasedDefinition :
# 691| mu0_2(unknown) = UnmodeledDefinition :
# 692| r0_3(glval<int[10]>) = VariableAddress[a] :
# 692| mu0_4(int[10]) = Uninitialized : r0_3
# 692| mu0_4(int[10]) = Uninitialized[a] : r0_3
# 693| r0_5(glval<int(&)[10]>) = VariableAddress[ra] :
# 693| r0_6(glval<int[10]>) = VariableAddress[a] :
# 693| m0_7(int(&)[10]) = Store : r0_5, r0_6
@@ -3871,7 +3871,7 @@ ir.cpp:
# 871| mu0_1(unknown) = AliasedDefinition :
# 871| mu0_2(unknown) = UnmodeledDefinition :
# 872| r0_3(glval<char[5]>) = VariableAddress[a] :
# 872| mu0_4(char[5]) = Uninitialized : r0_3
# 872| mu0_4(char[5]) = Uninitialized[a] : r0_3
# 873| r0_5(glval<char *>) = VariableAddress[p] :
# 873| r0_6(glval<char[5]>) = VariableAddress[a] :
# 873| r0_7(char *) = Convert : r0_6
@@ -3944,13 +3944,13 @@ ir.cpp:
# 888| r0_3(glval<int>) = VariableAddress[x] :
# 888| mu0_4(int) = InitializeParameter[x] : r0_3
# 889| r0_5(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 889| mu0_6(__va_list_tag[1]) = Uninitialized : r0_5
# 889| mu0_6(__va_list_tag[1]) = Uninitialized[args] : r0_5
# 891| r0_7(glval<__va_list_tag[1]>) = VariableAddress[args] :
# 891| r0_8(__va_list_tag *) = Convert : r0_7
# 891| r0_9(glval<int>) = VariableAddress[x] :
# 891| v0_10(void) = VarArgsStart : r0_8, r0_9
# 892| r0_11(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 892| mu0_12(__va_list_tag[1]) = Uninitialized : r0_11
# 892| mu0_12(__va_list_tag[1]) = Uninitialized[args2] : r0_11
# 893| r0_13(glval<__va_list_tag[1]>) = VariableAddress[args2] :
# 893| r0_14(__va_list_tag *) = Convert : r0_13
# 893| r0_15(glval<__va_list_tag[1]>) = VariableAddress[args] :
@@ -4182,7 +4182,7 @@ ir.cpp:
# 961| mu0_1(unknown) = AliasedDefinition :
# 961| mu0_2(unknown) = UnmodeledDefinition :
# 962| r0_3(glval<int[1000]>) = VariableAddress[a1] :
# 962| mu0_4(int[1000]) = Uninitialized : r0_3
# 962| mu0_4(int[1000]) = Uninitialized[a1] : r0_3
# 962| r0_5(int) = Constant[0] :
# 962| r0_6(glval<int>) = PointerAdd : r0_3, r0_5
# 962| r0_7(unknown[8]) = Constant[0] :

View File

@@ -16,15 +16,15 @@ test.cpp:
# 1| valnum = m0_6
# 2| r0_7(glval<int>) = VariableAddress[x] :
# 2| valnum = r0_7
# 2| m0_8(int) = Uninitialized : r0_7
# 2| m0_8(int) = Uninitialized[x] : r0_7
# 2| valnum = unique
# 2| r0_9(glval<int>) = VariableAddress[y] :
# 2| valnum = r0_9
# 2| m0_10(int) = Uninitialized : r0_9
# 2| m0_10(int) = Uninitialized[y] : r0_9
# 2| valnum = unique
# 3| r0_11(glval<unsigned char>) = VariableAddress[b] :
# 3| valnum = unique
# 3| m0_12(unsigned char) = Uninitialized : r0_11
# 3| m0_12(unsigned char) = Uninitialized[b] : r0_11
# 3| valnum = unique
# 5| r0_13(glval<int>) = VariableAddress[p0] :
# 5| valnum = r0_3
@@ -86,15 +86,15 @@ test.cpp:
# 12| valnum = m0_6
# 13| r0_7(glval<int>) = VariableAddress[x] :
# 13| valnum = r0_7
# 13| m0_8(int) = Uninitialized : r0_7
# 13| m0_8(int) = Uninitialized[x] : r0_7
# 13| valnum = unique
# 13| r0_9(glval<int>) = VariableAddress[y] :
# 13| valnum = r0_9
# 13| m0_10(int) = Uninitialized : r0_9
# 13| m0_10(int) = Uninitialized[y] : r0_9
# 13| valnum = unique
# 14| r0_11(glval<unsigned char>) = VariableAddress[b] :
# 14| valnum = unique
# 14| m0_12(unsigned char) = Uninitialized : r0_11
# 14| m0_12(unsigned char) = Uninitialized[b] : r0_11
# 14| valnum = unique
# 16| r0_13(glval<int>) = VariableAddress[p0] :
# 16| valnum = r0_3
@@ -168,15 +168,15 @@ test.cpp:
# 25| valnum = m0_6
# 26| r0_7(glval<int>) = VariableAddress[x] :
# 26| valnum = r0_7
# 26| m0_8(int) = Uninitialized : r0_7
# 26| m0_8(int) = Uninitialized[x] : r0_7
# 26| valnum = unique
# 26| r0_9(glval<int>) = VariableAddress[y] :
# 26| valnum = r0_9
# 26| m0_10(int) = Uninitialized : r0_9
# 26| m0_10(int) = Uninitialized[y] : r0_9
# 26| valnum = unique
# 27| r0_11(glval<unsigned char>) = VariableAddress[b] :
# 27| valnum = unique
# 27| m0_12(unsigned char) = Uninitialized : r0_11
# 27| m0_12(unsigned char) = Uninitialized[b] : r0_11
# 27| valnum = unique
# 29| r0_13(glval<int>) = VariableAddress[p0] :
# 29| valnum = r0_3
@@ -261,15 +261,15 @@ test.cpp:
# 39| valnum = m0_8
# 40| r0_9(glval<int>) = VariableAddress[x] :
# 40| valnum = r0_9
# 40| m0_10(int) = Uninitialized : r0_9
# 40| m0_10(int) = Uninitialized[x] : r0_9
# 40| valnum = unique
# 40| r0_11(glval<int>) = VariableAddress[y] :
# 40| valnum = r0_11
# 40| m0_12(int) = Uninitialized : r0_11
# 40| m0_12(int) = Uninitialized[y] : r0_11
# 40| valnum = unique
# 41| r0_13(glval<unsigned char>) = VariableAddress[b] :
# 41| valnum = unique
# 41| m0_14(unsigned char) = Uninitialized : r0_13
# 41| m0_14(unsigned char) = Uninitialized[b] : r0_13
# 41| valnum = unique
# 43| r0_15(glval<int>) = VariableAddress[p0] :
# 43| valnum = r0_3
@@ -353,7 +353,7 @@ test.cpp:
# 49| valnum = m0_6
# 50| r0_7(glval<char *>) = VariableAddress[ptr] :
# 50| valnum = r0_7
# 50| m0_8(char *) = Uninitialized : r0_7
# 50| m0_8(char *) = Uninitialized[ptr] : r0_7
# 50| valnum = unique
# 51| r0_9(glval<unsigned int>) = VariableAddress[result] :
# 51| valnum = r0_9
@@ -601,7 +601,7 @@ test.cpp:
# 84| valnum = m0_8
# 86| r0_9(glval<int>) = VariableAddress[v] :
# 86| valnum = r0_9
# 86| m0_10(int) = Uninitialized : r0_9
# 86| m0_10(int) = Uninitialized[v] : r0_9
# 86| valnum = unique
# 88| r0_11(glval<void *>) = VariableAddress[p] :
# 88| valnum = r0_7